frontend phase 13

This commit is contained in:
hamid
2026-07-10 16:58:15 +03:30
parent 6186f54294
commit 85488bc25b
57 changed files with 3283 additions and 105 deletions
@@ -12,6 +12,32 @@ for awareness.
- **Requests filed:** frontend/requests/for-backend.md (yes/no)
-->
## frontend-phase-13-b14 — Reviews & patient care records — 2026-07-10
- **Shipped:** the last feature-domain phase. Two new domains — **`services/reviews`** (`useNurseReviews`
infinite published-only aggregate+list / `useReviewEligibility` / `useMyReviewForBooking` / `useCreateReview`
— invalidates eligibility+my-review, NEVER the public list) and **`services/patientRecords`**
(`usePatientCareRecord` / `useRecordAccess` / `usePatientHistory` / `useUpdateCareRecord` CUSTOMER-only /
`useCreateVisitNote` NURSE-only). Screens: `/bookings/[id]/review` (RatingInput + ReviewTagSelector, gated
completed+can_review+1:1, under-review state) + `LeaveReviewCta` on the customer booking detail; C3 nurse
profile **reviews tab** (published-only aggregate+count+infinite list); E2 **`/patients/[id]/record`** (4 tabs
داروها/روتین/سوابق/وظایف + ownership banner + customer edit + non-leaking access-denied); nurse
**`NurseVisitNotesPanel`** (append-only task-checklist+note composer BELOW the f8 EVV banner). New shared
composites RatingInput/ReviewTagSelector/VisitNoteCard/PatientHeader (each tested; PatientCard now composes
PatientHeader + gained `onOpen`); `usePatient(id)`; new icons; `reviews`+`records` i18n namespaces (both
locales). Extended the f8 bookings mock: completed booking **5005** + cross-mock read mockGetBookingForReview.
- **Consumes:** dev/contracts/domains/reviews-records.md + openapi/swagger.v1.json (backend-phase-14). REAL &
mapped 1:1: `POST bookings/{id}/review`, `GET nurses/{id}/reviews`, `GET`/`POST patients/{id}/care_records`.
- **Mocked client-side:** `services/reviews` (`USE_REVIEWS_MOCK`) — eligibility + my-review are REQ-026 gaps,
moderation is admin-only/f15 (dev `__mockPublishSubmittedReview`). `services/patientRecords`
(`USE_PATIENT_RECORDS_MOCK`) — the visit-note history/append are REAL b14; the family-owned record
(meds/routine/tasks) + access check have NO backend (REQ-027). Both default `true`; swap is one flag. See
mocks-registry.
- **Gate:** npm run check green · npm run test:ci green (all suites, +17) · npm run build green with
NEXT_PUBLIC_API_URL set. 6-dimension adversarial review with per-finding verification.
- **Requests filed:** frontend/requests/for-backend.md — yes (REQ-026 review eligibility + my-review + masked
author; REQ-027 family-owned care record + access + structured taskResults — flags the E2 record has no
data-model entity).
## frontend-phase-12-b13 — Nurse earnings & payout history — 2026-07-10
- **Shipped:** the **last money-path frontend phase** — the read-only **nurse earnings** surface. A **new
`services/payouts` domain** (types/keys/constants/apis[client+mock]/4 read-only hooks + hooks-only barrel)
@@ -413,3 +413,46 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
`net_amount = gross_earnings clawback_applied`; a payout's booking-link `payout_amount_irr` sum = its
`gross_earnings_irr`; the nurse amount is **payment-method-invariant** (BNPL provider commission never deducted).
- **Status:** open
## REQ-026 — Review eligibility + my-review-for-booking reads (+ masked author confirmation) — filed by frontend-phase-13-b14 — 2026-07-10
- **Need:** Three customer-facing additions the leave-a-review flow renders that b14 does not serve:
1. **Review eligibility** — proposed `GET api/v1/bookings/{bookingId}/review_eligibility` (owner-scoped) →
`{ canReview: boolean, reason?: 'not_completed'|'already_reviewed'|'not_owner'|'not_found' }`. Lets the
CTA/form gate on "this booking is completed/closed AND not already reviewed" without probing the 1:1 `409`.
2. **My review for a booking** — proposed `GET api/v1/bookings/{bookingId}/my_review` (owner-scoped) →
`{ moderationStatus: 'pending_moderation'|'published'|'hidden'|'rejected'|'none', rating?, body?, tagCodes[], createdAt? }`.
Lets the CTA show the **persistent "under review" state across sessions** (a returning customer must never
see a second form) — today only the just-submitted result is known client-side.
3. **Masked author confirmation.** `ReviewListItemDto` (the public list) carries **no customer name**. The
client renders a generic masked author («کاربر بالین‌یار») on the profile reviews tab. Please confirm this
omission is intentional (privacy), or add a **server-masked** display name field if a masked name is wanted.
- **Why:** b14 serves the submit (`POST bookings/{id}/review`), the public `GET nurses/{id}/reviews`, and the tag
rollup — but there is no eligibility read and no my-review read, and moderation (`pending_moderation → published`)
is admin-only (f15). So the `services/reviews` domain is **mock-primary** (`USE_REVIEWS_MOCK = true`): the mock
reads the shared f8 bookings store for completed-booking eligibility, tracks the submission for the under-review
state, and seeds a published list per nurse. The real `reviewsClientApi` maps `getNurseReviews`/`createReview`
1:1 and targets the two proposed slugs for the gaps — one config flip when they land.
- **Status:** open
## REQ-027 — Family-owned care record (medications/routine/tasks) + record access + structured task results — filed by frontend-phase-13-b14 — 2026-07-10
- **Need:** The b14 `care_records` GET/POST serve the **nurse-authored visit-note history** (سوابق) — that half
is **real and consumed**. But the E2 record viewer's **family-owned editable record** and the nurse **task
checklist** have **no backend at all** (neither the b14 contract nor `data-model/10-reviews-and-records.md`
models them). Proposed:
1. **Family-owned record**`GET/PUT api/v1/patients/{patientId}/care_record` (owner-scoped for read;
owning-customer for write) → `{ patientId, medications: [{ id, name, dosage?, frequency, timingNote? }],
routine: [{ id, label, timeOfDay?, note? }], tasks: [{ id, label, done }] }`. **Patient-scoped, not
booking-scoped**; the **customer** owns/edits it; it persists across nurse changes. (New entity/table.)
2. **Record access** — proposed `GET api/v1/patients/{patientId}/record_access`
`{ canView, canEdit, canAppendNote, deniedReason? }` **or** confirm the client should derive access purely
from the **`403` on the history read** (the two-stage clinical-disclosure rule). Today the mock returns a
`403` for a foreign patient id so the non-leaking access-denied card is demoable.
3. **Structured task results on a visit note**`WriteCareRecordBody` is only `{ bookingId?, body }`. The
nurse's ticked checklist is currently **folded into `body`** as a leading summary line. A structured
`taskResults: [{ label, done }]` field would preserve it (and let the history render the checklist as chips).
- **Why:** E2 (داروها/روتین/سوابق/وظایف) + the nurse E3 task-checklist are the continuity-of-care surface. The
visit-note history/append are real (b14) and mapped 1:1 in `patientRecordsClientApi`; the family-record + access
methods target the proposed slugs (REQ-027) and the domain is **mock-primary** (`USE_PATIENT_RECORDS_MOCK = true`)
until they land. **Note:** the wireframe's four-tab E2 record is not in the data model — please confirm whether
the family-owned record is a real MVP entity or a future addition (the client treats it as forward-looking).
- **Status:** open