import React, { createContext, useContext, useState, useEffect } from 'react'; import axios from 'axios'; import { User } from './types'; interface AuthContextType { user: User | null; token: string | null; login: (token: string, user: User) => void; logout: () => void; refreshUser: () => Promise; isAuthenticated: boolean; } const AuthContext = createContext(undefined); export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [user, setUser] = useState(null); const [token, setToken] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const savedToken = localStorage.getItem('token'); const savedUser = localStorage.getItem('user'); if (savedToken && savedUser) { setToken(savedToken); setUser(JSON.parse(savedUser)); axios.defaults.headers.common['Authorization'] = `Bearer ${savedToken}`; } setLoading(false); }, []); const login = (newToken: string, newUser: User) => { setToken(newToken); setUser(newUser); localStorage.setItem('token', newToken); localStorage.setItem('user', JSON.stringify(newUser)); axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; }; const logout = React.useCallback(() => { setToken(null); setUser(null); localStorage.removeItem('token'); localStorage.removeItem('user'); delete axios.defaults.headers.common['Authorization']; window.location.href = '/login'; // Force redirect }, []); // Global Axios Interceptor for 401/403 useEffect(() => { const interceptor = axios.interceptors.response.use( (response) => response, (error) => { if (error.response && (error.response.status === 401 || error.response.status === 403)) { console.warn("Auth session expired or invalid. Logging out..."); logout(); } return Promise.reject(error); } ); return () => axios.interceptors.response.eject(interceptor); }, [logout]); const refreshUser = async () => { const currentToken = localStorage.getItem('token'); if (!currentToken) return; try { // Ensure auth header is set just in case axios.defaults.headers.common['Authorization'] = `Bearer ${currentToken}`; const res = await axios.get('/api/auth/me'); if (res.data) { setUser(res.data); localStorage.setItem('user', JSON.stringify(res.data)); } } catch (error) { console.error("Failed to refresh user data", error); } }; if (loading) return
Loading...
; return ( {children} ); }; export const useAuth = () => { const context = useContext(AuthContext); if (!context) throw new Error('useAuth must be used within an AuthProvider'); return context; };