veza/apps/web/src/features/dashboard/components/StatsSection.tsx
senke 4b57b46bac feat: frontend improvements — UI polish, player bar, auth flow, i18n
- Header, Sidebar, Toast, Dropdown, EmptyState component refinements
- Auth flow: LoginPage, RegisterPage, AuthInput, AuthLayout improvements
- Player bar: glass effect, progress, track info, controls enhancements
- Dashboard, Discover, Search pages updates
- PlaylistCard, TrackCard component improvements
- Auth store and API interceptors hardening
- i18n: updated en/es/fr locale files
- CSS additions in index.css
- Package.json and vite config updates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:35:44 +01:00

65 lines
2.3 KiB
TypeScript

import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { AnimatedNumber } from '@/components/ui/AnimatedNumber';
import { cn } from '@/lib/utils';
import { useTranslation } from '@/hooks/useTranslation';
import { Music, MessageSquare, Heart, Users } from 'lucide-react';
const STATS = [
{
titleKey: 'dashboard.stats.tracksListened',
value: 1234,
change: '+12%',
icon: Music,
color: 'text-primary',
shadow: 'drop-shadow-stat-icon',
},
{
titleKey: 'dashboard.stats.messagesSent',
value: 567,
change: '+8%',
icon: MessageSquare,
color: 'text-success',
shadow: 'drop-shadow-stat-icon',
},
{
titleKey: 'dashboard.stats.favorites',
value: 89,
change: '+23%',
icon: Heart,
color: 'text-destructive',
shadow: 'drop-shadow-stat-icon',
},
{
titleKey: 'dashboard.stats.activeFriends',
value: 45,
change: '+5%',
icon: Users,
color: 'text-destructive',
shadow: 'drop-shadow-stat-icon',
},
] as const;
export function StatsSection() {
const { t } = useTranslation();
return (
<section aria-label="Performance statistics" className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{STATS.map((stat, i) => (
<Card key={stat.titleKey} variant="glass" className="group hover:border-primary/50 hover-lift transition-all duration-[var(--sumi-duration-normal)] animate-content-reveal" style={{ animationDelay: `${i * 80}ms` }}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground group-hover:text-foreground transition-colors duration-[var(--duration-fast)]">
{t(stat.titleKey)}
</CardTitle>
<stat.icon className={cn("h-4 w-4 transition-all duration-[var(--sumi-duration-normal)]", stat.color, stat.shadow, "group-hover:scale-110")} />
</CardHeader>
<CardContent>
<AnimatedNumber value={stat.value} className="text-2xl font-bold text-foreground tracking-tight" />
<p className="text-xs text-muted-foreground mt-1">
<span className="text-success font-medium">{stat.change}</span> {t('dashboard.fromLastMonth')}
</p>
</CardContent>
</Card>
))}
</section>
);
}