frontend phase 2: onboarding & profiles — customer/patient, nurse profile & bank
Turns a logged-in user into a usable account, consuming the b3 identity-profiles
contract behind the services/{domain} seam.
Services (mock default true; real HTTP clients wired for a one-line flip):
- services/patients: rewritten to b3 PatientDto + client-augmented relation/conditions;
full CRUD, optimistic soft-archive, cache-splice on create, age<->birthDate helper.
- services/profiles: customer + nurse profile get/upsert + avatar (404->null mapping).
- services/nurse: payout bank accounts + IBAN(Sheba) util + pending-only polling.
Screens: A3->A4 onboarding wizard, E1 patients list/CRUD, A5 home (first-login gate +
nudge), customer profile (no national-ID), nurse profile bootstrap (unverified
placeholder), nurse bank settings (pending/verified/mismatch + make-primary).
Shared composites (each tested): GenderToggle, ConditionChips, RelationSelect,
PatientForm, PatientCard, BankStatusPanel; reuses f0 StepperHeader/StatusChip/PhoneField.
Adds onboarding/home/profile/nurseProfile/bank i18n namespaces (both locales, in sync),
the --bal-primary-soft token, and nurse sidebar Profile + Bank entries.
Contract gaps filed: REQ-005 (patient relation/conditions), REQ-006 (avatar route),
REQ-007 (customer name/language). Gate: check + 112 tests + build all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+21
-5
@@ -118,14 +118,17 @@ client/
|
||||
│ │ ├── select-role/page.tsx # /select-role — first-use role picker (no public role yet); role router lands here
|
||||
│ │ ├── (customer)/ # Customer (family) app — mobile-first, bottom-tab nav; no URL segment
|
||||
│ │ │ ├── layout.tsx # 'use client' — wraps CustomerLayout
|
||||
│ │ │ ├── page.tsx # / (home)
|
||||
│ │ │ ├── page.tsx # / (A5 home — 'use client'; first-login onboarding gate + record/profile nudges)
|
||||
│ │ │ ├── onboarding/page.tsx # /onboarding — A3→A4 wizard (relation → first patient)
|
||||
│ │ │ ├── bookings/page.tsx # /bookings
|
||||
│ │ │ ├── patients/page.tsx # /patients — reference services/{domain} + Query screen
|
||||
│ │ │ ├── patients/page.tsx # /patients — E1 list/CRUD (add/edit dialog reusing PatientForm, soft-archive)
|
||||
│ │ │ ├── wallet/page.tsx # /wallet
|
||||
│ │ │ └── profile/page.tsx # /profile
|
||||
│ │ │ └── profile/page.tsx # /profile — customer profile + emergency contact (no national-ID)
|
||||
│ │ ├── nurse/ # Nurse app (/nurse/…) — sidebar shell
|
||||
│ │ │ ├── layout.tsx # 'use client' — wraps NurseLayout
|
||||
│ │ │ ├── page.tsx # /nurse (dashboard)
|
||||
│ │ │ ├── profile/page.tsx # /nurse/profile — B7 profile bootstrap (avatar+bio+years; unverified placeholder)
|
||||
│ │ │ ├── bank/page.tsx # /nurse/bank — payout IBAN + ownership states (pending/verified/mismatch)
|
||||
│ │ │ ├── verification/page.tsx # /nurse/verification
|
||||
│ │ │ └── visits/page.tsx # /nurse/visits (EVV)
|
||||
│ │ └── admin/ # Admin/backoffice (/admin/…) — desktop sidebar shell
|
||||
@@ -142,6 +145,12 @@ client/
|
||||
│ ├── PhoneNumberField/ # Iranian mobile field (digit-normalizing, LTR-in-RTL, maskIranMobile)
|
||||
│ ├── StepperHeader/ # Progress header for onboarding/verification flows
|
||||
│ ├── StatusChip/ # Semantic status chip (verified/pending/rejected/…) off --bal-* tokens
|
||||
│ ├── GenderToggle/ # Required male/female toggle (never defaulted) — drives same-gender matching
|
||||
│ ├── ConditionChips/ # Multi-select patient-condition chips (stable codes, translated labels)
|
||||
│ ├── RelationSelect/ # Single-select relation radio cards (parent/spouse/child/self)
|
||||
│ ├── PatientForm/ # A4 patient form (name/age/gender/conditions/relation) — reused create+edit
|
||||
│ ├── PatientCard/ # E1 patient summary card + edit/archive actions
|
||||
│ ├── BankStatusPanel/ # Nurse bank-account ownership state (pending/verified/mismatch), masked IBAN
|
||||
│ └── auth/ # Auth-flow composites: LoginFlow, PhoneStep, OtpStep, RoleRouter, SelectRole, AuthCard, BrandMark, AuthSplash, useCountdown
|
||||
├── i18n/
|
||||
│ ├── routing.ts # defineRouting — locales: ['en', 'fa'], defaultLocale: 'fa'
|
||||
@@ -183,7 +192,9 @@ client/
|
||||
│ └── index.ts # Re-exports constants ONLY (never server/client)
|
||||
├── services/ # Domain services — no top-level barrel; import directly from the file
|
||||
│ ├── auth/ # Phone-OTP auth: requestOtp/verifyOtp/refresh/logout/me/selectRole + role router (routing.ts) + useSessionRoleSync
|
||||
│ ├── patients/ # Reference domain for the mock-behind-a-seam pattern (§ services pattern)
|
||||
│ ├── patients/ # Care-recipient CRUD (b3 PatientDto + client-augmented relation/conditions), soft-archive; age.ts helper
|
||||
│ ├── profiles/ # Customer + nurse profile get/upsert + avatar (behind the ProfilesApi seam)
|
||||
│ ├── nurse/ # Nurse payout bank accounts + IBAN(Sheba) util (iban.ts) + ownership-inquiry states
|
||||
│ └── {domain}/
|
||||
│ ├── types.ts # Request/response types + the domain's Api interface (the seam)
|
||||
│ ├── keys.ts # React Query key factory (hierarchical)
|
||||
@@ -265,7 +276,12 @@ async function MyServerComponent() {
|
||||
- `'nav'` — the actor shells (`CustomerLayout`/`NurseLayout`/`AdminLayout`) build their nav from here
|
||||
- `'common'` — `DarkModeButton.tsx` (dark/light labels), shared words (loading, retry, currency_toman, …)
|
||||
- `'shell'` — actor-shell titles + the not-yet-built placeholder body
|
||||
- `'patients'` — the reference services/{domain} demo screen
|
||||
- `'patients'` — the E1 patient list/CRUD (list, card, add/edit dialog, archive)
|
||||
- `'onboarding'` — the A3→A4 wizard + the shared enum labels (relation/condition/gender codes → labels)
|
||||
- `'home'` — the A5 family home (greeting + record/profile nudges)
|
||||
- `'profile'` — the customer profile + emergency contact
|
||||
- `'nurseProfile'` — the nurse B7 profile bootstrap (photo/bio/years + unverified placeholder)
|
||||
- `'bank'` — the nurse payout bank settings (IBAN form + the three ownership states)
|
||||
- `'auth'` — the phone-OTP login flow, role router, and SelectRole screen (`common.brand`/`brand_tagline` for the wordmark)
|
||||
|
||||
**Namespace conventions for the phases to come** (seed each when its feature lands, in both locale
|
||||
|
||||
Reference in New Issue
Block a user