b8934f531d
Three domain services (mirroring the patients/nurse template): services/geography (cached province→city→district lookups; Infinity staleTime + shared geographyKeys), services/addresses (address book CRUD + set-primary; single-primary invariant), and services/serviceAreas (coverage add/remove; areaExists dup-guard, districtId=null = whole city). Four tested composites in src/components/geography: CascadingRegionSelect (drives the cascade queries), AddressMapPicker (map-pin stand-in emitting real lat/lng), AddressForm, AddressCard. Screens: customer address book (/addresses, reached from the profile hub) and nurse coverage editor (/nurse/coverage, new sidebar tab, inline duplicate block + 409). Adds geo/address/coverage i18n namespaces (both locales), location/delete/coverage icons, ADDRESSES/NURSE_COVERAGE routes. Consumes the b4 geography-addresses contract; filed REQ-008 (accept the map pin on create/update) and REQ-009 (provinceId on CustomerAddressDto) for gaps. Gate: npm run check + npm run test:ci (129, +17) + npm run build all green. A 5-dimension adversarial review fixed 3 findings (map-marker RTL transform, page_size→pageSize pagination casing, coverage districts-scope dead-end on district-less cities). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.6 KiB
8.6 KiB
Frontend status log (append-only)
One block per completed frontend phase. Newest at the top. Frontend lane writes here; backend reads for awareness.
frontend-phase-3-b4 — Addresses, map picker & nurse coverage areas — 2026-07-03
- Shipped: three domain services —
services/geography(cached province→city→district reference lookups; InfinitystaleTime+ sharedgeographyKeys;useProvinces/useCities/useDistricts; seam+mock+client),services/addresses(address book CRUD + set-primary; single-primary invariant; every mutation invalidates the list;useAddresses/useCreateAddress/useUpdateAddress/useDeleteAddress/useSetPrimaryAddress),services/serviceAreas(coverage add/remove;areaExistsdup-guard;useServiceAreas/useAddServiceArea/useRemoveServiceArea). Shared composites (src/components/geography/, each tested):CascadingRegionSelect(drives the cached cascade),AddressMapPicker(map-pin stand-in emitting real lat/lng),AddressForm,AddressCard. Screens: customer address book (/addresses, reached from a profile-hub link — cascade + map pin dialog, set-primary, delete, empty/skeleton), nurse coverage editor (/nurse/coverage, new sidebar tab — chips, whole-city/specific-district scope toggle, inline duplicate block + 409, "won't appear in search" empty warning). Addedgeo/address/coveragei18n namespaces +nav.coverage(both locales);location/delete/coverageicons; routesADDRESSES/NURSE_COVERAGE. - Consumes: dev/contracts/domains/geography-addresses.md (backend-phase-4). Routes
api/v1/geo/{provinces, cities,districts},api/v1/customer_addresses/{list,create,update,set_primary,delete},api/v1/ nurse_service_areas/{list,add,remove}. Wire camelCase; geo query params snake_case; 409 on duplicate coverage. - Mocked client-side:
services/geography(USE_GEOGRAPHY_MOCK),services/addresses(USE_ADDRESSES_MOCK),services/serviceAreas(USE_SERVICE_AREAS_MOCK) — all defaulttrue; real clients wired for a one-line flip. TheAddressMapPickeris a stand-in (no real map tiles). See mocks-registry + the report. - Reviewed: 5-dimension adversarial review → 3 findings fixed (map marker RTL transform;
page_size→pageSizepagination casing on the real list calls; coverage "districts" dead-end on a district-less city). - Gate: npm run check green · npm run test:ci green (129 tests, +17 across 5 suites) · npm run build green with NEXT_PUBLIC_API_URL set (routes /addresses, /nurse/coverage generated).
- Requests filed: frontend/requests/for-backend.md — yes (REQ-008 accept the map pin on address create/update,
REQ-009
provinceIdonCustomerAddressDtofor edit prefill).
frontend-phase-2-b3 — Onboarding & profiles (customer, patient, nurse, bank) — 2026-07-02
- Shipped: three domain services —
services/patients(rewritten to the b3PatientDto+ client-augmentedrelation/conditions; full CRUD seam + mock + real client;usePatients/useCreatePatient/useUpdatePatient/useArchivePatientwith optimistic soft-archive),services/profiles(customer + nurse profile get/upsert + avatar;useCustomerProfile/useUpsertCustomerProfile/useNurseProfile/useUpsertNurseProfile/useUploadAvatar),services/nurse(bank accounts;useNurseBankAccountswith pending-onlyrefetchInterval,useAddNurseBankAccount,useSetPrimaryBankAccount;iban.tsSheba validate/normalize/bank-name). Screens: A3→A4 onboarding wizard ((customer)/onboarding), E1 patients list/CRUD (add/edit dialog reusing the A4 form, soft-archive confirm, empty + skeleton states), A5 Home (first-login redirect into onboarding when 0 patients + "complete patient record" nudge), customer profile (name + preferred language + emergency contact, no national-ID), nurse profile bootstrap (avatar + bio + years, unverified "not bookable" placeholder → verification), nurse bank settings (IBAN form + the three ownership states pending/verified/mismatch). Shared compositesGenderToggle/ConditionChips/RelationSelect/PatientForm/PatientCard/BankStatusPanel(each tested); reused the f0StepperHeader/StatusChip/PhoneNumberField. Addedonboarding/home/profile/nurseProfile/banki18n namespaces +patientsextensions (both locales);--bal-primary-softtoken (both schemes); nurse sidebar gains Profile + Bank. - Consumes: dev/contracts/domains/identity-profiles.md (backend-phase-3). Routes
api/v1/{customer_profiles, nurse_profiles}/{me,upsert},api/v1/patients/{list,get,create,update,archive},api/v1/nurse_bank_accounts/ {list,add,set_primary,verify_ownership}. - Mocked client-side:
services/patients(USE_PATIENTS_MOCK),services/profiles(USE_PROFILES_MOCK),services/nurse(USE_NURSE_BANK_MOCK) — all defaulttrue; real clients wired for a one-line flip. See mocks-registry + the report for exactly what/why (relation/conditions, avatar, customer name/language gaps). - Gate: npm run check green · npm run test:ci green (112 tests, +17) · npm run build green with NEXT_PUBLIC_API_URL set (routes /onboarding, /nurse/profile, /nurse/bank generated).
- Requests filed: frontend/requests/for-backend.md — yes (REQ-005 patient relation/conditions, REQ-006 avatar upload route, REQ-007 customer name/preferred-language).
frontend-phase-1-b2 — Auth: phone-OTP login & role routing — 2026-07-02
- Shipped:
services/authrewritten for phone-OTP (types/keys/apis[client+mock+seam]/hooks:useRequestOtp/useVerifyOtp/useMe/useRefresh/useLogout/useSelectRole/useSessionRoleSync) — the username/password stub is gone; A1/A2 customer login + B1/B2 nurse switch (one OTP flow parameterised by intended role) at/login; the role router (RoleRouter+ pureresolveRoleDestination) → customer→family, nurse→nurse app, no-role→/select-role, admin→admin console (splash while/meloads, no wrong-shell flash);SelectRolescreen at/select-role; silent token refresh in the fetch layer (single-flightattemptTokenRefresh, one retry on 401); widenedAuthState(roles viaSessionUser, hydrated from/mebyuseSessionRoleSyncin the private layout);authi18n namespace +common.brand*in both locales. - Consumes: dev/contracts/domains/identity-auth.md + openapi/swagger.v1.json (backend-phase-2). Wire is
camelCase; routes
api/v1/auth/{request_otp,verify_otp,refresh,logout},api/v1/me,api/v1/me/select_role. - Mocked client-side:
services/authviaauthMockApibehindUSE_AUTH_MOCK(default false — b2 is live; flip true for offline dev, dev code123456). See mocks-registry. - Gate: npm run check green · npm run test:ci green (95 tests, +23) · npm run build green with
NEXT_PUBLIC_API_URL set. Fixed the jest
@/→srcalias (was<rootDir>/$1). - Requests filed: frontend/requests/for-backend.md — yes (REQ-002 OTP length/expiry, REQ-003 verify
error codes + lockout retry-after, REQ-004 multi-role
activeRole?).
frontend-phase-0 — Foundations: app shells, design system & data/contract patterns — 2026-07-02
- Shipped: 3 actor shells (customer bottom-nav / nurse / admin sidebar) + role-aware routing under
(private-routes);useActorRole; theservices/{domain}reference (patients, mocked behind a seam) with deliberate Query caching + invalidation;lib/api/types.ts(envelope/pagination); money + Shamsi-date utils; shared compositesOtpInput/PhoneNumberField/StepperHeader/StatusChip/PlaceholderScreen(each tested); i18nnav/common/shell/patientsin both locales. Removed the demo scaffolding; fixed theBottomBarpathname bug. - Consumes: dev/contracts/conventions/* + openapi/swagger.v1.json (b0 = ping only). No feature contract consumed yet.
- Mocked client-side:
services/patientsviapatientsMockApi(USE_PATIENTS_MOCK=true) — template for f1+. Swap is one line once real endpoints land. - Gate: npm run check green · npm run test:ci green (72 tests) · npm run build green with NEXT_PUBLIC_API_URL set.
- Requests filed: frontend/requests/for-backend.md — yes (REQ-001).