diff --git a/src/hooks/use-auth.ts b/src/hooks/use-auth.ts new file mode 100644 index 0000000..3b220c0 --- /dev/null +++ b/src/hooks/use-auth.ts @@ -0,0 +1,57 @@ +import { useEffect, useState } from "react"; +import type { User } from "@supabase/supabase-js"; +import { supabase } from "@/integrations/supabase/client"; + +export type Role = "admin" | "teacher" | "parent" | "student"; + +export interface AuthState { + user: User | null; + roles: Role[]; + loading: boolean; +} + +export function useAuth(): AuthState { + const [user, setUser] = useState(null); + const [roles, setRoles] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + let mounted = true; + + const loadRoles = async (uid: string) => { + const { data } = await supabase.from("user_roles").select("role").eq("user_id", uid); + if (mounted) setRoles((data ?? []).map((r) => r.role as Role)); + }; + + supabase.auth.getSession().then(({ data }) => { + if (!mounted) return; + setUser(data.session?.user ?? null); + if (data.session?.user) loadRoles(data.session.user.id).finally(() => mounted && setLoading(false)); + else setLoading(false); + }); + + const { data: sub } = supabase.auth.onAuthStateChange((_e, session) => { + setUser(session?.user ?? null); + if (session?.user) { + setTimeout(() => loadRoles(session.user.id), 0); + } else { + setRoles([]); + } + }); + + return () => { + mounted = false; + sub.subscription.unsubscribe(); + }; + }, []); + + return { user, roles, loading }; +} + +export function highestRole(roles: Role[]): Role | null { + if (roles.includes("admin")) return "admin"; + if (roles.includes("teacher")) return "teacher"; + if (roles.includes("parent")) return "parent"; + if (roles.includes("student")) return "student"; + return null; +}