import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { Layout } from './components/Layout'; import { PrintersPage } from './pages/PrintersPage'; import { ArchivesPage } from './pages/ArchivesPage'; import { QueuePage } from './pages/QueuePage'; import { StatsPage } from './pages/StatsPage'; import { SettingsPage } from './pages/SettingsPage'; import { ProfilesPage } from './pages/ProfilesPage'; import { MaintenancePage } from './pages/MaintenancePage'; import { ProjectsPage } from './pages/ProjectsPage'; import { ProjectDetailPage } from './pages/ProjectDetailPage'; import { FileManagerPage } from './pages/FileManagerPage'; import { CameraPage } from './pages/CameraPage'; import { StreamOverlayPage } from './pages/StreamOverlayPage'; import { ExternalLinkPage } from './pages/ExternalLinkPage'; import { GroupEditPage } from './pages/GroupEditPage'; import InventoryPage from './pages/InventoryPage'; import { SystemInfoPage } from './pages/SystemInfoPage'; import { LoginPage } from './pages/LoginPage'; import { SetupPage } from './pages/SetupPage'; import { NotificationsPage } from './pages/NotificationsPage'; import { useWebSocket } from './hooks/useWebSocket'; import { ThemeProvider } from './contexts/ThemeContext'; import { ToastProvider } from './contexts/ToastContext'; import { AuthProvider, useAuth } from './contexts/AuthContext'; import { SpoolBuddyLayout } from './components/spoolbuddy/SpoolBuddyLayout'; import { SpoolBuddyDashboard } from './pages/spoolbuddy/SpoolBuddyDashboard'; import { SpoolBuddyAmsPage } from './pages/spoolbuddy/SpoolBuddyAmsPage'; import { SpoolBuddySettingsPage } from './pages/spoolbuddy/SpoolBuddySettingsPage'; import { SpoolBuddyCalibrationPage } from './pages/spoolbuddy/SpoolBuddyCalibrationPage'; import { SpoolBuddyWriteTagPage } from './pages/spoolbuddy/SpoolBuddyWriteTagPage'; const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60, retry: 1, }, }, }); function WebSocketProvider({ children }: { children: React.ReactNode }) { useWebSocket(); return <>{children}; } function ProtectedRoute({ children }: { children: React.ReactNode }) { const { authEnabled, loading, user } = useAuth(); if (loading) { return
Loading...
; } if (authEnabled && !user) { return ; } return <>{children}; } function AdminRoute({ children }: { children: React.ReactNode }) { const { authEnabled, loading, user, isAdmin } = useAuth(); if (loading) { return
Loading...
; } // If auth is not enabled, allow access (backward compatibility) if (!authEnabled) { return <>{children}; } // If auth is enabled but no user, redirect to login if (!user) { return ; } // If user is not admin, redirect to home if (!isAdmin) { return ; } return <>{children}; } function SetupRoute({ children }: { children: React.ReactNode }) { const { authEnabled, loading } = useAuth(); if (loading) { return
Loading...
; } // If auth is already enabled, redirect to login // Otherwise, allow access to setup page (even if setup was completed before) // This allows users to enable auth later if they skipped it during initial setup if (authEnabled) { return ; } return <>{children}; } function App() { return ( {/* Setup page - only accessible if auth not enabled */} } /> {/* Login page */} } /> {/* Camera page - standalone, no layout, no WebSocket (doesn't need real-time updates) */} } /> {/* Stream overlay page - standalone for OBS/streaming embeds, no auth required */} } /> {/* SpoolBuddy kiosk UI */} }> } /> } /> } /> } /> } /> {/* Main app with WebSocket for real-time updates */} }> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> ); } export default App;