Spaces:
Sleeping
Sleeping
| import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; | |
| import { login as apiLogin, verifyAuth, logout as apiLogout, getCurrentUser } from '@/utils/api'; | |
| import type { LoginRequest, AuthUser } from '@/types'; | |
| interface AuthContextValue { | |
| user: AuthUser | null; | |
| loading: boolean; | |
| login: (credentials: LoginRequest) => Promise<void>; | |
| logout: () => void; | |
| isAuthenticated: boolean; | |
| } | |
| const AuthContext = createContext<AuthContextValue | undefined>(undefined); | |
| export function AuthProvider({ children }: { children: ReactNode }) { | |
| const [user, setUser] = useState<AuthUser | null>(null); | |
| const [loading, setLoading] = useState(true); | |
| // Check authentication on mount | |
| useEffect(() => { | |
| checkAuth(); | |
| }, []); | |
| async function checkAuth() { | |
| try { | |
| const authUser = await verifyAuth(); | |
| if (authUser.authenticated) { | |
| setUser(authUser); | |
| } else { | |
| setUser(null); | |
| } | |
| } catch { | |
| setUser(null); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| async function login(credentials: LoginRequest) { | |
| setLoading(true); | |
| try { | |
| await apiLogin(credentials); | |
| const authUser = await getCurrentUser(); | |
| setUser(authUser); | |
| } catch (error) { | |
| setUser(null); | |
| throw error; | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| function logout() { | |
| apiLogout(); | |
| setUser(null); | |
| } | |
| return ( | |
| <AuthContext.Provider | |
| value={{ | |
| user, | |
| loading, | |
| login, | |
| logout, | |
| isAuthenticated: user?.authenticated ?? false, | |
| }} | |
| > | |
| {children} | |
| </AuthContext.Provider> | |
| ); | |
| } | |
| export function useAuth() { | |
| const context = useContext(AuthContext); | |
| if (context === undefined) { | |
| throw new Error('useAuth must be used within an AuthProvider'); | |
| } | |
| return context; | |
| } | |