refactor(modules): update existing module implementations across attendance, audit, auth, classes, course-plans, exams, files, homework, layout, proctoring, questions, scheduling, textbooks, users
- Update attendance components and data-access for record management - Update audit log views, filters, and data-access - Update auth login and register forms - Update classes actions, components, and data-access (admin, schedule, stats) - Update course-plans actions, form, list, progress, and schema - Update exams actions, AI pipeline, preview components, and hooks - Update files components (icon, list, preview, upload) and data-access - Update homework assignment form, review view, auto-save hook, and stats-service - Update layout sidebar, header, and navigation config - Update proctoring actions, anti-cheat monitor, and data-access - Update questions actions, components (dialog, actions, columns, filters), and data-access - Update scheduling actions, auto-scheduler, components, and schema - Update textbooks constants and text-selection hook - Update users class-registration, import-dialog, data-access, and user-service
This commit is contained in:
@@ -43,14 +43,19 @@ export function AttendanceRecordList({ records }: { records: AttendanceListItem[
|
||||
const handleDelete = async () => {
|
||||
if (!deleteId) return
|
||||
setIsDeleting(true)
|
||||
const result = await deleteAttendanceAction(deleteId)
|
||||
setIsDeleting(false)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("sheet.deleted"))
|
||||
setDeleteId(null)
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
try {
|
||||
const result = await deleteAttendanceAction(deleteId)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("sheet.deleted"))
|
||||
setDeleteId(null)
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
}
|
||||
} catch {
|
||||
toast.error(t("errors.unexpected"))
|
||||
} finally {
|
||||
setIsDeleting(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,12 +72,16 @@ export function AttendanceRulesForm({
|
||||
formData.set("earlyLeaveThresholdMinutes", earlyLeaveThreshold)
|
||||
formData.set("enableAutoMark", enableAutoMark ? "true" : "false")
|
||||
|
||||
const result = await saveAttendanceRulesAction(null, formData)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("rules.saved"))
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
try {
|
||||
const result = await saveAttendanceRulesAction(null, formData)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("rules.saved"))
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
}
|
||||
} catch {
|
||||
toast.error(t("errors.unexpected"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,14 +210,19 @@ export function AttendanceSheet({
|
||||
setIsSubmitting(true)
|
||||
formData.set("recordsJson", JSON.stringify(records))
|
||||
|
||||
const result = await batchRecordAttendanceAction(null, formData)
|
||||
setIsSubmitting(false)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("sheet.saved"))
|
||||
router.push("/teacher/attendance")
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
try {
|
||||
const result = await batchRecordAttendanceAction(null, formData)
|
||||
if (result.success) {
|
||||
toast.success(result.message || t("sheet.saved"))
|
||||
router.push("/teacher/attendance")
|
||||
router.refresh()
|
||||
} else {
|
||||
toast.error(result.message || t("errors.unexpected"))
|
||||
}
|
||||
} catch {
|
||||
toast.error(t("errors.unexpected"))
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Users, CheckCircle2, XCircle, Clock, LogOut, FileText } from "lucide-re
|
||||
import { useTranslations } from "next-intl"
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
|
||||
import { cn } from "@/shared/lib/utils"
|
||||
|
||||
interface AttendanceStatsCardsProps {
|
||||
stats: {
|
||||
@@ -68,8 +69,8 @@ export function AttendanceStatsCards({ stats }: AttendanceStatsCardsProps) {
|
||||
<Card key={card.title} className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">{card.title}</CardTitle>
|
||||
<div className={`flex h-8 w-8 items-center justify-center rounded-md ${card.bgColor}`}>
|
||||
<card.icon className={`h-4 w-4 ${card.color}`} />
|
||||
<div className={cn("flex h-8 w-8 items-center justify-center rounded-md", card.bgColor)}>
|
||||
<card.icon className={cn("h-4 w-4", card.color)} />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
users,
|
||||
} from "@/shared/db/schema"
|
||||
import { getClassActiveStudentsWithInfo } from "@/modules/classes/data-access"
|
||||
import { safeParseDate } from "@/shared/lib/action-utils"
|
||||
import type { DataScope } from "@/shared/types/permissions"
|
||||
|
||||
import type {
|
||||
@@ -96,9 +97,9 @@ export async function getAttendanceRecords(
|
||||
}
|
||||
if (params.classId) conditions.push(eq(attendanceRecords.classId, params.classId))
|
||||
if (params.studentId) conditions.push(eq(attendanceRecords.studentId, params.studentId))
|
||||
if (params.date) conditions.push(eq(attendanceRecords.date, new Date(params.date)))
|
||||
if (params.startDate) conditions.push(gte(attendanceRecords.date, new Date(params.startDate)))
|
||||
if (params.endDate) conditions.push(lte(attendanceRecords.date, new Date(params.endDate)))
|
||||
if (params.date) conditions.push(eq(attendanceRecords.date, safeParseDate(params.date, "日期")))
|
||||
if (params.startDate) conditions.push(gte(attendanceRecords.date, safeParseDate(params.startDate, "开始日期")))
|
||||
if (params.endDate) conditions.push(lte(attendanceRecords.date, safeParseDate(params.endDate, "结束日期")))
|
||||
if (params.status) conditions.push(eq(attendanceRecords.status, params.status))
|
||||
|
||||
const where = conditions.length > 0 ? and(...conditions) : undefined
|
||||
@@ -163,7 +164,7 @@ export async function createAttendanceRecord(
|
||||
studentId: data.studentId,
|
||||
classId: data.classId,
|
||||
scheduleId: data.scheduleId ?? null,
|
||||
date: new Date(data.date),
|
||||
date: safeParseDate(data.date, "日期"),
|
||||
status: data.status,
|
||||
remark: data.remark ?? null,
|
||||
recordedBy,
|
||||
@@ -181,7 +182,7 @@ export async function batchCreateAttendanceRecords(
|
||||
studentId: r.studentId,
|
||||
classId: r.classId,
|
||||
scheduleId: r.scheduleId ?? null,
|
||||
date: new Date(r.date),
|
||||
date: safeParseDate(r.date, "日期"),
|
||||
status: r.status,
|
||||
remark: r.remark ?? null,
|
||||
recordedBy,
|
||||
@@ -304,7 +305,7 @@ export async function getAttendanceStats(params: {
|
||||
conditions.push(eq(attendanceRecords.studentId, params.currentUserId))
|
||||
}
|
||||
if (params.classId) conditions.push(eq(attendanceRecords.classId, params.classId))
|
||||
if (params.date) conditions.push(eq(attendanceRecords.date, new Date(params.date)))
|
||||
if (params.date) conditions.push(eq(attendanceRecords.date, safeParseDate(params.date, "日期")))
|
||||
|
||||
const where = conditions.length > 0 ? and(...conditions) : undefined
|
||||
|
||||
|
||||
Reference in New Issue
Block a user