79 lines
2.6 KiB
JavaScript
79 lines
2.6 KiB
JavaScript
|
|
import { sql } from '../../../lib/sql.js';
|
||
|
|
import { getUserFromRequest } from '../../../lib/permission-middleware';
|
||
|
|
|
||
|
|
export default async function handler(req, res) {
|
||
|
|
try {
|
||
|
|
const user = await getUserFromRequest(req);
|
||
|
|
if (!user) {
|
||
|
|
return res.status(401).json({ error: 'Authentication required' });
|
||
|
|
}
|
||
|
|
|
||
|
|
const gameId = parseInt(req.query.id, 10);
|
||
|
|
if (!Number.isInteger(gameId)) {
|
||
|
|
return res.status(400).json({ error: 'Invalid game id' });
|
||
|
|
}
|
||
|
|
|
||
|
|
const found = await sql`
|
||
|
|
SELECT * FROM custom_games
|
||
|
|
WHERE id = ${gameId} AND user_id = ${user.userId}
|
||
|
|
`;
|
||
|
|
if (found.rows.length === 0) {
|
||
|
|
return res.status(404).json({ error: 'Game not found' });
|
||
|
|
}
|
||
|
|
const game = found.rows[0];
|
||
|
|
|
||
|
|
if (req.method === 'GET') {
|
||
|
|
const cards = await sql`
|
||
|
|
SELECT id, card_id, name, mana_cost, card_type, rarity,
|
||
|
|
rules_text, actions, flavor_quote, power, toughness,
|
||
|
|
frame_id, artwork_url, art_mode, created_at, updated_at
|
||
|
|
FROM custom_cards
|
||
|
|
WHERE custom_game_id = ${gameId}
|
||
|
|
ORDER BY updated_at DESC
|
||
|
|
`;
|
||
|
|
return res.status(200).json({ game, designs: cards.rows });
|
||
|
|
}
|
||
|
|
|
||
|
|
if (req.method === 'PUT') {
|
||
|
|
const name = typeof req.body?.name === 'string' ? req.body.name.trim() : '';
|
||
|
|
const description =
|
||
|
|
typeof req.body?.description === 'string' ? req.body.description.trim() : null;
|
||
|
|
|
||
|
|
if (!name) {
|
||
|
|
return res.status(400).json({ error: 'Game name is required' });
|
||
|
|
}
|
||
|
|
|
||
|
|
const clash = await sql`
|
||
|
|
SELECT id FROM custom_games
|
||
|
|
WHERE user_id = ${user.userId}
|
||
|
|
AND lower(name) = ${name.toLowerCase()}
|
||
|
|
AND id <> ${gameId}
|
||
|
|
`;
|
||
|
|
if (clash.rows.length > 0) {
|
||
|
|
return res.status(409).json({ error: 'You already have a game with that name' });
|
||
|
|
}
|
||
|
|
|
||
|
|
const updated = await sql`
|
||
|
|
UPDATE custom_games SET
|
||
|
|
name = ${name}, description = ${description},
|
||
|
|
updated_at = CURRENT_TIMESTAMP
|
||
|
|
WHERE id = ${gameId}
|
||
|
|
RETURNING *
|
||
|
|
`;
|
||
|
|
return res.status(200).json({ game: updated.rows[0] });
|
||
|
|
}
|
||
|
|
|
||
|
|
if (req.method === 'DELETE') {
|
||
|
|
// Designs keep existing (custom_game_id drops to NULL via FK);
|
||
|
|
// their catalog twins stay in the collection untouched.
|
||
|
|
await sql`DELETE FROM custom_games WHERE id = ${gameId}`;
|
||
|
|
return res.status(200).json({ message: 'Game deleted' });
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(405).json({ error: 'Method not allowed' });
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Custom game API error:', error);
|
||
|
|
return res.status(500).json({ error: 'Internal server error' });
|
||
|
|
}
|
||
|
|
}
|