'use client' import { useState, useMemo } from 'react' import type { TokenKpi, TokenJobRow } from '@/lib/insights/token-stats' export interface TokenUsageCardProps { kpi: TokenKpi jobs: TokenJobRow[] } type SortKey = 'cost' | 'duration' function fmt(n: number | null, decimals = 0): string { if (n === null) return '—' return n.toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals }) } function fmtCost(n: number | null): string { if (n === null) return '—' return '$' + n.toFixed(4) } function jobLabel(job: TokenJobRow): string { const label = job.taskTitle ?? job.ideaCode ?? job.jobId return label.length > 40 ? label.slice(0, 37) + '…' : label } export function TokenUsageCard({ kpi, jobs }: TokenUsageCardProps) { const [sortKey, setSortKey] = useState('cost') const sorted = useMemo(() => { return [...jobs].sort((a, b) => { if (sortKey === 'cost') return (b.costUsd ?? -Infinity) - (a.costUsd ?? -Infinity) return (b.durationSeconds ?? -Infinity) - (a.durationSeconds ?? -Infinity) }) }, [jobs, sortKey]) if (kpi.jobCount === 0) { return

Geen token-data

} return (
{/* KPI strip */}
{kpi.totalTokens.toLocaleString()}
Totaal tokens
${kpi.totalCostUsd.toFixed(4)}
Kosten (USD)
{kpi.avgCostPerJob ? '$' + kpi.avgCostPerJob.toFixed(4) : '—'}
Gem. per job
{/* Sortable table */}
{sorted.map(job => ( ))}
Taak Model Input Output Cache-R Cache-W setSortKey('cost')} > Kosten (USD) {sortKey === 'cost' ? '▾' : ''} setSortKey('duration')} > Duur (s) {sortKey === 'duration' ? '▾' : ''}
{jobLabel(job)} {job.modelId ?? '—'} {fmt(job.inputTokens)} {fmt(job.outputTokens)} {fmt(job.cacheReadTokens)} {fmt(job.cacheWriteTokens)} {fmtCost(job.costUsd)} {fmt(job.durationSeconds, 1)}
) }