import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; import type { ReactNode } from "react"; import { api, setToken, getToken } from "./api"; import type { Business, User } from "../../shared/types"; interface AuthState { user: User | null; business: Business | null; loading: boolean; login: (email: string, password: string) => Promise; logout: () => void; switchUser: (userId: number, email: string) => Promise; refreshBusiness: () => Promise; } const Ctx = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [business, setBusiness] = useState(null); const [loading, setLoading] = useState(true); const loadBusiness = useCallback(async (role?: string) => { if (role === "admin") return; // admins have no business try { const { business } = await api.business.get(); setBusiness(business); } catch { /* ignore */ } }, []); useEffect(() => { const t = getToken(); if (!t) { setLoading(false); return; } // Token is the user id; we need the user object. Quick login isn't re-called, // so we hydrate by calling /me. Server stores users in db; fetch demo list and match. (async () => { try { const res = await fetch("/api/auth/me", { headers: { authorization: `Bearer ${t}` } }); if (!res.ok) throw new Error(); const { user } = (await res.json()) as { user: User }; setUser(user); await loadBusiness(user.role); } catch { setToken(null); } finally { setLoading(false); } })(); }, [loadBusiness]); const login = useCallback( async (email: string, password: string) => { const { token, user } = await api.auth.login(email, password); setToken(token); setUser(user); await loadBusiness(user.role); }, [loadBusiness] ); const switchUser = useCallback( async (userId: number, email: string) => { // Quick demo: try logging in with known demo password try { const { token, user } = await api.auth.login(email, "demo1234"); setToken(token); setUser(user); await loadBusiness(user.role); void userId; } catch (e) { throw e; } }, [loadBusiness] ); const logout = useCallback(() => { setToken(null); setUser(null); setBusiness(null); }, []); const value = useMemo( () => ({ user, business, loading, login, logout, switchUser, refreshBusiness: loadBusiness }), [user, business, loading, login, logout, switchUser, loadBusiness] ); return {children}; } export function useAuth() { const ctx = useContext(Ctx); if (!ctx) throw new Error("useAuth must be used within AuthProvider"); return ctx; }