From 80d8a302e5a700095072bca90bb73ae77ac4386d Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 7 Aug 2026 04:15:46 +0000 Subject: [PATCH] Modified by www.SourceFiles.app --- src/routes/_authenticated/ledger.tsx | 79 ++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/routes/_authenticated/ledger.tsx diff --git a/src/routes/_authenticated/ledger.tsx b/src/routes/_authenticated/ledger.tsx new file mode 100644 index 0000000..5e74b6a --- /dev/null +++ b/src/routes/_authenticated/ledger.tsx @@ -0,0 +1,79 @@ +import { createFileRoute, Link } from "@tanstack/react-router"; +import { useQuery } from "@tanstack/react-query"; +import { supabase } from "@/integrations/supabase/client"; +import { Button } from "@/components/ui/button"; +import { ChevronRight, FileText } from "lucide-react"; +import { money } from "@/lib/reports"; + +export const Route = createFileRoute("/_authenticated/ledger")({ + head: () => ({ meta: [{ title: "Tuition — School Portal" }] }), + component: LedgerListPage, +}); + +function LedgerListPage() { + const { data: students } = useQuery({ + queryKey: ["students-with-balance"], + queryFn: async () => { + const { data: studs } = await supabase + .from("students") + .select("id, first_name, last_name, daily_tuition_cents"); + const { data: entries } = await supabase + .from("ledger_entries") + .select("student_id, amount_cents, kind"); + const balances: Record = {}; + (entries ?? []).forEach((e) => { + balances[e.student_id] = + (balances[e.student_id] ?? 0) + (e.kind === "charge" ? e.amount_cents : -e.amount_cents); + }); + return (studs ?? []).map((s) => ({ ...s, balance: balances[s.id] ?? 0 })); + }, + }); + + return ( +
+

Tuition ledger

+

+ Click a student to view and manage their ledger, or build an invoice. Students with a daily + rate are charged automatically when marked present or late. +

+
+ {(students ?? []).map((s) => ( +
+ + + {s.last_name}, {s.first_name} + + {s.daily_tuition_cents ? ( + + {money(s.daily_tuition_cents)}/day + + ) : ( + no rate + )} + + 0 ? "text-destructive" : "text-green-700"}`} + > + {money(s.balance)} + + + + + + + +
+ ))} + {students?.length === 0 && ( +
No students.
+ )} +
+
+ ); +}