"use client"; import React, { useEffect, useMemo, useState } from "react"; import { Bar, BarChart, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; import { AlertCircle, CheckCircle, TrendingUp } from "lucide-react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { assessWebVitals, type APIMetric, type PerformanceSummary } from "@/lib/performance-monitoring"; interface WebVitalsStatus { lcp: { value: number; status: "good" | "needs-improvement" | "poor" }; cls: { value: number; status: "good" | "needs-improvement" | "poor" }; fid: { value: number; status: "good" | "needs-improvement" | "poor" }; } interface MetricsResponse extends PerformanceSummary { apiMetrics: APIMetric[]; } interface AggregatedApiMetric { endpoint: string; avgDuration: number; maxDuration: number; } export function PerformanceDashboard() { const [metrics, setMetrics] = useState(null); const [vitalsStatus, setVitalsStatus] = useState(null); const [apiMetrics, setApiMetrics] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchMetrics() { try { const response = await fetch("/api/performance/metrics"); if (!response.ok) { throw new Error("Failed to fetch performance metrics"); } const data: MetricsResponse = await response.json(); setMetrics({ lcp: data.lcp, cls: data.cls, fid: data.fid, avgAPITime: data.avgAPITime, slowRequests: data.slowRequests, cachedRequests: data.cachedRequests, totalRequests: data.totalRequests, cacheHitRate: data.cacheHitRate, }); setApiMetrics(data.apiMetrics || []); } catch (error) { console.error("Failed to fetch metrics:", error); } finally { setLoading(false); } } setVitalsStatus(assessWebVitals() as WebVitalsStatus); void fetchMetrics(); const interval = setInterval(() => { void fetchMetrics(); }, 30000); return () => clearInterval(interval); }, []); const aggregatedApiMetrics = useMemo(() => { const byEndpoint = new Map(); for (const metric of apiMetrics) { const current = byEndpoint.get(metric.endpoint) || { total: 0, count: 0, max: 0 }; current.total += metric.duration; current.count += 1; current.max = Math.max(current.max, metric.duration); byEndpoint.set(metric.endpoint, current); } return Array.from(byEndpoint.entries()) .map(([endpoint, data]) => ({ endpoint, avgDuration: data.total / data.count, maxDuration: data.max, })) .sort((a, b) => b.avgDuration - a.avgDuration) .slice(0, 10); }, [apiMetrics]); const getStatusColor = (status: string) => { switch (status) { case "good": return "text-green-600"; case "needs-improvement": return "text-yellow-600"; case "poor": return "text-red-600"; default: return "text-gray-600"; } }; const getStatusIcon = (status: string) => { if (status === "good") { return ; } if (status === "poor") { return ; } return ; }; if (loading) { return (
{Array.from({ length: 3 }).map((_, index) => (
))}
); } return (
{vitalsStatus && ( <> Largest Contentful Paint (LCP) Page loading performance

{vitalsStatus.lcp.value.toFixed(0)}ms

{vitalsStatus.lcp.status === "good" ? "Good (<=2500ms)" : vitalsStatus.lcp.status === "needs-improvement" ? "Needs Improvement (2500-4000ms)" : "Poor (>4000ms)"}

{getStatusIcon(vitalsStatus.lcp.status)}
Cumulative Layout Shift (CLS) Visual stability

{vitalsStatus.cls.value.toFixed(3)}

{vitalsStatus.cls.status === "good" ? "Good (<=0.1)" : vitalsStatus.cls.status === "needs-improvement" ? "Needs Improvement (0.1-0.25)" : "Poor (>0.25)"}

{getStatusIcon(vitalsStatus.cls.status)}
First Input Delay (FID) Interactivity responsiveness

{vitalsStatus.fid.value.toFixed(0)}ms

{vitalsStatus.fid.status === "good" ? "Good (<=100ms)" : vitalsStatus.fid.status === "needs-improvement" ? "Needs Improvement (100-300ms)" : "Poor (>300ms)"}

{getStatusIcon(vitalsStatus.fid.status)}
)}
{metrics && ( <>
API Performance

Average Response Time

{metrics.avgAPITime.toFixed(0)}ms

Slow Requests (>1s)

{metrics.slowRequests}

Caching Efficiency

Cache Hit Rate

{metrics.cacheHitRate.toFixed(1)}%

Cached Requests

{metrics.cachedRequests}/{metrics.totalRequests}

Request Distribution API endpoint response times distribution
)} Performance Tips

Enable Caching

Current cache hit rate: {metrics?.cacheHitRate.toFixed(1)}%

Monitor Slow Requests

{metrics?.slowRequests} requests took longer than 1 second

Bundle Analysis

Use "npm run build:analyze" to identify large dependencies

); }