File
Blob: src/client/app.tsx
| 1 | import { lazy } from "react"; |
| 2 | import { Navigate, Outlet, Route, Routes, useLocation } from "react-router-dom"; |
| 3 | import { useAuth } from "@/client/auth"; |
| 4 | import { AppShell } from "@/client/components/app-shell"; |
| 5 | import { LoadingPanel } from "@/client/components/loading-panel"; |
| 6 | import { LandingPage } from "@/client/pages/landing-page"; |
| 7 | |
| 8 | const CreateProjectPage = lazy(() => |
| 9 | import("@/client/pages/create-project-page").then(({ CreateProjectPage }) => ({ default: CreateProjectPage })), |
| 10 | ); |
| 11 | const LoginPage = lazy(() => import("@/client/pages/login-page").then(({ LoginPage }) => ({ default: LoginPage }))); |
| 12 | const NotFoundPage = lazy(() => |
| 13 | import("@/client/pages/not-found-page").then(({ NotFoundPage }) => ({ default: NotFoundPage })), |
| 14 | ); |
| 15 | const ProfilePage = lazy(() => |
| 16 | import("@/client/pages/profile-page").then(({ ProfilePage }) => ({ default: ProfilePage })), |
| 17 | ); |
| 18 | const ProjectDetailPage = lazy(() => |
| 19 | import("@/client/pages/project-detail-page").then(({ ProjectDetailPage }) => ({ default: ProjectDetailPage })), |
| 20 | ); |
| 21 | const ProjectSettingsPage = lazy(() => |
| 22 | import("@/client/pages/project-settings-page").then(({ ProjectSettingsPage }) => ({ default: ProjectSettingsPage })), |
| 23 | ); |
| 24 | const ProjectsPage = lazy(() => |
| 25 | import("@/client/pages/projects-page").then(({ ProjectsPage }) => ({ default: ProjectsPage })), |
| 26 | ); |
| 27 | const RunDetailPage = lazy(() => |
| 28 | import("@/client/pages/run-detail-page").then(({ RunDetailPage }) => ({ default: RunDetailPage })), |
| 29 | ); |
| 30 | |
| 31 | const ProtectedRoute = () => { |
| 32 | const { isAuthenticated, isInitializing } = useAuth(); |
| 33 | const location = useLocation(); |
| 34 | |
| 35 | if (isInitializing) { |
| 36 | return <LoadingPanel label="Verifying session..." />; |
| 37 | } |
| 38 | |
| 39 | if (isAuthenticated) { |
| 40 | return <Outlet />; |
| 41 | } |
| 42 | |
| 43 | const returnTo = `${location.pathname}${location.search}${location.hash}`; |
| 44 | return <Navigate to={`/app/login?return_to=${encodeURIComponent(returnTo)}`} replace />; |
| 45 | }; |
| 46 | |
| 47 | export const App = () => ( |
| 48 | <Routes> |
| 49 | <Route element={<AppShell />}> |
| 50 | <Route path="/" element={<LandingPage />} /> |
| 51 | <Route path="/app/login" element={<LoginPage />} /> |
| 52 | <Route element={<ProtectedRoute />}> |
| 53 | <Route path="/app/projects" element={<ProjectsPage />} /> |
| 54 | <Route path="/app/projects/new" element={<CreateProjectPage />} /> |
| 55 | <Route path="/app/projects/:projectId/settings" element={<ProjectSettingsPage />} /> |
| 56 | <Route path="/app/projects/:projectId" element={<ProjectDetailPage />} /> |
| 57 | <Route path="/app/runs/:runId" element={<RunDetailPage />} /> |
| 58 | <Route path="/app/me" element={<ProfilePage />} /> |
| 59 | </Route> |
| 60 | <Route path="*" element={<NotFoundPage />} /> |
| 61 | </Route> |
| 62 | </Routes> |
| 63 | ); |