Untitled
unknown
plain_text
9 months ago
12 kB
7
Indexable
'use client';
import { 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 { Area, AreaChart, CartesianGrid, XAxis, YAxis, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
import { Leaf, TreePine, Recycle, Plane, TrendingUp } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useMetrics } from '@/hooks/useMetrics';
const timeRanges = ['Last Week', 'Last Month', 'Last 3 Months', 'Last Year', 'All Time'];
function StatCard({ title, value, icon: Icon, className }: { title: string; value: string; icon: any; className?: string }) {
return (
<Card className={cn("relative overflow-hidden", className)}>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">{title}</CardTitle>
<Icon className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{value}</div>
</CardContent>
</Card>
);
}
function App() {
const [timeRange, setTimeRange] = useState('Last Month');
const { metrics, loading, error } = useMetrics();
if (loading) return <div className="flex items-center justify-center min-h-screen">Loading...</div>;
if (error) return <div className="flex items-center justify-center min-h-screen">Error: {error}</div>;
if (!metrics) return <div className="flex items-center justify-center min-h-screen">No data available</div>;
// Mock time series data - replace with actual time series data from your API
const timeSeriesData = [
{ date: 'Jan', co2: 0.5 },
{ date: 'Feb', co2: 1.2 },
{ date: 'Mar', co2: metrics.environmental_impact.co2_saved },
];
const treeSeriesData = [
{ date: 'Jan', trees: 0.01 },
{ date: 'Feb', trees: 0.02 },
{ date: 'Mar', trees: metrics.environmental_impact.trees_saved },
];
const materialsData = [
{ name: 'Paper', value: metrics.environmental_impact.paper_weight_recycled },
{ name: 'Plastic', value: metrics.environmental_impact.plastic_weight_recycled },
{ name: 'Organic', value: metrics.environmental_impact.organic_weight_processed },
];
const COLORS = ['hsl(var(--chart-1))', 'hsl(var(--chart-2))', 'hsl(var(--chart-3))'];
return (
<div className="min-h-screen bg-background p-8">
<div className="mx-auto max-w-7xl">
<h1 className="text-4xl font-bold mb-8">Environmental Impact</h1>
<div className="grid gap-6">
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<StatCard
title="CO₂ Saved"
value={`${metrics.environmental_impact.co2_saved.toFixed(2)} kg`}
icon={Leaf}
/>
<StatCard
title="Trees Saved"
value={metrics.environmental_impact.trees_saved.toFixed(3)}
icon={TreePine}
/>
<StatCard
title="Materials Recycled"
value={`${(metrics.environmental_impact.paper_weight_recycled +
metrics.environmental_impact.plastic_weight_recycled +
metrics.environmental_impact.organic_weight_processed).toFixed(2)} kg`}
icon={Recycle}
/>
<StatCard
title="Flights Equivalent"
value={`${(metrics.environmental_impact.co2_saved / 200).toFixed(3)}`}
icon={Plane}
/>
</div>
<div className="grid gap-4 md:grid-cols-2">
<Card>
<CardHeader>
<div className="flex items-center justify-between mb-2">
<div>
<CardTitle>CO₂ Savings Trend</CardTitle>
<CardDescription>
Tracking the reduction in carbon emissions over time
</CardDescription>
</div>
<Select value={timeRange} onValueChange={setTimeRange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
{timeRanges.map((range) => (
<SelectItem key={range} value={range}>{range}</SelectItem>
))}
</SelectContent>
</Select>
</div>
</CardHeader>
<CardContent>
<div className="h-[300px]">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={timeSeriesData} margin={{ left: 12, right: 12 }}>
<CartesianGrid vertical={false} />
<XAxis dataKey="date" tickLine={false} axisLine={false} tickMargin={8} />
<YAxis tickLine={false} axisLine={false} tickMargin={8} />
<Tooltip />
<Area
type="monotone"
dataKey="co2"
stroke="hsl(var(--chart-1))"
fill="hsl(var(--chart-1))"
fillOpacity={0.2}
name="CO₂ Saved (kg)"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
<CardFooter>
<div className="flex w-full items-start gap-2 text-sm">
<div className="grid gap-2">
<div className="flex items-center gap-2 font-medium leading-none">
Total CO₂ saved: {metrics.environmental_impact.co2_saved.toFixed(2)} kg
<TrendingUp className="h-4 w-4" />
</div>
<div className="flex items-center gap-2 leading-none text-muted-foreground">
January - March 2024
</div>
</div>
</div>
</CardFooter>
</Card>
<Card>
<CardHeader>
<div className="flex items-center justify-between mb-2">
<div>
<CardTitle>Trees Saved Trend</CardTitle>
<CardDescription>
Equivalent number of trees preserved through recycling
</CardDescription>
</div>
<Select value={timeRange} onValueChange={setTimeRange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
{timeRanges.map((range) => (
<SelectItem key={range} value={range}>{range}</SelectItem>
))}
</SelectContent>
</Select>
</div>
</CardHeader>
<CardContent>
<div className="h-[300px]">
<ResponsiveContainer width="100%" height="100%">
<AreaChart data={treeSeriesData} margin={{ left: 12, right: 12 }}>
<CartesianGrid vertical={false} />
<XAxis dataKey="date" tickLine={false} axisLine={false} tickMargin={8} />
<YAxis tickLine={false} axisLine={false} tickMargin={8} />
<Tooltip />
<Area
type="monotone"
dataKey="trees"
stroke="hsl(var(--chart-2))"
fill="hsl(var(--chart-2))"
fillOpacity={0.2}
name="Trees Saved"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
<CardFooter>
<div className="flex w-full items-start gap-2 text-sm">
<div className="grid gap-2">
<div className="flex items-center gap-2 font-medium leading-none">
Total trees saved: {metrics.environmental_impact.trees_saved.toFixed(3)}
<TrendingUp className="h-4 w-4" />
</div>
<div className="flex items-center gap-2 leading-none text-muted-foreground">
January - March 2024
</div>
</div>
</div>
</CardFooter>
</Card>
<Card className="md:col-span-2">
<CardHeader>
<div className="flex items-center justify-between mb-2">
<div>
<CardTitle>Materials Recycled by Type</CardTitle>
<CardDescription>
Distribution of recycled materials by category
</CardDescription>
</div>
<Select value={timeRange} onValueChange={setTimeRange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select time range" />
</SelectTrigger>
<SelectContent>
{timeRanges.map((range) => (
<SelectItem key={range} value={range}>{range}</SelectItem>
))}
</SelectContent>
</Select>
</div>
</CardHeader>
<CardContent>
<div className="h-[300px]">
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={materialsData}
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={80}
fill="#8884d8"
paddingAngle={5}
dataKey="value"
label={({ name, value }) => `${name}: ${value.toFixed(2)}kg`}
>
{materialsData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip />
</PieChart>
</ResponsiveContainer>
</div>
</CardContent>
<CardFooter>
<div className="flex w-full items-start gap-2 text-sm">
<div className="grid gap-2">
<div className="flex items-center gap-2 font-medium leading-none">
Total materials recycled: {(
metrics.environmental_impact.paper_weight_recycled +
metrics.environmental_impact.plastic_weight_recycled +
metrics.environmental_impact.organic_weight_processed
).toFixed(2)} kg
</div>
</div>
</div>
</CardFooter>
</Card>
</div>
</div>
</div>
</div>
);
}
export default App;Editor is loading...
Leave a Comment