video-accessibility-old/frontend/src/App.tsx

139 lines
4.8 KiB
TypeScript

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { queryClient } from './lib/queryClient';
import './styles/index.css';
// Import route components (will be implemented in next phases)
import { Dashboard } from './routes/Dashboard';
import { Login } from './routes/Login';
import { NewJob } from './routes/jobs/NewJob';
import { JobsList } from './routes/jobs/JobsList';
import { JobDetail } from './routes/jobs/JobDetail';
import { QCList } from './routes/admin/QCList';
import { QCDetail } from './routes/admin/QCDetail';
import { FinalList } from './routes/admin/FinalList';
import { FinalDetail } from './routes/admin/FinalDetail';
import { UserList } from './routes/admin/UserList';
import { UserDetail } from './routes/admin/UserDetail';
import { Downloads } from './routes/Downloads';
import { RequireAuth } from './components/Auth/RequireAuth';
import { RoleGate } from './components/Auth/RoleGate';
import { ErrorBoundary } from './components/ErrorBoundary';
import { ToastContainer } from './components/Toast/Toast';
import { ToastProvider, useToastContext } from './contexts/ToastContext';
import { NotificationProvider } from './contexts/NotificationContext';
import { GlobalWebSocketProvider } from './contexts/GlobalWebSocketContext';
import { Layout } from './components/Layout/Layout';
// Helper component to wrap authenticated routes with Layout
function AuthenticatedRoute({ children }: { children: React.ReactNode }) {
return (
<RequireAuth>
<Layout>
{children}
</Layout>
</RequireAuth>
);
}
function AppContent() {
const { toasts, removeToast } = useToastContext();
return (
<Router basename="/video-accessibility">
<div className="min-h-screen bg-gray-50">
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/" element={
<AuthenticatedRoute>
<Dashboard />
</AuthenticatedRoute>
} />
<Route path="/jobs" element={
<AuthenticatedRoute>
<JobsList />
</AuthenticatedRoute>
} />
<Route path="/jobs/new" element={
<AuthenticatedRoute>
<NewJob />
</AuthenticatedRoute>
} />
<Route path="/jobs/:id" element={
<AuthenticatedRoute>
<JobDetail />
</AuthenticatedRoute>
} />
<Route path="/admin/qc" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['reviewer', 'production', 'admin']}>
<QCList />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/admin/qc/:id" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['reviewer', 'production', 'admin']}>
<QCDetail />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/admin/final" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['reviewer', 'production', 'admin']}>
<FinalList />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/admin/final/:id" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['reviewer', 'production', 'admin']}>
<FinalDetail />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/admin/users" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['admin']}>
<UserList />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/admin/users/:id" element={
<AuthenticatedRoute>
<RoleGate allowedRoles={['admin']}>
<UserDetail />
</RoleGate>
</AuthenticatedRoute>
} />
<Route path="/downloads/:id" element={
<AuthenticatedRoute>
<Downloads />
</AuthenticatedRoute>
} />
</Routes>
<ToastContainer toasts={toasts} onRemove={removeToast} />
</div>
</Router>
);
}
function App() {
return (
<ErrorBoundary>
<QueryClientProvider client={queryClient}>
<NotificationProvider>
<ToastProvider>
<GlobalWebSocketProvider>
<AppContent />
</GlobalWebSocketProvider>
<ReactQueryDevtools initialIsOpen={false} />
</ToastProvider>
</NotificationProvider>
</QueryClientProvider>
</ErrorBoundary>
);
}
export default App;