deckhearth/pages/api/collections.js
Randall Stillwell 00853fe499 Enhanced collections with detailed view and card management
- Created comprehensive collection detail page (/collection/[id]) with:
  * Hero section with collection metadata (name, creator, format, cost)
  * Action buttons (copy link, share, print proxies, save deck)
  * Collection statistics (total cards, value, views, favorites)
  * Advanced filtering and search functionality
  * Grid and list view modes for cards
  * Real-time card filtering by rarity, type, and search terms

- Added complete API endpoints for collection management:
  * GET/PUT/DELETE /api/collections/[id] - collection CRUD operations
  * POST/PUT/DELETE /api/collections/[id]/cards - card management
  * Enhanced /api/collections with database integration

- Features matching deck builder interface from image:
  * Beautiful hero section with background image
  * Metadata display (creator, format, cost, play guide)
  * Copy/share/save functionality
  * Comprehensive filtering system
  * Responsive card grid and list views
  * Real-time statistics and card counting

- Updated collections listing page to link to detailed views
- Proper error handling and loading states throughout
- Mobile-responsive design with modern UI/UX
2025-07-25 07:44:23 -05:00

79 lines
No EOL
2.6 KiB
JavaScript

import { sql } from '@vercel/postgres';
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') {
try {
// Get all collections with basic stats
const result = await sql`
SELECT
c.*,
u.email as creator_email,
COUNT(cc.card_id) as card_count,
COALESCE(SUM(cards.market_price * cc.quantity), 0) as total_value
FROM collections c
LEFT JOIN users u ON c.user_id = u.id
LEFT JOIN collection_cards cc ON c.id = cc.collection_id
LEFT JOIN cards ON cc.card_id = cards.id
WHERE c.is_public = true OR c.user_id = 1
GROUP BY c.id, u.email
ORDER BY c.updated_at DESC
`;
const collections = result.rows.map(collection => ({
id: collection.id,
name: collection.name,
description: collection.description,
tcg: collection.tcg || 'MTG',
cardCount: parseInt(collection.card_count) || 0,
value: parseFloat(collection.total_value) || 0,
lastViewed: collection.updated_at,
createdAt: collection.created_at,
isPublic: collection.is_public,
tags: collection.tags ? collection.tags.split(',') : [],
creator: collection.creator_email
}));
res.status(200).json(collections);
} catch (error) {
console.error('Error fetching collections:', error);
res.status(500).json({ error: 'Internal server error' });
}
} else if (req.method === 'POST') {
try {
const { name, description, tcg = 'MTG', isPublic = false, tags = [] } = req.body;
if (!name || !description) {
return res.status(400).json({ error: 'Name and description are required' });
}
// For now, use user_id = 1 (should be from auth token in real implementation)
const userId = 1;
const result = await sql`
INSERT INTO collections (name, description, tcg, is_public, tags, user_id)
VALUES (${name}, ${description}, ${tcg}, ${isPublic}, ${tags.join(',')}, ${userId})
RETURNING *
`;
res.status(201).json(result.rows[0]);
} catch (error) {
console.error('Error creating collection:', error);
res.status(500).json({ error: 'Internal server error' });
}
} else {
res.status(405).json({ error: 'Method not allowed' });
}
}