/* eslint-disable @next/next/no-img-element -- External or generated image URLs; next/image migration is out of scope. */ import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import Layout from '../../components/Layout'; import DeckDetailStatsSidebar from '../../components/DeckDetailStatsSidebar'; import { ManaCost } from '../../components/ManaSymbols'; import { Button } from '../../components/ui'; import { computeDeckStats } from '../../lib/deck-builder-stats.js'; import { groupDeckCards } from '../../lib/deck-detail-grouping.js'; import { getDeckFormatIcon } from '../../lib/deck-format-utils.js'; import { useAuth } from '../../lib/use-auth'; /* 2026-06-04 design-sweep pass: this page used the broken Tailwind token classes (bg-bg-*, text-text-*, bg-accent-ember, hover:bg-accent-ember-dark, border-accent-ember) that don't resolve in tailwind.config.js. Sweep replaces them with inline CSS variables + Button primitive + glass-panel surface + the nav-item-active / nav-item-hover utilities so the page renders with the Liquid Glass design system. */ export default function DeckDetail() { const { user } = useAuth(); const router = useRouter(); const { id: deckId } = router.query; const [deck, setDeck] = useState(null); const [loading, setLoading] = useState(true); const [groupBy, setGroupBy] = useState('type'); const fetchDeck = async () => { try { const token = localStorage.getItem('auth_token'); const headers = token ? { 'Authorization': `Bearer ${token}` } : {}; const response = await fetch(`/api/decks/${deckId}`, { headers }); if (response.ok) { const data = await response.json(); setDeck(data); } else { console.error('Failed to fetch deck'); router.push('/decks'); } } catch (error) { console.error('Error fetching deck:', error); router.push('/decks'); } finally { setLoading(false); } } useEffect(() => { if (deckId) { // eslint-disable-next-line react-hooks/set-state-in-effect -- load deck when route id changes fetchDeck(); } // eslint-disable-next-line react-hooks/exhaustive-deps -- refetch when route deck id changes }, [deckId]); if (loading) { return ( ); } if (!deck) { return ( Deck not found Back to Decks ); } const stats = computeDeckStats(deck.cards || []); const groupedCards = groupDeckCards(deck.cards, groupBy); const isOwner = user && deck.user_id === user.userId; return ( {/* Header */} ← Back to Decks {getDeckFormatIcon(deck.format)} {deck.name} {deck.is_public && ( Public )} by {deck.creator_username} • {deck.format} • {stats.totalCards} cards {deck.description && ( {deck.description} )} {isOwner && ( Edit Deck )} {/* Card List */} {deck.cards && deck.cards.length === 0 ? ( 🃏 Empty Deck This deck doesn't have any cards yet ) : ( {Object.entries(groupedCards) .sort(([a], [b]) => a.localeCompare(b)) .map(([group, cards]) => ( {group} ({cards.reduce((sum, card) => sum + card.quantity, 0)}) {cards .sort((a, b) => a.name.localeCompare(b.name)) .map((card) => ( {card.image_url && ( )} {card.name} {card.quantity}x {card.set_name} {card.mana_cost && ( )} {card.rarity && ( {card.rarity} )} ))} ))} )} ); }
by {deck.creator_username} • {deck.format} • {stats.totalCards} cards
{deck.description}
This deck doesn't have any cards yet
{card.set_name}