some ui phase improvement planning
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
# UI Phase 2 — Shells & navigation
|
||||
|
||||
> **Mission:** replace the starter chrome with per-actor shells — consumer-app chrome for customers, a
|
||||
> workspace for nurses, a dense console for admin/partner — and fix the navigation-correctness defects the
|
||||
> audit verified: the sidebar active state that never fires, the middleware redirect hop on every sidebar
|
||||
> click, the fragile RTL anchoring, and the desktop SSR mobile-first flash. Phases 0–1 gave the app a design
|
||||
> language and primitives; this phase is where every actor finally gets chrome that *looks like Balinyaar and
|
||||
> navigates correctly*. **This phase owns `client/src/layout/`.**
|
||||
>
|
||||
> **Track:** frontend · **Depends on:** [Phase 0](ui-phase-0-design-language.md),
|
||||
> [Phase 1](ui-phase-1-primitives-and-states.md) · **Unlocks:** every actor gets branded, correct chrome —
|
||||
> the area redesigns (phases 3–11) compose inside these shells
|
||||
> **Before you start, read [../../phases/_shared/agent-operating-rules.md](../../phases/_shared/agent-operating-rules.md) and invoke the frontend-designer skill — both are mandatory.**
|
||||
|
||||
## 1. Context — where this sits
|
||||
|
||||
The feature layer is disciplined, but the chrome around it is the untouched react-starter-kit. Diagnosed
|
||||
current state (all verified in code):
|
||||
|
||||
1. **The sidebar active highlight never fires.** `SideBarNavItem.tsx:28` compares
|
||||
`pathname.startsWith(path)` where `pathname` (from `next/navigation`) is locale-prefixed
|
||||
(`/fa/nurse/requests`) and `path` is unprefixed (`/nurse/requests`) — `defineRouting` uses
|
||||
`localePrefix: 'always'`, so the comparison always fails. Nurse/admin/partner users get zero "where am I"
|
||||
signal. `AppLink`'s `activeClassName` (`AppLinkNextNavigation.tsx:95`, `pathname == currentPath`) has the
|
||||
same bug.
|
||||
2. **Three locale strategies coexist in the chrome.** Sidebar links push unprefixed hrefs through raw
|
||||
`next/link` (`SideBarNavItem.tsx:34` via `AppLink`) — a middleware redirect hop on every click and a
|
||||
locale-flip risk for `/en` users; `BottomBar.tsx:14` and `NotificationBell` manually prefix with
|
||||
`/${locale}`; `CustomerLayout.tsx:52` does the same inline. There is no `createNavigation` wrapper —
|
||||
`src/i18n/` holds only `routing.ts` + `request.ts`.
|
||||
3. **The chrome is starter junk on a trust-first product.** `PublicLayout.tsx:9` titles the login screen
|
||||
`'Unauthorized - Balinyaar'` in English; `SideBar.tsx:56` renders `<UserInfo showAvatar />` with no user —
|
||||
an eternal English "Current User" / "Loading..." (`UserInfo.tsx:34-36`, prop typed `user?: any`);
|
||||
`TopBarAndSideBarLayout.tsx:71` tooltips `'Open Sidebar'`; `SideBar.tsx:76` says `'Logout Current User'`.
|
||||
4. **Structural defects:** `SERVER_SIDE_MOBILE_FIRST = true` (`hooks/layout.ts:8`) makes every desktop SSR
|
||||
paint the mobile shell, then content jumps 240px after hydration; content offset uses physical
|
||||
`paddingLeft/Right` keyed to anchor strings (`TopBarAndSideBarLayout.tsx:53-60`) — RTL correctness by
|
||||
double-flip coincidence; the drawer-close handler sits on the whole content `Stack` (`SideBar.tsx:52`) so
|
||||
any tap inside closes it; `BottomBar` has no safe-area padding and renders unconditionally on desktop
|
||||
(`CustomerLayout.tsx:81`); the customer shell has **no sign-out, no back affordance, no contextual
|
||||
title**; no shell has a locale switcher or an actor switcher for dual-role sessions.
|
||||
|
||||
**What already exists (do not rebuild):**
|
||||
|
||||
- **[Phase 0](ui-phase-0-design-language.md):** the brand mark (registered as `logo`), the
|
||||
`theme.components` pass (AppBar/Drawer/ListItemButton/BottomNavigation already restyled), the single icon
|
||||
family incl. a direction-aware back chevron, elevation/motion/focus tokens.
|
||||
- **[Phase 1](ui-phase-1-primitives-and-states.md):** PageHeader, state views, route-level
|
||||
`loading.tsx`/`error.tsx`/`not-found.tsx`, per-route metadata, formatting utils.
|
||||
- **RoleGuard + role hydration** (refinement phase 2): `RoleGuard` wraps all four shells with
|
||||
resolved-vs-pending `/me` hydration, error recovery, and mismatch redirects. Chrome only here — never touch it.
|
||||
- **The per-actor shell split:** `CustomerLayout` / `NurseLayout` / `AdminLayout` / `PartnerLayout` mapped
|
||||
1:1 to route groups. Restyle and restructure the chrome *inside* this architecture; keep the split.
|
||||
- **`BottomBar`'s longest-prefix active matching** (`BottomBar.tsx:31-41`) — the one nav component that
|
||||
matches correctly today. Keep its semantics; generalize them.
|
||||
- **Performance-conscious composition:** `DarkModeToggleButton`/`DarkModeFormSwitch` are the only
|
||||
`useColorScheme` subscribers; `NotificationBell` isolates the polling unread count. Shells never re-render
|
||||
on theme flips or bell updates — preserve this.
|
||||
- **`AdminLayout`'s capability-gated nav** via `useAdminCapabilities()` (`AdminLayout.tsx:21-37`).
|
||||
|
||||
## 2. Required reading (do this first)
|
||||
|
||||
- [audit/shell-and-navigation.md](audit/shell-and-navigation.md) — the full 20-problem inventory with
|
||||
file/line evidence and the keep-list. This is your problem spec.
|
||||
- [audit/cross-cutting-ux.md](audit/cross-cutting-ux.md) — the chrome-adjacent items (English chrome
|
||||
strings, `UserInfo`, `hooks/layout.ts`, metadata) and its keep-list.
|
||||
- The `frontend-designer` skill (`.claude/skills/frontend-designer/SKILL.md`) — the design contract; phase 0
|
||||
will have updated it with the new tokens/icons.
|
||||
- Code, in this order: `client/src/layout/` (all files — you own this folder), `client/src/i18n/routing.ts`,
|
||||
`client/src/components/common/AppLink/`, `client/src/components/UserInfo/UserInfo.tsx` (you will delete
|
||||
it), `client/src/components/auth/RoleGuard.tsx` (do not touch — know why), `client/src/hooks/layout.ts`,
|
||||
`client/src/hooks/auth.ts` (`useActorRole`, `useAdminCapabilities`), `client/src/context/auth/types.ts`
|
||||
(`SessionUser.roles` — feeds the actor switcher), `client/src/constants/routes.ts`,
|
||||
`client/src/components/TrustBadge/`, `client/src/services/profiles/` + `client/src/services/auth/hooks/useMe.ts`
|
||||
(feed the identity card), `client/src/components/notifications/NotificationBell.tsx`.
|
||||
- `client/CLAUDE.md` — "Golden rules", "Direction (RTL/LTR)", the theme system, and the Project Structure
|
||||
layout section you must update at close.
|
||||
- next-intl v4 docs for `createNavigation` (routing-aware `Link`/`usePathname`/`useRouter`/`redirect`).
|
||||
|
||||
## 3. Scope — build this
|
||||
|
||||
### 3.1 Locale-aware navigation — one wrapper, two bugs fixed
|
||||
|
||||
Create **`src/i18n/navigation.ts`**: `createNavigation(routing)` from `next-intl/navigation`, exporting
|
||||
`Link`, `usePathname`, `useRouter`, `redirect`, `getPathname`. Then route **all chrome navigation** through it:
|
||||
|
||||
- `SideBarNavItem` / `SideBarNavList`: link via the new `Link`; compute active state against the new
|
||||
`usePathname()` (which strips the locale prefix, so unprefixed `ROUTES.*` compare directly). This makes the
|
||||
active highlight fire for the first time **and** removes the middleware redirect hop + locale-flip risk in
|
||||
one move.
|
||||
- Active matching must be **longest-prefix winner-takes-all** (the `BottomBar` semantics): extract a small
|
||||
shared helper (e.g. `src/layout/matchActivePath.ts`, unit-tested) used by both the sidebar and the bottom
|
||||
bars — plain `startsWith` would keep `/nurse` (dashboard) lit on every nurse route.
|
||||
- `BottomBar`: drop the manual `withLocale` prefixing in favor of the wrapper's router; keep its matching via
|
||||
the shared helper.
|
||||
- `AppLink`'s `activeClassName` comparison, `NotificationBell`'s `router.push`, and `CustomerLayout`'s inline
|
||||
`` `/${locale}${…}` `` all migrate to the wrapper. After this, `grep -r '/${locale}' src/` inside chrome
|
||||
code should return nothing.
|
||||
|
||||
### 3.2 Customer shell — contextual header + deliberate desktop
|
||||
|
||||
Rework `CustomerLayout`:
|
||||
|
||||
- **Contextual header.** On the 5 root tabs (`/`, `/bookings`, `/patients`, `/wallet`, `/profile` — the
|
||||
`(customer)` group has no URL segment): the phase-0 **brand lockup** (mark + wordmark). On pushed routes
|
||||
(nurse profile, booking detail, checkout, ticket thread…): **page title + back chevron** (the phase-0
|
||||
auto-mirrored icon) that calls `router.back()`. Drive it with a route→title map in `src/layout/`
|
||||
(longest-prefix over `ROUTES.*`, titles from the existing `nav`/`shell` namespaces) plus a lightweight
|
||||
per-page override slot (React context) for dynamic titles — the area phases (4–6, 9) will feed nurse/booking
|
||||
names into it later; ship static titles now. **Kill the static «اپلیکیشن خانواده» label**
|
||||
(`tShell('customer_app')` today).
|
||||
- Keep the support entry, `NotificationBell`, and dark toggle in the header (badge/popover upgrades belong to
|
||||
phase 10 — leave slots, don't build them).
|
||||
- **BottomBar:** add `paddingBottom: 'env(safe-area-inset-bottom)'` on the Paper (the home-indicator overlap
|
||||
is on the primary mobile nav); refine the active state on top of the phase-0 BottomNavigation override
|
||||
(selected color + label weight — tokens, not hexes).
|
||||
- **Desktop treatment — decide and implement deliberately.** Recommended: a constrained app frame — the
|
||||
content column keeps `CONTENT_MAX_WIDTH`, gains side gutters on a `background.default` canvas — and above
|
||||
the `md` breakpoint **hide the mobile tab bar** in favor of a top-nav variant (the same 5 items as inline
|
||||
header tabs). Implement with CSS breakpoints (`sx` `display` keys), not `useIsMobile` branching (see 3.6).
|
||||
|
||||
### 3.3 Nurse shell — a workspace, not a starter drawer
|
||||
|
||||
Rework `NurseLayout` (still on the shared engine, which you are also refitting in 3.6):
|
||||
|
||||
- **Grouped sidebar** with subheaders + dividers, replacing the flat 10-item array (`NurseLayout.tsx:19-33`):
|
||||
**امروز** (dashboard, requests, visits) · **حرفهٔ من** (services, coverage, verification) · **مالی**
|
||||
(earnings, bank) · **پشتیبانی** (support). Extend the nav-item model with a group key; the engine renders
|
||||
`ListSubheader`-style sections. Group labels are i18n keys in both catalogs.
|
||||
- **A real identity card:** new typed **`ProfileSummary`** shared component
|
||||
(`src/components/ProfileSummary/`, co-located test): avatar, display name, masked phone in Persian digits,
|
||||
role label, and `TrustBadge` when the actor is a nurse. Feed it from the `/me` session (`useMe` — phone,
|
||||
roles) plus the profiles domain for name/avatar where hydrated; render graceful skeleton/fallback states —
|
||||
never English literals. **DELETE `src/components/UserInfo/`** (the starter `user?: any` card) and every
|
||||
import/test of it.
|
||||
- **Mobile: a 5-tab nurse bottom nav** so field nurses stop digging through a drawer: امروز (dashboard) ·
|
||||
درخواستها · ویزیتها · درآمد · بیشتر — «بیشتر» opens the drawer with the remaining items (profile,
|
||||
services, coverage, bank, verification, support, sign-out). Reuse `BottomBar`.
|
||||
- **TopBar shows the current page title** via the same route→title engine as 3.2 (kill the static «نمای
|
||||
پرستار»).
|
||||
|
||||
### 3.4 Admin + partner shells — a dense console
|
||||
|
||||
- **Slim top bar:** current page title (route→title map) as a start-anchored breadcrumb-style label — not the
|
||||
centered static console name — plus a **bell** (widen `NotificationBell`'s `role` union to include
|
||||
`'admin'`; the `/admin/notifications` center already exists — note this minimal foundation extension in
|
||||
your report) and an **identity chip** (`ProfileSummary` compact variant or a chip: name/phone + the
|
||||
fine-grained role label off `roleCodes` — a `finance` admin should *see* they're finance).
|
||||
- **Sectioned sidebar** with the now-working active state: **اعتماد** (verification, reviews) · **مالی**
|
||||
(payouts; refunds are worked *via tickets* — do not invent a refunds nav item) · **پشتیبانی** (tickets,
|
||||
alerts) · **سیستم** (config, holidays, audit, roles, partners, users). Add the missing `/admin/users` entry
|
||||
(`ROUTES.ADMIN_USERS` exists; gate it like roles on `caps.canManageRoles` — display convenience, server is
|
||||
the authority). The notifications sidebar item is replaced by the header bell. **Keep every
|
||||
`useAdminCapabilities` gate exactly as is** — grouping must not change what a role sees.
|
||||
- **Partner shell:** same engine + its own 4-item nav; identity area shows the **center name** from
|
||||
`useMyPartnerCenter` (fallback skeleton while resolving — the page-level access-denied handling stays where
|
||||
it is).
|
||||
|
||||
### 3.5 Public shell — strip it to a brand frame
|
||||
|
||||
`PublicLayout` today wraps login in starter dashboard chrome: the hard-coded English `'Unauthorized -
|
||||
Balinyaar'` title (`PublicLayout.tsx:9`), a pencil button opening a drawer containing only a dark-mode
|
||||
switch, and an **empty** `BottomBar` strip on mobile (`PublicLayout.tsx:34`, `BOTTOM_BAR_ITEMS = []`).
|
||||
Replace it with a minimal centered brand shell: the phase-0 logo, a locale switcher, and the dark toggle — no
|
||||
sidebar, no bottom bar, no `TopBarAndSideBarLayout`. Delete the dead `BOTTOM_BAR_DESKTOP_VISIBLE` flag from
|
||||
`layout/config.ts` with it. (The login screen itself — hero, trust presence — is **DEFERRED → phase 3**.)
|
||||
|
||||
### 3.6 Cross-cutting engine fixes (`TopBarAndSideBarLayout` + `SideBar` + `TopBar`)
|
||||
|
||||
- **Drawer close scoping:** move the close handler off the content `Stack` (`SideBar.tsx:52`) onto the nav
|
||||
links themselves — toggling dark mode or mis-tapping a divider must not close the drawer.
|
||||
- **Kill the desktop SSR flash:** stop deriving shell *structure* from `useIsMobile`
|
||||
(`SERVER_SIDE_MOBILE_FIRST` renders the mobile shell, then jumps 240px). Render responsively with CSS:
|
||||
breakpoint-keyed `sx` values (paddings, drawer variant/visibility via `display`) so the desktop first paint
|
||||
already includes the persistent sidebar. `hooks/layout.ts` stays for non-structural consumers; the shells
|
||||
stop depending on it for layout.
|
||||
- **Logical properties:** replace the physical `paddingLeft/Right` + `anchor?.includes('left')` logic
|
||||
(`TopBarAndSideBarLayout.tsx:53-60, 89-91`) with `paddingInlineStart` / start-anchored drawer semantics —
|
||||
RTL correctness by construction, not by the stylis double-flip coincidence.
|
||||
- **Chrome strings → both catalogs:** `'Open Sidebar'` (`TopBarAndSideBarLayout.tsx:71`), `'Logout Current
|
||||
User'` (`SideBar.tsx:76`); the `UserInfo` literals die with the component. Zero English chrome remains on `/fa`.
|
||||
- **TopBar:** fix the `whiteSpace: 'nowrap'` overflow risk (ellipsis + `minWidth: 0`); delete the starter
|
||||
comment residue (`TopBar.tsx:20`); title alignment becomes start-anchored for the console shells per 3.4.
|
||||
- **`layout/config.ts`:** delete the commented-out anchor alternates (lines 8-9) and dead flags; keep the
|
||||
constants authoritative — update them, never bypass them.
|
||||
|
||||
### 3.7 Session affordances — sign-out, actor switch, locale switch
|
||||
|
||||
- **Sign-out reachable in EVERY shell.** The customer shell currently has **none** — add a sign-out row to
|
||||
the profile-tab hub (`/profile`) now (the full hub redesign is **DEFERRED → phase 9**; one labeled row, not
|
||||
a redesign). Sidebar shells keep sign-out in the drawer footer — now labeled and translated.
|
||||
- **Actor switcher for dual-role sessions:** `SessionUser.roles` already lives in AuthContext. When a session
|
||||
holds both `customer` and `nurse`, show «نمای پرستار ⇄ اپلیکیشن خانواده» in the nurse sidebar and on the
|
||||
customer profile hub. Navigation only — `RoleGuard` and `resolveRoleDestination` stay the "which app"
|
||||
authority.
|
||||
- **Locale switcher (fa/en) in all shells** (sidebar footer / customer profile hub / public shell): switch
|
||||
locale **preserving the current path** via the 3.1 wrapper (`router.replace(pathname, { locale })`).
|
||||
- **Keep `DarkModeToggleButton`/`DarkModeFormSwitch` as the only `useColorScheme` subscribers** — the
|
||||
switchers must not add scheme subscriptions to the shells.
|
||||
|
||||
## 4. Mocks & seams in this phase
|
||||
|
||||
**None introduced.** This phase is chrome over data that already flows (`useMe`, profiles,
|
||||
`useMyPartnerCenter`, the notifications unread count) behind the existing `services/{domain}` seams — UI
|
||||
stays mock-tolerant regardless of each domain's mock flag. **REQ posture:** if a backend gap surfaces (the
|
||||
likely one: `/me` lacking a display name for `ProfileSummary`, forcing a second profile fetch per shell),
|
||||
append a REQ to
|
||||
[../../shared-working-context/frontend/requests/for-backend.md](../../shared-working-context/frontend/requests/for-backend.md)
|
||||
— REQ-001…038 are taken; number from **REQ-039**. Never edit `server/`.
|
||||
|
||||
## 5. Critical rules you must not get wrong
|
||||
|
||||
1. **RoleGuard and role/redirect logic untouched.** Refinement phase 2 built resolved-vs-pending hydration;
|
||||
this phase is chrome, not security or routing policy. The actor switcher navigates; it never re-derives roles.
|
||||
2. **`useAdminCapabilities` gating stays exactly as is** — sectioning the admin nav must not add, remove, or
|
||||
loosen a single capability gate.
|
||||
3. **Do not regress the keep-lists** ([audit](audit/shell-and-navigation.md)): the root `[locale]` layout
|
||||
(lang/dir, conditional Mikhak, cookie-seeded scheme, RTL Emotion cache) is untouchable; the per-actor
|
||||
shell split stays; the customer 5-tab IA (Home/Bookings/Patients/Wallet/Profile) stays; longest-prefix
|
||||
active matching stays; `DarkModeButton` remains the sole `useColorScheme` subscriber; `NotificationBell`
|
||||
keeps isolating the poll; `CONTENT_MAX_WIDTH` reading column stays for text-heavy views;
|
||||
`ErrorBoundary` keeps wrapping every shell's main content.
|
||||
4. **Design contract non-negotiables:** every new string in **both** `en.json`/`fa.json` (fa is the product's
|
||||
voice — write it first); tokens/palette keys, never hexes; logical/RTL-safe props only (this phase exists
|
||||
partly to *remove* physical ones — do not add new ones); verify dark mode on every surface you touch;
|
||||
MUI v9 API only (no `useFlexGap`/`flexWrap` as Stack props); new shared components (`ProfileSummary`, the
|
||||
active-path helper, any header context) get co-located tests.
|
||||
5. **Fetch/cookies/provider rules untouched:** no raw `fetch`, no `document.cookie`, no layout above
|
||||
`[locale]`, no `createTheme()` in components. `ProfileSummary` consumes existing hooks — it does not add
|
||||
API calls of its own design.
|
||||
6. **Deleting `UserInfo` is a removal, not a rename** — check `src/**/*.test.{ts,tsx}` and the
|
||||
`@/components` barrel for imports, and update the frontend-designer skill's component table (it lists
|
||||
`UserInfo`) to point at `ProfileSummary`.
|
||||
|
||||
## 6. Definition of Done
|
||||
|
||||
On top of the shared [definition-of-done.md](../../phases/_shared/definition-of-done.md):
|
||||
|
||||
- [ ] `npm run check` green; `npm run test:ci` green (new tests for `ProfileSummary`, the active-path
|
||||
helper, and any touched shared component); `en.json`/`fa.json` in sync.
|
||||
- [ ] `src/i18n/navigation.ts` exists and **all** chrome navigation flows through it — no raw `next/link`
|
||||
and no manual `/${locale}` prefixing left in `src/layout/` or chrome components.
|
||||
- [ ] The sidebar highlights the active item on every nurse/admin/partner route (first time ever), and
|
||||
clicking a sidebar link produces **one** navigation in the Network tab — no 307 middleware hop, no
|
||||
locale flip on `/en`.
|
||||
- [ ] Customer shell: brand lockup on the 5 root tabs; title + mirrored back chevron on pushed routes;
|
||||
safe-area padding on the bottom bar; on ≥`md` the mobile tab bar is hidden in favor of the desktop
|
||||
treatment.
|
||||
- [ ] Nurse shell: grouped sidebar (امروز/حرفهٔ من/مالی/پشتیبانی), `ProfileSummary` identity card with
|
||||
TrustBadge, 5-tab mobile bottom nav; `UserInfo` deleted repo-wide.
|
||||
- [ ] Admin/partner shells: sectioned capability-gated sidebar, page-title top bar, bell + identity chip
|
||||
(admin), center-name identity (partner).
|
||||
- [ ] Public shell: no English title, no pencil, no empty drawer or bottom strip — logo + locale switcher +
|
||||
dark toggle only.
|
||||
- [ ] Desktop first paint of a sidebar shell includes the persistent sidebar — no 240px post-hydration jump
|
||||
(verify with a hard reload, network throttled).
|
||||
- [ ] Sign-out is reachable in all four shells; a dual-role session sees the actor switcher; every shell has
|
||||
a locale switcher that preserves the current path.
|
||||
- [ ] Visual verification on the four axes — `/fa` + `/en` × light + dark — and mobile + desktop for every
|
||||
shell (fa first).
|
||||
|
||||
## 7. How to test (what a human can verify after this phase)
|
||||
|
||||
1. Log in as the seeded nurse → `/nurse`. The sidebar shows four labeled groups and your name/phone/TrustBadge
|
||||
— not "Current User". Click «ویزیتها»: the item highlights, the top bar reads the page title, and the
|
||||
Network tab shows a single navigation (no 307).
|
||||
2. Resize to mobile (or open devtools device mode): the nurse shell shows a 5-tab bottom nav; tab «بیشتر»
|
||||
opens the drawer; toggling dark mode inside the drawer does **not** close it; tapping a nav link does.
|
||||
3. As a customer on `/`: the header shows the brand lockup. Open a nurse profile from search → the header
|
||||
flips to title + back chevron; the chevron returns to results. On `/en` the chevron mirrors correctly.
|
||||
4. On desktop ≥900px as a customer: no mobile tab bar pinned to the bottom; the desktop nav variant is
|
||||
present; content sits in the framed column.
|
||||
5. Go to `/profile` as a customer: a sign-out row exists and works. With a dual customer+nurse session, the
|
||||
actor switcher appears here and in the nurse sidebar, and lands on the other shell (RoleGuard permitting).
|
||||
6. Log in as the seeded admin: top bar shows the page title, the bell, and your role chip (e.g. «مالی» for a
|
||||
finance admin); the sidebar is sectioned and still shows only capability-permitted consoles. As the
|
||||
finance-only admin, confirm no new items appeared.
|
||||
7. Open `/login` logged-out on `/fa`: no English anywhere, no drawer, no bottom strip — brand mark, locale
|
||||
switcher, dark toggle.
|
||||
8. Hard-reload `/nurse` on desktop: the sidebar is present at first paint; no sideways content jump.
|
||||
9. Switch locale from any shell's switcher on a deep route (e.g. `/fa/nurse/earnings`): you land on
|
||||
`/en/nurse/earnings`, same page.
|
||||
|
||||
## 8. Hand off & document (close the phase)
|
||||
|
||||
- Update **`client/CLAUDE.md` → Project Structure**: the `layout/` section (new shell composition,
|
||||
route→title map, removed starter engine parts), `i18n/navigation.ts`, `components/ProfileSummary/`, and
|
||||
the `UserInfo` deletion. Update the frontend-designer skill's §4 component table (`UserInfo` →
|
||||
`ProfileSummary`) and §5 layout description if shell variants changed.
|
||||
- Write the report at `dev/shared-working-context/reports/ui-phase-2-report.md`: what changed per shell, the
|
||||
navigation-wrapper migration list, the desktop-treatment decision you made, any foundation files you
|
||||
extended minimally (e.g. `NotificationBell` role union), and screenshots/notes from the four-axes check.
|
||||
- List any REQs filed (REQ-039+) with one-line rationales; "none" is an acceptable outcome.
|
||||
- Save a memory note per operating-rules §8: the shells are now the branded per-actor chrome, chrome
|
||||
navigation is `createNavigation`-based (active state + no redirect hop), `UserInfo` is gone, and
|
||||
phases 3–11 must route new chrome strings/titles through the route→title map rather than static labels.
|
||||
Reference in New Issue
Block a user