backend phase 13 & frontend phase 6

This commit is contained in:
hamid
2026-07-09 04:09:35 +03:30
parent dc64472631
commit de53f9d8a6
97 changed files with 11969 additions and 77 deletions
@@ -12,6 +12,29 @@ for awareness.
- **Requests filed:** frontend/requests/for-backend.md (yes/no)
-->
## frontend-phase-6-b7 — Search & discovery (find a verified, same-gender nurse) — 2026-07-09
- **Shipped:** the family discovery slice — `services/search` (types/keys/constants/apis/hooks + a shared
`filterParams.ts` C1↔C2 URL serializer) and screens **C1** `/search` (reused category grid + f3 region
picker + prominent same-gender facet + Toman price + live-count CTA; `useSearchFilters` colocated
controller with debounced price), **C2** `/search/results` (rating-sorted `NurseResultCard` list, all
four states incl. "relax filters" empty, load-more), **C3** `/search/nurse/[nurseId]` (TrustBadge + نظام
پرستاری badges, attribute chips, `ServicePriceRow` services, latest review, "درخواست رزرو" handoff).
Two shared tested components: `NurseResultCard`, `ServicePriceRow`. `/bookings/request` = f7 handoff stub.
i18n `search` (filled) + `booking` (seeded) in both locales. Reused f4 category grid, f5 TrustBadge, f3
geo picker, f0 money util — none rebuilt.
- **Headline caching:** the **filter object IS the query key** — reverting to a prior filter set is a cache
hit with zero network (keepPreviousData avoids flashing); price input debounced.
- **Consumes:** dev/contracts/domains/search.md (b7) + b6 trust badge / b5 variant reads.
- **Mocked client-side:** `services/search` via `searchMockApi` (**USE_SEARCH_MOCK=true, primary**) — b7's
index row + b5/b6 reads don't yet expose nurse name/avatar/distance or an aggregated profile
(name/bio/specialties/services list/latest review). Real `searchClientApi` maps what exists; swap is one
line once REQ-012 lands. Recorded in the phase report (not mocks-registry — that's for backend DI seams).
- **Gate:** npm run check green · npm run test:ci green (165 tests, +8). `npm run build` compiles + types
clean; prerender fails only on the pre-existing f5 `/nurse/verification` "Missing .env variable!" (needs
env set — unrelated to f6).
- **Requests filed:** frontend/requests/for-backend.md — yes (REQ-012: search row name/avatar/distance +
`GET nurses/{id}/profile` aggregation).
## frontend-phase-5-b6 — Nurse verification flow (trust engine) — 2026-07-09
- **Shipped:** `services/verification` domain (types/keys/constants/validation/apis[client+mock(primary)+seam]/
hooks/index) — ONE cached `status()` query drives B3+B6, every mutation invalidates it. The nurse
@@ -150,3 +150,24 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
- **Also (minor):** the contract's `VerificationStepDto` has no `isRequired` — the client treats **every**
seeded step as required (the "X از Y" meter Y = `steps.length`). Confirm that holds, or add `isRequired`.
- **Status:** open
## REQ-012 — Search result + nurse-profile enrichment for discovery (C2/C3) — filed by frontend-phase-6-b7 — 2026-07-09
- **Need:** Two extra read surfaces the discovery UI renders but b7/b6/b5 don't yet expose:
1. **On the `search/nurses` result row** (`NurseSearchResultDto`): the nurse's **display name** and
**avatar URL** (the C2 card's identity) and a **distance** value (km from the searched area) — b7's
index row today carries only ids + price/rating/gender/geo ids. Without the name/avatar the card falls
back to a generic label + initials; distance is simply hidden.
2. **An aggregated public nurse-profile endpoint** for C3 — proposed `GET api/v1/nurses/{id}/profile`
`{ nurseId, nurseName, avatarUrl, bio, yearsExperience, averageRating, totalReviews,
totalCompletedBookings, isVerified, inoMembership, attributeChips: string[] (specialty codes),
services: [{ variantId, displayName, priceIrr (string), priceUnit, sessionCount? }],
latestReview?: { rating, body, authorMasked, createdAt } }`. Today only the b6 public **trust badge**
(`nurses/{id}/trust_badge`, giving `isVerified` + `credentialTypes`) and the b5 single-variant read are
public — there is no name/bio/specialties/**full services list**/latest-review aggregation.
- **Why:** C2/C3 are the trust funnel — the family chooses a real, named, priced nurse here. The
`services/search` domain is **mock-primary** (`USE_SEARCH_MOCK = true`) precisely because these fields
aren't available; the real `searchClientApi` maps everything b7/b6 do provide and leaves the above blank.
When both land, the swap is a single config flip (no hook/component change).
- **Proposed shape:** enrich `NurseSearchResultDto` with `{ nurseName, avatarUrl, distanceKm? }`; add
`GET api/v1/nurses/{id}/profile` returning the object above. `price`/`priceIrr` stay IRR digit-strings.
- **Status:** open