import { useState, useEffect } from 'react'; import { RefreshCw, Trash2, BarChart3 } from 'lucide-react'; interface TokenUsageSummary { promptTokens: number; completionTokens: number; totalTokens: number; requestCount: number; } interface ModelBreakdown { [key: string]: { promptTokens: number; completionTokens: number; totalTokens: number; requestCount: number; }; } interface TokenUsageHistory { timestamp: number; conversationId: string; model: string; promptTokens: number; completionTokens: number; totalTokens: number; } interface TokenUsageData { summary: TokenUsageSummary; modelBreakdown: ModelBreakdown; history: TokenUsageHistory[]; } type TimePeriod = 'all' | 'today' | 'week'; export default function TokenUsagePanel() { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [period, setPeriod] = useState('all'); const [expandedModel, setExpandedModel] = useState(null); const fetchData = async () => { setLoading(true); try { const res = await fetch(`/api/token-usage?period=${period}`); const result = await res.json(); setData(result); } catch (err) { console.error('Failed to fetch token usage:', err); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, [period]); const handleClear = async () => { if (!confirm('Clear all token usage data?')) return; try { await fetch('/api/token-usage', { method: 'DELETE' }); setData(null); fetchData(); } catch (err) { console.error('Failed to clear token usage:', err); } }; const formatNumber = (n: number) => n.toLocaleString(); const formatTime = (timestamp: number) => { const date = new Date(timestamp); return date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }); }; return (
{/* Header */}

Token Usage

{/* Period filter */}
{(['all', 'today', 'week'] as TimePeriod[]).map((p) => { const labels = { all: 'All', today: 'Today', week: 'Week' }; return ( ); })}
{/* Summary */} {data && data.summary.requestCount > 0 ? (

Total Tokens

{formatNumber(data.summary.totalTokens)}

Requests

{data.summary.requestCount}

Prompt Tokens

{formatNumber(data.summary.promptTokens)}

Completion Tokens

{formatNumber(data.summary.completionTokens)}

) : (
{loading ? 'Loading...' : 'No token usage data yet'}
)} {/* Model breakdown */} {data && Object.keys(data.modelBreakdown).length > 0 && (

By Model

{Object.entries(data.modelBreakdown) .sort((a, b) => b[1].totalTokens - a[1].totalTokens) .map(([model, stats]) => (
{expandedModel === model && (
{/* Simple bar chart */}
Prompt
0 ? (stats.promptTokens / stats.totalTokens) * 100 : 0 }%`, }} />
{formatNumber(stats.promptTokens)}
Completion
0 ? (stats.completionTokens / stats.totalTokens) * 100 : 0 }%`, }} />
{formatNumber(stats.completionTokens)}
{/* Show recent history for this model */} {data.history.filter((h) => h.model === model).length > 0 && (

Recent requests

{data.history .filter((h) => h.model === model) .slice(-5) .reverse() .map((entry, i) => (
{formatTime(entry.timestamp)} {formatNumber(entry.totalTokens)} tokens
))}
)}
)}
))}
)} {/* History timeline */} {data && data.history.length > 0 && (

Recent History

{data.history.slice(-10).reverse().map((entry, i) => (
{formatTime(entry.timestamp)} {entry.model} {formatNumber(entry.totalTokens)}
))}
)}
); }