Untitled

 avatar
unknown
plain_text
a month ago
12 kB
2
Indexable
"use client"

import * as React from "react"
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts"
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  CardDescription,
} from "@/components/ui/card"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import {
  ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const chartConfig = {
  bin1: {
    label: "Bio",
    color: "hsl(var(--chart-1))",
  },
  bin2: {
    label: "Recycling",
    color: "hsl(var(--chart-2))",
  },
  bin3: {
    label: "Paper",
    color: "hsl(var(--chart-3))",
  },
  bin4: {
    label: "Residual",
    color: "hsl(var(--chart-4))",
  },
} satisfies ChartConfig

export function FillRates({ currentFillLevels }) {
  const [timeRange, setTimeRange] = React.useState("90d")

  // For now, let's create demo data based on current fill levels
  const generateHistoricalData = () => {
    const data = []
    const endDate = new Date()
    const startDate = new Date()
    startDate.setDate(endDate.getDate() - 90) // 90 days ago

    for (let date = new Date(startDate); date <= endDate; date.setDate(date.getDate() + 1)) {
      // Create random variations of current fill levels
      data.push({
        date: date.toISOString().split('T')[0],
        bin1: Math.max(0, Math.min(100, currentFillLevels.bin1 + (Math.random() - 0.5) * 20)),
        bin2: Math.max(0, Math.min(100, currentFillLevels.bin2 + (Math.random() - 0.5) * 20)),
        bin3: Math.max(0, Math.min(100, currentFillLevels.bin3 + (Math.random() - 0.5) * 20)),
        bin4: Math.max(0, Math.min(100, currentFillLevels.bin4 + (Math.random() - 0.5) * 20)),
      })
    }
    return data
  }

  const chartData = generateHistoricalData()

  // Filter data based on selected time range
  const filteredData = chartData.filter((item) => {
    const date = new Date(item.date)
    const referenceDate = new Date()
    let daysToSubtract = 90
    if (timeRange === "30d") daysToSubtract = 30
    if (timeRange === "7d") daysToSubtract = 7
    const startDate = new Date(referenceDate)
    startDate.setDate(startDate.getDate() - daysToSubtract)
    return date >= startDate
  })

  return (
    <Card>
      <CardHeader className="flex items-center gap-2 space-y-0 border-b py-4 sm:flex-row">
        <div className="grid flex-1 gap-1 text-center sm:text-left">
          <CardTitle>Fill Levels Over Time</CardTitle>
          <CardDescription>Historical fill levels for all bins</CardDescription>
        </div>
        <Select value={timeRange} onValueChange={setTimeRange}>
          <SelectTrigger className="w-[160px] rounded-lg">
            <SelectValue placeholder="Last 3 months" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="90d">Last 3 months</SelectItem>
            <SelectItem value="30d">Last 30 days</SelectItem>
            <SelectItem value="7d">Last 7 days</SelectItem>
          </SelectContent>
        </Select>
      </CardHeader>
      <CardContent className="pt-4">
        <ChartContainer config={chartConfig} className="h-[300px]">
          <AreaChart data={filteredData}>
            <defs>
              {Object.keys(chartConfig).map((bin) => (
                <linearGradient
                  key={bin}
                  id={`fill${bin}`}
                  x1="0"
                  y1="0"
                  x2="0"
                  y2="1"
                >
                  <stop
                    offset="5%"
                    stopColor={`var(--color-${bin})`}
                    stopOpacity={0.8}
                  />
                  <stop
                    offset="95%"
                    stopColor={`var(--color-${bin})`}
                    stopOpacity={0.1}
                  />
                </linearGradient>
              ))}
            </defs>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis
              dataKey="date"
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              minTickGap={32}
              tickFormatter={(value) => {
                const date = new Date(value)
                return date.toLocaleDateString("en-US", {
                  month: "short",
                  day: "numeric",
                })
              }}
            />
            <YAxis
              tickLine={false}
              axisLine={false}
              tickMargin={8}
              domain={[0, 100]}
              tickFormatter={(value) => `${value}%`}
            />
            <ChartTooltip
              content={
                <ChartTooltipContent
                  labelFormatter={(value) => {
                    return new Date(value).toLocaleDateString("en-US", {
                      month: "long",
                      day: "numeric",
                      year: "numeric",
                    })
                  }}
                />
              }
            />
            {Object.keys(chartConfig).map((bin) => (
              <Area
                key={bin}
                dataKey={bin}
                type="monotone"
                fill={`url(#fill${bin})`}
                stroke={`var(--color-${bin})`}
                strokeWidth={2}
              />
            ))}
            <ChartLegend content={<ChartLegendContent />} />
          </AreaChart>
        </ChartContainer>
      </CardContent>
    </Card>
  )
}





































"use client"

import { useEffect, useState } from "react"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Overview } from "@/components/statistics/overview"
import { DailySorting } from "@/components/statistics/daily-sorting"
import { HourlyActivity } from "@/components/statistics/hourly-activity"
import { FillRates } from "@/components/statistics/fill-rates"
import { ModelUsage } from "@/components/statistics/model-usage"
import { ClassificationTimes } from "@/components/statistics/classification-times"
import { Activity, Brain, ChartBar, LineChart, Recycle, Timer } from "lucide-react"

export default function StatisticsPage() {
  const [isLoading, setIsLoading] = useState(true)
  const [data, setData] = useState(null)
  const [fillLevels, setFillLevels] = useState(null)

  useEffect(() => {
    // Fetch both stats and fill levels
    Promise.all([
      fetch('/api/stats').then(res => res.json()),
      fetch('/api/fill-levels').then(res => res.json())
    ])
      .then(([statsData, fillLevelsData]) => {
        setData(statsData)
        setFillLevels(fillLevelsData)
        setIsLoading(false)
      })
      .catch(error => {
        console.error('Error fetching data:', error)
        setIsLoading(false)
      })
  }, [])

  if (isLoading) {
    return <div className="flex items-center justify-center h-screen">Loading...</div>
  }

  return (
    <div className="flex-1 space-y-4 p-8 pt-6">
      <div className="flex items-center justify-between space-y-2">
        <h2 className="text-3xl font-bold tracking-tight">Statistics</h2>
      </div>

      {/* Quick Stats Cards */}
      <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
            <CardTitle className="text-sm font-medium">Total Items</CardTitle>
            <Recycle className="h-4 w-4 text-muted-foreground" />
          </CardHeader>
          <CardContent>
            <div className="text-2xl font-bold">{data?.summary?.total_sorts || 0}</div>
            <p className="text-xs text-muted-foreground">
              +{data?.summary?.today_sorts || 0} today
            </p>
          </CardContent>
        </Card>

        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
            <CardTitle className="text-sm font-medium">API Usage</CardTitle>
            <Activity className="h-4 w-4 text-muted-foreground" />
          </CardHeader>
          <CardContent>
            <div className="text-2xl font-bold">
              {Math.round((data?.summary?.model_usage_total?.api /
                (data?.summary?.model_usage_total?.api +
                  data?.summary?.model_usage_total?.local || 1)) * 100)}%
            </div>
            <p className="text-xs text-muted-foreground">Of total classifications</p>
          </CardContent>
        </Card>

        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
            <CardTitle className="text-sm font-medium">Response Time</CardTitle>
            <Timer className="h-4 w-4 text-muted-foreground" />
          </CardHeader>
          <CardContent>
            <div className="text-2xl font-bold">
              {data?.summary?.avg_classification_time_ms || 0}ms
            </div>
            <p className="text-xs text-muted-foreground">Average classification speed</p>
          </CardContent>
        </Card>

        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
            <CardTitle className="text-sm font-medium">Daily Average</CardTitle>
            <ChartBar className="h-4 w-4 text-muted-foreground" />
          </CardHeader>
          <CardContent>
            <div className="text-2xl font-bold">
              {Math.round(data?.summary?.total_sorts / 
                (Object.keys(data?.daily_stats || {}).length || 1))}
            </div>
            <p className="text-xs text-muted-foreground">Items per day</p>
          </CardContent>
        </Card>
      </div>

      {/* Main Content Tabs */}
      <Tabs defaultValue="overview" className="space-y-4">
        <TabsList>
          <TabsTrigger value="overview" className="gap-2">
            <LineChart className="h-4 w-4" />
            Overview
          </TabsTrigger>
          <TabsTrigger value="sorting" className="gap-2">
            <ChartBar className="h-4 w-4" />
            Sorting
          </TabsTrigger>
          <TabsTrigger value="bins" className="gap-2">
            <Recycle className="h-4 w-4" />
            Bins
          </TabsTrigger>
          <TabsTrigger value="performance" className="gap-2">
            <Activity className="h-4 w-4" />
            Performance
          </TabsTrigger>
        </TabsList>

        <TabsContent value="overview" className="space-y-4">
          <Overview data={data} />
        </TabsContent>

        <TabsContent value="sorting" className="space-y-4">
          <div className="grid gap-4 md:grid-cols-2">
            <DailySorting data={data} />
            <HourlyActivity data={data} />
          </div>
        </TabsContent>

        <TabsContent value="bins" className="space-y-4">
          <FillRates currentFillLevels={fillLevels} />
        </TabsContent>

        <TabsContent value="performance" className="space-y-4">
          <div className="grid gap-4 md:grid-cols-2">
            <ModelUsage data={data} />
            <ClassificationTimes data={data} />
          </div>
        </TabsContent>
      </Tabs>
    </div>
  )
}
Editor is loading...
Leave a Comment