/* eslint-disable @next/next/no-img-element -- External or generated image URLs; next/image migration is out of scope. */ import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import dynamic from 'next/dynamic'; import Layout from '../../components/Layout'; import AdminProtected from '../../components/AdminProtected'; import CardEditorForm from '../../components/CardEditorForm'; import CardEditorPreview from '../../components/CardEditorPreview'; import CardEditorSearchPanel from '../../components/CardEditorSearchPanel'; // Make this component client-side only to avoid SSR issues const CardEditor = () => { const router = useRouter(); const { id } = router.query; const [card, setCard] = useState(null); const [fetchLoading, setFetchLoading] = useState(false); const loading = id ? fetchLoading : false; const [saving, setSaving] = useState(false); const [message, setMessage] = useState(''); const [searchQuery, setSearchQuery] = useState(''); const [searchResults, setSearchResults] = useState([]); const [searchLoading, setSearchLoading] = useState(false); // Form state const [formData, setFormData] = useState({ name: '', set_name: '', set_code: '', card_number: '', rarity: '', game: '', mana_cost: '', cmc: '', card_type: '', colors: [], oracle_text: '', power: '', toughness: '', image_url: '', stock_image_url: '', current_price: '', market_price: '' }); const fetchCard = async (cardId) => { setFetchLoading(true); try { const response = await fetch(`/api/cards/${cardId}`); if (response.ok) { const cardData = await response.json(); setCard(cardData); setFormData({ name: cardData.name || '', set_name: cardData.set_name || '', set_code: cardData.set_code || '', card_number: cardData.card_number || '', rarity: cardData.rarity || '', game: cardData.game || '', mana_cost: cardData.mana_cost || '', cmc: cardData.cmc || '', card_type: cardData.card_type || '', colors: Array.isArray(cardData.colors) ? cardData.colors : [], oracle_text: cardData.oracle_text || '', power: cardData.power || '', toughness: cardData.toughness || '', image_url: cardData.image_url || '', stock_image_url: cardData.stock_image_url || '', current_price: cardData.current_price || '', market_price: cardData.market_price || '' }); } else { setMessage('Card not found'); } } catch (error) { setMessage('Error loading card: ' + error.message); } finally { setFetchLoading(false); } }; // Load card data when editing an existing card useEffect(() => { if (id) { // eslint-disable-next-line react-hooks/set-state-in-effect -- load card when route id is set fetchCard(id); } }, [id]); const searchCards = async (query) => { if (!query.trim()) { setSearchResults([]); return; } setSearchLoading(true); try { const response = await fetch(`/api/cards/search?query=${encodeURIComponent(query)}&limit=20`); if (response.ok) { const data = await response.json(); setSearchResults(data.cards || []); } } catch (error) { console.error('Search error:', error); } finally { setSearchLoading(false); } }; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); }; const handleColorChange = (color, checked) => { setFormData(prev => ({ ...prev, colors: checked ? [...prev.colors, color] : prev.colors.filter(c => c !== color) })); }; const handleSave = async () => { if (!card?.id) { setMessage('No card selected to edit'); return; } setSaving(true); setMessage(''); try { const response = await fetch(`/api/cards/${card.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ ...formData, cmc: formData.cmc ? parseInt(formData.cmc) : null, current_price: formData.current_price ? parseFloat(formData.current_price) : null, market_price: formData.market_price ? parseFloat(formData.market_price) : null }) }); if (response.ok) { const updatedCard = await response.json(); setCard(updatedCard); setMessage('Card updated successfully!'); // Clear message after 3 seconds setTimeout(() => setMessage(''), 3000); } else { const errorData = await response.json(); setMessage('Error updating card: ' + (errorData.error || 'Unknown error')); } } catch (error) { setMessage('Error updating card: ' + error.message); } finally { setSaving(false); } }; const selectCard = (selectedCard) => { router.push(`/admin/card-editor?id=${selectedCard.id}`); }; if (loading) { return ( {(user) => ( )} ); } return ( {(user) => ( {/* Admin Navigation */} Admin Tools router.push('/admin/card-editor')} className="px-4 py-2 rounded-lg font-medium gradient-bg-purple text-white" > 🖊️ Card Editor router.push('/admin/card-import')} className="px-4 py-2 rounded-lg font-medium transition-all duration-200 border" style={{ backgroundColor: 'var(--bg-primary)', borderColor: 'var(--border)', color: 'var(--text-primary)' }} > 📥 Card Import Admin Card Editor Search for a card to edit its details, or continue editing the selected card. { setSearchQuery(value); searchCards(value); }} searchLoading={searchLoading} searchResults={searchResults} onSelectCard={selectCard} /> {/* Card Editor Form */} {card && ( )} {!card && !loading && ( 🔍 Search for a Card to Edit Use the search box above to find a card you want to edit. )} )} ); }; // Export with dynamic import to disable SSR export default dynamic(() => Promise.resolve(CardEditor), { ssr: false });
Search for a card to edit its details, or continue editing the selected card.
Use the search box above to find a card you want to edit.