Untitled

 avatar
unknown
plain_text
4 days ago
6.5 kB
1
Indexable
"use client"

import { useState, useMemo } from "react"
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
import { useMetrics } from "@/hooks/useMetrics"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const fillLevelRanges = [
  { label: "0-20%", min: 0, max: 20 },
  { label: "21-40%", min: 21, max: 40 },
  { label: "41-60%", min: 41, max: 60 },
  { label: "61-80%", min: 61, max: 80 },
  { label: "81-100%", min: 81, max: 100 },
]

export function ProactiveEmptyingChart() {
  const { metrics, helpers } = useMetrics()
  const [selectedPeriod, setSelectedPeriod] = useState("all")
  const [selectedBin, setSelectedBin] = useState("all")
  const [selectedType, setSelectedType] = useState("all")

  const chartData = useMemo(() => {
    if (!metrics || !helpers) return []

    // Calculate time range filter
    const now = new Date()
    let startDate = new Date(0)
    switch (selectedPeriod) {
      case "24h":
        startDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
        break
      case "week":
        startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
        break
      case "month":
        startDate = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate())
        break
      case "year":
        startDate = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate())
        break
    }

    // Get and filter emptying events
    const events = helpers.getEmptyingEvents(
      selectedBin === "all" ? undefined : selectedBin,
      selectedPeriod === "all" ? undefined : { start: startDate, end: now }
    )

    // Process events into range counts
    const rangeCounts = fillLevelRanges.map(range => ({
      range: range.label,
      proactive: 0,
      normal: 0,
    }))

    events.forEach(event => {
      const range = fillLevelRanges.find(r => 
        event.fill_level > r.min && event.fill_level <= r.max
      )
      if (!range) return
      
      const idx = fillLevelRanges.indexOf(range)
      const isProactive = event.fill_level < 80
      
      if (selectedType === "proactive" && isProactive) {
        rangeCounts[idx].proactive++
      } else if (selectedType === "normal" && !isProactive) {
        rangeCounts[idx].normal++
      } else {
        isProactive ? rangeCounts[idx].proactive++ : rangeCounts[idx].normal++
      }
    })

    return rangeCounts.map(item => ({
      ...item,
      total: item.proactive + item.normal,
    }))
  }, [metrics, selectedPeriod, selectedBin, selectedType, helpers])

  const activeBins = helpers?.getActiveBinIds() || []
  const chartConfig = {
    ...(selectedType !== "normal" && { proactive: { 
      label: "Proactive", 
      color: "hsl(var(--chart-1))" 
    }}),
    ...(selectedType !== "proactive" && { normal: { 
      label: "Normal", 
      color: "hsl(var(--chart-2))" 
    }}),
  } satisfies ChartConfig

  return (
    <Card>
      <CardHeader className="flex flex-row items-center justify-between gap-4">
        <div>
          <CardTitle>Emptying Statistics</CardTitle>
          <CardDescription>Distribution of emptying events by fill level</CardDescription>
        </div>
        <div className="flex gap-2">
          <Select value={selectedPeriod} onValueChange={setSelectedPeriod}>
            <SelectTrigger className="w-[120px]">
              <SelectValue placeholder="Period" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">All Time</SelectItem>
              <SelectItem value="24h">Last 24h</SelectItem>
              <SelectItem value="week">Last Week</SelectItem>
              <SelectItem value="month">Last Month</SelectItem>
              <SelectItem value="year">Last Year</SelectItem>
            </SelectContent>
          </Select>

          <Select value={selectedBin} onValueChange={setSelectedBin}>
            <SelectTrigger className="w-[100px]">
              <SelectValue placeholder="Bin" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">All</SelectItem>
              {activeBins.map(bin => (
                <SelectItem key={bin} value={bin}>{bin}</SelectItem>
              ))}
            </SelectContent>
          </Select>

          <Select value={selectedType} onValueChange={setSelectedType}>
            <SelectTrigger className="w-[120px]">
              <SelectValue placeholder="Type" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">All</SelectItem>
              <SelectItem value="proactive">Proactive</SelectItem>
              <SelectItem value="normal">Normal</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </CardHeader>

      <CardContent>
        <ChartContainer config={chartConfig} className="min-h-[300px]">
          <BarChart data={chartData}>
            <CartesianGrid vertical={false} />
            <XAxis
              dataKey="range"
              tickLine={false}
              axisLine={false}
              tickMargin={10}
            />
            <YAxis
              tickLine={false}
              axisLine={false}
              tickFormatter={(value) => `${value}`}
            />
            <ChartTooltip content={<ChartTooltipContent />} />

            {selectedType !== "normal" && (
              <Bar
                dataKey="proactive"
                fill="var(--color-proactive)"
                radius={4}
                stackId="a"
              />
            )}
            {selectedType !== "proactive" && (
              <Bar
                dataKey="normal"
                fill="var(--color-normal)"
                radius={4}
                stackId="a"
              />
            )}
          </BarChart>
        </ChartContainer>
      </CardContent>

      <CardFooter className="text-sm text-muted-foreground">
        Proactive emptying = below 80% fill level | Normal emptying = 80%+
      </CardFooter>
    </Card>
  )
}
Leave a Comment