frontend phase 3: geography — addresses, map-pin picker & nurse coverage areas
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>
This commit is contained in:
@@ -94,3 +94,29 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
|
||||
returns `roles` but no user `id` (only `/me` has it) — fine for now (context id is hydrated from `/me`),
|
||||
flagging in case that changes.
|
||||
- **Status:** open
|
||||
|
||||
## REQ-008 — Accept the client-picked map pin on address create/update — filed by frontend-phase-3-b4 — 2026-07-02
|
||||
- **Need:** Let `customer_addresses/create` and `customer_addresses/update/{id}` accept optional
|
||||
`latitude`/`longitude` (decimals) from the request body — the coordinates the user dropped with the map-pin
|
||||
picker — and persist those when provided, only falling back to the `IGeocoder` when the client sends none.
|
||||
- **Why:** The b4 contract's create body geocodes server-side from `addressLine`+city and does **not** accept
|
||||
client coordinates, but f3 requires the user to **drop a pin** on the map (a hard client-side validation) so
|
||||
the stored coordinate is the user's exact door location for the later EVV distance check (b9) — a geocoded
|
||||
street centroid is coarser. The client already sends `latitude`/`longitude` in the create/update body and
|
||||
echoes them locally; until the server accepts them, the real path silently ignores them and geocodes instead.
|
||||
- **Proposed shape:** create/update body gains `latitude?: number, longitude?: number`; when both present, store
|
||||
them (and mark the geocode source as "user-pin"); when absent, geocode as today. `CustomerAddressDto` already
|
||||
returns `latitude`/`longitude`.
|
||||
- **Status:** open
|
||||
|
||||
## REQ-009 — Add `provinceId` to `CustomerAddressDto` — filed by frontend-phase-3-b4 — 2026-07-02
|
||||
- **Need:** Add `provinceId` (long) to `CustomerAddressDto` (the province that owns the address's `cityId`).
|
||||
- **Why:** The address book's **edit** form prefills the cascading province → city → district dropdowns from a
|
||||
saved address, and the city list is fetched **per province** (`geo/cities?province_id=`). The DTO carries
|
||||
`cityId` but not its province, so the client can't drive the city query to preselect the city without the
|
||||
province id. The client currently augments `provinceId` behind the `services/addresses` seam (the mock
|
||||
persists it; the real client echoes the just-saved choice), so editing an address that was **loaded fresh from
|
||||
the server** can't prefill the province until this lands. `cityId` still implies the province server-side —
|
||||
this is purely to prefill the client cascade.
|
||||
- **Proposed shape:** `CustomerAddressDto { …, provinceId: long }` (join from `cities.province_id`).
|
||||
- **Status:** open
|
||||
|
||||
Reference in New Issue
Block a user