import type { Metadata } from "next" import type { JSX } from "react" import { getTranslations } from "next-intl/server" import { requirePermission } from "@/shared/lib/auth-guard" import { Permissions } from "@/shared/types/permissions" import { getTeacherIdForMutations } from "@/modules/classes/data-access" import { getGradeHomeworkInsights } from "@/modules/classes/data-access" import { getGradesForStaff } from "@/modules/school/data-access" import { EmptyState } from "@/shared/components/ui/empty-state" import { StatCard } from "@/shared/components/ui/stat-card" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Badge } from "@/shared/components/ui/badge" import { Button } from "@/shared/components/ui/button" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/shared/components/ui/table" import { BarChart3 } from "lucide-react" import { formatDate } from "@/shared/lib/utils" import { getParam, type SearchParams } from "@/shared/lib/search-params" export const dynamic = "force-dynamic" const formatScore = (v: number | null, digits = 1) => (typeof v === "number" && Number.isFinite(v) ? v.toFixed(digits) : "-") export async function generateMetadata(): Promise { const t = await getTranslations("school") return { title: `${t("classManagement.grade.insights.title")} - Next_Edu`, description: t("classManagement.grade.insights.description"), } } export default async function TeacherGradeInsightsPage({ searchParams }: { searchParams: Promise }): Promise { await requirePermission(Permissions.GRADE_RECORD_READ) const t = await getTranslations("school") const params = await searchParams const gradeId = getParam(params, "gradeId") const teacherId = await getTeacherIdForMutations() const grades = await getGradesForStaff(teacherId) const allowedIds = new Set(grades.map((g) => g.id)) const selected = gradeId && gradeId !== "all" && allowedIds.has(gradeId) ? gradeId : "" const insights = selected ? await getGradeHomeworkInsights({ gradeId: selected, limit: 50 }) : null if (grades.length === 0) { return (

{t("classManagement.grade.insights.title")}

{t("classManagement.grade.insights.description")}

) } return (

{t("classManagement.grade.insights.title")}

{t("classManagement.grade.insights.description")}

{t("classManagement.grade.insights.filters")} {grades.length}
{!selected ? ( ) : !insights ? ( ) : insights.assignments.length === 0 ? ( ) : (
{t("classManagement.grade.insights.homeworkTimeline")} {insights.assignments.length}
{t("classManagement.grade.insights.assignment")} {t("classManagement.grade.insights.status")} {t("classManagement.grade.insights.created")} {t("classManagement.grade.insights.targeted")} {t("classManagement.grade.insights.submitted")} {t("classManagement.grade.insights.graded")} {t("classManagement.grade.insights.avg")} {t("classManagement.grade.insights.median")} {insights.assignments.map((a) => ( {a.title} {a.status} {formatDate(a.createdAt)} {a.targetCount} {a.submittedCount} {a.gradedCount} {formatScore(a.scoreStats.avg)} {formatScore(a.scoreStats.median)} ))}
{t("classManagement.grade.insights.classRanking")} {insights.classes.length}
{t("classManagement.grade.insights.class")} {t("classManagement.grade.insights.students")} {t("classManagement.grade.insights.latestAvgCol")} {t("classManagement.grade.insights.prevAvg")} {t("classManagement.grade.insights.delta")} {t("classManagement.grade.insights.overallAvgCol")} {insights.classes.map((c) => ( {c.class.name} {c.class.homeroom ? • {c.class.homeroom} : null} {c.studentCounts.total} {formatScore(c.latestAvg)} {formatScore(c.prevAvg)} {formatScore(c.deltaAvg)} {formatScore(c.overallScores.avg)} ))}
)}
) }