Untitled
unknown
plain_text
10 months ago
9.2 kB
8
Indexable
"use client"
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
import { Leaf, TreePine, Recycle, PlaneTakeoff, Car, LightbulbOff, Smartphone, TrendingUp, AlertCircle } 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";
import { Alert, AlertDescription } from "@/components/ui/alert";
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 { metrics, loading, error } = useMetrics();
if (loading) return <div className="p-4">Loading...</div>;
if (error) return <div className="p-4">Error: {error}</div>;
if (!metrics) return null;
const { environmental_impact: impact } = metrics;
// 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
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",
name: "Paper",
weight: Math.round(impact.paper_weight_recycled * 100) / 100,
fill: "var(--color-paper)"
},
{
type: "plastic",
name: "Plastic",
weight: Math.round(impact.plastic_weight_recycled * 100) / 100,
fill: "var(--color-plastic)"
},
{
type: "organic",
name: "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>
</div>
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
These statistics are calculated based on default bin configurations. Custom bin settings may affect the accuracy of these measurements.
</AlertDescription>
</Alert>
<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>Total Materials Processed</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
formatter={(value: number, name: string) => [`${value.toFixed(2)} kg`, name]}
/>
}
/>
<Pie data={materialsData} dataKey="weight" nameKey="name">
<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}% <TrendingUp className="h-4 w-4" />
</div>
<div className="leading-none text-muted-foreground">
Total materials processed: {totalMaterials.toFixed(2)} kg
</div>
</CardFooter>
</Card>
</div>
</main>
</SidebarInset>
</SidebarProvider>
);
}Editor is loading...
Leave a Comment