M2-T06: scaffold React SPA frontend with typed OpenAPI client

- Vite + React 18 + TypeScript + Mantine + TanStack Query + react-router-dom
- typed client: openapi-typescript -> src/api/schema.d.ts (committed), openapi-fetch
- fetch wrapper middleware: cookies, X-CSRF-Token on writes, 401 -> /login,
  non-401 errors carry parsed JSON body
- SessionProvider/useSession (GET /api/session), ProtectedRoute skeleton
- app shell (Mantine + router) with placeholder login/home/config pages + gear nav
- dev proxy to FastAPI; vitest smoke test; frontend README
- npm scripts: dev/build/preview/lint/typecheck/test/codegen
This commit is contained in:
2026-06-13 15:20:50 +02:00
parent dba9e28540
commit 6cfeb2b865
23 changed files with 9741 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
/**
* ProtectedRoute — renders children when authenticated; redirects to /login otherwise.
*
* Shows nothing while the session is still loading to avoid flash-of-login.
* T07 can replace the loading placeholder with a proper spinner/skeleton.
*/
import type { ReactNode } from 'react'
import { Navigate } from 'react-router-dom'
import { useSession } from './SessionProvider'
interface ProtectedRouteProps {
children: ReactNode
}
export function ProtectedRoute({ children }: ProtectedRouteProps) {
const { status } = useSession()
if (status === 'loading') {
// Render nothing while we check the session — avoids a flash to /login.
return null
}
if (status === 'unauthenticated') {
return <Navigate to="/login" replace />
}
return <>{children}</>
}