# Refinement Phase 4 — Frontend de-mock (flip every domain to the real backend)

> **Mission:** make the frontend actually call the backend. Today 21 of 22 client service domains default to an
> in-browser mock (`USE_*_MOCK = true`), so the running app is almost entirely fake data. Each domain's real
> `clientApi` already exists and maps the live routes 1:1 — the swap is a **one-line flag flip per domain**,
> once that domain's REQ gaps ([Phase 3](refinement-phase-3-contract-batch.md)) are delivered and the demo data
> ([Phase 1](refinement-phase-1-database-and-seed.md)) exists. This phase flips them, in dependency order, and
> verifies each against the real API.
>
> **Track:** frontend · **Depends on:** [Phase 1](refinement-phase-1-database-and-seed.md),
> [Phase 2](refinement-phase-2-auth-and-role-nav.md), [Phase 3](refinement-phase-3-contract-batch.md) ·
> **Unlocks:** a genuinely integrated app
> **Before you start, read [../../phases/_shared/agent-operating-rules.md](../../phases/_shared/agent-operating-rules.md).**

## 1. Context — where this sits

The frontend was deliberately built **mock-primary** so each phase could ship before its backend counterpart
merged. Every domain follows the same seam: `services/{domain}/apis/index.ts` picks `mockApi` vs `clientApi`
from a compile-time `USE_{DOMAIN}_MOCK` constant in `constants.ts`; the `clientApi` already wraps `clientFetch`
and unwraps the `ApiResult` envelope. The design intent, recorded in every phase report and the mocks-registry,
is: **deliver the REQ → flip the flag → the domain is real, with no hook/component change.**

This phase executes that flip for every domain. The order matters because the domains form a funnel — a domain
whose *inputs* are still mocked can't meaningfully go real (e.g. `bookingRequests` needs `search`/`patients`/
`addresses` real first). Auth is already real and is the template.

**Note on flags:** the `USE_*_MOCK` constants are **hard-coded literals**, not env vars. Flipping means editing
the `constants.ts` line to `false`. Consider (optional, small) refactoring each to read
`process.env.NEXT_PUBLIC_USE_{DOMAIN}_MOCK` with a `false` default so environments can differ without code
edits — but the minimum deliverable is the flags flipped to real.

## 2. Required reading (do this first)

- **`dev/shared-working-context/reports/mocks-registry.md`** → the "Frontend client-side mocks" table. Every
  row lists the flag, the file, and the exact "Make it real →" precondition (which REQ + which upstream domain).
  This is your checklist.
- `client/CLAUDE.md` → "services/" section (the per-domain descriptions + their REQ gaps).
- `client/src/services/auth/` → the already-real template for how a flipped domain behaves.
- Each domain's `apis/clientApi.ts` (verify the routes it maps against the regenerated
  `dev/contracts/openapi/swagger.v1.json` — especially the ones Phase 3 flagged: partner-center **kebab-case**
  routes, BNPL `provider_code`, cancellation-policy codes).
- The [Phase 3](refinement-phase-3-contract-batch.md) hand-off (which REQs actually landed) — only flip a
  domain whose gaps are delivered.

## 3. Scope — flip these, in this order

Flip each `USE_*_MOCK` to `false` **only after its precondition holds**, then run the domain's screens against
the real backend and fix any real-path shape surprises. Group order mirrors the dependency funnel:

### Group 1 — identity & reference (few/no gaps)
- `USE_GEOGRAPHY_MOCK` — reference lookups; b4 live, **no REQ needed**. Flip early.
- `USE_PATIENTS_MOCK` — needs REQ-005 (relation/conditions).
- `USE_PROFILES_MOCK` — needs REQ-006 (avatar) + REQ-007 (name/language). `uploadAvatar` currently throws 501
  until REQ-006.
- `USE_NURSE_BANK_MOCK` — b3 live, **no REQ**. Flip.
- `USE_ADDRESSES_MOCK` — needs REQ-008 (pin) + REQ-009 (provinceId).
- `USE_SERVICE_AREAS_MOCK` — b4 live, **no REQ**. Flip.

### Group 2 — catalog, verification, search (the discovery funnel)
- `USE_CATALOG_MOCK` — b5 live; **data caveat**: a fresh backend has categories but **no option groups** until
  Phase 1 seeds them (or the f15 admin authors them). Flip only once option groups exist, or the variant
  builder's required-option step is empty.
- `USE_VERIFICATION_MOCK` — needs REQ-011 (credential_details) + REQ-034 (admin queue/doc-URL/approve).
- `USE_SEARCH_MOCK` — needs REQ-012 (name/avatar/distance + public profile). **The linchpin of the funnel.**

### Group 3 — booking funnel
- `USE_BOOKING_REQUESTS_MOCK` — needs REQ-013/014 **and** search/patients/addresses real (Groups 1–2).
- `USE_BOOKINGS_MOCK` — a booking only exists after a paid request converts, so needs booking-requests +
  payment real. Also set `NEXT_PUBLIC_EVV_MOCK_GPS=off` to use real `navigator.geolocation`.
- `USE_PAYMENT_MOCK` — needs REQ-016 (checkout summary) + REQ-017 (outcome/bookingId) + REQ-018 (invoice) and
  the upstream request flow real. Delete the dev mock-gateway harness page once flipped.

### Group 4 — money reversal & post-booking
- `USE_REFUNDS_MOCK` — needs REQ-019/020/021 (+ canonical cancellation codes) + REQ-035 (admin).
- `USE_BNPL_MOCK` — needs REQ-022/023/024 (+ the `balinyaar` provider decision) + upstream real. Delete the
  BNPL gateway harness page once flipped.
- `USE_PAYOUTS_MOCK` — needs REQ-025 (+ REQ-036 admin).
- `USE_REVIEWS_MOCK` — needs REQ-026 (+ REQ-037 admin `tagCodes`).
- `USE_PATIENT_RECORDS_MOCK` — the nurse visit-note half is already real (b14); the family-record half needs
  REQ-027 (**and the product decision** on whether it's a real entity). Flip only the parts that are backed;
  keep the family record mocked if the product defers it.

### Group 5 — comms & admin consoles
- `USE_TICKETS_MOCK` — needs REQ-028 + bookings real.
- `USE_NOTIFICATIONS_MOCK` — b1 live; real once upstream domains actually **dispatch** notifications (the
  mock exists because nothing dispatches while upstreams are mocked). Flip after Groups 3–4.
- `USE_ADMIN_MOCK` — needs REQ-029/030/031.
- `USE_PARTNER_MOCK` — needs REQ-032/033 **and** the route-casing reconciliation (verify the kebab-case routes
  bind before flipping).

### Cleanup
- Remove the dev-only test harness pages once their domains are real: the payment mock-gateway
  (`…/checkout/gateway/page.tsx`) and the BNPL provider-handoff (`…/checkout/bnpl/gateway/page.tsx`) — on the
  real path the PSP/provider `redirectUrl` is an absolute URL, so these are never linked.
- Remove the dev-only `__mock*` helpers (`__mockApproveAll`, `__mockPublishSubmittedReview`,
  `__mockPushNotification`, etc.) as their domains go real, or keep them behind a dev guard if still useful.

## 4. Mocks & seams in this phase

This phase *retires* mocks. The one client seam that legitimately stays is `ILocationProvider` (EVV GPS
capture) — set `NEXT_PUBLIC_EVV_MOCK_GPS=off` to select the real `navigator.geolocation`. The
`AddressMapPicker` remains a canvas stand-in until a real map widget is inlined (that's a separate design task,
not a data mock).

## 5. Critical rules you must not get wrong

- **Don't flip a domain whose inputs are still mocked** — you'll get empty screens or shape errors. Follow the
  group order; a domain is only real if the whole chain beneath it is.
- **Verify each `clientApi`'s routes against the regenerated swagger before flipping** — Phase 3 flagged three
  concrete casing/enum mismatches (partner-center kebab-case, BNPL `balinyaar`, cancellation codes). A wrong
  route silently 404s.
- **The flip is a flag, not a rewrite.** If a screen needs a hook/component change to work on the real path,
  that's a Phase 3 gap that wasn't fully delivered — file/finish the REQ, don't hack the component.
- **`npm run check` and `test:ci` stay green** after each flip; keep `en.json`/`fa.json` in sync (no new
  strings expected, but empty/error states may surface copy that was never exercised on the mock path).
- **Real error/empty states now matter.** The mocks always returned tidy data; real endpoints 404/return empty.
  Verify each domain's empty, error, and loading states against the real backend — this is where mock-only apps
  break.

## 6. Definition of Done

On top of the shared [definition-of-done.md](../../phases/_shared/definition-of-done.md):

- [ ] Every domain whose REQ preconditions are met has `USE_*_MOCK = false` and is verified working against the
      real backend; any domain still mocked is because its REQ/product decision is explicitly outstanding
      (documented, not forgotten).
- [ ] `npm run check` + `npm run test:ci` green; translations in sync.
- [ ] The full happy path runs on real data end-to-end: log in → browse categories → search → open a nurse
      profile → request a booking → nurse accepts → checkout → confirmation → booking detail → review.
- [ ] Dev test-harness pages + `__mock*` helpers for real domains removed or dev-guarded.
- [ ] `client/CLAUDE.md` and the mocks-registry updated to reflect which domains are now real.

## 7. How to test (what a human can verify after this phase)

1. With client + server running on real data (Phases 0–3 done), open the app and confirm the **Network tab
   shows real `/api/v1/*` calls for every screen** (not just auth) — no domain is serving in-browser mock data.
2. Walk the customer funnel: home category grid → search (real seeded nurses) → nurse profile → request →
   (switch to the nurse account) accept → (customer) checkout → pay (mock gateway is gone; on a real PSP this
   is [Phase 8](refinement-phase-8-external-rails.md), but the request→booking conversion works) → confirmation
   → booking detail.
3. Nurse funnel: verification flow, services builder, coverage, requests inbox, visits/EVV, earnings — all on
   real data.
4. Admin: verification queue, refunds, payouts, moderation, config/holidays/audit, partner centers — on real
   data with role-gated nav (Phase 2).
5. Confirm empty/error states render correctly where the demo data is sparse (e.g. a nurse with no reviews).

## 8. Hand off & document (close the phase)

- Update `client/CLAUDE.md` "services/" notes and `dev/shared-working-context/reports/mocks-registry.md`
  (frontend mocks table) to mark each flipped domain real.
- Report the flip status of all 22 domains (real / still-mocked-because-X) and any real-path surprises found.
  Save a memory note on the de-mock order and any domain that needed a Phase-3 follow-up.
