Labour-Connect / admin /src /auth /AuthContext.tsx
Abhisingh-18's picture
Mirror of github.com/Abhisingh18/Labour-Connect
b24b684 verified
Raw
History Blame Contribute Delete
2.12 kB
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState,
type ReactNode,
} from "react";
import { setUnauthorizedHandler, tokenStore } from "@/api/client";
import { fetchMe, login as loginRequest, logoutRequest } from "@/api/services";
import type { AppUser } from "@/api/types";
interface AuthContextValue {
user: AppUser | null;
loading: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<AppUser | null>(null);
const [loading, setLoading] = useState(true);
const logout = useCallback(() => {
const refresh = tokenStore.getRefresh();
if (refresh) void logoutRequest(refresh).catch(() => undefined); // revoke server-side
tokenStore.clear();
setUser(null);
}, []);
useEffect(() => {
setUnauthorizedHandler(() => setUser(null));
}, []);
// Restore session on load.
useEffect(() => {
const token = tokenStore.get();
if (!token) {
setLoading(false);
return;
}
fetchMe()
.then((u) => {
if (u.role === "admin") setUser(u);
else logout();
})
.catch(() => logout())
.finally(() => setLoading(false));
}, [logout]);
const login = useCallback(async (email: string, password: string) => {
const token = await loginRequest(email, password);
tokenStore.set(token.access_token, token.refresh_token);
const me = await fetchMe();
setUser(me);
}, []);
const value = useMemo(
() => ({ user, loading, login, logout }),
[user, loading, login, logout],
);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
// eslint-disable-next-line react-refresh/only-export-components
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth must be used within AuthProvider");
return ctx;
}