import { createFileRoute } from "@tanstack/react-router"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { supabase } from "@/integrations/supabase/client"; import { useAuth } from "@/hooks/use-auth"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useState } from "react"; import { toast } from "sonner"; export const Route = createFileRoute("/_authenticated/attendance")({ head: () => ({ meta: [{ title: "Attendance — School Portal" }] }), component: AttendancePage, }); function AttendancePage() { const { user, roles, loading } = useAuth(); const isAdmin = roles.includes("admin"); const qc = useQueryClient(); const [date, setDate] = useState(new Date().toISOString().slice(0, 10)); const [classId, setClassId] = useState(""); const { data: classes } = useQuery({ // isAdmin is in the key so the query refetches once roles resolve; gated on // !loading so it never runs with a not-yet-known (false) admin status. queryKey: ["my-classes", user?.id, isAdmin], queryFn: async () => { let q = supabase.from("classes").select("id, name, teacher_id"); if (!isAdmin) q = q.eq("teacher_id", user!.id); return (await q.order("name")).data ?? []; }, enabled: !!user && !loading, }); const { data: students } = useQuery({ queryKey: ["class-students", classId, date], queryFn: async () => { if (!classId) return []; const { data } = await supabase.from("students").select("id, first_name, last_name, attendance(status, date, id)").eq("class_id", classId); return data ?? []; }, enabled: !!classId, }); const mark = useMutation({ mutationFn: async ({ studentId, status }: { studentId: string; status: string }) => { const { error } = await supabase.from("attendance").upsert( { student_id: studentId, date, status: status as "present" | "absent" | "late" | "excused", recorded_by: user!.id }, { onConflict: "student_id,date" } ); if (error) throw error; }, onSuccess: () => qc.invalidateQueries({ queryKey: ["class-students", classId, date] }), onError: (e: Error) => toast.error(e.message), }); const getStatus = (s: { attendance: { date: string; status: string }[] }) => s.attendance.find((a) => a.date === date)?.status ?? ""; return (

Attendance

Mark today's attendance for your class.

setDate(e.target.value)} />
{classId && (
{(students ?? []).map((s) => { const status = getStatus(s as { attendance: { date: string; status: string }[] }); return (
{s.last_name}, {s.first_name}
{["present", "absent", "late", "excused"].map((opt) => ( ))}
); })} {students?.length === 0 &&
No students in this class.
}
)} {!classId &&

Select a class to begin.

}
); }