63 lines
1.5 KiB
TypeScript
63 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import { createContext, useContext, useEffect, useState, ReactNode } from "react";
|
|
|
|
export interface User {
|
|
user_id: string;
|
|
email: string;
|
|
name: string;
|
|
}
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
authEnabled: boolean;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType>({ user: null, authEnabled: false });
|
|
|
|
export function useAuth() {
|
|
return useContext(AuthContext);
|
|
}
|
|
|
|
export function AuthProvider({ children }: { children: ReactNode }) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [authEnabled, setAuthEnabled] = useState(false);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
fetch("/auth/me", { credentials: "include" })
|
|
.then(async (res) => {
|
|
if (res.status === 401) {
|
|
window.location.href = "/auth/login";
|
|
return;
|
|
}
|
|
const data = await res.json();
|
|
if (data.auth_enabled === false) {
|
|
setAuthEnabled(false);
|
|
} else {
|
|
setAuthEnabled(true);
|
|
setUser(data as User);
|
|
}
|
|
setLoading(false);
|
|
})
|
|
.catch(() => {
|
|
// Backend unreachable — don't block the UI
|
|
setLoading(false);
|
|
});
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="flex h-screen items-center justify-center bg-background">
|
|
<div className="h-8 w-8 animate-spin rounded-full border-2 border-border border-t-accent" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AuthContext.Provider value={{ user, authEnabled }}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|