import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuthStore } from '@/stores/auth'; import { useLibraryItems, useLibraryActions, useLibraryStatus } from '@/utils/storeSelectors'; import { useDashboard } from '@/features/dashboard/hooks/useDashboard'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Music, MessageSquare, Users, Heart, Library, Upload } from 'lucide-react'; import { formatDistanceToNow } from 'date-fns'; import { fr } from 'date-fns/locale'; /** * Page principale du dashboard avec statistiques et aperçu de l'activité. * FE-PAGE-001: Complete Dashboard page implementation */ export function DashboardPage() { const { user } = useAuthStore(); // FE-STATE-009: Use selector that returns denormalized array const items = useLibraryItems(); const { fetchItems } = useLibraryActions(); const { isLoading: isLoadingLibrary } = useLibraryStatus(); const { stats, recentActivity, isLoading: isLoadingDashboard } = useDashboard(); const navigate = useNavigate(); useEffect(() => { fetchItems({ limit: 5 }); }, [fetchItems]); // FE-PAGE-001: Format stats with real data const formatNumber = (num: number): string => { if (num >= 1000000) { return (num / 1000000).toFixed(1) + 'M'; } if (num >= 1000) { return (num / 1000).toFixed(1) + 'K'; } return num.toString(); }; const dashboardStats = [ { title: 'Pistes écoutées', value: stats ? formatNumber(stats.tracks_played) : '0', change: stats?.tracks_played_change || '+0%', icon: Music, color: 'text-blue-600', }, { title: 'Messages envoyés', value: stats ? formatNumber(stats.messages_sent) : '0', change: stats?.messages_sent_change || '+0%', icon: MessageSquare, color: 'text-green-600', }, { title: 'Favoris', value: stats ? formatNumber(stats.favorites) : '0', change: stats?.favorites_change || '+0%', icon: Heart, color: 'text-red-600', }, { title: 'Amis actifs', value: stats ? formatNumber(stats.active_friends) : '0', change: stats?.active_friends_change || '+0%', icon: Users, color: 'text-purple-600', }, ]; // FE-PAGE-001: Get activity icon color based on type const getActivityColor = (type: string) => { switch (type) { case 'track_upload': return 'bg-blue-600'; case 'message_received': return 'bg-green-600'; case 'favorite_added': return 'bg-red-600'; case 'playlist_created': return 'bg-purple-600'; case 'comment_added': return 'bg-yellow-600'; default: return 'bg-gray-600'; } }; // FE-PAGE-001: Format timestamp to relative time const formatTimestamp = (timestamp: string) => { try { return formatDistanceToNow(new Date(timestamp), { addSuffix: true, locale: fr, }); } catch { return 'Récemment'; } }; return (
{user?.first_name || user?.username ? `Bonjour, ${user.first_name || user.username} !` : 'Bienvenue sur Veza'}
{stat.change && ( {stat.change} )} {stat.change && ' par rapport au mois dernier'}
{activity.title}
{activity.description && ({activity.description}
)}{formatTimestamp(activity.timestamp)}
Aucune activité récente
)}{item.title}
{item.description || 'Aucune description'}
Aucune piste dans votre bibliothèque
)}