'use client' import { useQuery } from '@tanstack/react-query' import { Loader2, BarChart2 } from 'lucide-react' import { useLanguage } from '@/lib/i18n' import { cn } from '@/lib/utils' interface BalanceData { totalRemaining: number | null subscriptionRemaining: number | null purchasedRemaining: number subscriptionGranted: number | null spentThisPeriod: number unlimited: boolean } interface BreakdownRow { feature: string creditsUsed: number actionsCount: number percentOfSpent: number } /** Toutes les fonctions IA — même liste que le compteur sidebar. */ const FEATURE_LABEL_KEYS: Record = { semantic_search: 'usageMeter.featureSearch', auto_tag: 'usageMeter.featureTags', auto_title: 'usageMeter.featureTitles', reformulate: 'usageMeter.featureReformulate', chat: 'usageMeter.featureChat', brainstorm_create: 'usageMeter.featureBrainstormSessions', brainstorm_expand: 'usageMeter.featureBrainstormExpand', brainstorm_enrich: 'usageMeter.featureBrainstormEnrich', suggest_charts: 'usageMeter.featureCharts', publish_enhance: 'usageMeter.featurePublishEnhance', ai_flashcard: 'usageMeter.featureFlashcards', voice_transcribe: 'usageMeter.featureVoice', slide_generate: 'usageMeter.featureSlides', excalidraw_generate: 'usageMeter.featureDiagrams', } function UsageBar({ percent }: { percent: number }) { return (
= 40 ? 'bg-primary' : 'bg-primary/60', )} style={{ width: `${Math.min(Math.max(percent, 0), 100)}%` }} />
) } export function UsageBreakdown() { const { t } = useLanguage() const { data, isLoading } = useQuery({ queryKey: ['usage', 'current'], queryFn: async () => { const res = await fetch('/api/usage/current') if (!res.ok) throw new Error('Failed to fetch usage') return res.json() as Promise<{ balance: BalanceData breakdown: BreakdownRow[] period: string tier: string }> }, }) const balance = data?.balance const byFeature = new Map((data?.breakdown ?? []).map((r) => [r.feature, r])) const spent = balance?.spentThisPeriod ?? 0 const rows = Object.keys(FEATURE_LABEL_KEYS).map((key) => { const row = byFeature.get(key) return { feature: key, label: t(FEATURE_LABEL_KEYS[key]), creditsUsed: row?.creditsUsed ?? 0, actionsCount: row?.actionsCount ?? 0, } }) return (

{t('billing.usageThisPeriod')}

{isLoading ? (
) : !balance ? (

{t('billing.noUsage')}

) : ( <>

{t('billing.creditsRemaining')}

{balance.unlimited ? t('billing.unlimited') : balance.totalRemaining}

{t('billing.creditsSpent')}

{balance.spentThisPeriod}

{t('billing.creditsFromPacks')}

{balance.purchasedRemaining}

{t('billing.creditsWhereTitle')}

{t('billing.creditsUsageLegend')}

{rows.map((row) => { const barPct = spent > 0 && row.creditsUsed > 0 ? Math.min(100, (row.creditsUsed / spent) * 100) : 0 return (
{row.label} 0 ? 'text-foreground' : 'text-muted-foreground/60', )} > {row.creditsUsed > 0 ? `${row.creditsUsed} cr. · ${row.actionsCount}×` : '0'}
) })}
)}
) }