import { Navigate, Outlet, Route, Routes } from "react-router-dom"; import { AdminAuthProvider } from "./features/admin/AdminAuthContext"; import { RequireAdmin } from "./features/admin/RequireAdmin"; import { RedirectIfAuthenticated } from "./features/auth/RedirectIfAuthenticated"; import { RequireAuth } from "./features/auth/RequireAuth"; import { AdminLayout } from "./layouts/AdminLayout"; import { AppLayout } from "./layouts/AppLayout"; import { CatalogPage as AdminCatalogPage } from "./pages/admin/catalog/CatalogPage"; import { CorrectionsPage as AdminCorrectionsPage } from "./pages/admin/corrections/CorrectionsPage"; import { DashboardPage as AdminDashboardPage } from "./pages/admin/dashboard/DashboardPage"; import { AdminLoginPage } from "./pages/admin/login/AdminLoginPage"; import { MonitoringPage as AdminMonitoringPage } from "./pages/admin/monitoring/MonitoringPage"; import { LoginPage } from "./pages/auth/LoginPage"; import { SignupPage } from "./pages/auth/SignupPage"; import { CookingSessionPage } from "./pages/cooking-session/CookingSessionPage"; import { OnboardingAllergensPage } from "./pages/onboarding/OnboardingAllergensPage"; import { OnboardingDietPage } from "./pages/onboarding/OnboardingDietPage"; import { OnboardingHouseholdPage } from "./pages/onboarding/OnboardingHouseholdPage"; import { OnboardingSourcesPage } from "./pages/onboarding/OnboardingSourcesPage"; import { PlanningPage } from "./pages/planning/PlanningPage"; import { ImportRecipePage } from "./pages/recipes/ImportRecipePage"; import { RecipeFormPage } from "./pages/recipes/RecipeFormPage"; import { RecipesPage } from "./pages/recipes/RecipesPage"; import { AccountSettingsPage } from "./pages/settings/AccountSettingsPage"; import { CreditsPage } from "./pages/settings/CreditsPage"; import { HouseholdSettingsPage } from "./pages/settings/HouseholdSettingsPage"; import { PreferencesPage } from "./pages/settings/PreferencesPage"; import { UserPreferencesPage } from "./pages/settings/UserPreferencesPage"; import { ShoppingListPage } from "./pages/shopping-list/ShoppingListPage"; /** * Top-level route table. Every authenticated section is nested under one * `RequireAuth` + `AppLayout` parent route (sidebar chrome + `/auth` * guard applied once, not per-page — see {@link AppLayout}); `/login` and * `/signup` redirect an already-logged-in visitor to `/` instead (see * {@link RedirectIfAuthenticated}). Anything else falls back to `/`, which * itself redirects to `/login` if needed. * * `/parametres/*` (compte/préférences alimentaires/foyer/préférences * utilisateur/crédits) are the settings pages, reachable from the sidebar's * bottom "Paramètres" menu and the account menu (see `AppLayout`) — nested under * `AppLayout` like every other authenticated section. `/foyer` is the old, * pre-split combined page's path; it now just redirects to * `/parametres/foyer` so an existing bookmark/link keeps working. * * `/onboarding/*` (regime/foyer/sources/allergens, in that order) is also * `RequireAuth`-gated — reached right after signup, once a session already * exists — but deliberately its own top-level route group, *not* nested * under `AppLayout`: a focused, distraction-free wizard with no sidebar, * same full-page-card language as `/login`/`/signup` (see `onboarding.scss`). * `/onboarding/sources` is conditional — only reached when the `foyer` step * created/joined a household (see `OnboardingHouseholdPage`'s `goToNextStep`); * skipped otherwise, straight to `/onboarding/allergenes`. * * `/admin/*` is the internal admin surface (metrics, monitoring, correction * triage, off-catalog ingredient review). It's its own top-level group, * wrapped in {@link AdminAuthProvider} so the `GET /admin/api/auth/me` session * probe only runs under `/admin` — the admin session (cookie `admin_session`, * `ADMIN_JWT_SECRET`) is entirely separate from the end-user one, so this is * never nested under `RequireAuth`. `/admin/login` is the only * unauthenticated admin route; everything else sits under `RequireAdmin` + * `AdminLayout`. */ export function App() { return ( } > } /> {/* Same component for both — a master-detail layout, not a navigation to a separate page: the tab bar + table stay mounted, only RecipesPage's detail panel changes with `:id` (see RecipesPage.tsx). */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } > } /> } > } /> } /> } /> } /> } /> ); }