Untitled

 avatar
unknown
plain_text
5 months ago
10 kB
5
Indexable
"use client"

import React, { useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Leaf, TreePine, Recycle, PlaneTakeoff, Car, LightbulbOff, Smartphone, TrendingUp } from "lucide-react";
import { Pie, PieChart, LabelList } from "recharts";
import { useMetrics } from '@/hooks/useMetrics';
import { AppSidebar } from "@/components/app-sidebar";
import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
import { Separator } from "@/components/ui/separator";
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbList,
} from "@/components/ui/breadcrumb";
import {
  ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart";

const timeOptions = [
  { value: "day", label: "Last 24 Hours" },
  { value: "week", label: "Last Week" },
  { value: "month", label: "Last Month" },
  { value: "year", label: "Last Year" },
];

const materialChartConfig = {
  materials: {
    label: "Materials",
  },
  paper: {
    label: "Paper",
    color: "hsl(var(--chart-1))",
  },
  plastic: {
    label: "Plastic",
    color: "hsl(var(--chart-2))",
  },
  organic: {
    label: "Organic",
    color: "hsl(var(--chart-3))",
  },
} satisfies ChartConfig;

export default function EnvironmentalImpact() {
  const [selectedPeriod, setSelectedPeriod] = useState("month");
  const { metrics, loading, error } = useMetrics();

  const getPeriodMultiplier = (period) => {
    switch (period) {
      case 'day': return 1/30;
      case 'week': return 1/4;
      case 'year': return 12;
      default: return 1; // month
    }
  };

  const getAdjustedMetrics = (metrics, period) => {
    if (!metrics) return null;
    const multiplier = getPeriodMultiplier(period);
    const { environmental_impact: impact } = metrics;
    
    return {
      co2_saved: impact.co2_saved * multiplier,
      trees_saved: impact.trees_saved * multiplier,
      paper_weight_recycled: impact.paper_weight_recycled * multiplier,
      plastic_weight_recycled: impact.plastic_weight_recycled * multiplier,
      organic_weight_processed: impact.organic_weight_processed * multiplier,
    };
  };

  if (loading) return <div className="p-4">Loading...</div>;
  if (error) return <div className="p-4">Error: {error}</div>;
  if (!metrics) return null;

  const impact = getAdjustedMetrics(metrics, selectedPeriod);

  // Environmental equivalents calculations
  const carKmAvoided = impact.co2_saved * 4; // Approx 250g CO2 per km
  const flightsAvoided = Math.round(impact.co2_saved / 0.2); // Assuming 0.2kg CO2 per short flight
  const phoneCharges = Math.round(impact.co2_saved * 1000); // Rough estimate for phone charges
  const lightbulbHours = Math.round(impact.co2_saved * 100); // LED bulb hours equivalent

  // Tree equivalents
  const oxygenForPeople = Math.round(impact.trees_saved * 2); // People's oxygen needs per day
  const paperSheetsSaved = Math.round(impact.trees_saved * 8333); // Sheets per tree approximation

  // Calculate total materials for trend percentage
  const totalMaterials = impact.paper_weight_recycled + impact.plastic_weight_recycled + impact.organic_weight_processed;
  const previousTotal = totalMaterials * 0.95; // Example: assuming 5% increase
  const trendPercentage = ((totalMaterials - previousTotal) / previousTotal * 100).toFixed(1);

  const materialsData = [
    { 
      type: "paper",
      weight: Math.round(impact.paper_weight_recycled * 100) / 100,
      fill: "var(--color-paper)"
    },
    {
      type: "plastic",
      weight: Math.round(impact.plastic_weight_recycled * 100) / 100,
      fill: "var(--color-plastic)"
    },
    {
      type: "organic",
      weight: Math.round(impact.organic_weight_processed * 100) / 100,
      fill: "var(--color-organic)"
    }
  ].filter(item => item.weight > 0);

  return (
    <SidebarProvider>
      <AppSidebar />
      <SidebarInset>
        <header className="flex shrink-0 items-center gap-2 border-b px-4 py-6">
          <SidebarTrigger className="-ml-1" />
          <Separator orientation="vertical" className="mr-2 h-4" />
          <Breadcrumb>
            <BreadcrumbList>
              <BreadcrumbItem>
                <BreadcrumbLink href="/">Home</BreadcrumbLink>
              </BreadcrumbItem>
              <BreadcrumbItem>
                <BreadcrumbLink href="/impact">Environmental Impact</BreadcrumbLink>
              </BreadcrumbItem>
            </BreadcrumbList>
          </Breadcrumb>
        </header>
        
        <main className="p-4 space-y-4">
          <div className="flex justify-between items-center">
            <h1 className="text-2xl font-bold">Environmental Impact</h1>
            <Select value={selectedPeriod} onValueChange={setSelectedPeriod}>
              <SelectTrigger className="w-[180px]">
                <SelectValue placeholder="Select period" />
              </SelectTrigger>
              <SelectContent>
                {timeOptions.map((option) => (
                  <SelectItem key={option.value} value={option.value}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
            {/* CO2 Saved Card */}
            <Card className="xl:col-span-2">
              <CardHeader className="pb-2">
                <CardTitle className="flex items-center gap-2 text-lg">
                  <Leaf className="h-5 w-5 text-green-500" />
                  CO₂ Impact
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div className="mt-2 space-y-4">
                  <div className="text-3xl font-bold text-green-500">
                    {impact.co2_saved.toFixed(2)} kg CO₂ saved
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="flex items-center gap-2 text-sm">
                      <Car className="h-4 w-4 text-blue-500" />
                      <span>{carKmAvoided.toFixed(1)} km of driving avoided</span>
                    </div>
                    <div className="flex items-center gap-2 text-sm">
                      <PlaneTakeoff className="h-4 w-4 text-blue-500" />
                      <span>Equal to {flightsAvoided} short flights</span>
                    </div>
                    <div className="flex items-center gap-2 text-sm">
                      <Smartphone className="h-4 w-4 text-blue-500" />
                      <span>{phoneCharges} phone charges saved</span>
                    </div>
                    <div className="flex items-center gap-2 text-sm">
                      <LightbulbOff className="h-4 w-4 text-blue-500" />
                      <span>{lightbulbHours} hours of LED bulb usage</span>
                    </div>
                  </div>
                </div>
              </CardContent>
            </Card>

            {/* Trees Saved Card */}
            <Card>
              <CardHeader className="pb-2">
                <CardTitle className="flex items-center gap-2 text-lg">
                  <TreePine className="h-5 w-5 text-green-700" />
                  Tree Impact
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div className="mt-2 space-y-4">
                  <div className="text-3xl font-bold text-green-700">
                    {impact.trees_saved.toFixed(3)} trees preserved
                  </div>
                  <div className="space-y-2">
                    <div className="text-sm">
                      ⚡ Provides daily oxygen for {oxygenForPeople} people
                    </div>
                    <div className="text-sm">
                      📄 Saved {paperSheetsSaved.toLocaleString()} sheets of paper
                    </div>
                  </div>
                </div>
              </CardContent>
            </Card>

            {/* Materials Recycled Card */}
            <Card className="flex flex-col">
              <CardHeader className="items-center pb-0">
                <CardTitle>Materials Recycled by Type</CardTitle>
                <CardDescription>
                  {timeOptions.find(opt => opt.value === selectedPeriod)?.label}
                </CardDescription>
              </CardHeader>
              <CardContent className="flex-1 pb-0">
                <ChartContainer
                  config={materialChartConfig}
                  className="mx-auto aspect-square max-h-[250px] [&_.recharts-text]:fill-background"
                >
                  <PieChart>
                    <ChartTooltip
                      content={<ChartTooltipContent nameKey="weight" hideLabel />}
                    />
                    <Pie data={materialsData} dataKey="weight">
                      <LabelList
                        dataKey="type"
                        className="fill-background"
                        stroke="none"
                        fontSize={12}
                        formatter={(value: keyof typeof materialChartConfig) =>
                          materialChartConfig[value]?.label
                        }
                      />
                    </Pie>
                  </PieChart>
                </ChartContainer>
              </CardContent>
              <CardFooter className="flex-col gap-2 text-sm">
                <div className="flex items-center gap-2 font-medium leading-none">
                  Trending up by {trendPercentage}% this {selectedPeriod} <TrendingUp className="h-4 w-4" />
                </div>
                <div className="leading-none text-muted-foreground">
                  Showing total materials recycled for the selected period
                </div>
              </CardFooter>
            </Card>
          </div>
        </main>
      </SidebarInset>
    </SidebarProvider>
  );
}
Editor is loading...
Leave a Comment