Untitled
unknown
plain_text
a year ago
5.6 kB
10
Indexable
// components/overview-cards.tsx
"use client"
import { useMetrics } from "@/hooks/useMetrics"
import { useBinConfig } from "@/hooks/use-bin-config"
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, differenceInDays, subDays } from "date-fns"
export function OverviewCards() {
const { metrics } = useMetrics()
const { bins } = useBinConfig()
// 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,
currentLevel: prediction.current_level,
binName: bins.find(b => b.id === binId)?.name || `Mülleimer ${binId.slice(-1)}`
} : acc
}, null as {
binId: string
binName: string
predictedTime: Date
currentLevel: number
} | 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 with weekly calculation
const totalEmptyingsLastWeek = metrics?.fill_level_history
? Object.values(metrics.fill_level_history).reduce((total, binHistory) => {
const lastWeek = subDays(new Date(), 7)
return binHistory.emptying_timestamps.filter(t =>
new Date(t) > lastWeek
).length + total
}, 0)
: 0
// Format time remaining display
const formatTimeRemaining = (endDate: Date) => {
const hours = differenceInHours(endDate, new Date())
if (hours >= 24) {
const days = (hours / 24).toFixed(1)
return `${days} Tage verbleibend`
}
return `${hours} Stunden verbleibend`
}
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">Proaktive Leerungen</CardTitle>
<Trash2 className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{proactiveEmptyings}</div>
<p className="text-xs text-muted-foreground">
{totalEmptyings} Gesamtleerungen ({proactivePercentage}%)
</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">Nächste volle Tonne</CardTitle>
<Clock className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
{nextFullBin ? (
<>
<div className="text-2xl font-bold mb-1">
{nextFullBin.binName}
</div>
<div className="text-xs text-muted-foreground">
Aktuell: {Math.round(nextFullBin.currentLevel)}% voll
</div>
<div className="text-xs text-muted-foreground">
{format(nextFullBin.predictedTime, "dd.MM.yyyy HH:mm")}
</div>
<div className="text-xs text-muted-foreground mt-1">
{formatTimeRemaining(nextFullBin.predictedTime)}
</div>
</>
) : (
<div className="text-sm text-muted-foreground">Keine Vorhersagen</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">Durchschn. Füllstand</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">
Bei Leerungen
</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">Leerungen gesamt</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} letzte Woche
</p>
</CardContent>
</Card>
</div>
)
}Editor is loading...
Leave a Comment