Untitled
'use client' import { useEffect, useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, LineChart, Line, PieChart, Pie, Cell } from 'recharts'; import { Trash2, Recycle, Clock, BarChart2, Calendar, Zap, TrendingUp, RatioIcon as Balance, Timer } from 'lucide-react'; interface StatsData { totalItemsSorted: number; itemsPerWasteType: Record<string, number>; sortingTimestamps: Array<{ timestamp: string; wasteType: string }>; bins: Array<{ id: number; type: string; fillLevel: number; emptyings: number }>; modelUsage: { api: number; local: number }; dailyUsage: Array<{ date: string; count: number }>; weeklyUsage: Array<{ week: string; count: number }>; monthlyUsage: Array<{ month: string; count: number }>; timeBetweenSorts: { average: number; min: number; max: number }; timeOfDayPatterns: Array<{ hour: number; count: number }>; streaks: { daily: number; weekly: number; monthly: number }; binMetrics: { timeTo90PercentFull: { average: number; min: number; max: number }; fillRate: { average: number; min: number; max: number }; fillLevelBalance: number; }; classificationResponseTimes: { average: number; min: number; max: number }; } export default function StatsDisplay() { const [stats, setStats] = useState<StatsData | null>(null); useEffect(() => { fetch('/home/SortiMate/web/stats.json') .then(response => response.json()) .then(data => setStats(data)); }, []); if (!stats) return null; const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884D8']; return ( <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Total Items Sorted</CardTitle> <Trash2 className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="text-2xl font-bold">{stats.totalItemsSorted}</div> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Items per Waste Type</CardTitle> <Recycle className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <PieChart> <Pie data={Object.entries(stats.itemsPerWasteType).map(([name, value]) => ({ name, value }))} cx="50%" cy="50%" outerRadius={80} fill="#8884d8" dataKey="value" label > {Object.entries(stats.itemsPerWasteType).map((entry, index) => ( <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} /> ))} </Pie> <Tooltip /> <Legend /> </PieChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Sorting Timestamps</CardTitle> <Clock className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <LineChart data={stats.sortingTimestamps.slice(-50)}> <XAxis dataKey="timestamp" /> <YAxis /> <Tooltip /> <Line type="monotone" dataKey="wasteType" stroke="#8884d8" /> </LineChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Fill Levels per Bin</CardTitle> <BarChart2 className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <BarChart data={stats.bins}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="type" /> <YAxis /> <Tooltip /> <Legend /> <Bar dataKey="fillLevel" fill="#8884d8" /> </BarChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">API vs Local Model Usage</CardTitle> <Zap className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <PieChart> <Pie data={[ { name: 'API', value: stats.modelUsage.api }, { name: 'Local', value: stats.modelUsage.local } ]} cx="50%" cy="50%" outerRadius={80} fill="#8884d8" dataKey="value" label > <Cell fill="#0088FE" /> <Cell fill="#00C49F" /> </Pie> <Tooltip /> <Legend /> </PieChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Usage Counts</CardTitle> <Calendar className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <LineChart> <XAxis dataKey="date" /> <YAxis /> <Tooltip /> <Legend /> <Line type="monotone" data={stats.dailyUsage.slice(-30)} name="Daily" dataKey="count" stroke="#8884d8" /> <Line type="monotone" data={stats.weeklyUsage.slice(-4)} name="Weekly" dataKey="count" stroke="#82ca9d" /> <Line type="monotone" data={stats.monthlyUsage.slice(-12)} name="Monthly" dataKey="count" stroke="#ffc658" /> </LineChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Time of Day Patterns</CardTitle> <Clock className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent className="h-[200px]"> <ResponsiveContainer width="100%" height="100%"> <BarChart data={stats.timeOfDayPatterns}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="hour" /> <YAxis /> <Tooltip /> <Bar dataKey="count" fill="#8884d8" /> </BarChart> </ResponsiveContainer> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Bin Metrics</CardTitle> <TrendingUp className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="space-y-2"> <div> <span className="font-medium">Time to 90% Full (avg): </span> {Math.round(stats.binMetrics.timeTo90PercentFull.average / 3600)} hours </div> <div> <span className="font-medium">Fill Rate (avg): </span> {stats.binMetrics.fillRate.average.toFixed(2)} %/hour </div> <div> <span className="font-medium">Fill Level Balance: </span> {(stats.binMetrics.fillLevelBalance * 100).toFixed(2)}% </div> </div> </CardContent> </Card> <Card> <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2"> <CardTitle className="text-sm font-medium">Classification Response Times</CardTitle> <Timer className="h-4 w-4 text-muted-foreground" /> </CardHeader> <CardContent> <div className="space-y-2"> <div> <span className="font-medium">Average: </span> {stats.classificationResponseTimes.average} ms </div> <div> <span className="font-medium">Min: </span> {stats.classificationResponseTimes.min} ms </div> <div> <span className="font-medium">Max: </span> {stats.classificationResponseTimes.max} ms </div> </div> </CardContent> </Card> </div> ); }
Leave a Comment