"use client"; import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from "react"; import { MESHKEE_API_BASE } from "@/lib/meshkee"; export type AuthUser = { id?: string | number; firstName?: string; lastName?: string; name?: string; cellNumber?: string; email?: string; role?: string; roles?: string[]; isAdmin?: boolean; }; type AuthContextValue = { user: AuthUser | null; token: string | null; loading: boolean; isAdmin: boolean; logout: () => void; }; const AuthContext = createContext({ user: null, token: null, loading: true, isAdmin: false, logout: () => undefined, }); const tokenKeys = [ "accessToken", "meshkeeAccessToken", "meshkee_access_token", "meshkee-token", ]; function readToken() { try { for (const key of tokenKeys) { const value = window.localStorage.getItem(key); if (value) return value; } const authValue = window.localStorage.getItem("meshkee-auth"); if (authValue) { const auth = JSON.parse(authValue) as { accessToken?: string }; if (auth.accessToken) return auth.accessToken; } const cookies = document.cookie.split(";").map((item) => item.trim()); for (const key of tokenKeys) { const prefix = `${key}=`; const cookie = cookies.find((item) => item.startsWith(prefix)); if (cookie) return decodeURIComponent(cookie.slice(prefix.length)); } } catch { return null; } return null; } function clearTokens() { try { tokenKeys.forEach((key) => { window.localStorage.removeItem(key); document.cookie = `${key}=; Max-Age=0; path=/; domain=.glassmond.com`; document.cookie = `${key}=; Max-Age=0; path=/`; }); window.localStorage.removeItem("meshkee-auth"); } catch { // External customer portal remains the source of truth for authentication. } } export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [token, setToken] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const accessToken = readToken(); if (!accessToken) { setLoading(false); return; } setToken(accessToken); fetch(`${MESHKEE_API_BASE}/auth/me`, { headers: { Authorization: `Bearer ${accessToken}` }, }) .then(async (response) => { if (!response.ok) throw new Error("Unauthorized"); return response.json() as Promise<{ user: AuthUser }>; }) .then((data) => setUser(data.user)) .catch(() => { clearTokens(); setToken(null); }) .finally(() => setLoading(false)); }, []); const logout = useCallback(() => { clearTokens(); setUser(null); setToken(null); }, []); const isAdmin = useMemo(() => { const roles = [user?.role, ...(user?.roles ?? [])] .filter(Boolean) .map((role) => String(role).toLowerCase()); return Boolean( user?.isAdmin || roles.some((role) => ["admin", "owner", "superadmin", "business_admin"].includes(role)), ); }, [user]); return ( {children} ); } export function useAuth() { return useContext(AuthContext); }