frontend phase 9

This commit is contained in:
hamid
2026-07-10 11:49:55 +03:30
parent cd6c2591a6
commit 40cc1d163b
49 changed files with 4130 additions and 20 deletions
@@ -12,6 +12,41 @@ for awareness.
- **Requests filed:** frontend/requests/for-backend.md (yes/no)
-->
## frontend-phase-9-b10 — Checkout, card payment & invoice — 2026-07-10
- **Shipped:** the money moment — a **new `services/payment` domain** (types/keys/constants/
apis[client+mock]/invalidations/5 hooks + barrel) and the customer checkout flow: **C6 خلاصه و پرداخت**
`/bookings/checkout?request_id=` (acceptance badge, served **reconciling** service-cost/کارمزد/مالیات/مبلغ کل
breakdown, verbatim **escrow notice**, payment-window countdown, «ادامه پرداخت ←» with an
**idempotency-key-per-attempt**, disabled BNPL seam for f11), the **card states** (initiating → redirect →
dev **mock-gateway harness** `/bookings/checkout/gateway` → return `/bookings/checkout/return` with a
**backoff pending-callback poll** → succeeded/failed/expired), the **confirmation**
`/bookings/checkout/confirmation` («مشاهده رزرو» + «دانلود فاکتور»), and the **invoice**
`/bookings/[id]/invoice` (VAT-on-commission line, read-only مودیان state, pdfUrl download or print
receipt). Three shared tested composites: `PriceBreakdown`, `EscrowNotice`, `PaymentStatusBadge`. New
`payment` i18n namespace (53 keys, both locales).
- **Load-bearing rules honored:** money = IRR digit-strings, **BigInt only** (integer parts-per-10000 rate
math in the mock — zero floats); the breakdown **must reconcile** (`PriceBreakdown` dev-guards it; rows
are served, VAT never derived client-side); **VAT on the commission only** (invoice line labelled
accordingly); escrow copy **verbatim** in fa (pinned by test against fa.json), info tone never error;
**409 = benign convergence** (re-reads the outcome, never an error toast); poll uses **geometric backoff,
stops on terminal + bounded attempts**; success flips the booking **by cache invalidation** (exact keys,
no refetch storm).
- **Consumes:** dev/contracts/domains/payments.md (b10 — initiate route + `Idempotency-Key` header +
`InitiatePaymentResult`; status enum `pending|succeeded|failed`) and the invoice slice of
refunds-invoices.md (b11 — `GET invoices/{bookingId}`, `InvoiceDto`), casing verified against
swagger.v1.json. **Not served by any contract:** a checkout summary, a client transaction read, and the
converted request's booking id → REQ-016/017/018.
- **Mocked client-side:** `services/payment` via `paymentMockApi` (**USE_PAYMENT_MOCK=true, primary**) —
it is the missing **conversion trigger bridging the f7 ↔ f8 mock stores**: capture converts the request
(`converted` + client-augmented `bookingId`), inserts a **confirmed** booking into the f8 store, and
auto-issues the b11-shaped invoice, so C5 → C6 → gateway → confirmation → booking detail → invoice runs
end-to-end in one session. The dev **mock-gateway page is a test harness, not a product feature**. Real
`paymentClientApi`: initiate/invoice = published contract; summary targets the REQ-016 proposed slug;
outcome maps `booking_requests/get` (REQ-017).
- **Gate:** npm run check green · npm run test:ci green (204 tests, +9) · production build green.
- **Requests filed:** frontend/requests/for-backend.md — yes (REQ-016 checkout summary, REQ-017 payment
outcome + bookingId, REQ-018 customer invoice availability post-capture).
## frontend-phase-8-b9 — Booking detail, sessions & nurse EVV — 2026-07-10
- **Shipped:** the post-payment engagement — a **new** `services/bookings` domain (the sibling of
`bookingRequests`, NOT a rename): types/keys/constants/apis[client(1:1 b9)+mock+serverApi]/8 hooks +