import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/router'; import Layout from '../components/Layout'; import CardItem from '../components/CardItem'; import BulkSelectionToolbar from '../components/BulkSelectionToolbar'; import CollectionSelectionModal from '../components/CollectionSelectionModal'; export default function Cards() { const router = useRouter(); const user = { email: 'me@randallstillwell.com', role: 'user' }; const [cards, setCards] = useState([]); const [loading, setLoading] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [selectedTCG, setSelectedTCG] = useState('all'); const [selectedRarity, setSelectedRarity] = useState('all'); const [selectedSet, setSelectedSet] = useState('all'); const [selectedValueRange, setSelectedValueRange] = useState('all'); const [viewMode, setViewMode] = useState('grid'); // grid or list const [pagination, setPagination] = useState({ page: 1, limit: 50, total: 0, pages: 0 }); const [filters, setFilters] = useState({ games: [], rarities: [], sets: [] }); const [hasMore, setHasMore] = useState(true); const loadingMoreRef = useRef(false); const hasMoreRef = useRef(true); // Bulk selection state const [selectedCards, setSelectedCards] = useState([]); const [favoritedCards, setFavoritedCards] = useState(new Set()); // Modal states const [showCollectionModal, setShowCollectionModal] = useState(false); const [cardsToAdd, setCardsToAdd] = useState([]); // Fetch cards from database const fetchCards = async (isLoadMore = false) => { try { if (isLoadMore) { setLoadingMore(true); loadingMoreRef.current = true; } else { setLoading(true); } const params = new URLSearchParams({ query: searchQuery, game: selectedTCG, rarity: selectedRarity, set: selectedSet, minPrice: selectedValueRange === 'under-50' ? '0' : selectedValueRange === '50-100' ? '50' : selectedValueRange === '100-500' ? '100' : selectedValueRange === '500-1000' ? '500' : selectedValueRange === 'over-1000' ? '1000' : '', maxPrice: selectedValueRange === '50-100' ? '100' : selectedValueRange === '100-500' ? '500' : selectedValueRange === '500-1000' ? '1000' : '', page: pagination.page.toString(), limit: pagination.limit.toString() }); const response = await fetch(`/api/cards/search?${params}`); const data = await response.json(); if (data.success) { if (isLoadMore) { setCards(prevCards => [...prevCards, ...data.cards]); } else { setCards(data.cards); } setPagination(data.pagination); setFilters(data.filters); const hasMoreCards = data.pagination.page < data.pagination.pages; setHasMore(hasMoreCards); hasMoreRef.current = hasMoreCards; } else { console.error('Failed to fetch cards:', data.error); if (!isLoadMore) { setCards([]); } } } catch (error) { console.error('Error fetching cards:', error); if (!isLoadMore) { setCards([]); } } finally { setLoading(false); setLoadingMore(false); loadingMoreRef.current = false; } }; // Initial load useEffect(() => { setPagination(prev => ({ ...prev, page: 1 })); setCards([]); setHasMore(true); hasMoreRef.current = true; fetchCards(false); }, [selectedTCG, selectedRarity, selectedSet, selectedValueRange]); // Handle search with debounce const [searchTimeout, setSearchTimeout] = useState(null); const handleSearchChange = (value) => { setSearchQuery(value); // Clear existing timeout if (searchTimeout) { clearTimeout(searchTimeout); } // Set new timeout for search const newTimeout = setTimeout(() => { setPagination(prev => ({ ...prev, page: 1 })); setCards([]); setHasMore(true); hasMoreRef.current = true; fetchCards(false); }, 500); // 500ms delay setSearchTimeout(newTimeout); }; // Cleanup timeout on unmount useEffect(() => { return () => { if (searchTimeout) { clearTimeout(searchTimeout); } }; }, [searchTimeout]); // Load more cards const loadMoreCards = async () => { if (!loadingMoreRef.current && hasMoreRef.current) { const nextPage = pagination.page + 1; setPagination(prev => ({ ...prev, page: nextPage })); // Use the next page number directly in the fetch try { setLoadingMore(true); loadingMoreRef.current = true; const params = new URLSearchParams({ query: searchQuery, game: selectedTCG, rarity: selectedRarity, set: selectedSet, minPrice: selectedValueRange === 'under-50' ? '0' : selectedValueRange === '50-100' ? '50' : selectedValueRange === '100-500' ? '100' : selectedValueRange === '500-1000' ? '500' : selectedValueRange === 'over-1000' ? '1000' : '', maxPrice: selectedValueRange === '50-100' ? '100' : selectedValueRange === '100-500' ? '500' : selectedValueRange === '500-1000' ? '1000' : '', page: nextPage.toString(), limit: pagination.limit.toString() }); const response = await fetch(`/api/cards/search?${params}`); const data = await response.json(); if (data.success) { setCards(prevCards => [...prevCards, ...data.cards]); setPagination(data.pagination); setFilters(data.filters); const hasMoreCards = data.pagination.page < data.pagination.pages; setHasMore(hasMoreCards); hasMoreRef.current = hasMoreCards; } else { console.error('Failed to fetch more cards:', data.error); } } catch (error) { console.error('Error fetching more cards:', error); } finally { setLoadingMore(false); loadingMoreRef.current = false; } } }; // Update refs when state changes useEffect(() => { hasMoreRef.current = hasMore; loadingMoreRef.current = loadingMore; }, [hasMore, loadingMore]); // Intersection Observer for infinite scroll useEffect(() => { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting && hasMoreRef.current && !loadingMoreRef.current) { loadMoreCards(); } }); }, { rootMargin: '50px', threshold: 0.1 } ); const setupObserver = () => { const sentinel = document.getElementById('infinite-scroll-sentinel'); if (sentinel) { observer.observe(sentinel); } else { setTimeout(setupObserver, 100); } }; setupObserver(); return () => { const sentinel = document.getElementById('infinite-scroll-sentinel'); if (sentinel) { observer.unobserve(sentinel); } }; }, []); const getRarityColor = (rarity) => { // Map database rarity values to colors const rarityColorMap = { 'common': '#6B7280', 'uncommon': '#10B981', 'rare': '#F59E0B', 'mythic': '#FFD700', 'holographic': '#FF6B6B', 'enchanted': '#A855F7', 'secret rare': '#FF6B6B', 'ultra rare': '#A855F7' }; return rarityColorMap[rarity?.toLowerCase()] || '#6B7280'; }; const tcgOptions = [ { value: 'MTG', label: 'Magic: The Gathering', color: 'purple', icon: '🔮' }, { value: 'Pokemon', label: 'Pokemon', color: 'blue', icon: '⚡' }, { value: 'Lorcana', label: 'Disney Lorcana', color: 'pink', icon: '✨' } ]; const rarityOptions = [ { value: 'all', label: 'All Rarities' }, { value: 'common', label: 'Common' }, { value: 'uncommon', label: 'Uncommon' }, { value: 'rare', label: 'Rare' }, { value: 'mythic', label: 'Mythic' }, { value: 'enchanted', label: 'Enchanted' }, ...filters.rarities.filter(rarity => !['all', 'common', 'uncommon', 'rare', 'mythic', 'enchanted'].includes(rarity) ).map(rarity => ({ value: rarity, label: rarity, color: getRarityColor(rarity) })) ]; const setOptions = [ { value: 'all', label: 'All Sets' }, ...filters.sets.map(set => ({ value: set, label: set })) ]; const valueRangeOptions = [ { value: 'all', label: 'All Values' }, { value: 'under-50', label: 'Under $50' }, { value: '50-100', label: '$50 - $100' }, { value: '100-500', label: '$100 - $500' }, { value: '500-1000', label: '$500 - $1,000' }, { value: 'over-1000', label: 'Over $1,000' } ]; const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; const getRarityLabel = (rarity) => { const rarityOption = rarityOptions.find(option => option.value === rarity); return rarityOption ? rarityOption.label : rarity; }; // Bulk selection handlers const handleToggleSelect = (card) => { setSelectedCards(prev => { const isSelected = prev.some(c => c.id === card.id); if (isSelected) { return prev.filter(c => c.id !== card.id); } else { return [...prev, card]; } }); }; const handleClearSelection = () => { setSelectedCards([]); }; const handleToggleFavorite = async (card) => { try { const isFavorited = favoritedCards.has(card.id); const method = isFavorited ? 'DELETE' : 'POST'; const response = await fetch('/api/favorites', { method, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ itemType: 'card', itemId: card.id }) }); if (response.ok) { setFavoritedCards(prev => { const newSet = new Set(prev); if (isFavorited) { newSet.delete(card.id); } else { newSet.add(card.id); } return newSet; }); } } catch (error) { console.error('Error toggling favorite:', error); } }; // Bulk action handlers const handleBulkAddToCollection = (cards) => { setCardsToAdd(cards); setShowCollectionModal(true); }; const handleBulkAddToDeck = (cards) => { console.log('Adding to deck:', cards); alert(`Adding ${cards.length} cards to deck (functionality coming soon)`); }; const handleBulkMarkAsOwned = (cards) => { console.log('Marking as owned:', cards); alert(`Marking ${cards.length} cards as owned (functionality coming soon)`); }; const handleBulkRemoveFromOwned = (cards) => { console.log('Removing from owned:', cards); alert(`Removing ${cards.length} cards from owned (functionality coming soon)`); }; const handleBulkFavorite = async (cards) => { try { for (const card of cards) { if (!favoritedCards.has(card.id)) { await fetch('/api/favorites', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ itemType: 'card', itemId: card.id }) }); } } setFavoritedCards(prev => { const newSet = new Set(prev); cards.forEach(card => newSet.add(card.id)); return newSet; }); alert(`Added ${cards.length} cards to favorites`); } catch (error) { console.error('Error bulk favoriting:', error); } }; const handleBulkDelete = (cards) => { console.log('Bulk delete:', cards); alert(`Bulk delete functionality coming soon for ${cards.length} cards`); }; // Collection modal handlers const handleAddToCollections = (results, selectedCollectionIds, cards) => { const successCount = results.filter(r => r.success).length; const totalAttempts = results.length; if (successCount === totalAttempts) { alert(`Successfully added ${cards.length} card${cards.length !== 1 ? 's' : ''} to ${selectedCollectionIds.length} collection${selectedCollectionIds.length !== 1 ? 's' : ''}!`); } else { alert(`Added ${successCount} out of ${totalAttempts} cards. Some additions may have failed.`); } // Clear selection after successful addition setSelectedCards([]); }; if (loading && cards.length === 0) { return (
); } return ( {/* Header */}

Cards

Browse and manage your card collection

{/* Quick Filters */}

Quick Filters

{tcgOptions.map(option => ( ))}
{/* Advanced Filters */}
handleSearchChange(e.target.value)} onKeyPress={(e) => { if (e.key === 'Enter') { setPagination(prev => ({ ...prev, page: 1 })); setCards([]); setHasMore(true); hasMoreRef.current = true; fetchCards(false); } }} />
{/* Active Filters Display */} {(selectedTCG !== 'all' || selectedRarity !== 'all' || selectedSet !== 'all' || selectedValueRange !== 'all') && (
{selectedTCG !== 'all' && ( {tcgOptions.find(opt => opt.value === selectedTCG)?.label} )} {selectedRarity !== 'all' && ( {rarityOptions.find(opt => opt.value === selectedRarity)?.label} )} {selectedSet !== 'all' && ( {setOptions.find(opt => opt.value === selectedSet)?.label} )} {selectedValueRange !== 'all' && ( {valueRangeOptions.find(opt => opt.value === selectedValueRange)?.label} )}
)}
{/* Cards Display */}
{cards.length === 0 ? (
🃏

No cards found

Try adjusting your search or filters

) : ( <>
{cards.map(card => ( c.id === card.id)} onToggleSelect={handleToggleSelect} onAddToCollection={(card) => handleBulkAddToCollection([card])} onAddToDeck={handleBulkAddToDeck} onToggleFavorite={handleToggleFavorite} isFavorited={favoritedCards.has(card.id)} /> ))}
{/* Infinite Scroll Loading Indicator */} {loadingMore && (
Loading more cards...
)} {/* Infinite Scroll Sentinel */}
{/* Load More Button */} {hasMore && !loadingMore && (
)} {/* End of results indicator */} {!hasMore && cards.length > 0 && (
No more cards to load
)} )}
{/* Bulk Selection Toolbar */} {/* Collection Selection Modal */} setShowCollectionModal(false)} cards={cardsToAdd} onAddToCollections={handleAddToCollections} /> ); } // 3D Card Component function Card3D({ card, viewMode, getRarityLabel, getRarityColor }) { const [isHovered, setIsHovered] = useState(false); const [cardPosition, setCardPosition] = useState({ x: 0, y: 0, width: 0, height: 0 }); const [isFavorited, setIsFavorited] = useState(false); const handleMouseMove = (e) => { const rect = e.currentTarget.getBoundingClientRect(); setCardPosition({ x: rect.left, y: rect.top, width: rect.width, height: rect.height }); }; const handleMouseLeave = () => { setIsHovered(false); }; const handleMouseEnter = () => { setIsHovered(true); }; const getTCGColor = (game) => { const colors = { 'MTG': '#8B5CF6', // purple 'Pokemon': '#3B82F6', // blue 'Lorcana': '#EC4899' // pink }; return colors[game] || '#6B7280'; }; const getSetColor = (setName) => { // Generate a consistent color based on set name const hash = setName.split('').reduce((a, b) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0); const hue = Math.abs(hash) % 360; return `hsl(${hue}, 70%, 60%)`; }; const formatCurrency = (amount) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); }; const getRarityGradient = (rarity) => { const gradients = { common: 'from-gray-400 to-gray-500', uncommon: 'from-green-400 to-emerald-500', rare: 'from-yellow-400 to-orange-500', mythic: 'from-yellow-400 to-orange-500', holographic: 'from-red-400 to-pink-500', enchanted: 'from-purple-400 to-indigo-500', ultra: 'from-blue-400 to-cyan-500' }; return gradients[rarity] || 'from-gray-400 to-gray-500'; }; const getRarityGlow = (rarity) => { const glows = { common: '0 0 15px rgba(156, 163, 175, 0.4)', uncommon: '0 0 15px rgba(34, 197, 94, 0.4)', rare: '0 0 20px rgba(251, 191, 36, 0.5)', mythic: '0 0 20px rgba(255, 215, 0, 0.4), 0 0 40px rgba(255, 215, 0, 0.2), 0 0 60px rgba(255, 215, 0, 0.1)', holographic: '0 0 25px rgba(239, 68, 68, 0.6)', enchanted: '0 0 20px rgba(168, 85, 247, 0.4), 0 0 40px rgba(168, 85, 247, 0.2), 0 0 60px rgba(168, 85, 247, 0.1)', ultra: '0 0 25px rgba(59, 130, 246, 0.6)' }; return glows[rarity] || '0 0 15px rgba(156, 163, 175, 0.4)'; }; if (viewMode === 'list') { return (
{card.game}

{card.name}

{card.set_name} • {getRarityLabel(card.rarity)}

{card.oracle_text || card.card_type}

{formatCurrency(card.current_price || 0)}

{getRarityLabel(card.rarity)}
); } return (
{/* Card Container with proper ratio and rarity glow */}
{/* Particle Effects for All Rarities */} {card.rarity !== 'common' && (
{/* Get particle count and colors based on rarity */} {(() => { const rarityConfig = { 'mythic': { particleCount: 16, sparkleCount: 10, particleColor: '#FFD700', sparkleColor: '#FFA500', glowColor: '#FFD700' }, 'enchanted': { particleCount: 14, sparkleCount: 8, particleColor: '#A855F7', sparkleColor: '#EC4899', glowColor: '#A855F7' }, 'rare': { particleCount: 10, sparkleCount: 6, particleColor: '#3B82F6', sparkleColor: '#60A5FA', glowColor: '#3B82F6' }, 'uncommon': { particleCount: 6, sparkleCount: 4, particleColor: '#10B981', sparkleColor: '#34D399', glowColor: '#10B981' } }; const config = rarityConfig[card.rarity]; if (!config) return null; return ( <> {/* Floating Particles - Edge framing */}
{[...Array(config.particleCount)].map((_, i) => { // Position particles around the card edges let left, top; const edgeIndex = i % 4; // 4 edges const positionOnEdge = Math.floor(i / 4); if (edgeIndex === 0) { // Top edge left = `${10 + (positionOnEdge * 20)}%`; top = '2%'; } else if (edgeIndex === 1) { // Right edge left = '98%'; top = `${10 + (positionOnEdge * 20)}%`; } else if (edgeIndex === 2) { // Bottom edge left = `${10 + (positionOnEdge * 20)}%`; top = '98%'; } else { // Left edge left = '2%'; top = `${10 + (positionOnEdge * 20)}%`; } return (
); })}
{/* Sparkle Effects - Corner highlights */}
{[...Array(config.sparkleCount)].map((_, i) => { // Position sparkles in the corners and edge centers let left, top; if (i < 2) { // Top corners left = i === 0 ? '5%' : '95%'; top = '5%'; } else if (i < 4) { // Bottom corners left = i === 2 ? '5%' : '95%'; top = '95%'; } else if (i < 6) { // Edge centers left = i === 4 ? '50%' : '50%'; top = i === 4 ? '5%' : '95%'; } else { // Side centers left = i === 6 ? '5%' : '95%'; top = '50%'; } return (
); })}
{/* Rarity Aura - Blend with overall glow */}
); })()}
)} {/* Card Image */}
{card.image_url ? ( {card.name} { e.target.style.display = 'none'; e.target.nextSibling.style.display = 'flex'; }} /> ) : null} {/* Card Back placeholder when no image */}
{/* Owned Quantity Chip - Only show if owned */} {card.quantity > 0 && (
{card.quantity}
)} {/* Favorite Button */}
{/* Hover Details Panel */} {isHovered && (
{/* Card Title */}
{card.name}
{/* Top Section - TCG, Set, Type, HP in 2x2 grid */}
TCG
{card.game}
Set
{card.set_name}
{card.type && (
Type
{card.game === 'Pokemon' && card.type === 'Lightning' && ( )} {card.type}
)} {card.hp && (
HP
{card.hp}
)}
{/* Card Type and Form */}
Card type
{card.card_type || 'Card'}
{card.form && (
Form
{card.form}
)}
{/* Cost to Play */} {card.mana_cost && (
Cost to Play
{card.mana_cost}
)} {/* Card Rule Section */} {card.game === 'Pokemon' && card.form && card.form.includes('V') && (
Card rule
V rule: When your Pokémon V is Knocked Out, your opponent takes 2 Prize cards.
)} {/* Abilities/Attacks/Moves Section */} {card.oracle_text && (
Card Text
{card.oracle_text}
)} {/* Quote Section */} {card.flavor_text && (
Quote
"{card.flavor_text}"
)} {/* Current Price */} {card.current_price && (
Current Price
{formatCurrency(card.current_price)}
)} {/* Bottom Section - Weaknesses and Retreat */}
{card.weakness && (
Weaknesses
{card.game === 'Pokemon' && ( 👊 )} {card.weakness}
)} {card.retreat_cost && (
Retreat
{card.game === 'Pokemon' && ( <> )} {card.retreat_cost}
)}
{/* Decks and Collections */} {(card.decks && card.decks.length > 0) || (card.collections && card.collections.length > 0) && (
Included In
{card.decks && card.decks.length > 0 && (
Decks: {card.decks.join(', ')}
)} {card.collections && card.collections.length > 0 && (
Collections: {card.collections.join(', ')}
)}
)}
)}
); } // Card Back Component for placeholders function CardBack({ game }) { const getCardBackImage = () => { switch (game) { case 'MTG': return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE0MyIgdmlld0JveD0iMCAwIDIwMCAxNDMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTQzIiBmaWxsPSIjOEI0NTEzIi8+CjxyZWN0IHg9IjEwIiB5PSIxMCIgd2lkdGg9IjE4MCIgaGVpZ2h0PSIxMjMiIGZpbGw9IiNBMDUyMkQiIHJ4PSI4Ii8+Cjx0ZXh0IHg9IjEwMCIgeT0iMzAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9IiM0QTkwRTIiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1BR0lDPC90ZXh0Pgo8dGV4dCB4PSIxMDAiIHk9IjQ1IiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTIiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5UaGUgR2F0aGVyaW5nPC90ZXh0Pgo8Y2lyY2xlIGN4PSI3MCIgY3k9IjcwIiByPSI0IiBmaWxsPSJ3aGl0ZSIvPgo8Y2lyY2xlIGN4PSIxMzAiIGN4PSI3MCIgcj0iNCIgZmlsbD0iI0Y1OTlFMEIiLz4KPGNpcmNsZSBjeD0iMTAwIiBjeT0iODAiIHI9IjQiIGZpbGw9IiM0QTkwRTIiLz4KPGNpcmNsZSBjeD0iNzAiIGN5PSI5MCIgcj0iNCIgZmlsbD0iIzEwQjk4MSIvPgo8Y2lyY2xlIGN4PSIxMzAiIGN5PSI5MCIgcj0iNCIgZmlsbD0iYmxhY2siLz4KPHRleHQgeD0iMTAwIiB5PSIxMjAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9IiMyMEIyQUEiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkRFQ0tNQVNURVI8L3RleHQ+Cjwvc3ZnPgo='; case 'Pokemon': return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE0MyIgdmlld0JveD0iMCAwIDIwMCAxNDMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTQzIiBmaWxsPSIjRkY2QjZCIi8+CjxyZWN0IHg9IjEwIiB5PSIxMCIgd2lkdGg9IjE4MCIgaGVpZ2h0PSIxMjMiIGZpbGw9IiNGRjhFOEUiIHJ4PSI4Ii8+Cjx0ZXh0IHg9IjEwMCIgeT0iMzAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9IiNGRkQ3MDAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlBPS0VNT048L3RleHQ+Cjx0ZXh0IHg9IjEwMCIgeT0iNDUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgZmlsbD0id2hpdGUiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlRyYWRpbmcgQ2FyZCBHYW1lPC90ZXh0Pgo8Y2lyY2xlIGN4PSIxMDAiIGN5PSI3MCIgcj0iMjAiIGZpbGw9IndoaXRlIi8+Cjx0ZXh0IHg9IjEwMCIgeT0iNzgiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIyNCIgZmlsbD0iIzFGN0Y3RiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+4pePPC90ZXh0Pgo8dGV4dCB4PSIxMDAiIHk9IjEyMCIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEwIiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI0ZGRDcwMCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+R0FNRSBGUkVBSzwvdGV4dD4KPC9zdmc+Cg=='; case 'Lorcana': return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE0MyIgdmlld0JveD0iMCAwIDIwMCAxNDMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTQzIiBmaWxsPSIjRUM0ODk5Ii8+CjxyZWN0IHg9IjEwIiB5PSIxMCIgd2lkdGg9IjE4MCIgaGVpZ2h0PSIxMjMiIGZpbGw9IiNGNDcyQjYiIHJ4PSI4Ii8+Cjx0ZXh0IHg9IjEwMCIgeT0iMzAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9IiNGQkJGMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkRJU05FWTwvdGV4dD4KPHRleHQgeD0iMTAwIiB5PSI0NSIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBmaWxsPSJ3aGl0ZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TG9yY2FuYTwvdGV4dD4KPGNpcmNsZSBjeD0iMTAwIiBjeT0iNzAiIHI9IjIwIiBmaWxsPSJ3aGl0ZSIvPgo8dGV4dCB4PSIxMDAiIHk9Ijc4IiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiMxRjdGN0YiIHRleHQtYW5jaG9yPSJtaWRkbGUiPvCfkqQ8L3RleHQ+Cjx0ZXh0IHg9IjEwMCIgeT0iMTIwIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZvbnQtd2VpZ2h0PSJib2xkIiBmaWxsPSIjRjU5RTBCIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5SQVZFTlNERVJHPzwvdGV4dD4KPC9zdmc+Cg=='; default: return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE0MyIgdmlld0JveD0iMCAwIDIwMCAxNDMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTQzIiBmaWxsPSIjNkI3MjgwIi8+CjxyZWN0IHg9IjEwIiB5PSIxMCIgd2lkdGg9IjE4MCIgaGVpZ2h0PSIxMjMiIGZpbGw9IiM5Q0EzQUYiIHJ4PSI4Ii8+Cjx0ZXh0IHg9IjEwMCIgeT0iMzAiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5UQ0c8L3RleHQ+Cjx0ZXh0IHg9IjEwMCIgeT0iNDUiIGZvbnQtZmFtaWx5PSJBcmlhbCwgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgZmlsbD0id2hpdGUiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlRyYWRpbmcgQ2FyZDwvdGV4dD4KPGNpcmNsZSBjeD0iMTAwIiBjeT0iNzAiIHI9IjIwIiBmaWxsPSJ3aGl0ZSIvPgo8dGV4dCB4PSIxMDAiIHk9Ijc4IiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiMxRjdGN0YiIHRleHQtYW5jaG9yPSJtaWRkbGUiPvCfkqQ8L3RleHQ+Cjx0ZXh0IHg9IjEwMCIgeT0iMTIwIiBmb250LWZhbWlseT0iQXJpYWwsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZvbnQtd2VpZ2h0PSJib2xkIiBmaWxsPSIjNkI3MjgwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5DQVJEPC90ZXh0Pgo8L3N2Zz4K'; } }; return (
{`${game}
); }