+ Search for a card to edit its details, or continue editing the selected card. +
++ {searchCard.set_name} • {searchCard.game} +
++ {searchCard.rarity} +
++ {formData.set_name} • {formData.game} +
++ {formData.rarity} • {formData.card_type} +
+ {formData.current_price && ( ++ ${parseFloat(formData.current_price).toFixed(2)} +
+ )} ++ Use the search box above to find a card you want to edit. +
+Import cards from external APIs into your database
diff --git a/pages/api/cards/[id].js b/pages/api/cards/[id].js index a53173e..84246a9 100644 --- a/pages/api/cards/[id].js +++ b/pages/api/cards/[id].js @@ -1,42 +1,106 @@ import { sql } from '@vercel/postgres'; export default async function handler(req, res) { - if (req.method !== 'GET') { - return res.status(405).json({ error: 'Method not allowed' }); - } - const { id } = req.query; - try { - const result = await sql` - SELECT - id, name, set_name, set_code, card_number, rarity, game, + if (req.method === 'GET') { + try { + const result = await sql` + SELECT + id, 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, scryfall_id, verified, + quantity + FROM cards + WHERE id = ${id} + `; + + if (result.rows.length === 0) { + return res.status(404).json({ error: 'Card not found' }); + } + + const card = result.rows[0]; + + // Parse colors if it's a JSON string + if (card.colors && typeof card.colors === 'string') { + try { + card.colors = JSON.parse(card.colors); + } catch (e) { + card.colors = []; + } + } + + res.status(200).json(card); + } catch (error) { + console.error('Error fetching card:', error); + res.status(500).json({ error: 'Failed to fetch card' }); + } + } else if (req.method === 'PUT') { + try { + const { + 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, scryfall_id, verified, - quantity - FROM cards - WHERE id = ${id} - `; + current_price, market_price + } = req.body; - if (result.rows.length === 0) { - return res.status(404).json({ error: 'Card not found' }); - } - - const card = result.rows[0]; - - // Parse colors if it's a JSON string - if (card.colors && typeof card.colors === 'string') { - try { - card.colors = JSON.parse(card.colors); - } catch (e) { - card.colors = []; + // Validate required fields + if (!name || !game) { + return res.status(400).json({ error: 'Name and game are required fields' }); } - } - res.status(200).json(card); - } catch (error) { - console.error('Error fetching card:', error); - res.status(500).json({ error: 'Failed to fetch card' }); + // Update the card + const result = await sql` + UPDATE cards SET + name = ${name}, + set_name = ${set_name || null}, + set_code = ${set_code || null}, + card_number = ${card_number || null}, + rarity = ${rarity || null}, + game = ${game}, + mana_cost = ${mana_cost || null}, + cmc = ${cmc || null}, + card_type = ${card_type || null}, + colors = ${JSON.stringify(colors || [])}, + oracle_text = ${oracle_text || null}, + power = ${power || null}, + toughness = ${toughness || null}, + image_url = ${image_url || null}, + stock_image_url = ${stock_image_url || null}, + current_price = ${current_price || null}, + market_price = ${market_price || null}, + updated_at = CURRENT_TIMESTAMP + WHERE id = ${id} + RETURNING + id, 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, scryfall_id, verified, + quantity, created_at, updated_at + `; + + if (result.rows.length === 0) { + return res.status(404).json({ error: 'Card not found' }); + } + + const updatedCard = result.rows[0]; + + // Parse colors if it's a JSON string + if (updatedCard.colors && typeof updatedCard.colors === 'string') { + try { + updatedCard.colors = JSON.parse(updatedCard.colors); + } catch (e) { + updatedCard.colors = []; + } + } + + res.status(200).json(updatedCard); + } catch (error) { + console.error('Error updating card:', error); + res.status(500).json({ error: 'Failed to update card' }); + } + } else { + res.status(405).json({ error: 'Method not allowed' }); } } \ No newline at end of file diff --git a/scripts/add-updated-at-column.js b/scripts/add-updated-at-column.js new file mode 100644 index 0000000..f87e792 --- /dev/null +++ b/scripts/add-updated-at-column.js @@ -0,0 +1,36 @@ +#!/usr/bin/env node + +/** + * Add updated_at column to cards table + * + * This script adds the updated_at column to the cards table if it doesn't exist. + */ + +import dotenv from 'dotenv'; +import { neon } from '@neondatabase/serverless'; + +// Load environment variables from .env.local +dotenv.config({ path: '.env.local' }); + +async function addUpdatedAtColumn() { + const sql = neon(process.env.POSTGRES_URL); + + try { + console.log('✅ Connecting to Neon database...'); + + // Add updated_at column + await sql` + ALTER TABLE cards + ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + `; + console.log('✅ Added updated_at column to cards table'); + + console.log('🎉 Updated_at column added successfully!'); + + } catch (error) { + console.error('❌ Failed to add column:', error.message); + process.exit(1); + } +} + +addUpdatedAtColumn(); \ No newline at end of file