From 6f4e57eeff66c32124e96dc7cb3c588076ce4238 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Sun, 23 Nov 2025 13:17:24 -0800 Subject: [PATCH] feat(ui): apply global currency formatting to stats components - Update UsageSummaryCards to use global currency store and formatting - Update RevenueByModelTable to use global currency store and formatting - Ensure consistent sat/msat/usd display across all dashboard metrics --- ui/components/revenue-by-model-table.tsx | 32 +++++++++++++++------ ui/components/usage-summary-cards.tsx | 36 +++++++++++++++--------- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/ui/components/revenue-by-model-table.tsx b/ui/components/revenue-by-model-table.tsx index 867d911b..20a2c8b6 100644 --- a/ui/components/revenue-by-model-table.tsx +++ b/ui/components/revenue-by-model-table.tsx @@ -11,6 +11,10 @@ import { import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { ModelRevenueData } from '@/lib/api/services/admin'; +import { useCurrencyStore } from '@/lib/stores/currency'; +import { useQuery } from '@tanstack/react-query'; +import { fetchBtcUsdPrice, btcToSatsRate } from '@/lib/exchange-rate'; +import { formatFromMsat, convertToMsat } from '@/lib/currency'; interface RevenueByModelTableProps { models: ModelRevenueData[]; @@ -21,12 +25,24 @@ export function RevenueByModelTable({ models, totalRevenue, }: RevenueByModelTableProps) { + const { displayUnit } = useCurrencyStore(); + const { data: btcUsdPrice } = useQuery({ + queryKey: ['btc-usd-price'], + queryFn: fetchBtcUsdPrice, + refetchInterval: 120_000, + staleTime: 60_000, + }); + const usdPerSat = btcUsdPrice ? btcToSatsRate(btcUsdPrice) : null; + + const formatAmount = (sats: number) => + formatFromMsat(convertToMsat(sats, 'sat'), displayUnit, usdPerSat); + return ( Revenue by Model

- Total Revenue: {totalRevenue.toLocaleString(undefined, { maximumFractionDigits: 2 })} sats + Total Revenue: {formatAmount(totalRevenue)}

@@ -37,10 +53,10 @@ export function RevenueByModelTable({ Requests Successful Failed - Revenue (sats) + Revenue Share - Refunds (sats) - Net Revenue (sats) + Refunds + Net Revenue Avg/Request @@ -61,7 +77,7 @@ export function RevenueByModelTable({ {model.successful} {model.failed} - {model.revenue_sats.toLocaleString(undefined, { maximumFractionDigits: 2 })} + {formatAmount(model.revenue_sats)}
@@ -70,13 +86,13 @@ export function RevenueByModelTable({
- {model.refunds_sats.toLocaleString(undefined, { maximumFractionDigits: 2 })} + {formatAmount(model.refunds_sats)} - {model.net_revenue_sats.toLocaleString(undefined, { maximumFractionDigits: 2 })} + {formatAmount(model.net_revenue_sats)} - {model.avg_revenue_per_request.toLocaleString(undefined, { maximumFractionDigits: 3 })} + {formatAmount(model.avg_revenue_per_request)} ); diff --git a/ui/components/usage-summary-cards.tsx b/ui/components/usage-summary-cards.tsx index 2ca842ae..88224957 100644 --- a/ui/components/usage-summary-cards.tsx +++ b/ui/components/usage-summary-cards.tsx @@ -14,12 +14,28 @@ import { TrendingDown, Coins, } from 'lucide-react'; +import { useCurrencyStore } from '@/lib/stores/currency'; +import { useQuery } from '@tanstack/react-query'; +import { fetchBtcUsdPrice, btcToSatsRate } from '@/lib/exchange-rate'; +import { formatFromMsat } from '@/lib/currency'; interface UsageSummaryCardsProps { summary: UsageSummary; } export function UsageSummaryCards({ summary }: UsageSummaryCardsProps) { + const { displayUnit } = useCurrencyStore(); + const { data: btcUsdPrice } = useQuery({ + queryKey: ['btc-usd-price'], + queryFn: fetchBtcUsdPrice, + refetchInterval: 120_000, + staleTime: 60_000, + }); + const usdPerSat = btcUsdPrice ? btcToSatsRate(btcUsdPrice) : null; + + const formatAmount = (msat: number) => + formatFromMsat(msat, displayUnit, usdPerSat); + const cards = [ { title: 'Total Requests', @@ -34,32 +50,26 @@ export function UsageSummaryCards({ summary }: UsageSummaryCardsProps) { color: 'text-green-500', }, { - title: 'Revenue (sats)', - value: summary.revenue_sats.toLocaleString(undefined, { - maximumFractionDigits: 2, - }), + title: 'Revenue', + value: formatAmount(summary.revenue_msats), icon: Coins, color: 'text-green-600', }, { - title: 'Net Revenue (sats)', - value: summary.net_revenue_sats.toLocaleString(undefined, { - maximumFractionDigits: 2, - }), + title: 'Net Revenue', + value: formatAmount(summary.net_revenue_msats), icon: DollarSign, color: 'text-emerald-600', }, { - title: 'Refunds (sats)', - value: summary.refunds_sats.toLocaleString(undefined, { - maximumFractionDigits: 2, - }), + title: 'Refunds', + value: formatAmount(summary.refunds_msats), icon: TrendingDown, color: 'text-red-500', }, { title: 'Avg Revenue/Request', - value: `${(summary.avg_revenue_per_request_msats / 1000).toLocaleString(undefined, { maximumFractionDigits: 3 })} sats`, + value: formatAmount(summary.avg_revenue_per_request_msats), icon: CreditCard, color: 'text-cyan-500', },