From 39ad1ae76a797e2c9a30b4042e7b653b660137e7 Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 7 Aug 2026 04:12:32 +0000 Subject: [PATCH] Modified by www.SourceFiles.app --- src/components/reports.tsx | 460 ------------------------------------- 1 file changed, 460 deletions(-) delete mode 100644 src/components/reports.tsx diff --git a/src/components/reports.tsx b/src/components/reports.tsx deleted file mode 100644 index b0e1a08..0000000 --- a/src/components/reports.tsx +++ /dev/null @@ -1,460 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { supabase } from "@/integrations/supabase/client"; -import { useEffectiveConfig } from "@/components/gradebook"; -import { studentPercent, letterFor, fmtPct, type Assn, type Grd } from "@/lib/grades"; -import { SCHOOL_NAME, summarizeAttendance } from "@/lib/reports"; -import { GOAL_STATUS_LABEL, PLAN_TYPE_LABEL, formatDate } from "@/lib/plans"; -import { Loader2 } from "lucide-react"; - -// Documents avoid filled backgrounds and rely on rules instead — grey fills eat -// toner and read muddy on paper. -export function DocHeader({ title, subtitle }: { title: string; subtitle?: string }) { - return ( -
-
- -
-
{SCHOOL_NAME}
-
{subtitle}
-
-
-
-
{title}
-
- Printed {new Date().toLocaleDateString()} -
-
-
- ); -} - -function InfoGrid({ rows }: { rows: [string, string][] }) { - return ( -
- {rows.map(([k, v]) => ( -
- {k} - {v} -
- ))} -
- ); -} - -export function SignatureLines({ labels }: { labels: string[] }) { - return ( -
- {labels.map((l) => ( -
-
-
{l}
-
- ))} -
- ); -} - -function Loading() { - return ( -
- Loading… -
- ); -} - -// ── Report card / academic progress report ────────────────────────────────── -export function ReportCardDoc({ - studentId, - variant, - from, - to, -}: { - studentId: string; - variant: "report_card" | "progress"; - from: string; - to: string; -}) { - const { data: student } = useQuery({ - queryKey: ["report-student", studentId], - queryFn: async () => - ( - await supabase - .from("students") - .select("id, first_name, last_name, grade_level, class_id, classes(name)") - .eq("id", studentId) - .single() - ).data, - }); - - const classId = (student?.class_id as string | null) ?? ""; - const cfg = useEffectiveConfig(classId); - - const { data: assignments } = useQuery({ - queryKey: ["report-assignments", classId], - enabled: !!classId, - queryFn: async () => - ( - await supabase - .from("assignments") - .select("*") - .eq("class_id", classId) - .order("date", { ascending: true, nullsFirst: true }) - ).data ?? [], - }); - - // Undated assignments are kept: they belong to the class's body of work and - // excluding them would silently distort the overall percentage. - const inRange = (assignments ?? []).filter((a) => !a.date || (a.date >= from && a.date <= to)); - const aIds = inRange.map((a) => a.id); - - const { data: grades } = useQuery({ - queryKey: ["report-grades", studentId, aIds.length, from, to], - enabled: aIds.length > 0, - queryFn: async () => - ( - await supabase - .from("grades") - .select("assignment_id, student_id, points") - .eq("student_id", studentId) - .in("assignment_id", aIds) - ).data ?? [], - }); - - const { data: attendance } = useQuery({ - queryKey: ["report-attendance", studentId, from, to], - queryFn: async () => - ( - await supabase - .from("attendance") - .select("status, date") - .eq("student_id", studentId) - .gte("date", from) - .lte("date", to) - ).data ?? [], - }); - - if (!student) return ; - - const gr = (grades ?? []) as Grd[]; - const overall = studentPercent(studentId, inRange as Assn[], gr, cfg.categories); - const att = summarizeAttendance(attendance ?? [], from, to); - const title = variant === "report_card" ? "Report Card" : "Progress Report"; - - return ( -
- - - - - {!classId ? ( -

- This student isn't assigned to a class, so no grades can be reported. -

- ) : ( -
-

- Academic performance -

- - - - - - - - - - - {cfg.categories.map((cat) => { - const items = inRange.filter((a) => a.category_id === cat.id); - let earned = 0; - let possible = 0; - for (const a of items) { - const g = gr.find((x) => x.assignment_id === a.id && x.points != null); - if (!g) continue; - earned += Number(g.points); - possible += Number(a.max_points); - } - const pct = possible === 0 ? null : (earned / possible) * 100; - return ( - - - - - - - ); - })} - - - - - - -
CategoryPointsPercentWeight
{cat.name} - {possible === 0 ? "—" : `${earned} / ${possible}`} - {fmtPct(pct)}{Number(cat.weight)}%
Overall - {fmtPct(overall)}{letterFor(overall, cfg.scale)}
- - {/* A mid-term progress report is only actionable with the underlying - work listed, so the detail is included for that variant only. */} - {variant === "progress" && inRange.length > 0 && ( -
-

- Assignment detail -

- - - {cfg.categories.flatMap((cat) => { - const items = inRange.filter((a) => a.category_id === cat.id); - if (!items.length) return []; - return [ - - - , - ...items.map((a) => { - const g = gr.find((x) => x.assignment_id === a.id); - return ( - - - - - - ); - }), - ]; - })} - -
- {cat.name} -
{a.name} - {a.date ? formatDate(a.date) : "—"} - - {g?.points != null - ? `${Number(g.points)} / ${Number(a.max_points)}` - : "—"} -
-
- )} -
- )} - -
-

Attendance

-
- {[ - ["Present", att.present], - ["Late", att.late], - ["Absent", att.absent], - ["Excused", att.excused], - ["Days recorded", att.recorded], - ].map(([label, n]) => ( -
-
{n as number}
-
{label as string}
-
- ))} -
- {att.attendedPct !== null && ( -

- Attended {att.attendedPct.toFixed(1)}% of recorded days. -

- )} -
- -
-

Comments

-
-
- - -
- ); -} - -// ── 504 / IEP goal progress report ────────────────────────────────────────── -export function IepProgressDoc({ - studentId, - from, - to, -}: { - studentId: string; - from: string; - to: string; -}) { - const { data: student } = useQuery({ - queryKey: ["report-student", studentId], - queryFn: async () => - ( - await supabase - .from("students") - .select("id, first_name, last_name, grade_level, class_id, classes(name)") - .eq("id", studentId) - .single() - ).data, - }); - - const { data: plans } = useQuery({ - queryKey: ["report-plans", studentId], - queryFn: async () => - ( - await supabase - .from("student_plans") - .select("*") - .eq("student_id", studentId) - .neq("status", "archived") - ).data ?? [], - }); - - const planIds = (plans ?? []).map((p) => p.id); - - const { data: goals } = useQuery({ - queryKey: ["report-goals", planIds.join(",")], - enabled: planIds.length > 0, - queryFn: async () => - (await supabase.from("plan_goals").select("*").in("plan_id", planIds).order("sort_order")) - .data ?? [], - }); - - const goalIds = (goals ?? []).map((g) => g.id); - - const { data: progress } = useQuery({ - queryKey: ["report-progress", goalIds.join(","), from, to], - enabled: goalIds.length > 0, - queryFn: async () => - ( - await supabase - .from("plan_goal_progress") - .select("*") - .in("goal_id", goalIds) - .gte("date", from) - .lte("date", to) - .order("date") - ).data ?? [], - }); - - if (!student) return ; - - if ((plans ?? []).length === 0) { - return ( -
- -

- No active 504 or IEP plan is on file for {student.first_name} {student.last_name} — or the - plan is restricted to its case manager, administrators, and the student's parents. -

-
- ); - } - - return ( -
- - - - - {(plans ?? []).map((plan) => { - const planGoals = (goals ?? []).filter((g) => g.plan_id === plan.id); - return ( -
-
- {PLAN_TYPE_LABEL[plan.plan_type]} · effective {formatDate(plan.effective_date)} -
- - {planGoals.length === 0 && ( -

No goals recorded on this plan.

- )} - - {planGoals.map((goal, i) => { - const entries = (progress ?? []).filter((p) => p.goal_id === goal.id); - const latest = entries[entries.length - 1]; - return ( -
-
-
- Goal {i + 1} - {goal.area ? ` — ${goal.area}` : ""} -
-
{GOAL_STATUS_LABEL[goal.status]}
-
-

{goal.statement}

-
-
Baseline: {goal.baseline || "—"}
-
- Target:{" "} - {goal.target_value != null ? `${goal.target_value}${goal.unit ?? ""}` : "—"} - {goal.target_date ? ` by ${formatDate(goal.target_date)}` : ""} -
-
- Most recent:{" "} - {latest?.value != null - ? `${latest.value}${goal.unit ?? ""}` - : latest - ? "recorded" - : "—"} -
-
- {goal.target_criteria && ( -
- Mastery criteria: {goal.target_criteria} -
- )} - -
-
- Progress this period -
- {entries.length === 0 ? ( -

- No progress data recorded between {formatDate(from)} and {formatDate(to)}. -

- ) : ( - - - {entries.map((e) => ( - - - - - - ))} - -
{formatDate(e.date)} - {e.value != null ? `${e.value}${goal.unit ?? ""}` : "—"} - {e.narrative || ""}
- )} -
-
- ); - })} -
- ); - })} - - -
- ); -}