import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import CollaborationManager from '../../components/CollaborationManager'; import Layout from '../../components/Layout'; export default function CollectionView() { const router = useRouter(); const { id } = router.query; // Get user from auth context - for now using admin user const user = { email: 'admin@tcgvault.com', role: 'admin' }; const [collection, setCollection] = useState(null); const [cards, setCards] = useState([]); const [loading, setLoading] = useState(true); const [isFavorited, setIsFavorited] = useState(false); const [showShareModal, setShowShareModal] = useState(false); const [copySuccess, setCopySuccess] = useState(false); const [selectedTCG, setSelectedTCG] = useState('MTG'); // Filter states const [searchQuery, setSearchQuery] = useState(''); const [selectedRarity, setSelectedRarity] = useState('All Rarities'); const [selectedType, setSelectedType] = useState('All Types'); const [groupBy, setGroupBy] = useState('Group by Game'); const [sortBy, setSortBy] = useState('Sort by Name'); const [viewMode, setViewMode] = useState('grid'); const [searchCards, setSearchCards] = useState(''); const [searchResults, setSearchResults] = useState([]); const [showSearchResults, setShowSearchResults] = useState(false); useEffect(() => { if (id) { fetchCollectionData(); } }, [id]); const fetchCollectionData = async () => { try { const response = await fetch(`/api/collections/${id}`); if (response.ok) { const data = await response.json(); setCollection(data.collection); setCards(data.cards || []); } else { console.error('Failed to fetch collection'); setCollection(null); setCards([]); } } catch (error) { console.error('Error fetching collection:', error); setCollection(null); setCards([]); } finally { setLoading(false); } }; const handleSearchCards = async (query) => { if (query.length < 2) { setSearchResults([]); setShowSearchResults(false); return; } try { const response = await fetch(`/api/cards/search?q=${encodeURIComponent(query)}&limit=10`); if (response.ok) { const data = await response.json(); setSearchResults(data.cards || []); setShowSearchResults(true); } } catch (error) { console.error('Error searching cards:', error); } }; const handleAddCard = async (card) => { try { const response = await fetch(`/api/collections/${id}/cards`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ cardId: card.id, quantity: 1 }) }); if (response.ok) { setSearchCards(''); setShowSearchResults(false); fetchCollectionData(); // Refresh the collection data } } catch (error) { console.error('Error adding card:', error); } }; const handleShare = () => { const url = window.location.href; navigator.clipboard.writeText(url).then(() => { setCopySuccess(true); setTimeout(() => setCopySuccess(false), 2000); }); }; const toggleFavorite = () => { setIsFavorited(!isFavorited); }; const togglePublic = async () => { try { const response = await fetch(`/api/collections/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ is_public: !collection.is_public }) }); if (response.ok) { setCollection(prev => ({ ...prev, is_public: !prev.is_public })); } } catch (error) { console.error('Error updating collection:', error); } }; // Group cards by game const groupedCards = cards.reduce((acc, card) => { const game = card.game || 'Other'; if (!acc[game]) acc[game] = []; acc[game].push(card); return acc; }, {}); // Get game display names and counts const gameStats = { 'MTG': groupedCards['MTG']?.length || 0, 'Lorcana': groupedCards['Lorcana']?.length || 0, 'Pokemon': groupedCards['Pokemon']?.length || 0 }; if (loading) { return ( ); } if (!collection) { return ( Collection not found Back to Collections ); } return ( {/* Header */} {/* Back button and TCG tabs */} Back to collections {/* TCG Tabs */} {['MTG', 'Lorcana', 'Pokemon'].map((tcg) => ( setSelectedTCG(tcg)} className={`px-3 py-1 text-xs font-medium rounded ${ selectedTCG === tcg ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-600 hover:bg-gray-200' }`} > {tcg} ))} {/* Action buttons */} Upload Image 🪄 Generate AI Image {/* Collection Info */} {collection.name} {collection.description} {/* Creator and Stats */} Crafted by {collection.creator_email?.charAt(0).toUpperCase()} {collection.creator_email} Cards: {cards.length} Cost: ${collection.totalValue || '0'} Created {new Date(collection.created_at).toLocaleDateString()} Last updated {new Date(collection.updated_at).toLocaleDateString()} {/* Action Bar */} Share Favorite Download List 📧 Invite Collaborator Public Activity 123 {/* Content */} {/* Search and Filters */} { setSearchCards(e.target.value); handleSearchCards(e.target.value); }} className="w-64 px-4 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--bg-secondary)' }} /> setSelectedRarity(e.target.value)} className="px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--bg-secondary)' }} > All Rarities Common Uncommon Rare Mythic Legendary setSelectedType(e.target.value)} className="px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--bg-secondary)' }} > All Types Creature Instant Sorcery Artifact Enchantment setGroupBy(e.target.value)} className="px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--bg-secondary)' }} > Group by Game Group by Rarity Group by Type setSortBy(e.target.value)} className="px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500" style={{ borderColor: 'var(--border)', backgroundColor: 'var(--bg-secondary)' }} > Sort by Name Sort by Price Sort by Rarity Sort by Date Added setViewMode('grid')} className={`p-2 rounded-l-lg ${viewMode === 'grid' ? 'bg-purple-600 text-white' : 'bg-transparent'}`} style={viewMode !== 'grid' ? { color: 'var(--text-secondary)' } : {}} > setViewMode('list')} className={`p-2 rounded-r-lg ${viewMode === 'list' ? 'bg-purple-600 text-white' : 'bg-transparent'}`} style={viewMode !== 'list' ? { color: 'var(--text-secondary)' } : {}} > Add Cards Scan Cards {/* Game Sections */} {Object.entries(groupedCards).map(([game, gameCards]) => ( {game === 'MTG' ? 'Magic The Gathering' : game} {gameCards.length} {gameCards.map((card, index) => ( {card.image_url ? ( ) : ( 'Card' )} ))} {/* Add empty card slots to fill the row */} {Array.from({ length: Math.max(0, 7 - (gameCards.length % 7)) }, (_, index) => ( Card ))} ))} {cards.length === 0 && ( 🃏 Start Building Your Collection Add cards to get started with your collection Browse Cards to Add )} {/* Search Results Dropdown */} {showSearchResults && searchResults.length > 0 && ( {searchResults.map(card => ( handleAddCard(card)} className="flex items-center p-3 hover:bg-gray-50 cursor-pointer" > { e.target.src = 'https://via.placeholder.com/48x64/6366f1/ffffff?text=No+Image'; }} /> {card.name} {card.set_name} • ${card.market_price} ))} )} {/* Collaboration Manager */} ); }
{collection.description}
Add cards to get started with your collection