import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import CollaborationManager from '../../components/CollaborationManager'; import UploadImageModal from '../../components/UploadImageModal'; import ShareModal from '../../components/ShareModal'; 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); const [showUploadModal, setShowUploadModal] = 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 || []); // Check if collection is favorited checkIfFavorited(); } 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 checkIfFavorited = async () => { try { const response = await fetch(`/api/favorites?type=collection`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` } }); if (response.ok) { const data = await response.json(); const isFav = data.favorites.some(fav => fav.item_id === parseInt(id)); setIsFavorited(isFav); } } catch (error) { console.error('Error checking favorites:', error); } }; 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 toggleFavorite = async () => { try { if (isFavorited) { // Remove from favorites const response = await fetch('/api/favorites', { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ itemType: 'collection', itemId: parseInt(id) }) }); if (response.ok) { setIsFavorited(false); } } else { // Add to favorites const response = await fetch('/api/favorites', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ itemType: 'collection', itemId: parseInt(id) }) }); if (response.ok) { setIsFavorited(true); } } } catch (error) { console.error('Error toggling favorite:', error); } }; 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); } }; const handleImageUpload = async (imageUrl) => { try { const response = await fetch(`/api/collections/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` }, body: JSON.stringify({ image: imageUrl }) }); if (response.ok) { setCollection(prev => ({ ...prev, image: imageUrl })); } } catch (error) { console.error('Error updating collection image:', error); } }; const handleDownloadCSV = () => { if (cards.length === 0) { alert('No cards to download'); return; } // Create CSV headers const headers = [ 'Name', 'Set Name', 'Set Code', 'Card Number', 'Rarity', 'Game', 'Mana Cost', 'CMC', 'Type', 'Colors', 'Oracle Text', 'Power', 'Toughness', 'Market Price', 'Quantity', 'Added Date' ]; // Create CSV rows const csvRows = [ headers.join(','), // Header row ...cards.map(card => [ `"${(card.name || '').replace(/"/g, '""')}"`, `"${(card.set_name || '').replace(/"/g, '""')}"`, `"${card.set_code || ''}"`, `"${card.card_number || ''}"`, `"${card.rarity || ''}"`, `"${card.game || ''}"`, `"${card.mana_cost || ''}"`, `"${card.cmc || ''}"`, `"${card.card_type || ''}"`, `"${Array.isArray(card.colors) ? card.colors.join(', ') : (card.colors || '')}"`, `"${(card.oracle_text || '').replace(/"/g, '""')}"`, `"${card.power || ''}"`, `"${card.toughness || ''}"`, `"${card.market_price || ''}"`, `"${card.quantity || 1}"`, `"${card.created_at ? new Date(card.created_at).toLocaleDateString() : ''}"` ].join(',')) ]; // Create and download the CSV file const csvContent = csvRows.join('\n'); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); if (link.download !== undefined) { const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', `${collection.name || 'collection'}_cards.csv`); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } }; // 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

); } return (
{/* Header */}
{/* Back button */}
{/* Action buttons */}
{/* Collection Info */}

{collection.name}

{collection.description}

{/* TCG Tags */}
{Object.entries(gameStats).map(([game, count]) => count > 0 ? ( {game} ) : null )}
{/* 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 */}
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)' }} />
{/* Game Sections */} {Object.entries(groupedCards).map(([game, gameCards]) => (

{game === 'MTG' ? 'Magic The Gathering' : game} {gameCards.length}

{gameCards.map((card, index) => (
{card.image_url ? ( {card.name} ) : ( '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

)}
{/* Search Results Dropdown */} {showSearchResults && searchResults.length > 0 && (
{searchResults.map(card => (
handleAddCard(card)} className="flex items-center p-3 hover:bg-gray-50 cursor-pointer" > {card.name} { e.target.src = 'https://via.placeholder.com/48x64/6366f1/ffffff?text=No+Image'; }} />
{card.name}
{card.set_name} • ${card.market_price}
))}
)} {/* Collaboration Manager */}
{/* Upload Image Modal */} setShowUploadModal(false)} onUpload={handleImageUpload} currentImage={collection.image} /> {/* Share Modal */} setShowShareModal(false)} collectionId={id} isPublic={collection.is_public} onTogglePublic={togglePublic} onInviteUser={(email) => console.log('Invited:', email)} />
); }