kioai / artifacts /image-gen /src /contexts /AuthContext.tsx
kinaiok
Initial deployment setup for Hugging Face Spaces
5ef6e9d
import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from "react";
export interface AuthUser {
id: number;
email: string;
displayName?: string | null;
isAdmin: boolean;
}
interface AuthContextValue {
user: AuthUser | null;
isLoaded: boolean;
isSignedIn: boolean;
isAdmin: boolean;
signIn: (email: string, password: string) => Promise<void>;
signUp: (email: string, password: string, displayName?: string) => Promise<void>;
signOut: () => Promise<void>;
refetch: () => Promise<void>;
}
const AuthContext = createContext<AuthContextValue | null>(null);
const BASE = import.meta.env.BASE_URL.replace(/\/$/, "");
const API_BASE = `${BASE}/api`;
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<AuthUser | null>(null);
const [isLoaded, setIsLoaded] = useState(false);
const fetchMe = useCallback(async () => {
try {
const res = await fetch(`${API_BASE}/auth/me`, { credentials: "include" });
if (res.ok) {
const data = await res.json();
setUser(data);
} else {
setUser(null);
}
} catch {
setUser(null);
} finally {
setIsLoaded(true);
}
}, []);
useEffect(() => { fetchMe(); }, [fetchMe]);
const signIn = async (email: string, password: string) => {
const res = await fetch(`${API_BASE}/auth/login`, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || "Login failed");
setUser(data);
};
const signUp = async (email: string, password: string, displayName?: string) => {
const res = await fetch(`${API_BASE}/auth/signup`, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password, displayName }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || "Registration failed");
setUser(data);
};
const signOut = async () => {
await fetch(`${API_BASE}/auth/logout`, { method: "POST", credentials: "include" });
setUser(null);
};
return (
<AuthContext.Provider value={{
user,
isLoaded,
isSignedIn: !!user,
isAdmin: !!user?.isAdmin,
signIn,
signUp,
signOut,
refetch: fetchMe,
}}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth must be used within AuthProvider");
return ctx;
}