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 ( +
Rosters and gradebooks.
+ + {isAdmin && ( +Applied to any class that hasn't set its own categories/scale.
+ {showDefaults &&