# Admin Marketplace Dashboard — Frontend Spec

> **For the AI agent building the admin UI.**  
> All endpoints listed below are live on staging (`https://sanad.work/staging/api`).  
> All admin routes require an authenticated admin session — the existing axios interceptor attaches the bearer token automatically.  
> All admin routes share the prefix `/admin/marketplace`.

---

## 1. What Changed in the Backend (Recent Commits)

### Commit `34254197` — Refund on creator decline
When a creator declines a paid collaboration request, the `wallet_used` amount is now automatically refunded to the brand's wallet as a `refund` transaction. The brand will see a new credit row in their wallet ledger with `source: "refund"` and `related_type: CollaborationRequest`.

**Frontend impact:** The brand wallet ledger (`/brand/wallet/transactions`) will show `source: "refund"` rows. The existing `TransactionTable` component handles this — no change needed.

### New controllers added (pulled with the backend update)
- `AdminWalletChargesController` — approve/reject brand wallet bank-transfer top-ups  
- `BrandWalletsController` — list/view/adjust brand wallets  
- `MarketplaceTransfersController` — view per-CR money flow and full ledger  
- `MarketplaceTransfersController` — money overview stats  
- `AdminWithdrawalsController` (existing) — approve/mark-paid creator withdrawals  

---

## 2. Full Admin API Reference

### 2a. Wallet Charges (Brand Top-Up Approvals)

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/admin/marketplace/wallet-charges` | List all top-up requests. Filter: `?status=pending\|approved\|rejected&payment_method=bank_transfer\|card&from=&to=&per_page=25` |
| `POST` | `/admin/marketplace/wallet-charges/{id}/approve` | Approve a pending bank-transfer charge → credits brand wallet |
| `POST` | `/admin/marketplace/wallet-charges/{id}/reject` | Reject a pending bank-transfer charge |

**Approve request body:**
```json
{ "admin_notes": "Verified via bank statement" }
```

**Reject request body:**
```json
{
  "rejection_reason": "Amount does not match transfer receipt",
  "admin_notes": "optional internal note"
}
```

**Charge object shape:**
```json
{
  "id": 1,
  "brand_id": 42,
  "amount": 2000.00,
  "currency": "SAR",
  "payment_method": "bank_transfer",
  "status": "pending",
  "sender_bank_name": "Al Rajhi Bank",
  "sender_account_holder": "Mohammed Al-Saeed",
  "proof_file_url": "https://...",
  "external_payment_id": null,
  "wallet_transaction_id": null,
  "rejection_reason": null,
  "admin_notes": null,
  "reviewed_at": null,
  "approved_at": null,
  "rejected_at": null,
  "created_at": "2026-05-06T10:00:00Z",
  "updated_at": "2026-05-06T10:00:00Z"
}
```

---

### 2b. Creator Withdrawals

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/admin/marketplace/withdrawals` | List withdrawals. Filter: `?status=requested\|approved\|paid\|rejected\|cancelled&creator_id=&from=&to=&per_page=25` |
| `GET` | `/admin/marketplace/withdrawals/{id}` | View single withdrawal |
| `POST` | `/admin/marketplace/withdrawals/{id}/approve` | Approve (status: requested → approved) |
| `POST` | `/admin/marketplace/withdrawals/{id}/reject` | Reject (status: requested → rejected) |
| `POST` | `/admin/marketplace/withdrawals/{id}/mark-paid` | Mark as paid (status: approved → paid) |

**Approve body:** `{}` (no body required)

**Reject body:**
```json
{
  "rejection_reason": "Bank details invalid",
  "admin_notes": "optional"
}
```

**Mark-paid body:**
```json
{
  "payment_reference": "TXN-20260506-001",
  "payment_method": "bank_transfer",
  "paid_at": "2026-05-06T14:00:00Z",
  "admin_notes": "optional"
}
```

**Withdrawal object shape:**
```json
{
  "id": 5,
  "creator_id": 12,
  "creator": { "id": 12, "username": "creator_name", "photo_url": "..." },
  "amount": 1500.00,
  "currency": "SAR",
  "status": "requested",
  "bank_snapshot": {
    "account_holder": "Ahmed Ali",
    "bank_name": "SNB",
    "iban": "SA0380000000608010167519",
    "account_number": "608010167519"
  },
  "creator_notes": "Monthly payout",
  "admin_notes": null,
  "rejection_reason": null,
  "payment_reference": null,
  "payment_method": null,
  "approved_at": null,
  "rejected_at": null,
  "paid_at": null,
  "created_at": "2026-05-06T09:00:00Z"
}
```

---

### 2c. Brand Wallets

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/admin/marketplace/brand-wallets` | List all brand wallets. Filter: `?per_page=25` |
| `GET` | `/admin/marketplace/brand-wallets/{brandId}` | View one brand's wallet + recent transactions |
| `GET` | `/admin/marketplace/brand-wallets/{brandId}/transactions` | Full transaction ledger for a brand |
| `POST` | `/admin/marketplace/brand-wallets/{brandId}/adjust` | Manually adjust balance (credit or debit) |

**Adjust body:**
```json
{
  "type": "credit",
  "amount": 500.00,
  "note": "Compensation for failed payment"
}
```
`type` must be `"credit"` or `"debit"`.

---

### 2d. Collaboration Request Money Flow

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/admin/marketplace/collaboration-requests/{crId}/transfers` | Per-CR money breakdown |
| `GET` | `/admin/marketplace/transfers` | Full ledger of all transfers. Filter: `?account_type=creator\|platform\|vat&from=&to=&per_page=25` |
| `GET` | `/admin/marketplace/money/overview` | Platform-level totals: revenue, VAT, pending withdrawals |

**Transfers response shape (per-CR):**
```json
{
  "collaboration_request_id": 7,
  "brand_paid": 1725.00,
  "transfers": [
    { "account_type": "creator",  "amount": 1500.00, "posted_at": "..." },
    { "account_type": "platform", "amount": 150.00,  "posted_at": "..." },
    { "account_type": "vat",      "amount": 75.00,   "posted_at": "..." }
  ],
  "summary": {
    "creator_earned": 1500.00,
    "platform_fee":   150.00,
    "vat_collected":  75.00
  }
}
```

---

## 3. Admin Dashboard Pages to Build

### Page 1: Wallet Charges (Top-Up Approvals)
**Route:** `/admin/marketplace/wallet-charges`  
**Purpose:** Admin reviews bank-transfer top-up proofs and approves or rejects them.

**UI Requirements:**
- Table columns: `#`, `Brand`, `Amount`, `Method`, `Status`, `Sender Bank`, `Proof` (link), `Notes`, `Requested At`, `Actions`
- Status chips: `pending` = amber, `approved` = green, `rejected` = red
- Filter bar: status dropdown, date range, search by brand name
- **Approve action:** Button opens a small dialog with optional `admin_notes` field → POST approve
- **Reject action:** Button opens dialog with required `rejection_reason` + optional `admin_notes` → POST reject
- After action: refresh row in table, show success toast
- Proof link: opens the uploaded image/PDF in a new tab
- Default view: filter to `status=pending`

---

### Page 2: Creator Withdrawals
**Route:** `/admin/marketplace/withdrawals`  
**Purpose:** Admin processes creator payout requests through a 3-step approval pipeline.

**Status pipeline:**
```
requested → [Approve] → approved → [Mark Paid] → paid
requested → [Reject]  → rejected
```

**UI Requirements:**
- Table columns: `#`, `Creator` (name + photo), `Amount`, `Bank` (from bank_snapshot), `IBAN`, `Status`, `Requested At`, `Actions`
- Status chips: `requested` = amber, `approved` = blue, `paid` = green, `rejected` = red, `cancelled` = gray
- Filter bar: status tab group (All / Requested / Approved / Paid / Rejected)
- **Approve:** simple confirm button (no form) → POST approve
- **Reject:** dialog with required `rejection_reason` → POST reject
- **Mark Paid:** dialog with required `payment_reference`, optional `payment_method` and `paid_at` → POST mark-paid
- Show bank snapshot details inline (bank name, IBAN) — these are frozen at request time
- Pagination

---

### Page 3: Brand Wallets
**Route:** `/admin/marketplace/brand-wallets`  
**Purpose:** Admin can view and manually adjust any brand's wallet balance.

**UI Requirements:**
- Table: `Brand Name`, `Balance (SAR)`, `Pending`, `Currency`, `Last Updated`, `Actions`
- Click row → expands or navigates to brand wallet detail
- Detail view: wallet balance card + full transaction ledger table (same as brand's own view)
- **Adjust balance:** Button opens dialog with `type` (credit/debit toggle), `amount`, `note` → POST adjust
- After adjustment: show new balance in the card

---

### Page 4: Money Overview (Dashboard)
**Route:** `/admin/marketplace` (or `/admin/marketplace/overview`)  
**Purpose:** High-level financial health of the marketplace.

**UI Requirements:**
- Stat cards:
  - Total Platform Revenue (commission collected)
  - Total VAT Collected
  - Total Creator Earnings (posted to ledger)
  - Pending Withdrawals (locked_for_withdrawal sum)
  - Pending Wallet Charges (count of pending bank transfers)
- Quick links to: Pending Charges, Pending Withdrawals

---

### Page 5: Transfers Ledger (optional / advanced)
**Route:** `/admin/marketplace/transfers`  
**Purpose:** Full audit log of every money movement.

**UI Requirements:**
- Table: `CR ID`, `Account Type`, `Amount`, `Note`, `Posted At`
- Filter: account_type, date range
- Clickable CR ID → navigates to that CR's detail

---

## 4. Shared Component: MoneyFlowPanel
Already built in the frontend at `components/Dashboard/Wallet/MoneyFlowPanel.tsx`.  
It calls `GET /brand/collaboration-requests/{id}/transfers`.  
The admin version calls `GET /admin/marketplace/collaboration-requests/{crId}/transfers` — same response shape.  
Reuse the component by making the API URL a prop.

---

## 5. Key Constants

```typescript
// Status colors — consistent across brand and admin views
const CHARGE_STATUS_COLOR = {
  pending:  { color: "#F79009", bg: "#FFFAEB" },
  approved: { color: "#12B76A", bg: "#ECFDF3" },
  rejected: { color: "#F04438", bg: "#FEF3F2" },
};

const WITHDRAWAL_STATUS_COLOR = {
  requested:  { color: "#F79009", bg: "#FFFAEB" },
  approved:   { color: "#2E90FA", bg: "#EFF8FF" },
  paid:       { color: "#12B76A", bg: "#ECFDF3" },
  rejected:   { color: "#F04438", bg: "#FEF3F2" },
  cancelled:  { color: "#718096", bg: "#F5F8FA" },
};
```

---

## 6. What the Admin Does NOT Need to Build

- The brand-side wallet UI (already built: `WalletWidget`, `TopUpModal`, `TransactionTable`, `WalletChargesTable`)
- The creator-side earnings/withdrawal UI (already built in `components/influencer/Earnings/`)
- The collaboration request wizard (already built for brands)
- Content submission review (already built at `BrandSubmissionReviewController` — brand-only)
