import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Layout from '../../components/Layout'; import { useIsAdmin } from '../../lib/admin-auth'; import { useAuth } from '../../lib/use-auth'; import CollectionSelectionModal from '../../components/CollectionSelectionModal'; import { ManaCost, ColorIdentity, AdvancedManaCost } from '../../components/ManaSymbols'; import ManaSymbolSettings from '../../components/ManaSymbolSettings'; export default function CardDetail() { const router = useRouter(); const { id } = router.query; const { user } = useAuth(); const [card, setCard] = useState(null); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState('details'); const [ownedQuantity, setOwnedQuantity] = useState(0); const [showQuantityModal, setShowQuantityModal] = useState(false); const [showCollectionModal, setShowCollectionModal] = useState(false); const [showDeckModal, setShowDeckModal] = useState(false); const [selectedCollection, setSelectedCollection] = useState(''); const [selectedDeck, setSelectedDeck] = useState(''); const [quantity, setQuantity] = useState(1); const [isFavorited, setIsFavorited] = useState(false); const [collections, setCollections] = useState([]); const [decks, setDecks] = useState([]); const [cardCollections, setCardCollections] = useState([]); const [cardDecks, setCardDecks] = useState([]); // Mana symbol settings const [manaSymbolSettings, setManaSymbolSettings] = useState({ useSVG: false }); // Check admin status const { isAdmin, loading: adminLoading } = useIsAdmin(); // Fetch card data from API useEffect(() => { const fetchCard = async () => { if (!id) return; try { const response = await fetch(`/api/cards/${id}`); if (response.ok) { const cardData = await response.json(); setCard(cardData); // Fetch user's ownership of this card const token = localStorage.getItem('auth_token'); if (token) { try { const ownershipResponse = await fetch(`/api/cards/${id}/ownership`, { headers: { 'Authorization': `Bearer ${token}` } }); if (ownershipResponse.ok) { const ownershipData = await ownershipResponse.json(); setOwnedQuantity(ownershipData.quantity || 0); } } catch (error) { console.error('Error fetching ownership:', error); } // Check if card is favorited try { const favoritesResponse = await fetch(`/api/favorites?type=card`, { headers: { 'Authorization': `Bearer ${token}` } }); if (favoritesResponse.ok) { const favoritesData = await favoritesResponse.json(); const isCardFavorited = favoritesData.favorites.some(fav => fav.item_id == id); setIsFavorited(isCardFavorited); } } catch (error) { console.error('Error checking favorites:', error); } } } else { console.error('Failed to fetch card'); } } catch (error) { console.error('Error fetching card:', error); } finally { setLoading(false); } }; fetchCard(); }, [id]); // Fetch user's collections and decks useEffect(() => { const fetchUserData = async () => { try { const token = localStorage.getItem('auth_token'); const headers = { 'Authorization': `Bearer ${token}` }; // Fetch collections const collectionsResponse = await fetch('/api/collections', { headers }); if (collectionsResponse.ok) { const collectionsData = await collectionsResponse.json(); setCollections(collectionsData); } // Fetch decks const decksResponse = await fetch('/api/decks', { headers }); if (decksResponse.ok) { const decksData = await decksResponse.json(); setDecks(decksData); } // Fetch card's current collections and decks if (card) { const cardCollectionsResponse = await fetch(`/api/cards/${id}/collections`, { headers }); if (cardCollectionsResponse.ok) { const cardCollectionsData = await cardCollectionsResponse.json(); setCardCollections(cardCollectionsData); } const cardDecksResponse = await fetch(`/api/cards/${id}/decks`, { headers }); if (cardDecksResponse.ok) { const cardDecksData = await cardDecksResponse.json(); setCardDecks(cardDecksData); } } } catch (error) { console.error('Error fetching user data:', error); } }; if (card) { fetchUserData(); } }, [card, id]); const getRarityGradient = (rarity) => { const rarityKey = rarity?.toLowerCase(); const gradients = { 'common': '#9ca3af, #6b7280, #4b5563', // Subtle gray glow 'uncommon': '#10b981, #059669, #047857', // Green glow 'rare': '#f59e0b, #d97706, #b45309', // Gold glow 'mythic': '#fbbf24, #f59e0b, #d97706', // Rich gold glow 'holographic': '#ec4899, #db2777, #be185d', // Pink glow 'enchanted': '#a855f7, #9333ea, #7c3aed', // Purple glow 'super rare': '#3b82f6, #2563eb, #1d4ed8', // Blue glow 'legendary': '#fbbf24, #f59e0b, #ea580c' // Vibrant gold-orange glow }; return gradients[rarityKey] || '#6b7280, #4b5563, #374151'; }; const getParticleCount = (rarity) => { const rarityKey = rarity?.toLowerCase(); const particleCounts = { 'common': 0, 'uncommon': 15, 'rare': 25, 'mythic': 40, 'holographic': 50, 'enchanted': 60, 'super rare': 45, 'legendary': 80 }; return particleCounts[rarityKey] || 0; }; const getParticleColor = (rarity) => { const rarityKey = rarity?.toLowerCase(); const colors = { 'common': '#ffffff', 'uncommon': '#10b981', 'rare': '#f59e0b', 'mythic': '#ffd700', 'holographic': '#ff6b6b', 'enchanted': '#a855f7', 'super rare': '#3b82f6', 'legendary': '#ffd700' }; return colors[rarityKey] || '#ffffff'; }; const getTCGIcon = (game) => { const icons = { 'MTG': '🔮', 'Pokemon': '⚡', 'Lorcana': '✨' }; return icons[game] || '🃏'; }; const formatCurrency = (amount) => { if (!amount) return '$0.00'; return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; const getRarityLabel = (rarity) => { const rarityMap = { 'common': 'Common', 'uncommon': 'Uncommon', 'rare': 'Rare', 'mythic': 'Mythic', 'holographic': 'Holographic', 'enchanted': 'Enchanted', 'super rare': 'Super Rare', 'legendary': 'Legendary' }; return rarityMap[rarity?.toLowerCase()] || rarity; }; const getRarityColor = (rarity) => { const colors = { 'common': '#6B7280', 'uncommon': '#10B981', 'rare': '#F59E0B', 'mythic': '#FFD700', 'holographic': '#FF6B6B', 'enchanted': '#A855F7', 'super rare': '#3B82F6', 'legendary': '#FFD700' }; return colors[rarity?.toLowerCase()] || '#6B7280'; }; const handleOwnershipUpdate = async (newQuantity) => { try { const token = localStorage.getItem('auth_token'); const response = await fetch(`/api/cards/${id}/ownership`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ quantity: newQuantity }) }); if (response.ok) { setOwnedQuantity(newQuantity); setShowQuantityModal(false); } else { console.error('Failed to update ownership'); } } catch (error) { console.error('Error updating ownership:', error); } }; const handleAddToCollection = async () => { try { const token = localStorage.getItem('auth_token'); const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }; const response = await fetch(`/api/cards/${id}/collections`, { method: 'POST', headers, body: JSON.stringify({ collectionId: selectedCollection }) }); if (response.ok) { // Refresh card collections const cardCollectionsResponse = await fetch(`/api/cards/${id}/collections`, { headers: { 'Authorization': `Bearer ${token}` } }); if (cardCollectionsResponse.ok) { const cardCollectionsData = await cardCollectionsResponse.json(); setCardCollections(cardCollectionsData); } setShowCollectionModal(false); setSelectedCollection(''); } else { console.error('Failed to add to collection'); } } catch (error) { console.error('Error adding to collection:', error); } }; const handleAddToDeck = async () => { try { const token = localStorage.getItem('auth_token'); const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }; const response = await fetch(`/api/cards/${id}/decks`, { method: 'POST', headers, body: JSON.stringify({ deckId: selectedDeck }) }); if (response.ok) { // Refresh card decks const cardDecksResponse = await fetch(`/api/cards/${id}/decks`, { headers: { 'Authorization': `Bearer ${token}` } }); if (cardDecksResponse.ok) { const cardDecksData = await cardDecksResponse.json(); setCardDecks(cardDecksData); } setShowDeckModal(false); setSelectedDeck(''); } else { console.error('Failed to add to deck'); } } catch (error) { console.error('Error adding to deck:', error); } }; const handleToggleFavorite = async () => { try { const token = localStorage.getItem('auth_token'); const response = await fetch(`/api/cards/${id}/favorite`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ favorited: !isFavorited }) }); if (response.ok) { setIsFavorited(!isFavorited); } else { console.error('Failed to toggle favorite'); } } catch (error) { console.error('Error toggling favorite:', error); } }; if (loading) { return (
); } if (!card) { return (
🃏

Card Not Found

The card you're looking for doesn't exist.

); } return (
{/* Hero Section with Card Image and Basic Info */}
{/* Animated Particles Background */} {getParticleCount(card.rarity) > 0 && (
{Array.from({ length: getParticleCount(card.rarity) }).map((_, i) => (
))}
)} {/* Background Pattern */}
{/* Card Image */}
{/* Rarity Glow Effect */}
{card.image_url ? ( {card.name} ) : (
{getTCGIcon(card.game)}

{card.name}

{card.set_name}

{getRarityLabel(card.rarity)}
)}
{/* Card Info */}

{card.name}

{card.oracle_text || card.card_type}

{/* Ownership Status and Actions */}
Ownership Status
{ownedQuantity > 0 && ( Owned ({ownedQuantity}) )}
{getTCGIcon(card.game)} {card.game} {getRarityLabel(card.rarity)}
{formatCurrency(card.current_price || 0)}
{/* Admin Edit Button */} {isAdmin && !adminLoading && (
)}
{/* Current Collections and Decks */} {(cardCollections.length > 0 || cardDecks.length > 0) && (

Currently In:

{cardCollections.map(collection => (
📁 {collection.name}
))} {cardDecks.map(deck => (
🎴 {deck.name}
))}
)}
{/* Content Tabs */}
{['details', 'price-history', 'purchase'].map((tab) => ( ))}
{/* Tab Content */}
{activeTab === 'details' && (
{/* Card Metadata */}

Card Information

TCG {card.game}
Set {card.set_name}
Card Number {card.card_number}
Type {card.card_type}
Rarity {getRarityLabel(card.rarity)}
{card.mana_cost && (
Cost to Play
)} {card.power && (
Power {card.power}
)} {card.toughness && (
Toughness {card.toughness}
)} {card.current_price && (
Current Price {formatCurrency(card.current_price)}
)}
{/* Card Text */}

Card Text

{card.oracle_text && (

{card.oracle_text}

)}
)} {activeTab === 'price-history' && (

Price History

{/* Price Graph Placeholder */}

Price Trend

Price history data will be available soon

{/* Price Statistics Cards */}
{/* Current Price */}
💰
Current Price
{formatCurrency(card.current_price || 0)}
)} {activeTab === 'purchase' && ( )}
{/* Quantity Modal */} {showQuantityModal && (

{ownedQuantity > 0 ? 'Update Quantity' : 'Mark as Owned'}

{quantity}
)} {/* Collection Selection Modal */} setShowCollectionModal(false)} cards={card ? [card] : []} onAddToCollections={(results, selectedCollectionIds, cards) => { const successCount = results.filter(r => r.success).length; if (successCount > 0) { // Refresh card collections const fetchCardCollections = async () => { try { const token = localStorage.getItem('auth_token'); const response = await fetch(`/api/cards/${id}/collections`, { headers: { 'Authorization': `Bearer ${token}` } }); if (response.ok) { const data = await response.json(); setCardCollections(data); } } catch (error) { console.error('Error refreshing card collections:', error); } }; fetchCardCollections(); } }} /> {/* Deck Modal */} {showDeckModal && (

Add to Deck

)}
); }