ui phase 9

This commit is contained in:
hamid
2026-07-19 15:14:44 +03:30
parent 1ef4feb911
commit b638e25a0e
47 changed files with 2628 additions and 666 deletions
@@ -461,6 +461,19 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
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:** delivered in refinement-phase-3
- **ui-phase-9 addendum (2026-07-19):** the family-owned record's editing surface was rebuilt from a
whole-list free-text edit mode to per-item bottom sheets with **structured fields**, so the eventual
real table (whenever REQ-027's family-record half lands) should match this shape, not the original
free-text one quoted above:
- `Medication { id, name, doseAmount: string | null, doseUnit: 'tablet'|'capsule'|'drop'|'cc'|'unit' |
null, frequencyCode: 'once_daily'|'twice_daily'|'three_times_daily'|'every_8_hours'|'as_needed' |
null, frequencyText: string | null (free-text fallback when frequencyCode is null),
timeOfDay: ('morning'|'noon'|'evening'|'night')[], timingNote: string | null }`.
- `RoutineItem { id, label, timeOfDay: ('morning'|'noon'|'evening'|'night')[], note: string | null }`
(was a free-text `timeOfDay: string | null` — now the same stable chip codes as medications).
- `CareTask` is unchanged (`{ id, label, done }`).
- See `client/src/services/patientRecords/types.ts` for the authoritative current shape and
`apis/mockApi.ts` for the seeded example data.
## REQ-028 — Ticket inbox enrichment (unread + last-activity), message author name, by-booking lookup, optimistic idempotency — filed by frontend-phase-14-b15 — 2026-07-10
- **Need:** Four additions the f14 messaging UI renders that the b15 `TicketSummaryDto`/`TicketThreadDto`/message
@@ -896,3 +909,28 @@ delivers fixes in its own change. **Frontend never edits backend code to "fix" a
doc's instruction); at authoring time no such read was found in the b6 contract or swagger snapshot.
- **Status:** open — mock-only until served; the real path degrades to the pre-phase-8 blank-form
behavior (documented, not a regression — just not yet as helpful as the mock demonstrates).
## REQ-057 — Patient care metadata: `lastVisitAt` (+ optional `visitCount`) on the patient read model — filed by ui-phase-9 — 2026-07-19
- **Need:** Add `lastVisitAt: string | null` (UTC ISO, the most recent completed visit) and optionally
`visitCount: number` to the patient read model served by `patients/list`/`patients/get` (`PatientDto`).
- **Why:** The care-circle card (phase §3.2.3) wants an «آخرین ویزیت: ۱۲ تیر» teaser per person, best-effort
from already-cached data if possible. It isn't possible: the customer booking-list row
(`BookingListItemDto`, `services/bookings/types.ts`) carries no `patientId` at all, so there is no
client-side join from the cached bookings list to a specific patient without an N+1 fetch per row (which
the client deliberately does not do — same rule as REQ-052's `variantLabel`). The `PatientCard` component
already accepts an optional `lastVisitLabel` prop for this (`client/src/components/PatientCard/PatientCard.tsx`)
but `patients/page.tsx` never populates it — the teaser is simply omitted today, never fabricated.
- **Proposed shape:** `PatientDto { …, lastVisitAt: string | null, visitCount?: number }`, populated from the
most recent `booking_sessions` (or booking) whose `patientId` matches, `status = completed`.
- **Status:** open — the card renders no teaser until this (or a `patientId` on `BookingListItemDto`) lands.
## REQ-058 — Patient photo upload (optional, product-gated) — filed by ui-phase-9 — 2026-07-19
- **Need:** An object-storage-backed avatar for a patient (mirroring nurse `avatarUrl` — REQ-006), e.g.
`avatarUrl: string | null` on `PatientDto` + an upload endpoint.
- **Why:** The care-circle reframe (phase §3.2.2) ships **warm auto-colored initials** for every person
(`InitialsAvatar`, deterministic per name, no backend needed) as the shipped solution — this REQ is filed
only so a future "real photo" upgrade has a tracked ask; it is explicitly optional and gated on product
wanting it (a family may not want to upload a photo of a parent/child at all).
- **Proposed shape:** `PatientDto { …, avatarUrl: string | null }` + `POST patients/{id}/avatar` (multipart),
same seam shape as the nurse profile's `uploadAvatar`.
- **Status:** deferred, non-blocking — no UI currently reads a patient `avatarUrl`; initials-only ships either way.