import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import Layout from '../components/Layout'; import { Modal, Input, Button } from '../components/ui'; import { useAuth } from '../lib/use-auth'; export default function Decks() { const { user } = useAuth(); const router = useRouter(); const [decks, setDecks] = useState([]); const [loading, setLoading] = useState(true); const [showCreateModal, setShowCreateModal] = useState(false); const [editingDeck, setEditingDeck] = useState(null); const [newDeck, setNewDeck] = useState({ name: '', description: '', format: 'Commander', is_public: false }); const fetchDecks = async () => { try { const token = localStorage.getItem('auth_token'); const response = await fetch('/api/decks', { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const data = await response.json(); setDecks(data); } else { console.error('Failed to fetch decks'); } } catch (error) { console.error('Error fetching decks:', error); } finally { setLoading(false); } } useEffect(() => { if (user) { // eslint-disable-next-line react-hooks/set-state-in-effect -- load decks when user is available fetchDecks(); } }, [user]); ; const handleCreateDeck = async (e) => { e.preventDefault(); try { const token = localStorage.getItem('auth_token'); const response = await fetch('/api/decks', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(newDeck) }); if (response.ok) { const createdDeck = await response.json(); setDecks([createdDeck, ...decks]); setShowCreateModal(false); setNewDeck({ name: '', description: '', format: 'Commander', is_public: false }); // Navigate to deck builder for the new deck router.push(`/deck-builder?deck=${createdDeck.id}`); } else { console.error('Failed to create deck'); } } catch (error) { console.error('Error creating deck:', error); } }; const handleEditDeck = async (e) => { e.preventDefault(); try { const token = localStorage.getItem('auth_token'); const response = await fetch(`/api/decks/${editingDeck.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(editingDeck) }); if (response.ok) { const updatedDeck = await response.json(); setDecks(decks.map(deck => deck.id === updatedDeck.id ? updatedDeck : deck)); setEditingDeck(null); } else { console.error('Failed to update deck'); } } catch (error) { console.error('Error updating deck:', error); } }; const handleDeleteDeck = async (deckId) => { if (!confirm('Are you sure you want to delete this deck? This action cannot be undone.')) { return; } try { const token = localStorage.getItem('auth_token'); const response = await fetch(`/api/decks/${deckId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { setDecks(decks.filter(deck => deck.id !== deckId)); } else { console.error('Failed to delete deck'); } } catch (error) { console.error('Error deleting deck:', error); } }; const getFormatIcon = (format) => { switch (format) { case 'Commander': return '⚔️'; case 'Standard': return '🏆'; case 'Modern': return '🔥'; case 'Legacy': return '💎'; default: return '🃏'; } }; const getFormatColor = (format) => { switch (format) { case 'Commander': return 'bg-purple-100 text-purple-800'; case 'Standard': return 'bg-blue-100 text-blue-800'; case 'Modern': return 'bg-red-100 text-red-800'; case 'Legacy': return 'bg-yellow-100 text-yellow-800'; default: return 'bg-gray-100 text-gray-800'; } }; if (!user) { return ( Please log in to view your decks Go to Login ); } if (loading) { return ( ); } return ( {/* Header */} My Decks Build and manage your MTG decks setShowCreateModal(true)} className="bg-accent-ember text-white px-6 py-3 rounded-lg hover:bg-accent-ember-dark transition-colors" > Create New Deck {/* Stats */} {decks.length} Total Decks {decks.filter(d => d.format === 'Commander').length} Commander {decks.filter(d => d.is_public).length} Public {decks.reduce((sum, deck) => sum + (deck.card_count || 0), 0)} Total Cards {/* Decks Grid */} {decks.length === 0 ? ( 🃏 No decks yet Create your first deck to get started setShowCreateModal(true)} className="bg-accent-ember text-white px-6 py-3 rounded-lg hover:bg-accent-ember-dark transition-colors" > Create Your First Deck ) : ( {decks.map((deck) => ( {getFormatIcon(deck.format)} {deck.format} setEditingDeck({...deck})} className="text-text-secondary hover:text-accent-ember transition-colors" > ✏️ handleDeleteDeck(deck.id)} className="text-text-secondary hover:text-red-500 transition-colors" > 🗑️ {deck.name} {deck.description && ( {deck.description} )} {deck.card_count || 0} cards {deck.is_public && Public} Edit Deck View ))} )} setShowCreateModal(false)} title="Create New Deck" size="md" > setNewDeck({ ...newDeck, name: e.target.value })} placeholder="Enter deck name" /> Format setNewDeck({ ...newDeck, format: e.target.value })} className="w-full px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-secondary text-text-primary" > Commander Standard Modern Legacy Description setNewDeck({ ...newDeck, description: e.target.value })} className="w-full px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-secondary text-text-primary" rows="3" placeholder="Describe your deck strategy..." /> setNewDeck({ ...newDeck, is_public: e.target.checked })} className="mr-2" style={{ accentColor: 'var(--accent-ember)' }} /> Make deck public setShowCreateModal(false)} className="flex-1" > Cancel Create Deck setEditingDeck(null)} title="Edit Deck" size="md" > {editingDeck && ( setEditingDeck({ ...editingDeck, name: e.target.value }) } /> Format setEditingDeck({ ...editingDeck, format: e.target.value }) } className="w-full px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-secondary text-text-primary" > Commander Standard Modern Legacy Description setEditingDeck({ ...editingDeck, description: e.target.value }) } className="w-full px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-secondary text-text-primary" rows="3" /> setEditingDeck({ ...editingDeck, is_public: e.target.checked }) } className="mr-2" style={{ accentColor: 'var(--accent-ember)' }} /> Make deck public setEditingDeck(null)} className="flex-1" > Cancel Save Changes )} ); }
Build and manage your MTG decks
Create your first deck to get started
{deck.description}