import Link from "next/link" import { notFound } from "next/navigation" import { BookOpen, Calendar, ChevronRight, Clock, Users } from "lucide-react" import { getClassHomeworkInsights, getClassSchedule, getClassStudents } from "@/modules/classes/data-access" import { ScheduleView } from "@/modules/classes/components/schedule-view" import { Badge } from "@/shared/components/ui/badge" import { Button } from "@/shared/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/shared/components/ui/table" import { Avatar, AvatarFallback, AvatarImage } from "@/shared/components/ui/avatar" import { cn, formatDate } from "@/shared/lib/utils" export const dynamic = "force-dynamic" type SearchParams = { [key: string]: string | string[] | undefined } const getParam = (params: SearchParams, key: string) => { const v = params[key] return Array.isArray(v) ? v[0] : v } const formatNumber = (v: number | null, digits = 1) => { if (typeof v !== "number" || Number.isNaN(v)) return "-" return v.toFixed(digits) } const getInitials = (name: string) => { return name .split(" ") .map((n) => n[0]) .join("") .toUpperCase() .slice(0, 2) } export default async function ClassDetailPage({ params, searchParams, }: { params: Promise<{ id: string }> searchParams: Promise }) { const { id } = await params const sp = await searchParams const hw = getParam(sp, "hw") const hwFilter = hw === "active" || hw === "overdue" ? hw : "all" const [insights, students, schedule] = await Promise.all([ getClassHomeworkInsights({ classId: id, limit: 50 }), getClassStudents({ classId: id }), getClassSchedule({ classId: id }), ]) if (!insights) return notFound() const latest = insights.latest const filteredAssignments = insights.assignments.filter((a) => { if (hwFilter === "all") return true if (hwFilter === "overdue") return a.isOverdue if (hwFilter === "active") return a.isActive return true }) const hasAssignments = filteredAssignments.length > 0 const scheduleBuilderClasses = [ { id: insights.class.id, name: insights.class.name, grade: insights.class.grade, homeroom: insights.class.homeroom ?? null, room: insights.class.room ?? null, studentCount: insights.studentCounts.total, }, ] return (
{/* Header */}
My Classes {insights.class.name}

{insights.class.name}

{insights.class.grade} {insights.class.homeroom && ( <> Homeroom: {insights.class.homeroom} )} {insights.class.room && ( <> Room: {insights.class.room} )}
{/* Stats Grid */}
Total Students
{insights.studentCounts.total}
{insights.studentCounts.active} active · {insights.studentCounts.inactive} inactive
Schedule Items
{schedule.length}
Weekly sessions
Active Assignments
{insights.assignments.filter((a) => a.isActive).length}
{insights.assignments.filter((a) => a.isOverdue).length} overdue
Class Average
{formatNumber(insights.overallScores.avg, 1)}%
Based on {insights.overallScores.count} graded submissions
{/* Main Content Area */}
{/* Latest Homework */} {latest && (
Latest Homework Most recent assignment activity
{latest.status}
{latest.title}
Due {latest.dueAt ? formatDate(latest.dueAt) : "No due date"} · {latest.submittedCount}/{latest.targetCount} Submitted
{latest.gradedCount}
Graded
{formatNumber(latest.scoreStats.avg, 1)}
Average
{formatNumber(latest.scoreStats.median, 1)}
Median
)} {/* Students Preview */}
Students Recently active students
{students.length === 0 ? (
No students enrolled yet.
) : (
{students.slice(0, 5).map((s) => (
{getInitials(s.name)}
{s.name}
{s.email}
{s.status}
))}
)}
{/* Sidebar Area */}
{/* Schedule Widget */} Schedule {/* Homework History */} History
{filteredAssignments.slice(0, 5).map((a) => (
{a.title} {a.status}
Due {a.dueAt ? formatDate(a.dueAt) : "-"}
{a.submittedCount} submitted {formatNumber(a.scoreStats.avg, 0)}% avg
))} {filteredAssignments.length === 0 && (
No assignments found
)}
{filteredAssignments.length > 5 && (
)}
) }