Untitled
'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;
Leave a Comment