import { createFileRoute } from "@tanstack/react-router"; import { requireSignedIn } from "~/lib/route-guards"; import { z } from "zod"; import { adminGrantCustomDomains, adminSetPlan, getAdminBilling } from "~/fns/billing"; import { useAction } from "~/hooks/use-action"; import { formatQuantity, meterDef } from "~/lib/meters"; import { Badge } from "~/ui/Badge"; import { Button } from "~/ui/Button"; import { ErrorBanner } from "~/ui/Callout"; import { EmptyState } from "~/ui/EmptyState"; import { PageContainer } from "~/ui/PageContainer"; import { Panel } from "~/ui/Panel"; import { Heading } from "~/ui/Heading"; import { TextLink } from "~/ui/TextLink"; import { cn } from "~/utils/cn"; export const Route = createFileRoute("/admin/billing")({ beforeLoad: ({ context, location }) => { requireSignedIn({ context, location }); }, validateSearch: z.object({ period: z.string().optional() }), loaderDeps: ({ search }) => ({ period: search.period }), loader: ({ deps }) => getAdminBilling({ data: { period: deps.period } }), component: AdminBillingPage, }); type Account = Awaited>["accounts"][number]; type Meter = Account["meters"][number]; const OVER = 1; const NEAR = 0.8; function usageTone(meter: Meter): "danger" | "warning" | "neutral" { if (!meter.included) return "neutral"; const ratio = meter.quantity / meter.included; if (ratio >= OVER) return "danger"; return ratio >= NEAR ? "warning" : "neutral"; } function MeterLine({ meter }: { meter: Meter }) { const def = meterDef(meter.meter); const unit = def?.unit ?? "count"; const tone = usageTone(meter); const color = tone === "danger" ? "text-danger-300" : tone === "warning" ? "text-warning-300" : "text-gray-300"; return (
  • {def?.label ?? meter.meter} {formatQuantity(unit, meter.quantity)} {meter.included !== null && meter.included > 0 && ( {" "} / {formatQuantity(unit, meter.included)} {meter.hardCap !== null ? " cap" : ""} )}
  • ); } function AccountRow({ account }: { account: Account }) { const plan = useAction(adminSetPlan); const domains = useAction(adminGrantCustomDomains); const next = account.plan === "pro" ? "free" : "pro"; const editable = account.kind !== null && account.plan !== "scratch"; return (
  • {account.name ? ( {account.name} ) : ( {account.accountId} )} {account.plan} {account.kind === "org" && org} {account.pinned && pinned} {account.domainsGranted && domains granted}
    {editable && ( )} {editable && account.pinned && ( )} {editable && ( )}
  • ); } function AdminBillingPage() { const data = Route.useLoaderData(); return (
    Platform usage ({data.period}) Back to site admin

    Accounts among the heaviest users of any meter this period, closest to their allowance first. Usage is shown against the account's plan allowance; "cap" means the plan blocks at that amount. Free accounts never pay: capped meters stop and the rest only alert. Pro accounts are billed for overage, bounded by their spending limit.

    {data.accounts.length === 0 ? ( ) : (
      {data.accounts.map((account) => ( ))}
    )}
    ); }