Untitled

 avatar
unknown
plain_text
17 days ago
5.4 kB
6
Indexable
"use client"

import React, { useEffect, useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { TreePine, Leaf, Trophy, Unlock } from "lucide-react";
import { Progress } from "@/components/ui/progress";
import { Alert, AlertDescription } from "@/components/ui/alert";

interface TreeVisualizationProps {
  impact: {
    co2_saved: number;
    trees_saved: number;
  };
}

const SingleTree = ({ scale }: { scale: number }) => {
  if (scale === 0) return null;
  
  return (
    <svg
      viewBox="0 0 100 100"
      className="w-full h-full transform transition-all duration-1000"
      style={{ transform: `scale(${0.5 + (scale * 0.5) / 100})` }}
    >
      <path
        d="M45 90 L55 90 L53 60 L47 60 Z"
        fill="#8B4513"
        className="transition-all duration-1000"
        style={{ 
          transform: `scaleY(${0.8 + (scale * 0.2) / 100})`,
          transformOrigin: 'center bottom' 
        }}
      />
      <g className="transition-all duration-1000">
        <path
          d="M20 60 L80 60 L50 30 Z"
          fill="#2F855A"
          opacity={scale >= 20 ? "1" : "0"}
          className="transition-all duration-500"
        />
        <path
          d="M25 45 L75 45 L50 20 Z"
          fill="#276749"
          opacity={scale >= 50 ? "1" : "0"}
          className="transition-all duration-500"
        />
        <path
          d="M30 30 L70 30 L50 10 Z"
          fill="#22543D"
          opacity={scale >= 80 ? "1" : "0"}
          className="transition-all duration-500"
        />
        {scale >= 95 && (
          <>
            <circle cx="35" cy="50" r="2" fill="#48BB78" />
            <circle cx="65" cy="50" r="2" fill="#48BB78" />
            <circle cx="50" cy="25" r="2" fill="#48BB78" />
          </>
        )}
      </g>
    </svg>
  );
};

const TreeVisualization: React.FC<TreeVisualizationProps> = ({ impact }) => {
  const [treeStates, setTreeStates] = useState<number[]>([]);
  const maxTrees = 5;
  
  useEffect(() => {
    const totalTrees = Math.floor(impact.trees_saved);
    const partialTreeScale = (impact.trees_saved % 1) * 100;
    
    let newTreeStates: number[] = [];
    
    // Add full trees
    for (let i = 0; i < Math.min(totalTrees, maxTrees - 1); i++) {
      newTreeStates.push(100);
    }
    
    // Add partial tree if there's room
    if (newTreeStates.length < maxTrees) {
      newTreeStates.push(partialTreeScale);
    }
    
    // Pad with empty trees if needed
    while (newTreeStates.length < maxTrees) {
      newTreeStates.push(0);
    }
    
    setTreeStates(newTreeStates.slice(0, maxTrees));
  }, [impact.trees_saved]);

  const totalProgress = (impact.trees_saved / maxTrees) * 100;
  const isMaxed = impact.trees_saved >= maxTrees;

  return (
    <>
      <CardHeader className="items-center pb-2">
        <CardTitle className="flex items-center gap-2">
          <TreePine className="h-5 w-5 text-green-700" />
          Your Impact Forest
        </CardTitle>
        <CardDescription>Watch your forest grow with your impact</CardDescription>
      </CardHeader>
      <CardContent className="flex flex-col items-center space-y-4">
        <div className={`grid grid-cols-5 gap-2 w-full h-48 transition-all duration-200 ${
          isMaxed 
            ? 'dark:bg-gradient-to-br dark:from-primary/10 dark:to-primary/5 ' +
              'bg-gradient-to-br from-primary/20 to-background border-primary/50 ' +
              'shadow-lg shadow-primary/5 rounded-lg p-2'
            : ''
        }`}>
          {treeStates.map((scale, index) => (
            <div key={index} className="relative flex items-center justify-center">
              <SingleTree scale={scale} />
            </div>
          ))}
        </div>

        <div className="w-full space-y-2">
          <div className="flex justify-between text-sm">
            <span>Forest Growth Progress</span>
            <span>{Math.min(Math.round(totalProgress), 100)}%</span>
          </div>
          <Progress value={Math.min(totalProgress, 100)} className="h-2" />
        </div>

        <div className="grid grid-cols-2 gap-4 text-sm text-muted-foreground">
          <div className="flex items-center gap-2">
            <Leaf className="h-4 w-4 text-green-500" />
            <span>{impact.co2_saved.toFixed(2)} kg CO₂ saved</span>
          </div>
          <div className="flex items-center gap-2">
            <TreePine className="h-4 w-4 text-green-700" />
            <span>{impact.trees_saved.toFixed(3)} trees preserved</span>
          </div>
        </div>

        {isMaxed && (
          <Card className="w-full bg-gradient-to-br from-primary/20 to-background border-primary/50">
            <CardContent className="flex items-center justify-between p-4">
              <div className="flex items-center gap-2">
                <Trophy className="h-5 w-5 text-primary" />
                <span className="font-medium">Maximum Forest Size Reached!</span>
              </div>
              <Unlock className="h-5 w-5 text-primary" />
            </CardContent>
          </Card>
        )}
      </CardContent>
    </>
  );
};

export default TreeVisualization;
Editor is loading...
Leave a Comment