{invoice.invoiceNumber ?? 'Draft'}
Status: {invoice.status}
-
{invoice.items.map((item) => (
- {item.description} — {item.quantity} × {item.unitAmount} ))}
| {pricing.product.name} | {pricing.tiers.map((tier) => ({tier.name}{tier.isPopular ? ' ★' : ''} | ))}||
|---|---|---|---|
| {feature.name} | {pricing.tiers.map((tier) => { const ent = tier.entitlementBySlug[feature.slug]; if (!ent) return— | ; if (ent.mode === 'unlimited') returnUnlimited | ; return{ent.value ?? ent.periodAllocation} | ; })}
Loading wallets…
; if (error) returnFailed to load wallets.
; if (accounts.length === 0) returnNo credit wallets yet.
; return (Loading…
; const available = currencies.filter( (c) => !accounts.some((a) => a.creditCurrencyId === c.id), ); return (Loading history…
; if (error) returnFailed to load history.
; if (attempts.length === 0) returnNo top-up attempts yet.
; return (Loading ledger…
; if (error) returnFailed to load ledger.
; return ({usage} / {limit} used · {remaining} left
{nextResetAt &&Resets {new Date(nextResetAt).toLocaleDateString()}
}Loading…
; if (error) returnFailed to load invoices.
; if (invoices.length === 0) returnNo invoices yet.
; return (Loading…
; if (error || !invoice) returnCouldn’t load this invoice.
; return (Status: {invoice.status}
Loading…
; if (error) returnCouldn’t load your next invoice.
; if (!invoice) returnNo upcoming renewal.
; return (Next charge: {invoice.amountDue} {invoice.currency} on{' '} {new Date(invoice.billingDate).toLocaleDateString()}
); } ```Loading…
; return (Checking…
; if (data.blocksDetach) { return (This card powers {data.activeSubscriptions.length} subscription(s) and{' '} {data.autoTopupAccounts.length} auto-topup rule(s). Replace it instead.
); } return ; } ```Loading…
; if (error) returnFailed to load subscriptions.
; if (subscriptions.length === 0) returnNo subscriptions yet.
; return (Loading…
; if (!subscription) returnNo active subscription.
; return (On {subscription.planId} ({subscription.status}) until{' '} {subscription.currentBillingPeriodEnd}
); } ``` Scope to one product by passing its plan ids: ```tsx theme={null} import { useActiveSubscription, usePricing } from '@unitpay/react'; export default function ProductPlan({ productId }: { productId: string }) { const { pricing } = usePricing(productId); const planIds = pricing?.tiers.flatMap((t) => t.plans.map((p) => p.id)) ?? []; const { subscription } = useActiveSubscription({ planIds }); return{subscription ? subscription.planId : 'Not subscribed to this product.'}
; } ``` ## useSubscription A read-only hook that fetches one subscription by id and exposes `previewChange`, a parameterized read that previews what switching to another plan would cost. Mutations live in the dedicated hooks below. **Parameters**Loading…
; if (!subscription) returnNot found.
; return (Current plan: {subscription.planId}
{preview && (Switch is a {preview.direction}; due now {preview.dueNow.amount} {preview.dueNow.currency}.
)}