From 8c2e0379bab88e4e5859d2871180956c9e63795d Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 7 Aug 2026 04:15:27 +0000 Subject: [PATCH] Modified by www.SourceFiles.app --- src/routes/_authenticated/classes.index.tsx | 87 +++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/routes/_authenticated/classes.index.tsx diff --git a/src/routes/_authenticated/classes.index.tsx b/src/routes/_authenticated/classes.index.tsx new file mode 100644 index 0000000..b6ca955 --- /dev/null +++ b/src/routes/_authenticated/classes.index.tsx @@ -0,0 +1,87 @@ +import { createFileRoute, Link } 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 { GradingConfigEditor } from "@/components/gradebook"; +import { BookOpen, ChevronRight, Plus, SlidersHorizontal } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; + +export const Route = createFileRoute("/_authenticated/classes/")({ + head: () => ({ meta: [{ title: "Classes — School Portal" }] }), + component: ClassesIndex, +}); + +function ClassesIndex() { + const { user, roles } = useAuth(); + const isAdmin = roles.includes("admin"); + const qc = useQueryClient(); + + const { data: classes } = useQuery({ + queryKey: ["classes-list"], + queryFn: async () => (await supabase.from("classes").select("id, name, teacher_id").order("name")).data ?? [], + }); + const visible = isAdmin ? (classes ?? []) : (classes ?? []).filter((c) => c.teacher_id === user?.id); + + const { data: teachers } = useQuery({ + queryKey: ["teachers"], enabled: isAdmin, + queryFn: async () => { + const { data: r } = await supabase.from("user_roles").select("user_id").eq("role", "teacher"); + const ids = (r ?? []).map((x) => x.user_id); + if (!ids.length) return []; + return (await supabase.from("profiles").select("id, full_name, email").in("id", ids)).data ?? []; + }, + }); + const [name, setName] = useState(""); + const [teacherId, setTeacherId] = useState(""); + const create = useMutation({ + mutationFn: async () => { const { error } = await supabase.from("classes").insert({ name: name.trim(), teacher_id: teacherId || null }); if (error) throw error; }, + onSuccess: () => { setName(""); setTeacherId(""); qc.invalidateQueries({ queryKey: ["classes-list"] }); toast.success("Class created"); }, + onError: (e: Error) => toast.error(e.message), + }); + const [showDefaults, setShowDefaults] = useState(false); + + return ( +
+

Classes

+

Rosters and gradebooks.

+ + {isAdmin && ( +
+
New class
+
+ setName(e.target.value)} /> + + +
+
+ )} + +
+ {visible.map((c) => ( + + {c.name} + + + ))} + {visible.length === 0 &&
{isAdmin ? "No classes yet — create one above." : "You have no classes assigned."}
} +
+ + {isAdmin && ( +
+ +

Applied to any class that hasn't set its own categories/scale.

+ {showDefaults &&
} +
+ )} +
+ ); +}