/* 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 { ManaCost, ColorIdentity } from '../../components/ManaSymbols'; import { useAuth } from '../../lib/use-auth'; import { getColorIdentity } from '../../lib/mana-symbols'; 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]); ; const getDeckStats = () => { if (!deck?.cards) return { totalCards: 0, avgCmc: 0, colorCounts: {}, typeCounts: {} }; const totalCards = deck.cards.reduce((sum, card) => sum + card.quantity, 0); const avgCmc = deck.cards.length > 0 ? (deck.cards.reduce((sum, card) => sum + (card.cmc || 0) * card.quantity, 0) / totalCards).toFixed(1) : 0; const colorCounts = deck.cards.reduce((counts, card) => { if (card.colors) { try { const colors = JSON.parse(card.colors); colors.forEach(color => { counts[color] = (counts[color] || 0) + card.quantity; }); } catch (e) { // Handle non-JSON color format } } return counts; }, {}); const typeCounts = deck.cards.reduce((counts, card) => { if (card.card_type) { const types = card.card_type.split(' — ')[0].split(' '); types.forEach(type => { counts[type] = (counts[type] || 0) + card.quantity; }); } return counts; }, {}); return { totalCards, avgCmc, colorCounts, typeCounts }; }; const getGroupedCards = () => { if (!deck?.cards) return {}; return deck.cards.reduce((groups, card) => { let key; switch (groupBy) { case 'type': key = card.card_type ? card.card_type.split(' — ')[0] : 'Unknown'; break; case 'cmc': key = `${card.cmc || 0} Mana`; break; case 'color': try { const colors = card.colors ? JSON.parse(card.colors) : []; key = colors.length === 0 ? 'Colorless' : colors.map(c => c).join(''); } catch (e) { key = 'Colorless'; } break; case 'rarity': key = card.rarity || 'Unknown'; break; default: key = 'All Cards'; } if (!groups[key]) groups[key] = []; groups[key].push(card); return groups; }, {}); }; const getFormatIcon = (format) => { switch (format) { case 'Commander': return '⚔️'; case 'Standard': return '🏆'; case 'Modern': return '🔥'; case 'Legacy': return '💎'; default: return '🃏'; } }; if (loading) { return (
); } if (!deck) { return (

Deck not found

Back to Decks
); } const stats = getDeckStats(); const groupedCards = getGroupedCards(); const isOwner = user && deck.user_id === user.userId; return (
{/* Header */}
← Back to Decks
{getFormatIcon(deck.format)}

{deck.name}

{deck.is_public && ( Public )}

by {deck.creator_username} • {deck.format} • {stats.totalCards} cards

{deck.description && (

{deck.description}

)}
{isOwner && (
Edit Deck
)}
{/* Stats Sidebar */}

Statistics

Total Cards: {stats.totalCards}
Avg. CMC: {stats.avgCmc}
Format: {deck.format}
{/* Color Distribution */} {Object.keys(stats.colorCounts).length > 0 && (

Color Distribution

{Object.entries(stats.colorCounts) .sort(([,a], [,b]) => b - a) .map(([color, count]) => (
{color} {color}
{count}
))}
)} {/* Type Distribution */} {Object.keys(stats.typeCounts).length > 0 && (

Card Types

{Object.entries(stats.typeCounts) .sort(([,a], [,b]) => b - a) .slice(0, 8) .map(([type, count]) => (
{type} {count}
))}
)}
{/* Group By Controls */}

Group Cards By

{[ { value: 'type', label: 'Card Type' }, { value: 'cmc', label: 'Mana Cost' }, { value: 'color', label: 'Color' }, { value: 'rarity', label: 'Rarity' } ].map(option => ( ))}
{/* 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.name}

{card.quantity}x

{card.set_name}

{card.mana_cost && ( )} {card.rarity && {card.rarity}}
))}
))}
)}
); }