import React from 'react'; import { useTranslation } from 'react-i18next'; import { AlertTriangle, TrendingUp, ArrowUpRight, Infinity } from 'lucide-react'; import { Card, Button } from '../ui'; import type { SubscriptionTier } from '../../api'; interface UsageMetricCardProps { metric: string; label: string; current: number; limit: number | null; // null = unlimited unit?: string; trend?: number[]; // 30-day history predictedBreachDate?: string | null; daysUntilBreach?: number | null; currentTier: SubscriptionTier; upgradeTier?: SubscriptionTier; upgradeLimit?: number | null; onUpgrade?: () => void; icon?: React.ReactNode; } export const UsageMetricCard: React.FC = ({ metric, label, current, limit, unit = '', trend, predictedBreachDate, daysUntilBreach, currentTier, upgradeTier = 'professional', upgradeLimit, onUpgrade, icon }) => { const { t } = useTranslation('subscription'); // Calculate percentage const percentage = limit ? Math.min((current / limit) * 100, 100) : 0; const isUnlimited = limit === null || limit === -1; // Determine status color const getStatusColor = () => { if (isUnlimited) return 'green'; if (percentage >= 90) return 'red'; if (percentage >= 80) return 'yellow'; return 'green'; }; const statusColor = getStatusColor(); // Color classes const colorClasses = { green: { bg: 'bg-green-500', text: 'text-green-600 dark:text-green-400', border: 'border-green-500', bgLight: 'bg-green-50 dark:bg-green-900/20', ring: 'ring-green-500/20' }, yellow: { bg: 'bg-yellow-500', text: 'text-yellow-600 dark:text-yellow-400', border: 'border-yellow-500', bgLight: 'bg-yellow-50 dark:bg-yellow-900/20', ring: 'ring-yellow-500/20' }, red: { bg: 'bg-red-500', text: 'text-red-600 dark:text-red-400', border: 'border-red-500', bgLight: 'bg-red-50 dark:bg-red-900/20', ring: 'ring-red-500/20' } }; const colors = colorClasses[statusColor]; // Format display value const formatValue = (value: number | null) => { if (value === null || value === -1) return t('limits.unlimited'); return `${value.toLocaleString()}${unit}`; }; // Render trend sparkline const renderSparkline = () => { if (!trend || trend.length === 0) return null; const max = Math.max(...trend, current); const min = Math.min(...trend, 0); const range = max - min || 1; const points = trend.map((value, index) => { const x = (index / (trend.length - 1)) * 100; const y = 100 - ((value - min) / range) * 100; return `${x},${y}`; }).join(' '); return (
); }; return ( {/* Header */}
{icon &&
{icon}
}

{label}

{currentTier.charAt(0).toUpperCase() + currentTier.slice(1)} tier

{/* Status Badge */} {!isUnlimited && (
{Math.round(percentage)}%
)}
{/* Usage Display */}
{formatValue(current)} / {formatValue(limit)}
{/* Progress Bar */} {!isUnlimited && (
)}
{/* Trend Sparkline */} {trend && trend.length > 0 && (
30-day trend
{renderSparkline()}
)} {/* Warning Message */} {!isUnlimited && percentage >= 80 && (
{daysUntilBreach !== null && daysUntilBreach !== undefined && daysUntilBreach > 0 ? (

You'll hit your limit in ~{daysUntilBreach} days

) : percentage >= 100 ? (

You've reached your limit

) : (

You're approaching your limit

)}
)} {/* Upgrade CTA */} {!isUnlimited && percentage >= 80 && upgradeTier && onUpgrade && (
Upgrade to {upgradeTier.charAt(0).toUpperCase() + upgradeTier.slice(1)} {formatValue(upgradeLimit)}
{upgradeTier === 'professional' && (

{upgradeLimit === null || upgradeLimit === -1 ? 'Get unlimited capacity' : `${((upgradeLimit || 0) / (limit || 1) - 1) * 100}x more capacity` }

)}
)} {/* Unlimited Badge */} {isUnlimited && (

Unlimited

)} ); };