deckhearth/api/cards/index.js

267 lines
No EOL
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from 'next/server';
import { sql } from '@vercel/postgres';
import { verifyToken } from '../auth-utils.js';
// GET /api/cards - Search cards from database
export async function GET(request) {
try {
const { searchParams } = new URL(request.url);
const query = searchParams.get('q') || searchParams.get('search') || '';
const game = searchParams.get('game');
const page = parseInt(searchParams.get('page') || '1');
const limit = parseInt(searchParams.get('limit') || '20');
const offset = (page - 1) * limit;
console.log(`🔍 Searching cards: "${query}" game: "${game}" page: ${page}`);
// Build the SQL query
let sqlQuery = `
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,
verified,
created_at,
updated_at
FROM cards
WHERE 1=1
`;
const params = [];
let paramIndex = 1;
// Add search filter
if (query.trim()) {
sqlQuery += ` AND (
name ILIKE $${paramIndex} OR
oracle_text ILIKE $${paramIndex} OR
card_type ILIKE $${paramIndex} OR
set_name ILIKE $${paramIndex}
)`;
params.push(`%${query}%`);
paramIndex++;
}
// Add game filter
if (game && game !== 'ALL') {
sqlQuery += ` AND game = $${paramIndex}`;
params.push(game);
paramIndex++;
}
// Add ordering and pagination
sqlQuery += ` ORDER BY name ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`;
params.push(limit, offset);
console.log(`📝 SQL Query: ${sqlQuery}`);
console.log(`📝 Parameters:`, params);
// Execute the query
const result = await sql.query(sqlQuery, params);
// Get total count for pagination
let countQuery = `
SELECT COUNT(*) as total
FROM cards
WHERE 1=1
`;
const countParams = [];
let countParamIndex = 1;
if (query.trim()) {
countQuery += ` AND (
name ILIKE $${countParamIndex} OR
oracle_text ILIKE $${countParamIndex} OR
card_type ILIKE $${countParamIndex} OR
set_name ILIKE $${countParamIndex}
)`;
countParams.push(`%${query}%`);
countParamIndex++;
}
if (game && game !== 'ALL') {
countQuery += ` AND game = $${countParamIndex}`;
countParams.push(game);
countParamIndex++;
}
const countResult = await sql.query(countQuery, countParams);
const total = parseInt(countResult.rows[0].total);
// Transform the results
const cards = result.rows.map(row => ({
id: row.id,
name: row.name,
set_name: row.set_name,
set_code: row.set_code,
card_number: row.card_number,
rarity: row.rarity,
game: row.game,
mana_cost: row.mana_cost,
cmc: row.cmc,
card_type: row.card_type,
colors: row.colors ? JSON.parse(row.colors) : [],
oracle_text: row.oracle_text,
power: row.power,
toughness: row.toughness,
image_url: row.image_url,
stock_image_url: row.stock_image_url,
current_price: row.current_price,
market_price: row.market_price,
verified: row.verified,
createdAt: row.created_at,
updatedAt: row.updated_at,
}));
console.log(`✅ Found ${cards.length} cards (total: ${total})`);
return NextResponse.json({
success: true,
data: cards,
pagination: {
page,
limit,
total,
totalPages: Math.ceil(total / limit),
hasNext: page * limit < total,
hasPrev: page > 1
},
search: {
query,
game,
results: cards.length
}
});
} catch (error) {
console.error('❌ Error searching cards:', error);
return NextResponse.json(
{ error: 'Failed to search cards', details: error.message },
{ status: 500 }
);
}
}
// POST /api/cards - Find or create card
export async function POST(request) {
try {
const token = request.headers.get('authorization')?.replace('Bearer ', '');
const user = await verifyToken(token);
if (!user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { name, game, set_name, set_code, card_number } = await request.json();
if (!name || !game) {
return NextResponse.json({ error: 'Name and game are required' }, { status: 400 });
}
console.log(`🔍 Finding or creating card: "${name}" (${game})`);
// Try to find existing card
let result = await sql.query(`
SELECT * FROM cards
WHERE name = $1 AND game = $2
ORDER BY created_at DESC
LIMIT 1
`, [name, game]);
if (result.rows.length > 0) {
const card = result.rows[0];
console.log(`✅ Found existing card: ${card.name}`);
return NextResponse.json({
success: true,
data: {
id: card.id,
name: card.name,
set_name: card.set_name,
set_code: card.set_code,
card_number: card.card_number,
rarity: card.rarity,
game: card.game,
mana_cost: card.mana_cost,
cmc: card.cmc,
card_type: card.card_type,
colors: card.colors ? JSON.parse(card.colors) : [],
oracle_text: card.oracle_text,
power: card.power,
toughness: card.toughness,
image_url: card.image_url,
stock_image_url: card.stock_image_url,
current_price: card.current_price,
market_price: card.market_price,
verified: card.verified,
createdAt: card.created_at,
updatedAt: card.updated_at,
},
message: 'Card found'
});
}
// Create new card if not found
console.log(` Creating new card: ${name}`);
result = await sql.query(`
INSERT INTO cards (
name, game, set_name, set_code, card_number, verified
) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *
`, [name, game, set_name || '', set_code || '', card_number || '', false]);
const newCard = result.rows[0];
return NextResponse.json({
success: true,
data: {
id: newCard.id,
name: newCard.name,
set_name: newCard.set_name,
set_code: newCard.set_code,
card_number: newCard.card_number,
rarity: newCard.rarity,
game: newCard.game,
mana_cost: newCard.mana_cost,
cmc: newCard.cmc,
card_type: newCard.card_type,
colors: newCard.colors ? JSON.parse(newCard.colors) : [],
oracle_text: newCard.oracle_text,
power: newCard.power,
toughness: newCard.toughness,
image_url: newCard.image_url,
stock_image_url: newCard.stock_image_url,
current_price: newCard.current_price,
market_price: newCard.market_price,
verified: newCard.verified,
createdAt: newCard.created_at,
updatedAt: newCard.updated_at,
},
message: 'Card created'
});
} catch (error) {
console.error('❌ Error finding/creating card:', error);
return NextResponse.json(
{ error: 'Failed to find/create card', details: error.message },
{ status: 500 }
);
}
}