TypeScript 97.5%
SQL 1.4%
Python 0.8%
1import Link from "next/link";2import { Download } from "lucide-react";3import { requireAdmin } from "@/lib/session";4import { getEconomics, parseRange, rangeLabel } from "@/lib/queries/admin";5import { formatBytes, formatNumber, formatPercent, formatUsd } from "@/lib/format";6import { PageHeader } from "@/components/ui/page-header";7import { Button } from "@/components/ui/button";8import { Table, TableBody, TableCell, TableEmpty, TableHead, TableHeader, TableRow } from "@/components/ui/table";9import { MarginText, NetworkBadge, Panel, PlanBadge, ProviderBadge, RangeTabs, numCell } from "@/components/admin/primitives";10import { EconomicsChart } from "@/components/admin/charts";11import type { EconRow } from "@/lib/queries/admin";1213export const dynamic = "force-dynamic";1415function EconTable({ rows, labelHead, renderLabel }: { rows: EconRow[]; labelHead: string; renderLabel: (r: EconRow) => React.ReactNode }) {16 return (17 <Table>18 <TableHeader>19 <TableRow>20 <TableHead>{labelHead}</TableHead>21 <TableHead className="text-right">Requests</TableHead>22 <TableHead className="text-right">Success</TableHead>23 <TableHead className="text-right">Revenue</TableHead>24 <TableHead className="text-right">Upstream</TableHead>25 <TableHead className="text-right">Margin</TableHead>26 <TableHead className="text-right">GB</TableHead>27 </TableRow>28 </TableHeader>29 <TableBody>30 {rows.length === 0 ? (31 <TableEmpty colSpan={7}>No data in this range.</TableEmpty>32 ) : (33 rows.map((r) => (34 <TableRow key={r.key}>35 <TableCell>{renderLabel(r)}</TableCell>36 <TableCell className={numCell}>{formatNumber(r.requests)}</TableCell>37 <TableCell className={numCell}>{formatPercent(r.requests ? (r.successes / r.requests) * 100 : null)}</TableCell>38 <TableCell className={numCell}>{formatUsd(r.revenue, true)}</TableCell>39 <TableCell className={numCell}>{formatUsd(r.cost, true)}</TableCell>40 <TableCell className="text-right">41 <MarginText value={r.margin} pct={r.marginPct} />42 </TableCell>43 <TableCell className={numCell}>{formatBytes(r.bytes)}</TableCell>44 </TableRow>45 ))46 )}47 </TableBody>48 </Table>49 );50}5152export default async function AdminUsagePage({ searchParams }: { searchParams: Promise<Record<string, string | string[] | undefined>> }) {53 await requireAdmin();54 const sp = await searchParams;55 const range = parseRange(sp.range);56 const e = await getEconomics(range);57 const totals = e.byBucket.reduce((acc, r) => ({ revenue: acc.revenue + r.revenue, cost: acc.cost + r.cost, requests: acc.requests + r.requests }), { revenue: 0, cost: 0, requests: 0 });5859 return (60 <>61 <PageHeader62 eyebrow="Unit economics"63 title="Usage"64 description={`${rangeLabel(range)} · revenue is what customers are billed (price_usd); upstream cost is what providers charge us (cost_usd).`}65 actions={66 <>67 <RangeTabs current={range} basePath="/admin/usage" />68 <Button asChild variant="outline" size="sm">69 <Link href={`/admin/usage/export?range=${range}`} prefetch={false}>70 <Download className="size-3.5" /> Export CSV71 </Link>72 </Button>73 </>74 }75 />7677 <Panel title={`Revenue vs upstream cost by ${e.unit}`} description={`Total: ${formatUsd(totals.revenue)} revenue · ${formatUsd(totals.cost)} cost · ${formatNumber(totals.requests)} requests`} bodyClassName="p-2 pt-3">78 <EconomicsChart data={e.byBucket} unit={e.unit as "hour" | "day"} />79 </Panel>8081 <Panel title={`By ${e.unit}`} flush className="mt-6">82 <EconTable rows={e.byBucket} labelHead={e.unit === "hour" ? "Hour" : "Day"} renderLabel={(r) => <span className="font-mono text-[12.5px]">{e.unit === "hour" ? new Date(r.key).toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : new Date(r.key).toLocaleDateString(undefined, { month: "short", day: "numeric" })}</span>} />83 </Panel>8485 <div className="mt-6 grid gap-6 xl:grid-cols-2">86 <Panel title="By plan" flush>87 <EconTable rows={e.byPlan} labelHead="Plan" renderLabel={(r) => <PlanBadge plan={r.key} />} />88 </Panel>89 <Panel title="By network" flush>90 <EconTable rows={e.byNetwork} labelHead="Network" renderLabel={(r) => <NetworkBadge network={r.key} />} />91 </Panel>92 </div>9394 <Panel title="By provider" description="Attempt-level. Attributed revenue = price of requests whose successful attempt ran on this provider." flush className="mt-6">95 <Table>96 <TableHeader>97 <TableRow>98 <TableHead>Provider</TableHead>99 <TableHead className="text-right">Attempts</TableHead>100 <TableHead className="text-right">Successes</TableHead>101 <TableHead className="text-right">Success</TableHead>102 <TableHead className="text-right">Upstream cost</TableHead>103 <TableHead className="text-right">Attributed revenue</TableHead>104 <TableHead className="text-right">Margin</TableHead>105 <TableHead className="text-right">Cost / success</TableHead>106 <TableHead className="text-right">GB</TableHead>107 </TableRow>108 </TableHeader>109 <TableBody>110 {e.byProvider.length === 0 ? (111 <TableEmpty colSpan={9}>No attempts in this range.</TableEmpty>112 ) : (113 e.byProvider.map((p) => (114 <TableRow key={p.provider}>115 <TableCell>116 <ProviderBadge id={p.provider} />117 </TableCell>118 <TableCell className={numCell}>{formatNumber(p.attempts)}</TableCell>119 <TableCell className={numCell}>{formatNumber(p.successes)}</TableCell>120 <TableCell className={numCell}>{formatPercent(p.attempts ? (p.successes / p.attempts) * 100 : null)}</TableCell>121 <TableCell className={numCell}>{formatUsd(p.cost, true)}</TableCell>122 <TableCell className={numCell}>{formatUsd(p.attributedRevenue, true)}</TableCell>123 <TableCell className="text-right">124 <MarginText value={p.attributedRevenue - p.cost} pct={p.attributedRevenue > 0 ? ((p.attributedRevenue - p.cost) / p.attributedRevenue) * 100 : null} />125 </TableCell>126 <TableCell className={`${numCell} font-semibold`}>{formatUsd(p.costPerSuccess, true)}</TableCell>127 <TableCell className={numCell}>{formatBytes(p.bytes)}</TableCell>128 </TableRow>129 ))130 )}131 </TableBody>132 </Table>133 </Panel>134135 <Panel title="Top 20 customers" description="Ordered by revenue in the selected range." flush className="mt-6">136 <Table>137 <TableHeader>138 <TableRow>139 <TableHead>Organization</TableHead>140 <TableHead>Plan</TableHead>141 <TableHead className="text-right">Requests</TableHead>142 <TableHead className="text-right">Success</TableHead>143 <TableHead className="text-right">Revenue</TableHead>144 <TableHead className="text-right">Upstream</TableHead>145 <TableHead className="text-right">Margin</TableHead>146 <TableHead className="text-right">GB</TableHead>147 </TableRow>148 </TableHeader>149 <TableBody>150 {e.topCustomers.length === 0 ? (151 <TableEmpty colSpan={8}>No customer activity in this range.</TableEmpty>152 ) : (153 e.topCustomers.map((c) => (154 <TableRow key={c.key}>155 <TableCell>156 <Link href={`/admin/organizations/${c.key}`} className="font-medium hover:underline">157 {c.name}158 </Link>159 </TableCell>160 <TableCell>161 <PlanBadge plan={c.plan} />162 </TableCell>163 <TableCell className={numCell}>{formatNumber(c.requests)}</TableCell>164 <TableCell className={numCell}>{formatPercent(c.requests ? (c.successes / c.requests) * 100 : null)}</TableCell>165 <TableCell className={numCell}>{formatUsd(c.revenue, true)}</TableCell>166 <TableCell className={numCell}>{formatUsd(c.cost, true)}</TableCell>167 <TableCell className="text-right">168 <MarginText value={c.margin} pct={c.marginPct} />169 </TableCell>170 <TableCell className={numCell}>{formatBytes(c.bytes)}</TableCell>171 </TableRow>172 ))173 )}174 </TableBody>175 </Table>176 </Panel>177 </>178 );179}180