# Admin · Finance — UI parity

## A. Shop Balances (demo) — NEW screen, NO equivalent on our side

Demo `ShopBalances.tsx`:
- Header row: a **Segmented** toggle `Owing shops | All shops` + caption "Negative = the shop owes Navagoo; it auto-bills when it crosses the credit limit."
- A `Card` wrapping a `DataTable` with columns: **Shop** (ShopTile avatar + name) · **Collectable** (muted Money) · **Outstanding fees** (muted) · **Running balance** (signed, bold) · **Credit limit** (muted) · **In negative** (`{ageDays}d` or `—`) · action cell.
- Action cell states: `issuable>0` → subtle **"Issue invoice now"** button; else `carried>0` → amber text **"Invoiced — awaiting payment"**; else nothing.
- Empty state: `empty="No shops match this filter."`

OUR side: **no view exists**. There is no admin page listing shop running balances / who-owes-Navagoo / credit limits / age-in-negative. Status: **MISSING (whole screen)**.

---

## B. Transfer Requests (demo) ≈ OUR Withdrawal index + settlement form

### List/table
Demo `TransferRequests.tsx` columns: **TR ID** (mono, brand) · **Shop** (ShopTile + name) · **Earned** · **Tips** · **Marketing** · **Payment Processing** · **Fee VAT** · **Net Payout** (bold) · **Amount Paid** (or `—`) · **Status** (`TransferBadge`) · action (**Review** if `requested`, else **View**). Row click opens the settle modal.

OUR `backend/views/withdrawal/index.php` (Tailwind, no AdminLTE):
- KPI stat tiles (sum transferable, sum collected, settled count) — **extra, not in demo**.
- Columns: serial · TR id (link to earnings) · Shop · **Total Collected** · **Total Navagoo Fees** · **Total Tips** · **Net Transferable** (bold accent) · settlement-status chip · dates (created/confirmed/settled) · shop-confirmation user · Navagoo invoice / transfer receipt / other docs links · transfer reference · remarks · update action.
- Collapsible filter form (TR id, shop, settlement status, created-at range) + CSV/XLSX ExportMenu + LinkPager — **richer than demo**.
- Settlement-status chips colour-mapped (NEW=brand, REQUESTED=amber, IN_PROGRESS=sky, SETTLED=accent) — matches demo `TransferBadge` semantics.

**UI gaps (table):** demo splits fees into Marketing / Payment-Processing / Fee-VAT columns; ours collapses to one "Total Navagoo Fees" column (VAT not surfaced in list).

### Settle screen
Demo `SettleModal` (a `Modal`, size lg):
- Title `{TR id} · {shop}`, subtitle `{n} bookings · created {date}`.
- **FormulaStrip**: Collected + Tips − Marketing − Payment Processing − Fee VAT = **Net payout** (colour-toned terms).
- DataRows: Shop confirmation user, Confirmed at, (Settled at when settled).
- **Step 1a** UploadStep: "Upload invoice document" → toggles done (green check).
- **Step 1b**: disabled **"Generate invoice via API"** placeholder ("enabled after billing-system integration").
- **Step 2** UploadStep: "Upload bank-transfer confirmation".
- **Step 3**: "Amount paid" Input; on mismatch (`|paid − netPayout| > 0.01`) a red **AlertTriangle** banner with the delta.
- Footer: **"Settle & mark paid"** disabled until BOTH uploads done; settled view shows summary + read-only.
- **Associated invoices** section: lists invoices this settlement clears, each expandable to an `InvoiceDocument`.

OUR `backend/views/withdrawal/_settlement_form.php` (rendered in update, AJAX-capable; **note: update/create still use the default non-Tailwind layout per controller comments**):
- "Transfer Details" cards: Shop name, Total Collected, Net Transferable (highlight).
- "Settlement Information": `amount_transferred` number input, `transfer_reference`, `remarks`.
- "Documents": `DocumentUploadWidget` for navagoo_invoice, transfer_receipt, other_documents (multi).
- Actions: Cancel + **"Execute Settlement"** with SweetAlert confirm.

**UI gaps (settle):**
1. No FormulaStrip / fee breakdown (marketing/processing/VAT) on the settle screen.
2. No amount-paid **mismatch warning** vs net payout.
3. No **associated-invoices** section, no generated `InvoiceDocument`, no "Generate via API" placeholder.
4. Uploads are not gated to enable the settle button the way the demo gates "Settle & mark paid" on both files present (ours falls back to defaults / validates server-side).
5. Settle form chrome is the **legacy admin layout**, not the Tailwind "aurora" reskin used on the index.

### RTL / bilingual
- Ours: settlement form labels are bilingual inline (`'Shop Name | اسم المتجر'`), settlement-status labels are Arabic-only in `getSettlementStatuses()` (`base/Withdrawal.php:350-353`). Demo is English-only (no i18n layer). Our i18n is ahead, but the Arabic-only status labels are a polish issue.

### Refs
- Demo: `portals/admin/finance/{ShopBalances,TransferRequests}.tsx`, `components/InvoiceDocument`, `portals/finance/shared FormulaStrip`.
- Ours: `backend/views/withdrawal/{index,_settlement_form,_detail,view,update}.php`, `backend/views/finance/*`, `backend/views/earnings/*`, `backend/views/payment/*`.
