import Link from "next/link"; import { CreditCard, Receipt } from "lucide-react"; import { requireAdmin } from "@/lib/session"; import { getBillingOverview } from "@/lib/queries/admin"; import { formatNumber, formatUsd } from "@/lib/format"; import { PageHeader } from "@/components/ui/page-header"; import { Alert } from "@/components/ui/alert"; import { Badge, StatusBadge } from "@/components/ui/badge"; import { EmptyState } from "@/components/ui/empty-state"; import { Stat, StatGrid } from "@/components/ui/stat"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { DateCell, MarginText, Mono, Panel, PlanBadge, numCell } from "@/components/admin/primitives"; export const dynamic = "force-dynamic"; export default async function AdminBillingPage() { await requireAdmin(); const b = await getBillingOverview(); const paying = b.distribution.filter((d) => d.price > 0).reduce((s, d) => s + d.orgs, 0); return ( <> {!b.stripeConfigured ? ( `STRIPE_SECRET_KEY` is not set and there is nothing to bill: every organization is on the Unlimited plan (private platform, no billing). Subscriptions and billing events below stay empty unless a Stripe integration is added later. ) : null} 0 ? ((b.usageRevenue30d - b.usageCost30d) / b.usageRevenue30d) * 100 : null} />} hint="vs upstream cost" /> Plan Organizations List price / mo MRR {b.distribution.map((d) => ( {formatNumber(d.orgs)} {formatUsd(d.price)} {formatUsd(d.mrr)} view → ))} {b.unknown.map((u) => ( {u.plan} legacy plan value — treated as Unlimited; run `pnpm db:seed` to normalize {u.n} — — ))}
{b.subs.length === 0 ? (
) : ( Organization Plan Status Period Stripe {b.subs.map((s) => ( {s.orgName ?? s.organizationId} {s.cancelAtPeriodEnd ? cancels : null} → {s.stripeSubscriptionId ?? "—"} ))}
)}
{b.events.length === 0 ? (
) : ( When Type Organization Stripe event {b.events.map((e) => ( {e.type} {e.orgName ?? e.organizationId ?? "—"} {e.stripeEventId ?? "—"} ))}
)}
); }