import { useState, useEffect, useMemo } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import Layout from '../components/Layout'; import DashboardFeaturedCollection from '../components/DashboardFeaturedCollection'; import DashboardRecentActivity from '../components/DashboardRecentActivity'; import DashboardCardSpotlight from '../components/DashboardCardSpotlight'; import { Button, StatCard } from '../components/ui'; import { useAuth } from '../lib/use-auth'; import { VOCAB } from '../lib/collection-vocabulary.js'; import { formatRelativeTime } from '../lib/format-relative-time.js'; function authHeaders() { const token = typeof window !== 'undefined' ? localStorage.getItem('auth_token') : null; const headers = { 'Content-Type': 'application/json' }; if (token) headers.Authorization = `Bearer ${token}`; return headers; } function mapRecentActivityRows(recentActivity) { if (!Array.isArray(recentActivity)) return []; return recentActivity.slice(0, 5).map((row, index) => ({ id: `${row.name}-${row.addedAt}-${index}`, actor: { name: 'You', initial: 'Y' }, action: `added to ${VOCAB.MY_COLLECTION}`, subject: [row.name, row.game].filter(Boolean).join(' ยท '), time: formatRelativeTime(row.addedAt), })); } export default function Dashboard() { const router = useRouter(); const { user, loading: authLoading } = useAuth(); const [stats, setStats] = useState(null); const [recentCards, setRecentCards] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { if (!authLoading && !user) { router.push('/login'); } }, [authLoading, user, router]); useEffect(() => { if (!user) return; let cancelled = false; const fetchAll = async () => { const headers = authHeaders(); try { const [statsRes, cardsRes] = await Promise.all([ fetch('/api/user/stats', { headers }), fetch('/api/user-cards', { headers }), ]); if (!cancelled) { if (statsRes.ok) { setStats(await statsRes.json()); } else { setStats(null); } if (cardsRes.ok) { const data = await cardsRes.json(); setRecentCards(Array.isArray(data) ? data.slice(0, 8) : []); } else { setRecentCards([]); } } } catch (error) { console.error('[dashboard] fetch error:', error); if (!cancelled) { setStats(null); setRecentCards([]); } } finally { if (!cancelled) { setLoading(false); } } }; fetchAll(); return () => { cancelled = true; }; }, [user]); const activityRows = useMemo( () => mapRecentActivityRows(stats?.recentActivity), [stats?.recentActivity] ); const spotlightCard = recentCards[0] ?? null; const totalCards = stats?.totalCards ?? 0; const collectionValue = stats?.totalValue ?? 0; const totalDecks = stats?.totalDecks ?? 0; const statsLoaded = stats !== null; const isEmptyCollection = statsLoaded && totalCards === 0 && recentCards.length === 0; return (
{isEmptyCollection && (

Welcome{user?.username ? `, ${user.username}` : ''}

Scan or browse cards to start {VOCAB.MY_COLLECTION}.

)} {loading ? (
) : ( <>
} /> } /> } />
)}
); }