'use client'; import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useRouter } from 'next/navigation'; import { cn } from '@/lib/utils'; import { Sparkles, X, Crown } from 'lucide-react'; import { useLanguage } from '@/lib/i18n'; interface QuotaData { remaining: number; limit: number; used: number; } interface UsageMeterProps { className?: string; } function formatRemaining(value: number): string { if (!Number.isFinite(value)) return '∞'; return String(value); } export function UsageMeter({ className }: UsageMeterProps) { const { t } = useLanguage(); const router = useRouter(); const [showModal, setShowModal] = useState(false); 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 quotas'); const data = await res.json(); return data.quotas as Record; }, refetchInterval: 30000, }); if (isLoading || !data) { return (
); } const features = [ { key: 'semantic_search', labelKey: 'usageMeter.featureSearch' as const }, { key: 'auto_tag', labelKey: 'usageMeter.featureTags' as const }, { key: 'auto_title', labelKey: 'usageMeter.featureTitles' as const }, ] as const; const featureQuotas = features.map((f) => { const quota = data[f.key]; return { ...f, label: t(f.labelKey), used: quota?.used ?? 0, limit: quota?.limit ?? 0, remaining: quota?.remaining ?? 0, }; }); const isUnlimited = featureQuotas.every((f) => !Number.isFinite(f.limit)); const totalRemaining = featureQuotas.reduce( (sum, f) => sum + (Number.isFinite(f.remaining) ? f.remaining : 0), 0, ); const totalLimit = featureQuotas.reduce( (sum, f) => sum + (Number.isFinite(f.limit) ? f.limit : 0), 0, ); const used = totalLimit - totalRemaining; const percentage = totalLimit > 0 ? Math.min((used / totalLimit) * 100, 100) : 0; const isExhausted = !isUnlimited && totalRemaining <= 0; const isLow = !isUnlimited && percentage >= 75 && !isExhausted; return ( <>
{t('usageMeter.packName')}
{isUnlimited ? t('usageMeter.unlimited') : t('usageMeter.remaining', { count: totalRemaining })}
{!isUnlimited && (
)}
{showModal && (

{t('usageMeter.upgradeTitle')}

{t('usageMeter.upgradeDescription')}

{t('usageMeter.proIncludes')}
  • • {t('usageMeter.proSearch')}
  • • {t('usageMeter.proTags')}
  • • {t('usageMeter.proTitles')}
  • • {t('usageMeter.proReformulate')}
  • • {t('usageMeter.proChat')}
)} ); }