import { useMemo, useCallback } from 'react';
import { useScenarios } from '@/hooks/useScenarios';
import { Activity, DollarSign, Server, AlertTriangle, TrendingUp } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { CostBreakdownChart } from '@/components/charts';
import { formatCurrency, formatNumber } from '@/components/charts/chart-utils';
import { Skeleton } from '@/components/ui/skeleton';
import { Link } from 'react-router-dom';
import { analytics, useFeatureTracking } from '@/components/analytics/analytics-service';
import { useTranslation } from 'react-i18next';
interface StatCardProps {
title: string;
value: string | number;
description?: string;
icon: React.ElementType;
trend?: 'up' | 'down' | 'neutral';
href?: string;
}
const StatCard = ({
title,
value,
description,
icon: Icon,
trend,
href,
}: StatCardProps) => {
const content = (
{title}
{value}
{trend && (
{trend === 'up' ? 'Increasing' : trend === 'down' ? 'Decreasing' : 'Stable'}
)}
{description && (
{description}
)}
);
if (href) {
return (
{content}
);
}
return content;
};
export function Dashboard() {
const { t } = useTranslation();
const { data: scenarios, isLoading: scenariosLoading } = useScenarios(1, 100);
const trackFeature = useFeatureTracking();
// Track dashboard view
const trackDashboardClick = useCallback((feature: string) => {
trackFeature(feature);
analytics.trackFeatureUsage(`dashboard_click_${feature}`);
}, [trackFeature]);
// Aggregate metrics from all scenarios
const totalScenarios = scenarios?.total || 0;
const runningScenarios = useMemo(
() => scenarios?.items.filter(s => s.status === 'running').length || 0,
[scenarios?.items]
);
const totalCost = useMemo(
() => scenarios?.items.reduce((sum, s) => sum + s.total_cost_estimate, 0) || 0,
[scenarios?.items]
);
// Calculate cost breakdown
const costBreakdown = useMemo(() => [
{ service: 'SQS', cost_usd: totalCost * 0.35, percentage: 35 },
{ service: 'Lambda', cost_usd: totalCost * 0.25, percentage: 25 },
{ service: 'Bedrock', cost_usd: totalCost * 0.40, percentage: 40 },
].filter(item => item.cost_usd > 0), [totalCost]);
if (scenariosLoading) {
return (
{[...Array(4)].map((_, i) => (
))}
);
}
return (
{t('dashboard.title')}
{t('dashboard.subtitle')}
trackDashboardClick('scenarios')}>
0 ? 'up' : 'neutral'}
/>
{/* Charts Section */}
{costBreakdown.length > 0 && (
)}
{t('dashboard.recent_activity')}
Latest scenario executions
{scenarios?.items.slice(0, 5).map((scenario) => (
trackDashboardClick('recent_scenario')}
>
{scenario.name}
{scenario.region}
{formatCurrency(scenario.total_cost_estimate)}
{formatNumber(scenario.total_requests)} requests
))}
{(!scenarios?.items || scenarios.items.length === 0) && (
No scenarios yet. Create one to get started.
)}
{/* Quick Actions */}
{t('dashboard.quick_actions')}
trackDashboardClick('view_all')}>
trackDashboardClick('analytics')}>
);
}