diff --git a/src/pages/admin/AdminClientPerformancePage.tsx b/src/pages/admin/AdminClientPerformancePage.tsx index b2bbf25d9..06a5acf23 100644 --- a/src/pages/admin/AdminClientPerformancePage.tsx +++ b/src/pages/admin/AdminClientPerformancePage.tsx @@ -3,28 +3,29 @@ import { PageSEO } from '@/components/seo/PageSEO'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; -import { - Activity, - Clock, - Trash2, - RefreshCw, - Zap, - BarChart3, - Layout, +import { + Activity, + Clock, + Trash2, + RefreshCw, + Zap, + BarChart3, + Layout, Palette, - Timer + Timer, + type LucideIcon, } from 'lucide-react'; -import { - LineChart, - Line, - XAxis, - YAxis, - CartesianGrid, - Tooltip as RechartsTooltip, +import { + LineChart, + Line, + XAxis, + YAxis, + CartesianGrid, + Tooltip as RechartsTooltip, ResponsiveContainer, BarChart, Bar, - Cell + Cell, } from 'recharts'; import { performanceTracker, type PerformanceMetric } from '@/utils/performance'; import { format } from 'date-fns'; @@ -36,122 +37,124 @@ export default function AdminClientPerformancePage() { useEffect(() => { setMetrics(performanceTracker.getHistory()); - + // Auto-refresh stats every 5s if there's activity const interval = setInterval(() => { setMetrics(performanceTracker.getHistory()); }, 5000); - + return () => clearInterval(interval); }, [tick]); const handleClear = () => { performanceTracker.clear(); setMetrics([]); - setTick(t => t + 1); + setTick((t) => t + 1); }; - const routeMetrics = metrics.filter(m => m.name.startsWith('Route:')); - const themeMetrics = metrics.filter(m => m.name.startsWith('Theme:')); - - const avgRouteTime = routeMetrics.length - ? routeMetrics.reduce((acc, m) => acc + m.duration, 0) / routeMetrics.length + const routeMetrics = metrics.filter((m) => m.name.startsWith('Route:')); + const themeMetrics = metrics.filter((m) => m.name.startsWith('Theme:')); + + const avgRouteTime = routeMetrics.length + ? routeMetrics.reduce((acc, m) => acc + m.duration, 0) / routeMetrics.length : 0; - - const avgThemeTime = themeMetrics.length - ? themeMetrics.reduce((acc, m) => acc + m.duration, 0) / themeMetrics.length + + const avgThemeTime = themeMetrics.length + ? themeMetrics.reduce((acc, m) => acc + m.duration, 0) / themeMetrics.length : 0; - const chartData = metrics.map(m => ({ + const chartData = metrics.map((m) => ({ ...m, time: format(m.timestamp, 'HH:mm:ss'), - shortName: m.name.replace('Route: ', '').replace('Theme: ', '') + shortName: m.name.replace('Route: ', '').replace('Theme: ', ''), })); - const COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899']; - return ( <> - - -
+ +
{/* Header */} -
+
-
+
-

Performance Client-side

-

Métricas de experiência do usuário (UX) em tempo real

+

+ Performance Client-side +

+

+ Métricas de experiência do usuário (UX) em tempo real +

- +
- -
{/* KPIs */} -
- + 500 ? 'warning' : 'success'} /> - 300 ? 'warning' : 'success'} /> - -
{/* Charts Section */} -
+
{/* Timeline Chart */} - +
- + Timeline de Latência @@ -164,35 +167,39 @@ export default function AdminClientPerformancePage() { {metrics.length > 0 ? ( - - + - - - @@ -206,9 +213,9 @@ export default function AdminClientPerformancePage() { {/* Distribution Chart */} - + - + Distribuição por Tipo @@ -218,32 +225,38 @@ export default function AdminClientPerformancePage() {
{metrics.length > 0 ? ( - - - + + - - @@ -261,7 +274,7 @@ export default function AdminClientPerformancePage() {
{/* Logs Table */} - + Log Detalhado de Eventos Lista completa dos últimos 50 eventos medidos @@ -278,30 +291,41 @@ export default function AdminClientPerformancePage() { - {[...metrics].reverse().map((m, i) => ( - - - {m.name} - - - {format(m.timestamp, 'dd/MM/yyyy HH:mm:ss')} - - - {m.duration.toFixed(2)}ms - - - 500 ? 'destructive' : m.duration > 200 ? 'warning' : 'secondary'} - className="text-[10px] px-2 py-0" - > - {m.duration > 500 ? 'Lento' : m.duration > 200 ? 'Ok' : 'Excelente'} - - - - ))} + {[...metrics].reverse().map((m, i) => { + const isSlow = m.duration > 500; + const isWarning = !isSlow && m.duration > 200; + + return ( + + + {m.name} + + + {format(m.timestamp, 'dd/MM/yyyy HH:mm:ss')} + + + {m.duration.toFixed(2)}ms + + + + {isSlow ? 'Lento' : isWarning ? 'Ok' : 'Excelente'} + + + + ); + })} {metrics.length === 0 && ( - + Nenhum log disponível. @@ -316,34 +340,50 @@ export default function AdminClientPerformancePage() { ); } -function StatCard({ icon: Icon, label, value, sub, status }: { - icon: any, - label: string, - value: string, - sub: string, - status?: 'success' | 'warning' | 'destructive' -}) { +interface StatCardProps { + icon: LucideIcon; + label: string; + value: string; + sub: string; + status?: 'success' | 'warning' | 'destructive'; +} + +function StatCard({ icon, label, value, sub, status }: StatCardProps) { + const Icon = icon; + return ( - - -
+ + +
-

{label}

-

{value}

-

{sub}

+

+ {label} +

+

{value}

+

{sub}

@@ -352,9 +392,9 @@ function StatCard({ icon: Icon, label, value, sub, status }: { function EmptyState({ message }: { message: string }) { return ( -
+

{message}

); -} \ No newline at end of file +}