import { Link } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { ArrowLeft } from 'lucide-react'; import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import { api } from '@/lib/api'; import { Spinner } from '@/components/ui/spinner'; import { chartPalette } from '@/theme/uqo'; interface Costs { budget: { budget_usd: number; spent_usd: number; ratio: number }; daily: { day: string; model: string; cost_usd: number; tokens_in: number; tokens_out: number; calls: number }[]; by_course: { course: string; cost_usd: number; calls: number }[]; models: Record } export function AdminCostsPage() { const { data } = useQuery({ queryKey: ['admin-costs'], queryFn: () => api('/admin/costs?days=30') }); if (!data) return
; const models = [...new Set(data.daily.map((d) => d.model))]; const byDay = new Map>(); for (const d of data.daily) { const row = byDay.get(d.day) || { day: d.day }; row[d.model] = ((row[d.model] as number) || 0) + d.cost_usd; byDay.set(d.day, row); } const rows = [...byDay.values()].sort((a, b) => String(a.day).localeCompare(String(b.day))); const daysElapsed = new Date().getDate(); const projected = daysElapsed ? (data.budget.spent_usd / daysElapsed) * 30 : 0; return (

Coûts OpenRouter

{[['Dépensé ce mois', `${data.budget.spent_usd.toFixed(2)} $`], ['Budget', `${data.budget.budget_usd} $`], ['Utilisation', `${Math.round(data.budget.ratio * 100)} %`], ['Projection mensuelle', `${projected.toFixed(2)} $`]].map(([l, v]) => (
{l}
{v}
))}

Coût par jour et par modèle ($ US)

String(d).slice(5)} fontSize={11} /> v.toFixed(4)} />{models.map((m, i) => )}

Par cours

{data.by_course.map((c) => )}
{c.course}{c.calls} appels{c.cost_usd.toFixed(3)} $

Modèles configurés

{Object.entries(data.models).map(([k, v]) => <>
{k}
{v}
)}
); }