veza/apps/web/src/pages/DashboardPage.tsx

186 lines
6.2 KiB
TypeScript
Raw Normal View History

import { useEffect } from 'react';
import { useAuthStore } from '@/stores/auth';
import { useLibraryStore } from '@/stores/library';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
2025-12-13 02:34:34 +00:00
import { Music, MessageSquare, Users, Heart } from 'lucide-react';
/**
* Page principale du dashboard avec statistiques et aperçu de l'activité.
*/
export function DashboardPage() {
const { user } = useAuthStore();
const { items, fetchItems, isLoading } = useLibraryStore();
useEffect(() => {
fetchItems({ limit: 5 });
}, [fetchItems]);
2025-12-17 13:07:35 +00:00
// Sécuriser items pour s'assurer que c'est toujours un tableau
const safeItems = Array.isArray(items) ? items : [];
const stats = [
{
title: 'Pistes écoutées',
value: '1,234',
change: '+12%',
icon: Music,
color: 'text-blue-600',
},
{
title: 'Messages envoyés',
value: '567',
change: '+8%',
icon: MessageSquare,
color: 'text-green-600',
},
{
title: 'Favoris',
value: '89',
change: '+23%',
icon: Heart,
color: 'text-red-600',
},
{
title: 'Amis actifs',
value: '45',
change: '+5%',
icon: Users,
color: 'text-purple-600',
},
];
return (
<div className="p-6">
<h1 className="text-3xl font-bold tracking-tight mb-2">Dashboard</h1>
2025-12-13 02:34:34 +00:00
{/* En-tête avec salutation */}
<div className="mb-6">
<p className="text-muted-foreground">
{user?.first_name || user?.username
? `Bonjour, ${user.first_name || user.username} !`
: 'Bienvenue sur Veza'}
</p>
</div>
{/* Statistiques */}
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 mb-6">
2025-12-13 02:34:34 +00:00
{stats.map((stat) => (
<Card key={stat.title}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
{stat.title}
</CardTitle>
<stat.icon className={`h-4 w-4 ${stat.color}`} />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stat.value}</div>
<p className="text-xs text-muted-foreground">
<span className="text-green-600">{stat.change}</span> par
rapport au mois dernier
</p>
</CardContent>
</Card>
))}
</div>
{/* Aperçu récent */}
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{/* Activité récente */}
<Card className="md:col-span-2">
<CardHeader>
<CardTitle>Activité récente</CardTitle>
<CardDescription>
Vos dernières interactions sur la plateforme
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center space-x-4">
<div className="w-2 h-2 bg-blue-600 rounded-full"></div>
<div className="flex-1 space-y-1">
<p className="text-sm font-medium">Nouvelle piste ajoutée</p>
<p className="text-xs text-muted-foreground">
Il y a 2 heures
</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="w-2 h-2 bg-green-600 rounded-full"></div>
<div className="flex-1 space-y-1">
<p className="text-sm font-medium">Message reçu de @alice</p>
<p className="text-xs text-muted-foreground">
Il y a 4 heures
</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="w-2 h-2 bg-purple-600 rounded-full"></div>
<div className="flex-1 space-y-1">
<p className="text-sm font-medium">Nouveau favori ajouté</p>
<p className="text-xs text-muted-foreground">
Il y a 6 heures
</p>
</div>
</div>
</div>
</CardContent>
</Card>
{/* Pistes récentes */}
<Card>
<CardHeader>
<CardTitle>Pistes récentes</CardTitle>
<CardDescription>
Dernières pistes de votre bibliothèque
</CardDescription>
</CardHeader>
<CardContent>
{isLoading ? (
<div className="space-y-2">
{[...Array(3)].map((_, i) => (
<div key={i} className="flex items-center space-x-3">
<div className="w-10 h-10 bg-muted rounded"></div>
<div className="flex-1 space-y-1">
<div className="h-4 bg-muted rounded w-3/4"></div>
<div className="h-3 bg-muted rounded w-1/2"></div>
</div>
</div>
))}
</div>
) : (
<div className="space-y-3">
2025-12-17 13:07:35 +00:00
{safeItems.slice(0, 3).map((item) => (
<div key={item.id} className="flex items-center space-x-3">
<div className="w-10 h-10 bg-muted rounded flex items-center justify-center">
<Music className="h-4 w-4 text-muted-foreground" />
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium truncate">
{item.title}
</p>
<p className="text-xs text-muted-foreground truncate">
{item.description || 'Aucune description'}
</p>
</div>
</div>
))}
2025-12-17 13:07:35 +00:00
{safeItems.length === 0 && (
<p className="text-sm text-muted-foreground text-center py-4">
Aucune piste dans votre bibliothèque
</p>
)}
</div>
)}
</CardContent>
</Card>
</div>
</div>
);
}