Web: wire AppLayout into routing + stub section pages (step 3/5)
- App.tsx: every authenticated route now nests under one
RequireAuth + AppLayout parent route (react-router nested
routes/<Outlet />) instead of each page wrapping its own guard.
- New routes/pages: /recettes, /liste-de-courses, /foyer, each a thin
wrapper around a shared ComingSoonPage ("cette section arrive
bientôt.") — no backend behind them yet, matches the "pages stub
dédiées" choice discussed in chat.
- locales/fr/translation.json: nav labels + stub copy.
HomePage still shows its own greeting/logout card here (unchanged,
now nested inside AppLayout's <Outlet /> — briefly duplicating the
sidebar's greeting/logout) — replaced by the actual planning view in
the next commit.
This commit is contained in:
parent
f4ab482b52
commit
c07f8ad82e
7 changed files with 90 additions and 7 deletions
|
|
@ -1,27 +1,37 @@
|
|||
import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { RedirectIfAuthenticated } from "./features/auth/RedirectIfAuthenticated";
|
||||
import { RequireAuth } from "./features/auth/RequireAuth";
|
||||
import { AppLayout } from "./layouts/AppLayout";
|
||||
import { HomePage } from "./pages/HomePage";
|
||||
import { HouseholdPage } from "./pages/HouseholdPage";
|
||||
import { LoginPage } from "./pages/LoginPage";
|
||||
import { RecipesPage } from "./pages/RecipesPage";
|
||||
import { ShoppingListPage } from "./pages/ShoppingListPage";
|
||||
import { SignupPage } from "./pages/SignupPage";
|
||||
|
||||
/**
|
||||
* Top-level route table. `/` requires an authenticated session (see
|
||||
* {@link RequireAuth}); `/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.
|
||||
* 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.
|
||||
*/
|
||||
export function App() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<HomePage />
|
||||
<AppLayout />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/recettes" element={<RecipesPage />} />
|
||||
<Route path="/liste-de-courses" element={<ShoppingListPage />} />
|
||||
<Route path="/foyer" element={<HouseholdPage />} />
|
||||
</Route>
|
||||
<Route
|
||||
path="/login"
|
||||
element={
|
||||
|
|
|
|||
|
|
@ -42,5 +42,17 @@
|
|||
"home": {
|
||||
"greeting": "Bonjour {{firstName}} {{lastName}} 👋",
|
||||
"logout": "Se déconnecter"
|
||||
},
|
||||
"recipes": {
|
||||
"title": "Recettes",
|
||||
"comingSoon": "Cette section arrive bientôt."
|
||||
},
|
||||
"shoppingList": {
|
||||
"title": "Liste de courses",
|
||||
"comingSoon": "Cette section arrive bientôt."
|
||||
},
|
||||
"household": {
|
||||
"title": "Foyer & profil",
|
||||
"comingSoon": "Cette section arrive bientôt."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
apps/web/src/pages/ComingSoonPage.scss
Normal file
12
apps/web/src/pages/ComingSoonPage.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// =============================================================================
|
||||
// Styles for ComingSoonPage — shared by every stub section page.
|
||||
// =============================================================================
|
||||
|
||||
.coming-soon-page {
|
||||
max-width: 40rem;
|
||||
|
||||
p {
|
||||
color: var(--color-text-muted);
|
||||
font-size: var(--font-size-md);
|
||||
}
|
||||
}
|
||||
23
apps/web/src/pages/ComingSoonPage.tsx
Normal file
23
apps/web/src/pages/ComingSoonPage.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import "./ComingSoonPage.scss";
|
||||
|
||||
interface ComingSoonPageProps {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Placeholder rendered by every section that has a route/sidebar entry but
|
||||
* no real feature behind it yet (Recettes, Liste de courses, Foyer &
|
||||
* profil — see `RecipesPage.tsx` etc.). One shared component instead of
|
||||
* three near-identical markup blocks; each page still gets its own file
|
||||
* (and its own copy, via i18n) so building out a real feature later means
|
||||
* rewriting one dedicated file, not splitting a generic route.
|
||||
*/
|
||||
export function ComingSoonPage({ title, description }: ComingSoonPageProps) {
|
||||
return (
|
||||
<div className="coming-soon-page">
|
||||
<h1>{title}</h1>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
8
apps/web/src/pages/HouseholdPage.tsx
Normal file
8
apps/web/src/pages/HouseholdPage.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { ComingSoonPage } from "./ComingSoonPage";
|
||||
|
||||
/** Household & profile section — routed at `/foyer`. No backend yet beyond auth, stub for now. */
|
||||
export function HouseholdPage() {
|
||||
const { t } = useTranslation();
|
||||
return <ComingSoonPage title={t("household.title")} description={t("household.comingSoon")} />;
|
||||
}
|
||||
8
apps/web/src/pages/RecipesPage.tsx
Normal file
8
apps/web/src/pages/RecipesPage.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { ComingSoonPage } from "./ComingSoonPage";
|
||||
|
||||
/** Recipes section — routed at `/recettes`. No backend yet (see README's "Planning" section), stub for now. */
|
||||
export function RecipesPage() {
|
||||
const { t } = useTranslation();
|
||||
return <ComingSoonPage title={t("recipes.title")} description={t("recipes.comingSoon")} />;
|
||||
}
|
||||
10
apps/web/src/pages/ShoppingListPage.tsx
Normal file
10
apps/web/src/pages/ShoppingListPage.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { ComingSoonPage } from "./ComingSoonPage";
|
||||
|
||||
/** Shopping list section — routed at `/liste-de-courses`. No backend yet, stub for now. */
|
||||
export function ShoppingListPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<ComingSoonPage title={t("shoppingList.title")} description={t("shoppingList.comingSoon")} />
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue