"use client"; /** * 班级课表页 - 客户端组件(ARCHITECTURE.md §7.3 详情页 / §9.1 / §10 P2) * * 数据契约: * - 课表查询 classSchedule(classId):❌ schema 无此字段 → MSW 兜底(@contract-pending) * - 契约工单:docs/architecture/issues/contracts/classes_contract.md#class-schedule * * URL 状态:?classId=(可选,指定班级课表;未指定时返回默认课表) * * 三态规范(§11.3 DoD): * - loading:DetailPageSkeleton * - error:errorNode 局部降级 * - empty:data 为 null 时显示空态节点 * * 关联:ARCHITECTURE.md §5.3 / §5.4 / §7.3 / §9.1 / §10 P2 / §11.3 / §11.4 */ import { Calendar } from "lucide-react"; import { useSearchParams } from "next/navigation"; import { useTranslations } from "next-intl"; import { useClassSchedule, type ClassScheduleItem } from "@/lib/api"; import { EmptyState } from "@/shared/components/ui/empty-state"; import { DetailPageShell, DetailPageSkeleton, DetailSection, DetailField, } from "@/shared/components/page-templates"; import { formatSchedulePeriod, formatScheduleTime, formatWeekday, groupScheduleByWeekday, sortScheduleByDay, } from "@/features/teacher/classes/transformations"; /** * 课表客户端主体。需由 server page 包裹在 中。 */ export function ClassScheduleClient(): React.ReactElement { const t = useTranslations("classes"); const tCommon = useTranslations("common"); const searchParams = useSearchParams(); const classId = searchParams.get("classId") ?? "cls-001"; // @contract-pending:MSW 兜底 const { data, loading, error } = useClassSchedule(classId); const errorNode = error ? (

{tCommon("error.loadFailed", { message: String(error) })}

{t("schedule.mswNotice")}

) : undefined; const emptyNode = !loading && !error && !data ? ( ) : undefined; return ( } backHref="/shell/teacher/classes" loading={loading} loadingNode={} errorNode={errorNode} emptyNode={emptyNode} > {data ? : null} {data ? : null} ); } type ScheduleData = NonNullable["data"]>; /** * 课表概览区。 */ function ScheduleOverviewSection({ data, }: { data: ScheduleData; }): React.ReactElement { const t = useTranslations("classes"); return ( ); } /** * 按星期分组的课表区。 */ function ScheduleByDaySection({ items, }: { items: ClassScheduleItem[]; }): React.ReactElement { const t = useTranslations("classes"); const sorted = sortScheduleByDay(items); const groups = groupScheduleByWeekday(sorted); return (
{groups.map((group, idx) => { if (group.length === 0) return null; return (

{formatWeekday(idx)}

{group.map((item) => ( ))}
{t("schedule.colPeriod")} {t("schedule.colSubject")} {t("schedule.colTeacher")} {t("schedule.colClassroom")} {t("schedule.colTime")}
{formatSchedulePeriod(item.period)} {item.subjectName} {item.teacherName} {item.classroom ?? "--"} {formatScheduleTime(item.startTime, item.endTime)}
); })}
); }