import { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import axios from 'axios'; const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8051'; // Every component that talks to the API via axios imports the same default // instance, so registering the interceptor once here attaches the stored // token everywhere - without it, auth only ever covers the two fetch() calls // in this file, and every axios-based request (projects, kanban, hooks, // most of the app) goes out unauthenticated. axios.interceptors.request.use((config) => { const token = localStorage.getItem('auth_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); interface AuthContextType { isAuthenticated: boolean; isAuthEnabled: boolean; isLoading: boolean; user: { email: string } | null; login: (email: string, password: string) => Promise; logout: () => void; } const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: ReactNode }) { const [isAuthenticated, setIsAuthenticated] = useState(false); const [isAuthEnabled, setIsAuthEnabled] = useState(true); const [isLoading, setIsLoading] = useState(true); const [user, setUser] = useState<{ email: string } | null>(null); useEffect(() => { checkAuthStatus(); }, []); const checkAuthStatus = async () => { try { // Check if auth is enabled const statusRes = await fetch(`${API_BASE}/api/auth/status`); if (statusRes.ok) { const statusData = await statusRes.json(); setIsAuthEnabled(statusData.auth_enabled); if (!statusData.auth_enabled) { setIsAuthenticated(true); setIsLoading(false); return; } } // Check if user is already logged in const token = localStorage.getItem('auth_token'); if (token) { const meRes = await fetch(`${API_BASE}/api/auth/me`, { headers: { Authorization: `Bearer ${token}` } }); if (meRes.ok) { const userData = await meRes.json(); setUser(userData); setIsAuthenticated(true); } else { localStorage.removeItem('auth_token'); } } } catch (error) { // If we can't reach the server, assume auth is disabled for local dev console.warn('Could not check auth status:', error); setIsAuthEnabled(false); setIsAuthenticated(true); } finally { setIsLoading(false); } }; const login = async (email: string, password: string) => { const res = await fetch(`${API_BASE}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); if (!res.ok) { const error = await res.json(); throw new Error(error.detail || 'Login failed'); } const data = await res.json(); localStorage.setItem('auth_token', data.access_token); setUser({ email }); setIsAuthenticated(true); }; const logout = () => { localStorage.removeItem('auth_token'); setUser(null); setIsAuthenticated(false); }; return ( {children} ); } export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; }