ui phase 2

This commit is contained in:
hamid
2026-07-17 19:05:17 +03:30
parent 370c1beefa
commit 222856d600
42 changed files with 1354 additions and 451 deletions
+31 -9
View File
@@ -147,7 +147,7 @@ wrapper over the bare MUI component — the wrappers carry the house defaults.
| `AppImage` | images | wrapper around next/image conventions |
| `AppLoading` | loading state | default circular, `primary`, `3rem` |
| `ErrorBoundary` | wrapping fault-prone subtrees | already wraps page content in the shell |
| `UserInfo` | user avatar/identity block | feature component |
| `ProfileSummary` | the identity card in chrome | avatar+name+masked phone+role label+optional `TrustBadge`; vertical or `compact` horizontal chip |
Defaults for these live in `src/components/config.ts` (`APP_BUTTON_VARIANT`,
`APP_ICON_SIZE = 24`, `CONTENT_MAX_WIDTH = 800`, `CONTENT_MIN_WIDTH = 320`, alert/link/
@@ -166,19 +166,41 @@ CLAUDE.md "Unit Testing"; wrap with `<ThemeProvider>`, never mock MUI).
## 5. Layout & page shells
- **Private (authenticated) screens** render inside `PrivateLayout`
`TopBarAndSideBarLayout` (`src/layout/`): a `TopBar` + a `SideBar` (variant
`sidebarPersistentOnDesktop`: persistent ≥desktop, temporary drawer on mobile) +
a dark-mode toggle. Sidebar nav items are `{ title, path, icon }` arrays built with
`useTranslations('nav')`. Page content is auto-wrapped in `ErrorBoundary`.
- **Public screens** use `PublicLayout`.
- **Four per-actor shells**, each wrapped in `RoleGuard` (don't touch): `CustomerLayout`
(mobile-first — contextual `TopBar`: brand lockup on the 5 root tabs, title + back
chevron on pushed routes, an inline desktop top-nav at `≥md` replacing the mobile
`BottomBar`), `NurseLayout` / `AdminLayout` / `PartnerLayout` (all three share
`TopBarAndSideBarLayout`, `src/layout/`). All chrome navigation goes through
`@/i18n/navigation` (`Link`/`usePathname`/`useRouter`) — never a raw `next/link` or a
manual `` `/${locale}` `` prefix.
- `TopBarAndSideBarLayout`: a fixed `TopBar` (title from `useRouteTitle()`, the
route→title map in `layout/routeTitle.tsx`) + a `SideBar` rendered as **two Drawers
sharing one content tree** — mobile `temporary` and desktop `variant="permanent"` —
switched purely by `sx` breakpoint, not `useIsMobile()`; the permanent Drawer is a
normal flex sibling of the main column, so desktop reserves its own width with no
manual offset math and no post-hydration layout jump. Optional `identity` (TopBar
chip — admin/partner), `sidebarIdentity` (sidebar card — nurse's `ProfileSummary`),
and `mobileBottomBar` slots.
- Sidebar nav items are `{ title, path, icon, group? }` arrays (`@/utils`'s
`LinkToPage`) built with `useTranslations('nav')`; a shared `group` string on
consecutive items renders a `ListSubheader` section (see `NurseLayout`/`AdminLayout`).
Selection is computed once via the shared `matchActivePath` (longest-prefix,
winner-takes-all) helper — reuse it for any new nav list, never hand-roll
`pathname.startsWith`.
- **Public screens** use `PublicLayout` — a minimal corner strip (logo +
`LocaleSwitcher` + dark toggle), no sidebar/bottom bar; the step content (`AuthCard`)
carries its own larger `BrandMark`, so don't duplicate a big lockup in the shell.
- Page content is auto-wrapped in `ErrorBoundary` inside every shell.
- Shell dimensions are constants in `src/layout/config.ts` (`SIDE_BAR_WIDTH = 240px`,
top-bar `56px` mobile / `64px` desktop, anchors). Respect them; don't hard-code.
top-bar `56px` mobile / `64px` desktop). Respect them; don't hard-code.
- A page is `src/app/[locale]/(private|public-routes)/…/page.tsx`. Keep page bodies to
composition + content; push reusable visuals into `src/components/`.
- Constrain reading width with `CONTENT_MAX_WIDTH` (800) for text-heavy views; full-bleed
is fine for dashboards/tables.
- Use `useIsMobile()` (`@/hooks`) for responsive branching, or MUI breakpoints in `sx`.
- Prefer MUI breakpoints in `sx` (`{ xs: …, md: … }`) for responsive branching over
`useIsMobile()` (`@/hooks`) — the latter is JS/post-hydration and is what caused the
desktop SSR flash `TopBarAndSideBarLayout` now avoids; reach for it only for genuinely
non-structural, JS-only behavior.
---