deckhearth/api/collections/index.js

245 lines
7.6 KiB
JavaScript
Raw Normal View History

import { NextResponse } from 'next/server';
import { sql } from '@vercel/postgres';
import { verifyToken } from '../setup-auth.js';
// GET /api/collections - Get user collections
export async function GET(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 { searchParams } = new URL(request.url);
const collectionId = searchParams.get('id');
if (collectionId) {
// Get specific collection with cards
const result = await sql.query(`
SELECT
c.id,
c.name,
c.description,
c.is_public,
c.created_at,
c.updated_at,
cc.quantity,
cc.condition,
cc.notes,
cc.purchase_price,
cc.purchase_date,
card.id as card_id,
card.name as card_name,
card.set_name,
card.set_code,
card.card_number,
card.rarity,
card.game,
card.card_type,
card.mana_cost,
card.cmc,
card.colors,
card.oracle_text,
card.power,
card.toughness,
card.image_url,
card.stock_image_url,
card.current_price,
card.market_price
FROM user_collections c
LEFT JOIN collection_cards cc ON c.id = cc.collection_id
LEFT JOIN cards card ON cc.card_id = card.id
WHERE c.id = $1 AND c.user_id = $2
ORDER BY card.name ASC
`, [collectionId, user.id]);
if (result.rows.length === 0) {
return NextResponse.json({ error: 'Collection not found' }, { status: 404 });
}
const collection = {
id: result.rows[0].id,
name: result.rows[0].name,
description: result.rows[0].description,
is_public: result.rows[0].is_public,
created_at: result.rows[0].created_at,
updated_at: result.rows[0].updated_at,
cards: result.rows
.filter(row => row.card_id)
.map(row => ({
quantity: row.quantity,
condition: row.condition,
notes: row.notes,
purchase_price: row.purchase_price,
purchase_date: row.purchase_date,
card: {
id: row.card_id,
name: row.card_name,
set_name: row.set_name,
set_code: row.set_code,
card_number: row.card_number,
rarity: row.rarity,
game: row.game,
card_type: row.card_type,
mana_cost: row.mana_cost,
cmc: row.cmc,
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
}
}))
};
return NextResponse.json({
success: true,
data: collection
});
} else {
// Get all user collections
const result = await sql.query(`
SELECT
c.id,
c.name,
c.description,
c.is_public,
c.created_at,
c.updated_at,
COUNT(cc.card_id) as card_count
FROM user_collections c
LEFT JOIN collection_cards cc ON c.id = cc.collection_id
WHERE c.user_id = $1
GROUP BY c.id, c.name, c.description, c.is_public, c.created_at, c.updated_at
ORDER BY c.created_at DESC
`, [user.id]);
return NextResponse.json({
success: true,
data: result.rows.map(row => ({
id: row.id,
name: row.name,
description: row.description,
is_public: row.is_public,
created_at: row.created_at,
updated_at: row.updated_at,
card_count: parseInt(row.card_count)
}))
});
}
} catch (error) {
console.error('Error fetching collections:', error);
return NextResponse.json(
{ error: 'Failed to fetch collections', details: error.message },
{ status: 500 }
);
}
}
// POST /api/collections - Create collection or add card to collection
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 { searchParams } = new URL(request.url);
const action = searchParams.get('action');
if (action === 'create') {
// Create new collection
const { name, description, is_public } = await request.json();
if (!name) {
return NextResponse.json({ error: 'Collection name is required' }, { status: 400 });
}
const result = await sql.query(`
INSERT INTO user_collections (user_id, name, description, is_public)
VALUES ($1, $2, $3, $4)
RETURNING *
`, [user.id, name, description || '', is_public || false]);
return NextResponse.json({
success: true,
data: result.rows[0],
message: 'Collection created successfully'
});
}
if (action === 'add-card') {
// Add card to collection
const { collection_id, card_id, quantity, condition, notes, purchase_price, purchase_date } = await request.json();
if (!collection_id || !card_id) {
return NextResponse.json({ error: 'Collection ID and card ID are required' }, { status: 400 });
}
// Verify collection belongs to user
const collectionCheck = await sql.query(`
SELECT id FROM user_collections WHERE id = $1 AND user_id = $2
`, [collection_id, user.id]);
if (collectionCheck.rows.length === 0) {
return NextResponse.json({ error: 'Collection not found or access denied' }, { status: 404 });
}
// Check if card already exists in collection
const existingCard = await sql.query(`
SELECT id, quantity FROM collection_cards
WHERE collection_id = $1 AND card_id = $2
`, [collection_id, card_id]);
if (existingCard.rows.length > 0) {
// Update existing card quantity
const newQuantity = (existingCard.rows[0].quantity || 0) + (quantity || 1);
await sql.query(`
UPDATE collection_cards
SET quantity = $1, updated_at = NOW()
WHERE id = $2
`, [newQuantity, existingCard.rows[0].id]);
return NextResponse.json({
success: true,
message: 'Card quantity updated in collection'
});
} else {
// Add new card to collection
await sql.query(`
INSERT INTO collection_cards (
collection_id, card_id, quantity, condition, notes, purchase_price, purchase_date
) VALUES ($1, $2, $3, $4, $5, $6, $7)
`, [
collection_id,
card_id,
quantity || 1,
condition || 'near-mint',
notes || '',
purchase_price || null,
purchase_date || null
]);
return NextResponse.json({
success: true,
message: 'Card added to collection'
});
}
}
return NextResponse.json({ error: 'Invalid action' }, { status: 400 });
} catch (error) {
console.error('Error with collections:', error);
return NextResponse.json(
{ error: 'Failed to process collection action', details: error.message },
{ status: 500 }
);
}
}