import { useEffect, useState } from 'react'; import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom'; import { MainApp } from './pages/MainApp'; import { Login } from './pages/Login'; import { Settings } from './pages/Settings'; import { isAuthenticated, getCurrentUser, setAuthTokenFromHash, ensureDemoToken, isDemoSession } from './services/auth'; import { AuthLoadingSkeleton } from './components/AuthLoadingSkeleton'; import { Toaster } from './components/ui/toaster'; import './App.css'; // Protected route wrapper with auth check function ProtectedRoute({ children }: { children: React.ReactNode }) { const navigate = useNavigate(); const location = useLocation(); const [isChecking, setIsChecking] = useState(true); const [hasToken, setHasToken] = useState(isAuthenticated()); // T110: Check if user is authenticated on mount useEffect(() => { const checkAuth = async () => { // Check for OAuth callback token in URL hash const tokenExtracted = setAuthTokenFromHash(); if (tokenExtracted) { console.log('OAuth token extracted from URL hash'); setHasToken(true); setIsChecking(false); return; } if (!isAuthenticated()) { const demoReady = await ensureDemoToken(); if (!demoReady) { setHasToken(false); setIsChecking(false); return; } } setHasToken(true); if (isDemoSession()) { setIsChecking(false); return; } const token = localStorage.getItem('auth_token'); // Skip validation for local dev token if (token === 'local-dev-token') { setIsChecking(false); return; } try { // Verify the token is valid by calling getCurrentUser await getCurrentUser(); setIsChecking(false); } catch { // Token is invalid (401), redirect to login console.warn('Authentication failed, redirecting to login'); localStorage.removeItem('auth_token'); setHasToken(false); setIsChecking(false); if (location.pathname !== '/login') { navigate('/login', { replace: true, state: { from: location } }); } } }; checkAuth(); }, [navigate, location]); if (isChecking) { return ; } if (!hasToken) { return ; } return <>{children}; } function App() { return ( <> } /> } /> } /> ); } export default App;