import React, { useState, useEffect } from 'react'; import { Box, Chip, Typography, Tooltip, CircularProgress, Alert, IconButton, Menu, MenuItem, Divider, LinearProgress } from '@mui/material'; import { TrendingUp, TrendingDown, Warning, CheckCircle, Refresh, MoreVert, Dashboard } from '@mui/icons-material'; import { apiClient } from '../../api/client'; import { useSubscription } from '../../contexts/SubscriptionContext'; interface UsageStats { total_calls: number; total_cost: number; usage_status: string; provider_breakdown: Record; } interface UsageLimits { limits: { gemini_calls: number; openai_calls: number; anthropic_calls: number; mistral_calls: number; tavily_calls: number; serper_calls: number; metaphor_calls: number; firecrawl_calls: number; stability_calls: number; monthly_cost: number; }; } interface DashboardData { current_usage: UsageStats; limits: UsageLimits; projections: { projected_monthly_cost: number; cost_limit: number; projected_usage_percentage: number; }; summary: { total_api_calls_this_month: number; total_cost_this_month: number; usage_status: string; unread_alerts: number; }; } interface UsageDashboardProps { compact?: boolean; showFullDashboard?: boolean; } const UsageDashboard: React.FC = ({ compact = true, showFullDashboard = false }) => { const { subscription } = useSubscription(); const [dashboardData, setDashboardData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [anchorEl, setAnchorEl] = useState(null); const [lastUpdated, setLastUpdated] = useState(null); const userId = localStorage.getItem('user_id'); const fetchUsageData = async () => { if (!userId) return; setLoading(true); setError(null); try { const response = await apiClient.get(`/api/subscription/dashboard/${userId}`); setDashboardData(response.data.data); setLastUpdated(new Date()); } catch (err) { console.error('Error fetching usage data:', err); setError('Failed to load usage data'); } finally { setLoading(false); } }; useEffect(() => { fetchUsageData(); }, [userId]); const handleRefresh = () => { fetchUsageData(); }; const handleMenuOpen = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; const handleMenuClose = () => { setAnchorEl(null); }; const handleViewFullDashboard = () => { handleMenuClose(); window.open('/billing', '_blank'); }; const getUsageColor = (used: number, limit: number) => { const percentage = (used / limit) * 100; if (percentage >= 90) return '#f44336'; // Red if (percentage >= 75) return '#ff9800'; // Orange if (percentage >= 50) return '#ffeb3b'; // Yellow return '#4caf50'; // Green }; const getUsageStatusIcon = (status: string) => { switch (status) { case 'active': return ; case 'warning': return ; case 'limit_exceeded': return ; default: return ; } }; const getProviderDisplayName = (provider: string) => { const names: Record = { 'gemini': 'Gemini', 'openai': 'OpenAI', 'anthropic': 'Claude', 'mistral': 'Mistral', 'tavily': 'Tavily', 'serper': 'Serper', 'metaphor': 'Metaphor', 'firecrawl': 'Firecrawl', 'stability': 'Stability' }; return names[provider] || provider; }; if (!subscription || !dashboardData) { if (loading) { return ( Loading usage... ); } if (error) { return ( {error} ); } return null; } if (compact) { // Compact view - show key metrics as chips const totalCalls = dashboardData.summary.total_api_calls_this_month; const totalCost = dashboardData.summary.total_cost_this_month; const monthlyLimit = dashboardData.limits.limits.monthly_cost; const usagePercentage = (totalCost / monthlyLimit) * 100; return ( {/* Total API Calls */} {/* Monthly Cost */} } label={`$${totalCost.toFixed(2)}`} size="small" variant="outlined" sx={{ bgcolor: `${getUsageColor(totalCost, monthlyLimit)}20`, borderColor: getUsageColor(totalCost, monthlyLimit), color: getUsageColor(totalCost, monthlyLimit), fontWeight: 600, '& .MuiChip-icon': { color: getUsageColor(totalCost, monthlyLimit) } }} /> {/* Usage Progress */} {usagePercentage.toFixed(0)}% {/* Refresh Button */} {/* More Options */} View Full Dashboard Refresh Data {lastUpdated && ( Last updated: {lastUpdated.toLocaleTimeString()} )} ); } // Full dashboard view (for dedicated usage page) return ( Usage Dashboard {/* Total Calls */} Total API Calls {dashboardData.summary.total_api_calls_this_month.toLocaleString()} {/* Total Cost */} Monthly Cost ${dashboardData.summary.total_cost_this_month.toFixed(2)} of ${dashboardData.limits.limits.monthly_cost} limit {/* Usage by Provider */} Usage by Provider {Object.entries(dashboardData.current_usage.provider_breakdown).map(([provider, stats]) => ( {getProviderDisplayName(provider)} {stats.calls.toLocaleString()} ))} ); }; export default UsageDashboard;