163 lines
No EOL
4.2 KiB
JavaScript
163 lines
No EOL
4.2 KiB
JavaScript
import { sql } from '@vercel/postgres';
|
|
import { verifyToken } from '../auth-utils.js';
|
|
|
|
// GET /api/cards - Search cards from database
|
|
export default async function handler(req, res) {
|
|
// Set CORS headers
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
|
|
// Handle preflight requests
|
|
if (req.method === 'OPTIONS') {
|
|
res.status(200).end();
|
|
return;
|
|
}
|
|
|
|
if (req.method !== 'GET' && req.method !== 'POST') {
|
|
return res.status(405).json({ error: 'Method not allowed' });
|
|
}
|
|
|
|
try {
|
|
const { q, search, game, page = '1', limit = '20' } = req.query;
|
|
const query = q || search || '';
|
|
const pageNum = parseInt(page);
|
|
const limitNum = parseInt(limit);
|
|
const offset = (pageNum - 1) * limitNum;
|
|
|
|
console.log(`🔍 Searching cards: "${query}" game: "${game}" page: ${pageNum}`);
|
|
|
|
// 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(limitNum, 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);
|
|
|
|
// Format the response
|
|
const cards = result.rows.map(card => ({
|
|
id: card.id,
|
|
name: card.name,
|
|
setName: card.set_name,
|
|
setCode: card.set_code,
|
|
cardNumber: card.card_number,
|
|
rarity: card.rarity,
|
|
game: card.game,
|
|
manaCost: card.mana_cost,
|
|
cmc: card.cmc,
|
|
cardType: card.card_type,
|
|
colors: card.colors ? JSON.parse(card.colors) : [],
|
|
oracleText: card.oracle_text,
|
|
power: card.power,
|
|
toughness: card.toughness,
|
|
imageUrl: card.image_url,
|
|
stockImageUrl: card.stock_image_url,
|
|
currentPrice: card.current_price,
|
|
marketPrice: card.market_price,
|
|
verified: card.verified,
|
|
createdAt: card.created_at,
|
|
updatedAt: card.updated_at
|
|
}));
|
|
|
|
return res.status(200).json({
|
|
success: true,
|
|
cards,
|
|
pagination: {
|
|
page: pageNum,
|
|
limit: limitNum,
|
|
total,
|
|
pages: Math.ceil(total / limitNum)
|
|
}
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error in cards API:', error);
|
|
return res.status(500).json({
|
|
error: 'Failed to search cards',
|
|
details: error.message
|
|
});
|
|
}
|
|
}
|