Spaces:
Sleeping
Sleeping
| import { createContext, useContext, useState, useEffect, useCallback } from 'react' | |
| const AuthContext = createContext(null) | |
| const TOKEN_KEY = 'leadgen_token' | |
| const USER_KEY = 'leadgen_user' | |
| export function AuthProvider({ children }) { | |
| const [token, setToken] = useState(() => localStorage.getItem(TOKEN_KEY)) | |
| const [user, setUser] = useState(() => { | |
| try { return JSON.parse(localStorage.getItem(USER_KEY)) } catch { return null } | |
| }) | |
| const login = useCallback(async (username, password) => { | |
| const form = new URLSearchParams() | |
| form.append('username', username) | |
| form.append('password', password) | |
| const base = import.meta.env.DEV ? '/api' : '' | |
| const res = await fetch(`${base}/auth/token`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, | |
| body: form, | |
| }) | |
| if (!res.ok) { | |
| const err = await res.json().catch(() => ({})) | |
| throw new Error(err.detail || 'Login failed') | |
| } | |
| const data = await res.json() | |
| localStorage.setItem(TOKEN_KEY, data.access_token) | |
| localStorage.setItem(USER_KEY, JSON.stringify(data.user)) | |
| setToken(data.access_token) | |
| setUser(data.user) | |
| return data.user | |
| }, []) | |
| const logout = useCallback(() => { | |
| localStorage.removeItem(TOKEN_KEY) | |
| localStorage.removeItem(USER_KEY) | |
| setToken(null) | |
| setUser(null) | |
| }, []) | |
| // Refresh user info from API on mount (validates token is still good) | |
| useEffect(() => { | |
| if (!token) return | |
| const base = import.meta.env.DEV ? '/api' : '' | |
| fetch(`${base}/auth/me`, { headers: { Authorization: `Bearer ${token}` } }) | |
| .then(r => { | |
| if (r.status === 401) { logout(); return null } | |
| return r.json() | |
| }) | |
| .then(u => { if (u) { setUser(u); localStorage.setItem(USER_KEY, JSON.stringify(u)) } }) | |
| .catch(() => {}) | |
| }, [token, logout]) | |
| return ( | |
| <AuthContext.Provider value={{ token, user, login, logout, isAdmin: user?.is_admin }}> | |
| {children} | |
| </AuthContext.Provider> | |
| ) | |
| } | |
| export function useAuth() { | |
| return useContext(AuthContext) | |
| } | |