Untitled

 avatar
unknown
plain_text
a month ago
25 kB
3
Indexable
"use client"

import { useState } from "react"
import { 
  Bar, 
  BarChart, 
  Line, 
  LineChart, 
  XAxis, 
  YAxis, 
  CartesianGrid, 
  Tooltip, 
  Legend, 
  ResponsiveContainer, 
  PieChart, 
  Pie, 
  Cell 
} from "recharts"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { AppSidebar } from "@/components/app-sidebar"
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { useTranslation, type SupportedLanguages } from "@/utils/translations"
import { useSettings } from "@/hooks/useSettings"
import { useBinConfig } from "@/hooks/use-bin-config"
import { useMetrics } from "@/hooks/useMetrics"
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import { 
  ChartContainer, 
  ChartTooltip, 
  ChartTooltipContent,
  type ChartConfig
} from "@/components/ui/chart"
import { format, parseISO } from "date-fns"

export default function Page() {
  const { settings } = useSettings()
  const { t } = useTranslation((settings?.language as SupportedLanguages) || "EN")
  const { metrics, loading, error } = useMetrics()
  const { bins } = useBinConfig()
  const [activeTab, setActiveTab] = useState("distribution")

  if (loading || !metrics) {
    return (
      <SidebarProvider>
        <div className="flex h-screen w-full">
          <AppSidebar />
          <div className="flex-1 overflow-auto">
            <header className="flex shrink-0 items-center gap-2 border-b px-4 py-6">
              <SidebarTrigger />
              <Separator orientation="vertical" className="mx-2 h-4" />
              <Breadcrumb>
                <BreadcrumbList>
                  <BreadcrumbItem className="hidden sm:block">
                    <BreadcrumbLink href="/">{t('navigation.home')}</BreadcrumbLink>
                  </BreadcrumbItem>
                  <BreadcrumbSeparator className="hidden sm:block" />
                  <BreadcrumbItem>
                    <BreadcrumbPage>{t('navigation.patterns')}</BreadcrumbPage>
                  </BreadcrumbItem>
                </BreadcrumbList>
              </Breadcrumb>
            </header>
            <main className="container mx-auto p-4">
              <div className="flex items-center justify-center h-64">
                <p className="text-lg text-muted-foreground">Loading metrics...</p>
              </div>
            </main>
          </div>
        </div>
      </SidebarProvider>
    )
  }

  if (error) {
    return (
      <SidebarProvider>
        <div className="flex h-screen w-full">
          <AppSidebar />
          <div className="flex-1 overflow-auto">
            <header className="flex shrink-0 items-center gap-2 border-b px-4 py-6">
              <SidebarTrigger />
              <Separator orientation="vertical" className="mx-2 h-4" />
              <Breadcrumb>
                <BreadcrumbList>
                  <BreadcrumbItem className="hidden sm:block">
                    <BreadcrumbLink href="/">{t('navigation.home')}</BreadcrumbLink>
                  </BreadcrumbItem>
                  <BreadcrumbSeparator className="hidden sm:block" />
                  <BreadcrumbItem>
                    <BreadcrumbPage>{t('navigation.patterns')}</BreadcrumbPage>
                  </BreadcrumbItem>
                </BreadcrumbList>
              </Breadcrumb>
            </header>
            <main className="container mx-auto p-4">
              <div className="flex items-center justify-center h-64">
                <p className="text-lg text-destructive">Error loading metrics: {error}</p>
              </div>
            </main>
          </div>
        </div>
      </SidebarProvider>
    )
  }

  // Prepare data for different charts based on the specified requirements
  
  // 1. Sorting Distribution: Items per bin type (bar chart)
  const getItemsPerBinData = () => {
    const data = []
    Object.entries(metrics.basic_metrics.items_sorted_per_bin).forEach(([binId, count]) => {
      const bin = bins.find(b => b.id === binId)
      data.push({
        bin: bin?.name || binId,
        count,
        fill: bin ? (settings?.theme === "dark" ? bin.color_dark : bin.color) : "#888888"
      })
    })
    return data.sort((a, b) => b.count - a.count)
  }

  // Config for items per bin chart
  const itemsPerBinConfig = {
    count: {
      label: "Items",
      color: settings?.theme === "dark" ? "#3b82f6" : "#2563eb"
    }
  }

  // 2. Classification methods (API vs. Local)
  const getClassificationMethodsData = () => {
    const { api, local } = metrics.basic_metrics.api_vs_local_usage
    return [
      { name: "API", value: api, fill: settings?.theme === "dark" ? "#3b82f6" : "#2563eb" },
      { name: "Local", value: local, fill: settings?.theme === "dark" ? "#10b981" : "#059669" }
    ]
  }

  // Config for classification methods chart
  const classificationMethodsConfig = {
    api: {
      label: "API",
      color: settings?.theme === "dark" ? "#3b82f6" : "#2563eb"
    },
    local: {
      label: "Local",
      color: settings?.theme === "dark" ? "#10b981" : "#059669"
    }
  }

  // 3. Daily/Weekly/Monthly sorting trends (line chart)
  const getSortingTrendsData = () => {
    // Daily data
    const dailyData = Object.entries(metrics.time_metrics.daily_usage_counts)
      .map(([date, count]) => ({
        date,
        count,
        formattedDate: format(parseISO(date), 'MMM dd')
      }))
      .sort((a, b) => parseISO(a.date).getTime() - parseISO(b.date).getTime())
    
    // Weekly data
    const weeklyData = Object.entries(metrics.time_metrics.weekly_usage_counts)
      .map(([week, count]) => ({
        week,
        count
      }))
      .sort((a, b) => a.week.localeCompare(b.week))
    
    // Monthly data
    const monthlyData = Object.entries(metrics.time_metrics.monthly_usage_counts)
      .map(([month, count]) => ({
        month,
        count,
        formattedMonth: month.substring(5)
      }))
      .sort((a, b) => a.month.localeCompare(b.month))
    
    return {
      daily: dailyData,
      weekly: weeklyData,
      monthly: monthlyData
    }
  }

  // Config for sorting trends chart
  const sortingTrendsConfig = {
    count: {
      label: "Items Sorted",
      color: settings?.theme === "dark" ? "#3b82f6" : "#2563eb"
    }
  }

  // 4. Most common waste types (table or graph)
  const getWasteTypesData = () => {
    const wasteTypes = {}
    
    // Collect all waste types from bin specialization
    Object.values(metrics.bin_specialization).forEach(bin => {
      Object.entries(bin.items_by_type).forEach(([type, count]) => {
        wasteTypes[type] = (wasteTypes[type] || 0) + count
      })
    })
    
    // Convert to array and sort by count
    return Object.entries(wasteTypes)
      .map(([type, count]) => ({ type, count }))
      .sort((a, b) => b.count - a.count)
  }

  // Config for waste types chart
  const wasteTypesConfig = {
    count: {
      label: "Items",
      color: settings?.theme === "dark" ? "#3b82f6" : "#2563eb"
    }
  }

  return (
    <SidebarProvider>
      <div className="flex h-screen w-full">
        <AppSidebar />
        <div className="flex-1 overflow-auto">
          <header className="flex shrink-0 items-center gap-2 border-b px-4 py-6">
            <SidebarTrigger />
            <Separator orientation="vertical" className="mx-2 h-4" />
            <Breadcrumb>
              <BreadcrumbList>
                <BreadcrumbItem className="hidden sm:block">
                  <BreadcrumbLink href="/">{t('navigation.home')}</BreadcrumbLink>
                </BreadcrumbItem>
                <BreadcrumbSeparator className="hidden sm:block" />
                <BreadcrumbItem>
                  <BreadcrumbPage>{t('navigation.patterns')}</BreadcrumbPage>
                </BreadcrumbItem>
              </BreadcrumbList>
            </Breadcrumb>
          </header>
          
          <main className="container mx-auto py-6 px-4">
            <div className="flex flex-col gap-6">
              <div>
                <h1 className="text-3xl font-bold tracking-tight">Sorting Analytics</h1>
                <p className="text-muted-foreground">Analyze sorting trends and patterns in detail</p>
              </div>
              
              <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
                <TabsList className="mb-4">
                  <TabsTrigger value="distribution">Sorting Distribution</TabsTrigger>
                  <TabsTrigger value="trends">Trends</TabsTrigger>
                  <TabsTrigger value="classifications">Top Classifications</TabsTrigger>
                </TabsList>
                
                <TabsContent value="distribution" className="space-y-6">
                  <div className="grid grid-cols-1 gap-6">
                    {/* Items per bin type (bar chart) */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Items per Bin Type</CardTitle>
                        <CardDescription>Distribution of sorted items across different bins</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={itemsPerBinConfig} className="min-h-[300px]">
                          <BarChart accessibilityLayer data={getItemsPerBinData()}>
                            <CartesianGrid vertical={false} />
                            <XAxis 
                              dataKey="bin" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <YAxis 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <ChartTooltip content={<ChartTooltipContent />} />
                            <Bar 
                              dataKey="count"
                              nameKey="bin"
                              radius={[4, 4, 0, 0]}
                              fill="fill"
                            />
                          </BarChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                    
                    {/* Classification methods (API vs. Local) */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Classification Methods</CardTitle>
                        <CardDescription>Distribution between API vs. Local classification</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={classificationMethodsConfig} className="min-h-[300px]">
                          <PieChart>
                            <Pie
                              data={getClassificationMethodsData()}
                              cx="50%"
                              cy="50%"
                              labelLine={false}
                              outerRadius={100}
                              dataKey="value"
                              nameKey="name"
                              label={({ name, percent }) => `${name}: ${(percent * 100).toFixed(0)}%`}
                            >
                              {getClassificationMethodsData().map((entry, index) => (
                                <Cell key={`cell-${index}`} fill={entry.fill} />
                              ))}
                            </Pie>
                            <Tooltip
                              formatter={(value, name) => [`${value} items`, name]}
                              contentStyle={{ 
                                backgroundColor: 'var(--background)', 
                                borderColor: 'var(--border)',
                                borderRadius: '0.5rem'
                              }}
                            />
                            <Legend />
                          </PieChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                  </div>
                </TabsContent>
                
                <TabsContent value="trends" className="space-y-6">
                  <div className="grid grid-cols-1 gap-6">
                    {/* Daily/Weekly/Monthly sorting trends (line chart) */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Daily Sorting Trends</CardTitle>
                        <CardDescription>Number of items sorted each day</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={sortingTrendsConfig} className="min-h-[300px]">
                          <LineChart accessibilityLayer data={getSortingTrendsData().daily}>
                            <CartesianGrid vertical={false} />
                            <XAxis 
                              dataKey="formattedDate" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <YAxis 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <ChartTooltip content={<ChartTooltipContent />} />
                            <Line 
                              type="monotone" 
                              dataKey="count" 
                              name="Items Sorted"
                              stroke={settings?.theme === "dark" ? "#3b82f6" : "#2563eb"}
                              strokeWidth={2}
                              dot={{ r: 3 }}
                              activeDot={{ r: 6 }}
                            />
                          </LineChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                    
                    <Card>
                      <CardHeader>
                        <CardTitle>Monthly Sorting Trends</CardTitle>
                        <CardDescription>Number of items sorted each month</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={sortingTrendsConfig} className="min-h-[300px]">
                          <BarChart accessibilityLayer data={getSortingTrendsData().monthly}>
                            <CartesianGrid vertical={false} />
                            <XAxis 
                              dataKey="formattedMonth" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <YAxis 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <ChartTooltip content={<ChartTooltipContent />} />
                            <Bar 
                              dataKey="count" 
                              name="Items Sorted"
                              fill={settings?.theme === "dark" ? "#3b82f6" : "#2563eb"}
                              radius={[4, 4, 0, 0]}
                            />
                          </BarChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                    
                    {/* Time of Day Heatmap */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Time of Day Heatmap</CardTitle>
                        <CardDescription>When items are most frequently sorted</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={sortingTrendsConfig} className="min-h-[300px]">
                          <BarChart accessibilityLayer data={
                            metrics.time_metrics.time_of_day_patterns.map((count, hour) => ({
                              hour: `${hour}:00`,
                              count
                            }))
                          }>
                            <CartesianGrid vertical={false} />
                            <XAxis 
                              dataKey="hour" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                              interval={2}
                            />
                            <YAxis 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <ChartTooltip content={<ChartTooltipContent />} />
                            <Bar 
                              dataKey="count" 
                              name="Items Sorted"
                              fill={settings?.theme === "dark" ? "#3b82f6" : "#2563eb"}
                              radius={[4, 4, 0, 0]}
                            />
                          </BarChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                  </div>
                </TabsContent>
                
                <TabsContent value="classifications" className="space-y-6">
                  <div className="grid grid-cols-1 gap-6">
                    {/* Most common waste types (table or graph) */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Most Common Waste Types</CardTitle>
                        <CardDescription>Distribution of waste classifications</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <ChartContainer config={wasteTypesConfig} className="min-h-[300px]">
                          <BarChart 
                            accessibilityLayer 
                            data={getWasteTypesData()} 
                            layout="vertical"
                            margin={{ left: 100 }}
                          >
                            <CartesianGrid horizontal={false} />
                            <XAxis 
                              type="number" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                            />
                            <YAxis 
                              type="category"
                              dataKey="type" 
                              axisLine={false} 
                              tickLine={false}
                              tickMargin={8}
                              width={100}
                            />
                            <ChartTooltip content={<ChartTooltipContent />} />
                            <Bar 
                              dataKey="count" 
                              nameKey="type"
                              fill={settings?.theme === "dark" ? "#3b82f6" : "#2563eb"}
                              radius={[0, 4, 4, 0]}
                            />
                          </BarChart>
                        </ChartContainer>
                      </CardContent>
                    </Card>
                    
                    {/* Most common waste types as a table */}
                    <Card>
                      <CardHeader>
                        <CardTitle>Most Common Waste Types</CardTitle>
                        <CardDescription>Tabular view of waste classifications</CardDescription>
                      </CardHeader>
                      <CardContent>
                        <div className="overflow-x-auto">
                          <table className="w-full border-collapse">
                            <thead>
                              <tr>
                                <th className="text-left py-3 px-4 font-medium text-muted-foreground">Waste Type</th>
                                <th className="text-left py-3 px-4 font-medium text-muted-foreground">Count</th>
                                <th className="text-left py-3 px-4 font-medium text-muted-foreground">Percentage</th>
                              </tr>
                            </thead>
                            <tbody className="divide-y">
                              {getWasteTypesData().map((item, index) => {
                                const totalItems = metrics.basic_metrics.total_items_sorted;
                                const percentage = (item.count / totalItems) * 100;
                                
                                return (
                                  <tr key={index} className="hover:bg-muted/50">
                                    <td className="py-3 px-4">{item.type}</td>
                                    <td className="py-3 px-4">{item.count}</td>
                                    <td className="py-3 px-4">{percentage.toFixed(1)}%</td>
                                  </tr>
                                );
                              })}
                            </tbody>
                          </table>
                        </div>
                      </CardContent>
                    </Card>
                  </div>
                </TabsContent>
              </Tabs>
              
              {/* Interactive Features Section */}
              <div className="space-y-4 mt-6">
                <h2 className="text-2xl font-bold tracking-tight">Interactive Features</h2>
                
                <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
                  {/* Date range comparisons */}
                  <Card>
                    <CardHeader>
                      <CardTitle>Date Range Comparisons</CardTitle>
                      <CardDescription>Compare sorting metrics between time periods</CardDescription>
                    </CardHeader>
                    <CardContent>
                      <div className="flex flex-col p-6 items-center justify-center text-center border rounded-lg bg-muted/10">
                        <p className="text-muted-foreground">
                          Select date ranges to compare sorting patterns and identify trends over time.
                        </p>
                        <button className="mt-4 px-4 py-2 border rounded-md hover:bg-muted">
                          Coming soon
                        </button>
                      </div>
                    </CardContent>
                  </Card>
                  
                  {/* Bin fill level predictions */}
                  <Card>
                    <CardHeader>
                      <CardTitle>Bin Fill Level Predictions</CardTitle>
                      <CardDescription>Projected time until bins need emptying</CardDescription>
                    </CardHeader>
                    <CardContent>
                      <div className="flex flex-col p-6 items-center justify-center text-center border rounded-lg bg-muted/10">
                        <p className="text-muted-foreground">
                          View predictive analytics on bin fill rates and optimal emptying times.
                        </p>
                        <button className="mt-4 px-4 py-2 border rounded-md hover:bg-muted">
                          Coming soon
                        </button>
                      </div>
                    </CardContent>
                  </Card>
                </div>
              </div>
            </div>
          </main>
        </div>
      </div>
    </SidebarProvider>
  )
}
Editor is loading...
Leave a Comment