Untitled
unknown
plain_text
9 months ago
4.7 kB
6
Indexable
// components/overview-cards.tsx
"use client"
import { useMetrics } from "@/hooks/useMetrics"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Gauge, Clock, Trash2, TrendingUp } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { format, differenceInHours } from "date-fns"
export function OverviewCards() {
const { metrics } = useMetrics()
// Card 1: Proactive emptying count
const proactiveEmptyings = metrics?.proactive_emptying?.count || 0
const totalEmptyings = metrics?.basic_metrics?.bin_emptying_counts
? Object.values(metrics.basic_metrics.bin_emptying_counts).reduce((a, b) => a + b, 0)
: 0
const proactivePercentage = totalEmptyings > 0
? Math.round((proactiveEmptyings / totalEmptyings) * 100)
: 0
// Card 2: Next full bin prediction
const predictions = metrics?.fill_predictions || {}
const nextFullBin = Object.entries(predictions).reduce((acc, [binId, prediction]) => {
const predictedTime = new Date(prediction.predicted_full_time)
return (!acc || predictedTime < acc.predictedTime) ? { binId, predictedTime } : acc
}, null as { binId: string; predictedTime: Date } | null)
// Card 3: Average fill level at emptying
const fillLevels = metrics?.fill_level_history
? Object.values(metrics.fill_level_history).flatMap(h => h.fill_levels_at_empty)
: []
const averageFillLevel = fillLevels.length > 0
? Math.round(fillLevels.reduce((a, b) => a + b, 0) / fillLevels.length)
: null
// Card 4: Total emptyings count
const totalEmptyingsLastWeek = 42 // You'll need to implement time-based filtering
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
{/* Proactive Emptying Card */}
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Proactive Emptying</CardTitle>
<Badge variant="outline" className="text-xs">
<TrendingUp className="h-3 w-3 mr-1" />
{proactivePercentage}%
</Badge>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{proactiveEmptyings}</div>
<p className="text-xs text-muted-foreground">
{totalEmptyings} total emptyings
</p>
</CardContent>
</Card>
{/* Next Full Bin Card */}
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Next Full Bin</CardTitle>
<Clock className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
{nextFullBin ? (
<>
<div className="text-2xl font-bold mb-1">
{nextFullBin.binId.toUpperCase()}
</div>
<div className="text-xs text-muted-foreground">
{format(nextFullBin.predictedTime, "MMM dd, HH:mm")}
</div>
<div className="text-xs text-muted-foreground">
{differenceInHours(nextFullBin.predictedTime, new Date())} hours remaining
</div>
</>
) : (
<div className="text-sm text-muted-foreground">No upcoming predictions</div>
)}
</CardContent>
</Card>
{/* Average Fill Level Card */}
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Avg. Fill Level</CardTitle>
<Gauge className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{averageFillLevel !== null ? `${averageFillLevel}%` : "N/A"}
</div>
<p className="text-xs text-muted-foreground">
When bins are emptied
</p>
</CardContent>
</Card>
{/* Total Emptyings Card */}
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Total Emptyings</CardTitle>
<Trash2 className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{totalEmptyings}</div>
<p className="text-xs text-muted-foreground">
+{totalEmptyingsLastWeek} last week
</p>
</CardContent>
</Card>
</div>
)
}Editor is loading...
Leave a Comment