1.8 KiB
1.8 KiB
Billing Tab
Nav id: billing
Icon: ◈
What it shows
A read-only ledger of all payment transactions for this client — a running total of paid amounts at the top, then a chronological list of individual entries. Status badges distinguish paid / pending / refunded.
Data flow
getBillingHistory(token) — GET /vip/billing?token=<token> — returns an array of VipBillingEntry objects.
Billing entry object
interface VipBillingEntry {
id: string
description: string // e.g. "2hr date — March 15"
amountCents: number
currency: string // ISO 4217, e.g. "usd"
status: 'paid' | 'pending' | 'refunded'
billedAt: string // ISO 8601
}
Display logic
Total card — sums amountCents where status === 'paid'. Currency is taken from entries[0].currency (all entries for a client share the same currency). Formatted via Intl.NumberFormat with style: 'currency'.
Transaction list — sorted by API (newest first assumed). Each row shows:
- Description (left, primary)
- Date (
formatDate— month day year) (left, secondary) - Amount (right, primary)
- Status badge (right, secondary)
Status badge colors:
| Status | Background | Text |
|---|---|---|
paid |
#1a2d1a |
#30d158 (green) |
pending |
#2d2a1a |
#ffd60a (yellow) |
refunded |
T.input |
T.secondary (muted purple) |
Non-obvious details
- Currency is not shown as
USDbut rendered byIntl.NumberFormat— e.g.$2,400.00for usd. This correctly handles non-USD currencies if ever used. entries[0]?.currency ?? 'usd'fallback assumes homogeneous currency per client — mixing currencies on a single ledger is not supported in the UI.- Billing is purely informational — no payment action (pay now, dispute) is available from this tab.