Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-06-30 20:41:27 +00:00
co-authored by renee-png
parent d7e7de54d3
commit a2a4e6c811
5 changed files with 359 additions and 17 deletions
+56
View File
@@ -0,0 +1,56 @@
import { useEffect, useState } from "react";
import type { User } from "@supabase/supabase-js";
import { supabase } from "@/integrations/supabase/client";
export type Role = "admin" | "teacher" | "parent";
export interface AuthState {
user: User | null;
roles: Role[];
loading: boolean;
}
export function useAuth(): AuthState {
const [user, setUser] = useState<User | null>(null);
const [roles, setRoles] = useState<Role[]>([]);
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";
return null;
}