Untitled
import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { Switch } from '@/components/ui/switch'; import { Badge } from '@/components/ui/badge'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import * as icons from 'lucide-react'; import achievementsData from '@/data/achievements.json'; import './App.css'; type Achievement = { id: string; title: string; description: string; progress: number; target: number; completed: boolean; icon: keyof typeof icons; category: string; archived: boolean; }; function App() { const [showArchived, setShowArchived] = useState(false); const achievements = achievementsData.achievements as Achievement[]; const categories = [...new Set(achievements.map((a) => a.category.charAt(0).toUpperCase() + a.category.slice(1) ))]; const filteredAchievements = achievements.filter( (achievement) => achievement.archived === showArchived ); return ( <div className="min-h-screen bg-background p-8"> <div className="max-w-4xl mx-auto space-y-8"> <div className="flex items-center justify-between"> <div> <h1 className="text-4xl font-bold text-foreground mb-2">EcoBot Achievements</h1> <p className="text-muted-foreground">Track your recycling journey</p> </div> <div className="flex items-center space-x-2"> <span className="text-sm text-muted-foreground">Show Archived</span> <Switch checked={showArchived} onCheckedChange={setShowArchived} /> </div> </div> <Tabs defaultValue={categories[0].toLowerCase()} className="space-y-4"> <TabsList> {categories.map((category) => ( <TabsTrigger key={category} value={category.toLowerCase()} className="capitalize" > {category} </TabsTrigger> ))} </TabsList> {categories.map((category) => ( <TabsContent key={category} value={category.toLowerCase()} className="grid gap-6 md:grid-cols-2" > {filteredAchievements .filter((a) => a.category === category.toLowerCase()) .map((achievement) => { const Icon = icons[achievement.icon]; return ( <Card key={achievement.id}> <CardHeader className="flex flex-row items-center gap-4"> <div className="p-2 bg-primary/10 rounded-lg"> {Icon && <Icon className="h-6 w-6 text-primary" />} </div> <div className="flex-1"> <CardTitle className="flex items-center gap-2"> {achievement.title} {achievement.completed && ( <Badge variant="default" className="bg-green-600"> Completed </Badge> )} </CardTitle> <CardDescription>{achievement.description}</CardDescription> </div> </CardHeader> <CardContent> <div className="flex items-center justify-between mb-2"> <span className="text-sm text-muted-foreground"> Progress: {achievement.progress}/{achievement.target} </span> <span className="text-sm text-muted-foreground"> {Math.round((achievement.progress / achievement.target) * 100)}% </span> </div> <Progress value={(achievement.progress / achievement.target) * 100} className="h-2" /> </CardContent> </Card> ); })} </TabsContent> ))} </Tabs> </div> </div> ); } export default App;
Leave a Comment