167 lines
11 KiB
Markdown
167 lines
11 KiB
Markdown
# Frontend Phase 0 — Foundations: app shells, design system & the data/contract patterns
|
||
|
||
> **Mission:** turn the inherited starter into a clean Balinyaar foundation for the three actor
|
||
> experiences (family/customer, nurse, admin). Remove the demo leftovers, build the **app shells** and
|
||
> route groups each actor needs, and lock in the **patterns** every later frontend phase will follow:
|
||
> how a `services/{domain}` talks to the API, how TanStack Query caches it, how types come from the
|
||
> published contract, and where shareable components live. No real feature data yet (no backend
|
||
> dependency) — this phase makes f1–f15 fast, consistent, and re-render-cheap.
|
||
>
|
||
> **Track:** frontend · **Depends on:** nothing (`frontend-phase-0`, no backend phase required) ·
|
||
> **Unlocks:** every frontend phase
|
||
> **Before you start, read [`../_shared/agent-operating-rules.md`](../_shared/agent-operating-rules.md).** It is not optional.
|
||
|
||
---
|
||
|
||
## 1. Context — where this sits
|
||
|
||
The client (`client/`, **Next.js 16 App Router + React 19 + MUI v9 + next-intl**, `fa` default & RTL)
|
||
already ships a full app shell and an `App*` component library — you **keep and build on** these and
|
||
**remove** the demo bits.
|
||
|
||
**What already exists (do not rebuild) — confirmed in the codebase:**
|
||
- Root layout `src/app/[locale]/layout.tsx` (renders `<html lang dir>`, providers: NextIntl → Auth →
|
||
Theme → Query → Notistack), `(private-routes)`/`(public-routes)` groups, the `TopBarAndSideBarLayout`
|
||
engine + `TopBar`/`SideBar`/`BottomBar`.
|
||
- Theme system (brand tokens **teal `#1d4a40`**, **terracotta `#d98c6a`**, cream in `theme/colors.ts` +
|
||
`tokens.css`; `APP_THEME_LTR/RTL`, dark mode), i18n (`routing.ts`, `request.ts`), the cookie manager,
|
||
`clientFetch`/`serverFetch` + `ApiError`, TanStack Query (`makeQueryClient`/`QueryProvider`), the toast
|
||
bridge, `AuthContext`, the middleware auth gate.
|
||
- The `App*` library: `AppButton`, `AppIconButton`, `AppAlert`, `AppIcon`, `AppImage`, `AppLink`,
|
||
`AppLoading` (+ `ErrorBoundary`, `UserInfo`); the `auth` service (`useLogin`/`useLogout`/`useCurrentUser`).
|
||
|
||
**What is demo scaffolding you will remove in this phase:**
|
||
- The `toastDemo` i18n namespace (both `en.json`/`fa.json`) and the placeholder `HomePage`
|
||
(`<Typography>Balin yaar</Typography>` with its unused `t`).
|
||
- The unregistered dead icons `AppIcon/icons/CurrencyIcon.tsx` and `YellowPlanIcon.tsx`.
|
||
- Fix the small drift noted in the audit: `AppLoading` missing from the `@/components` barrel export;
|
||
`BottomBar` reading global `location` instead of `usePathname`.
|
||
|
||
> **Auth note:** login is currently **username/password**. It becomes **phone-OTP** in **f1-b2** — don't
|
||
> wire login screens here; this phase only prepares the shells and patterns.
|
||
|
||
## 2. Required reading (do this first)
|
||
|
||
- [`../_shared/agent-operating-rules.md`](../_shared/agent-operating-rules.md) and
|
||
[`../_shared/frontend-conventions-checklist.md`](../_shared/frontend-conventions-checklist.md).
|
||
- [`client/CLAUDE.md`](../../../client/CLAUDE.md) in full — the engineering contract (RSC boundary,
|
||
layouts, i18n, theme, cookies, fetch services, anti-patterns). Note the doc/code drift the audit found
|
||
(e.g. a `ColorSchemeScript` is referenced but doesn't exist) — trust the code, and fix the doc if you
|
||
touch that area.
|
||
- **Invoke the `frontend-designer` skill** — it is the design/brand contract (palette, tokens,
|
||
typography, the `App*` library, layout shells, the hard UI rules). All visual work goes through it.
|
||
- [`product/wireframes/index.html`](../../../product/wireframes/index.html) — the visual baseline:
|
||
mobile-first RTL app, deep-green brand, the **5-tab bottom nav** for the customer app
|
||
(خانه/Home · رزروها/Bookings · بیماران/Patients · کیفپول/Wallet · پروفایل/Profile), and the nurse-only
|
||
screens. This phase builds the *shells* those screens will live in.
|
||
- [`../../contracts/README.md`](../../contracts/README.md) +
|
||
[`conventions/api-conventions.md`](../../contracts/conventions/api-conventions.md) +
|
||
[`money-and-types.md`](../../contracts/conventions/money-and-types.md) — how you'll type and format
|
||
server data (envelope, IRR-as-string + Toman display, enums-as-codes, UTC + Shamsi display).
|
||
- The existing `src/services/auth/*` — the exact pattern (`types.ts`/`keys.ts`/`apis/clientApi.ts`/
|
||
`hooks/use*.ts`/`index.ts`) every new domain service copies.
|
||
|
||
## 3. Scope — build this
|
||
|
||
### 3.1 Clean up the demo scaffolding
|
||
Remove the `toastDemo` namespace, the placeholder home page content, the two dead icons; fix the
|
||
`AppLoading` barrel export and the `BottomBar` `usePathname` bug. Keep everything else. `npm run check`
|
||
stays green throughout.
|
||
|
||
### 3.2 The three actor app shells + routing
|
||
Balinyaar has three audiences with different chrome. Establish them now (empty/placeholder content is
|
||
fine — they fill up in later phases):
|
||
- **Customer (family) app** — mobile-first shell with the **bottom tab nav** (Home/Bookings/Patients/
|
||
Wallet/Profile) per the wireframe; this is the primary experience.
|
||
- **Nurse app** — its own shell (the wireframe's "نمای پرستار" screens: verification, dashboard, EVV).
|
||
- **Admin/backoffice** — a desktop-oriented shell (sidebar nav) for the ops console (f15).
|
||
|
||
Decide the routing that expresses these cleanly within the existing `[locale]` + route-group structure
|
||
(e.g. role-scoped route groups/segments under `(private-routes)`), **without** adding any layout above
|
||
`[locale]` and **without** breaking the server/client boundary. Drive nav by role from `AuthContext`
|
||
(roles arrive in f1-b2 — design the shell to read a role and render the right chrome; default gracefully
|
||
until roles exist). Build a **shared bottom-nav** and **shared sidebar-nav** component at the right level
|
||
in `src/layout/` / `src/components/`. Update the **Project Structure** tree in `client/CLAUDE.md` for any
|
||
new route group/folder.
|
||
|
||
### 3.3 The `services/{domain}` + Query caching pattern (the reference implementation)
|
||
Codify the data pattern every later phase copies, using the `auth` service as the template and the
|
||
checklist's caching rules:
|
||
- A `keys.ts` query-key factory per domain; deliberate `staleTime`/`gcTime`; **mutations invalidate or
|
||
`setQueryData`** so data already in cache is never needlessly refetched.
|
||
- `apis/clientApi.ts` (+ `serverApi.ts` only when an RSC needs it) wrapping `clientFetch`/`serverFetch`;
|
||
**one hook per file**.
|
||
- A documented way to derive `types.ts` from the published contract (`dev/contracts/`) — and, when a
|
||
backend phase isn't ready, a **mock `clientApi`** behind the same seam plus a row in your report (so
|
||
it's swapped cleanly once the real endpoint lands). Provide a tiny example domain (or thoroughly
|
||
document the `auth` one) so f1 starts by copying, not inventing.
|
||
- A small **money/format util** (`formatIrrToToman`, integer-safe parse of IRR strings, Shamsi date
|
||
display) in `src/utils/` per the money-and-types contract — used wherever prices/dates render.
|
||
|
||
### 3.4 Shared composite components (built once, reused everywhere)
|
||
Build the cross-cutting composite components the wireframe implies, at the shared level (`src/components/…`),
|
||
each with a co-located `*.test.tsx`, each composed from MUI/`App*` primitives (never re-implementing a
|
||
root primitive): an **OTP code input**, a **phone-number field** (Iranian format, RTL-safe), a **stepper/
|
||
progress header** (used by onboarding + verification), a **status chip** (verified/pending/…); a
|
||
**nurse/result card** and a **price-breakdown** can be stubbed here or deferred to their phases — your
|
||
call, but if you build them, build them shared. Keep page-only composition in pages.
|
||
|
||
### 3.5 i18n namespaces baseline
|
||
Establish the namespace conventions for the feature areas to come (e.g. `auth`, `onboarding`,
|
||
`verification`, `search`, `booking`, `payment`, `bnpl`, `reviews`, `notifications`, `admin`, `common`,
|
||
`nav`) — seed `common`/`nav` with the shell strings you add, in **both** `en.json` and `fa.json`, in
|
||
sync. RTL-first.
|
||
|
||
## 4. Mocks & seams in this phase
|
||
|
||
No backend dependency. Where you demonstrate the data pattern without a live endpoint, use a **mock
|
||
`clientApi`** behind the `services/{domain}` seam and note it in your report — this is the template f1+
|
||
follow until their backend phase is merged.
|
||
|
||
## 5. Critical rules you must not get wrong
|
||
|
||
- **Never add a layout above `[locale]`** and never break the RSC/client boundary (the audit shows the
|
||
current setup is load-bearing — see `client/CLAUDE.md`).
|
||
- **Design RTL-first**, `fa` default; every string in both locale files.
|
||
- **Colours from tokens**, MUI v9 API only, pre-built themes only.
|
||
- **Caching is a feature:** set `queryKey`/`staleTime` deliberately and invalidate on mutation — the
|
||
whole point of this phase is that later phases don't over-fetch or over-render.
|
||
- **MUI primitives stay MUI;** shareable composites live shared, not in a page.
|
||
- Keep `npm run check` green and translations in sync at every step.
|
||
|
||
## 6. Definition of Done
|
||
|
||
The shared [definition-of-done.md](../_shared/definition-of-done.md), plus:
|
||
- [ ] Demo scaffolding removed; the two barrel/`BottomBar` bugs fixed; `npm run check` green;
|
||
`npm run test:ci` green for the shared components you add.
|
||
- [ ] The three actor shells exist and render with role-aware nav (degrading gracefully before roles
|
||
exist); no layout added above `[locale]`.
|
||
- [ ] The `services/{domain}` + Query caching pattern is implemented and documented as the reference;
|
||
the money/format util exists.
|
||
- [ ] The shared composite components added each have a co-located test.
|
||
- [ ] `client/CLAUDE.md` *Project Structure* updated for new route groups/folders; any doc drift you
|
||
touched is corrected.
|
||
|
||
## 7. How to test (what a human can verify after this phase)
|
||
|
||
- `npm run dev` → the app boots; visiting the customer area shows the mobile shell with the 5-tab bottom
|
||
nav; the nurse and admin areas show their shells; switching locale flips `dir`/strings correctly; dark
|
||
mode still works.
|
||
- `npm run check` and `npm run test:ci` pass; the new shared components render and their interactions
|
||
fire callbacks in tests.
|
||
- The reference `services/{domain}` (or the documented `auth` one) shows a query caching + a mutation
|
||
invalidating it in React Query Devtools.
|
||
|
||
## 8. Hand off & document (close the phase)
|
||
|
||
- **Docs:** update `client/CLAUDE.md` *Project Structure* (route groups, new shared components, the
|
||
services pattern note); fix any drift you touched.
|
||
- **Contracts:** none produced (frontend consumes). If the b0 swagger snapshot exists, wire the
|
||
types-from-contract step against it; otherwise document the intended step. File any envelope/format
|
||
question in `shared-working-context/frontend/requests/for-backend.md`.
|
||
- **Handoff & report:** append to `shared-working-context/frontend/STATUS.md`; write
|
||
`reports/frontend-phase-0-report.md` (shells built, the reference data pattern, which composites are
|
||
shared, what's mocked client-side and how f1 swaps it).
|
||
- **Memory:** save a `project` memory note for the actor-shell/routing decision and the data pattern,
|
||
with a `MEMORY.md` pointer.
|