refactor(school,classes): 完成 school/grade/class 审计全量改进项
P0-1/P0-2: 删除 grade-management 死模块,年级 CRUD 统一由 school 模块负责 P0-3: classes/actions.ts 从 974 行拆分为 6 个职责文件 + barrel re-export P0-5: 13 个页面 i18n 全量接入(grades/departments/academic-year/classes/insights) P1-1: 角色硬编码改为 hasAdminScope/hasTeacherScope/hasStudentScope 基于 dataScope.type P1-3: 新增 SchoolErrorBoundary + SchoolListSkeleton/SchoolCardSkeleton,4 个页面包裹 Error Boundary P1-4: classes/types.ts 跨领域类型添加归属决策注释 P1-5: schools-view.tsx 拆分为组合模式(SchoolFormDialog + SchoolDeleteDialog + SchoolListToolbar) P1-6: 新增 getSchoolsForUser/getGradesForUser 权限感知查询函数 P2-1: 抽取 useSchoolData hook,对话框状态管理与 UI 分离 同步更新架构图文档 004/005
This commit is contained in:
124
src/modules/classes/actions-schedule.ts
Normal file
124
src/modules/classes/actions-schedule.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
||||
import { Permissions } from "@/shared/types/permissions"
|
||||
|
||||
import type { ActionState } from "@/shared/types/action-state"
|
||||
import {
|
||||
createClassScheduleItem,
|
||||
updateClassScheduleItem,
|
||||
deleteClassScheduleItem,
|
||||
} from "@/modules/scheduling/data-access-class-schedule"
|
||||
import {
|
||||
CreateClassScheduleItemSchema,
|
||||
UpdateClassScheduleItemSchema,
|
||||
DeleteClassScheduleItemSchema,
|
||||
} from "./schema"
|
||||
import { toWeekday } from "./actions-shared"
|
||||
|
||||
export async function createClassScheduleItemAction(
|
||||
prevState: ActionState<string> | null,
|
||||
formData: FormData
|
||||
): Promise<ActionState<string>> {
|
||||
try {
|
||||
await requirePermission(Permissions.CLASS_SCHEDULE)
|
||||
|
||||
const parsed = CreateClassScheduleItemSchema.safeParse({
|
||||
classId: formData.get("classId"),
|
||||
weekday: formData.get("weekday"),
|
||||
course: formData.get("course"),
|
||||
startTime: formData.get("startTime"),
|
||||
endTime: formData.get("endTime"),
|
||||
location: formData.get("location"),
|
||||
})
|
||||
if (!parsed.success) {
|
||||
return { success: false, message: "Invalid schedule item data" }
|
||||
}
|
||||
|
||||
const { classId, weekday, course, startTime, endTime, location } = parsed.data
|
||||
|
||||
try {
|
||||
const id = await createClassScheduleItem({
|
||||
classId,
|
||||
weekday: toWeekday(weekday),
|
||||
startTime,
|
||||
endTime,
|
||||
course,
|
||||
location: location ?? null,
|
||||
})
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
return { success: true, message: "Schedule item created successfully", data: id }
|
||||
} catch (error) {
|
||||
return { success: false, message: error instanceof Error ? error.message : "Failed to create schedule item" }
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateClassScheduleItemAction(
|
||||
scheduleId: string,
|
||||
prevState: ActionState | null,
|
||||
formData: FormData
|
||||
): Promise<ActionState> {
|
||||
try {
|
||||
await requirePermission(Permissions.CLASS_SCHEDULE)
|
||||
|
||||
const parsed = UpdateClassScheduleItemSchema.safeParse({
|
||||
scheduleId,
|
||||
classId: formData.get("classId"),
|
||||
weekday: formData.get("weekday") || undefined,
|
||||
course: formData.get("course"),
|
||||
startTime: formData.get("startTime"),
|
||||
endTime: formData.get("endTime"),
|
||||
location: formData.get("location"),
|
||||
})
|
||||
if (!parsed.success) {
|
||||
return { success: false, message: "Missing or invalid schedule id" }
|
||||
}
|
||||
|
||||
const { scheduleId: validatedScheduleId, classId, weekday, course, startTime, endTime, location } = parsed.data
|
||||
|
||||
try {
|
||||
await updateClassScheduleItem(validatedScheduleId, {
|
||||
classId: classId ?? undefined,
|
||||
weekday: typeof weekday === "number" ? toWeekday(weekday) : undefined,
|
||||
startTime: startTime ?? undefined,
|
||||
endTime: endTime ?? undefined,
|
||||
course: course ?? undefined,
|
||||
location: location ?? undefined,
|
||||
})
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
return { success: true, message: "Schedule item updated successfully" }
|
||||
} catch (error) {
|
||||
return { success: false, message: error instanceof Error ? error.message : "Failed to update schedule item" }
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteClassScheduleItemAction(scheduleId: string): Promise<ActionState> {
|
||||
try {
|
||||
await requirePermission(Permissions.CLASS_SCHEDULE)
|
||||
|
||||
const parsed = DeleteClassScheduleItemSchema.safeParse({ scheduleId })
|
||||
if (!parsed.success) {
|
||||
return { success: false, message: "Missing schedule id" }
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteClassScheduleItem(parsed.data.scheduleId)
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
return { success: true, message: "Schedule item deleted successfully" }
|
||||
} catch (error) {
|
||||
return { success: false, message: error instanceof Error ? error.message : "Failed to delete schedule item" }
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
|
||||
throw e
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user