Untitled
unknown
plain_text
9 months ago
9.3 kB
5
Indexable
"use client";
import React from 'react';
import { useMetrics } from '@/hooks/useMetrics';
import { AppSidebar } from "@/components/app-sidebar";
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb";
import { Separator } from "@/components/ui/separator";
import {
SidebarInset,
SidebarProvider,
SidebarTrigger,
} from "@/components/ui/sidebar";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import {
Trophy,
Lock,
Unlock,
Target,
Calendar,
CalendarRange,
Recycle,
Trees,
Leaf,
Timer,
Binary,
Trash2,
Scale,
Network,
BarChart,
Flame,
Zap,
Share2,
Activity,
Star,
SunDim,
Snowflake,
Bird,
Moon,
Sun,
StickyNote,
Footprints
} from 'lucide-react';
import { useTranslation, type SupportedLanguages } from "@/utils/translations";
import { useSettings } from "@/hooks/useSettings";
const AchievementsPage = () => {
const { metrics, loading, error } = useMetrics();
const { settings } = useSettings();
const { t } = useTranslation(settings?.language as SupportedLanguages || 'EN');
if (loading) return <div className="p-4">Loading achievements...</div>;
if (error) return <div className="p-4 text-red-500">Error loading achievements</div>;
if (!metrics) return null;
const achievements = Object.entries(metrics.achievements);
const unlockedCount = achievements.filter(([_, a]) => a.status === 'completed').length;
const totalCount = achievements.length;
const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString('de-DE', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
};
const getAchievementTranslation = (id: string) => {
return {
name: t(`achievements.${id}.name`),
description: t(`achievements.${id}.description`)
};
};
const formatProgressValue = (id: string, value: number) => {
if (id.includes('eco_warrior') || id.includes('tree')) {
return Number(value.toFixed(3));
}
return value;
};
const getAchievementIcon = (achievement, id: string) => {
const getTierColor = (tier) => {
switch (tier) {
case 'bronze': return 'text-amber-600';
case 'silver': return 'text-gray-400';
case 'gold': return 'text-yellow-400';
default: return 'text-primary';
}
};
const baseSize = "w-8 h-8";
const color = achievement.tier ? getTierColor(achievement.tier) : 'text-primary';
switch (id) {
case 'first_sort': return <Footprints className={`${baseSize} ${color}`} />;
case 'seasonal_master': return <SunDim className={`${baseSize} ${color}`} />;
case 'winter_sorter': return <Snowflake className={`${baseSize} ${color}`} />;
case 'monthly_master': return <Calendar className={`${baseSize} ${color}`} />;
case 'paper_specialist': return <StickyNote className={`${baseSize} ${color}`} />;
case 'early_bird': return <Bird className={`${baseSize} ${color}`} />;
case 'night_owl': return <Moon className={`${baseSize} ${color}`} />;
case 'weekend_warrior': return <CalendarRange className={`${baseSize} ${color}`} />;
case 'summer_sorter': return <Sun className={`${baseSize} ${color}`} />;
case 'recycling_specialist': return <Recycle className={`${baseSize} ${color}`} />;
case 'quick_draw': return <Timer className={`${baseSize} ${color}`} />;
case 'organic_specialist': return <Leaf className={`${baseSize} ${color}`} />;
case 'residual_specialist': return <Trash2 className={`${baseSize} ${color}`} />;
case 'tree_hero': return <Trees className={`${baseSize} ${color}`} />;
case 'time_lord': return <Timer className={`${baseSize} ${color}`} />;
case 'perfect_balance': return <Scale className={`${baseSize} ${color}`} />;
case 'efficient_manager': return <BarChart className={`${baseSize} ${color}`} />;
default: return <Trophy className={`${baseSize} ${color}`} />;
}
};
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="/">{t('navigation.home')}</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/achievements">{t('navigation.achievements')}</BreadcrumbLink>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<main className="p-4">
<Card className="mb-6">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Trophy className="w-6 h-6 text-primary" />
{t('navigation.achievements')}
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-4">
<Progress value={(unlockedCount / totalCount) * 100} className="w-full" />
<span className="text-sm font-medium">
{unlockedCount}/{totalCount}
</span>
</div>
</CardContent>
</Card>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{achievements.sort(([, a], [, b]) => {
if (a.status === 'completed' && b.status !== 'completed') return -1;
if (a.status !== 'completed' && b.status === 'completed') return 1;
return (b.progress / b.target) - (a.progress / a.target);
}).map(([id, achievement]) => {
const translation = getAchievementTranslation(id);
return (
<Card
key={id}
className={`relative overflow-hidden transition-all duration-200 ${
achievement.status === 'completed'
? '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'
: 'opacity-75'
}`}
>
<CardHeader>
<CardTitle className="flex items-center justify-between">
<div className="flex items-center gap-2">
{getAchievementIcon(achievement, id)}
<span>{translation.name}</span>
</div>
{achievement.status === 'completed' ? (
<Unlock className="w-5 h-5 text-primary" />
) : (
<Lock className="w-5 h-5" />
)}
</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-4 text-sm text-muted-foreground">
{translation.description}
</p>
<div className="space-y-4">
<div className="flex items-center gap-2">
<Target className="w-4 h-4" />
<Progress
value={achievement.status === 'completed' ? 100 : (achievement.progress / achievement.target) * 100}
className="flex-1"
/>
<span className="text-sm font-medium">
{achievement.status === 'completed'
? formatProgressValue(id, achievement.target)
: formatProgressValue(id, achievement.progress)}
/{formatProgressValue(id, achievement.target)}
</span>
</div>
{(achievement.unlock_date || achievement.status === 'completed') && (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<Calendar className="w-4 h-4" />
<span>
{t('navigation.unlocked')}: {
achievement.unlock_date
? formatDate(achievement.unlock_date)
: formatDate(new Date().toISOString())
}
</span>
</div>
)}
</div>
</CardContent>
</Card>
);
})}
</div>
</main>
</SidebarInset>
</SidebarProvider>
);
};
export default AchievementsPage;Editor is loading...
Leave a Comment