"use client" import { useEffect, useMemo, useState } from "react" import { MoreHorizontal, Pencil, Plus, Trash2 } from "lucide-react" import { toast } from "sonner" import { useRouter } from "next/navigation" import type { AdminClassListItem, ClassSubjectTeacherAssignment, TeacherOption } from "../types" import { DEFAULT_CLASS_SUBJECTS } from "../types" import { createGradeClassAction, deleteGradeClassAction, updateGradeClassAction } from "../actions" import { Button } from "@/shared/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/shared/components/ui/dialog" import { Input } from "@/shared/components/ui/input" import { Label } from "@/shared/components/ui/label" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/shared/components/ui/table" import { EmptyState } from "@/shared/components/ui/empty-state" import { Badge } from "@/shared/components/ui/badge" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/shared/components/ui/dropdown-menu" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/shared/components/ui/alert-dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/shared/components/ui/select" import { formatDate } from "@/shared/lib/utils" export function GradeClassesClient({ classes, teachers, managedGrades, }: { classes: AdminClassListItem[] teachers: TeacherOption[] managedGrades: { id: string; name: string; schoolId: string; schoolName: string | null }[] }) { const router = useRouter() const [isWorking, setIsWorking] = useState(false) const [createOpen, setCreateOpen] = useState(false) const [editItem, setEditItem] = useState(null) const [deleteItem, setDeleteItem] = useState(null) const defaultTeacherId = useMemo(() => teachers[0]?.id ?? "", [teachers]) const [createTeacherId, setCreateTeacherId] = useState(defaultTeacherId) const [createGradeId, setCreateGradeId] = useState(managedGrades[0]?.id ?? "") const [editTeacherId, setEditTeacherId] = useState("") const [editGradeId, setEditGradeId] = useState("") const [editSubjectTeachers, setEditSubjectTeachers] = useState>([]) useEffect(() => { if (!createOpen) return setCreateTeacherId(defaultTeacherId) setCreateGradeId(managedGrades[0]?.id ?? "") }, [createOpen, defaultTeacherId, managedGrades]) useEffect(() => { if (!editItem) return setEditTeacherId(editItem.teacher.id) setEditGradeId(editItem.gradeId ?? managedGrades[0]?.id ?? "") setEditSubjectTeachers( DEFAULT_CLASS_SUBJECTS.map((s) => ({ subject: s, teacherId: editItem.subjectTeachers.find((st) => st.subject === s)?.teacher?.id ?? null, })) ) }, [editItem, managedGrades]) const handleCreate = async (formData: FormData) => { setIsWorking(true) try { const res = await createGradeClassAction(undefined, formData) if (res.success) { toast.success(res.message) setCreateOpen(false) router.refresh() } else { toast.error(res.message || "Failed to create class") } } catch { toast.error("Failed to create class") } finally { setIsWorking(false) } } const handleUpdate = async (formData: FormData) => { if (!editItem) return setIsWorking(true) try { const res = await updateGradeClassAction(editItem.id, undefined, formData) if (res.success) { toast.success(res.message) setEditItem(null) router.refresh() } else { toast.error(res.message || "Failed to update class") } } catch { toast.error("Failed to update class") } finally { setIsWorking(false) } } const handleDelete = async () => { if (!deleteItem) return setIsWorking(true) try { const res = await deleteGradeClassAction(deleteItem.id) if (res.success) { toast.success(res.message) setDeleteItem(null) router.refresh() } else { toast.error(res.message || "Failed to delete class") } } catch { toast.error("Failed to delete class") } finally { setIsWorking(false) } } const setSubjectTeacher = (subject: string, teacherId: string | null) => { setEditSubjectTeachers((prev) => prev.map((p) => (p.subject === subject ? { ...p, teacherId } : p))) } const formatSubjectTeachers = (list: ClassSubjectTeacherAssignment[]) => { const pairs = list .filter((x) => x.teacher) .map((x) => `${x.subject}:${x.teacher?.name ?? ""}`) .filter((x) => x.length > 0) return pairs.length > 0 ? pairs.join(",") : "-" } const selectedCreateGrade = managedGrades.find(g => g.id === createGradeId) const selectedEditGrade = managedGrades.find(g => g.id === editGradeId) return ( <>
All classes {classes.length} {classes.length === 0 ? ( ) : ( School Name Grade Homeroom Room 班主任 任课老师 Students Updated {classes.map((c) => ( {c.schoolName ?? "-"} {c.name} {c.grade} {c.homeroom ?? "-"} {c.room ?? "-"} {c.teacher.name} {formatSubjectTeachers(c.subjectTeachers)} {c.studentCount} {formatDate(c.updatedAt)} setEditItem(c)}> Edit setDeleteItem(c)} > Delete ))}
)}
New class
{ if (isWorking) return if (!open) setEditItem(null) }} > Edit class {editItem ? (
任课老师
{DEFAULT_CLASS_SUBJECTS.map((subject) => { const selected = editSubjectTeachers.find((x) => x.subject === subject)?.teacherId ?? null return (
) })}
) : null}
{ if (!open) setDeleteItem(null) }} > Delete class This will permanently delete {deleteItem?.name || "this class"}. Cancel Delete ) }