diff --git a/backend/src/lib/handlers/cards.ts b/backend/src/lib/handlers/cards.ts index 40e60a2..957bb1b 100644 --- a/backend/src/lib/handlers/cards.ts +++ b/backend/src/lib/handlers/cards.ts @@ -1,60 +1,91 @@ import { route, HandlerContext, HttpError } from '@/lib/router'; import { getDb } from '@/lib/db'; +function log(method: string, path: string, steamId: string, msg: string) { + console.log(`[Cards] ${method} ${path} steam=${steamId} — ${msg}`); +} + route('player/:steamId/card-levels', ['GET'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; + log('GET', 'card-levels', steamId, 'loading card levels'); const db = getDb(); - const row = db.prepare('SELECT card_levels FROM card_levels WHERE steam_id = ?').get(ctx.params.steamId) as any; - return { card_levels: row ? JSON.parse(row.card_levels) : {} }; + const row = db.prepare('SELECT card_levels FROM card_levels WHERE steam_id = ?').get(steamId) as any; + const result = { card_levels: row ? JSON.parse(row.card_levels) : {} }; + log('GET', 'card-levels', steamId, `returned ${Object.keys(result.card_levels).length} card levels`); + return result; }); route('player/:steamId/card-levels', ['PUT'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; const { card_levels } = ctx.body as any; + const keys = card_levels ? Object.keys(card_levels) : []; + log('PUT', 'card-levels', steamId, `saving ${keys.length} card levels: ${JSON.stringify(keys.slice(0, 10))}${keys.length > 10 ? '...' : ''}`); const db = getDb(); db.prepare(` INSERT INTO card_levels (steam_id, card_levels, updated_at) VALUES (?, ?, datetime('now')) ON CONFLICT(steam_id) DO UPDATE SET card_levels = ?, updated_at = datetime('now') - `).run(ctx.params.steamId, JSON.stringify(card_levels || {}), JSON.stringify(card_levels || {})); + `).run(steamId, JSON.stringify(card_levels || {}), JSON.stringify(card_levels || {})); + log('PUT', 'card-levels', steamId, 'saved successfully'); return { success: true }; }); route('player/:steamId/decks', ['GET'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; const db = getDb(); - const rows = db.prepare('SELECT * FROM decks WHERE steam_id = ? ORDER BY deck_index').all(ctx.params.steamId) as any[]; + const rows = db.prepare('SELECT * FROM decks WHERE steam_id = ? ORDER BY deck_index').all(steamId) as any[]; const decks: Record = {}; for (const r of rows) { decks[r.deck_index] = { name: r.name, cards: JSON.parse(r.cards || '[]') }; } + log('GET', 'decks', steamId, `returned ${Object.keys(decks).length} decks: indices=[${Object.keys(decks).join(',')}]`); return { decks }; }); route('player/:steamId/decks/:index', ['GET'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; + const idx = ctx.params.index; const db = getDb(); - const deck = db.prepare('SELECT * FROM decks WHERE steam_id = ? AND deck_index = ?').get(ctx.params.steamId, parseInt(ctx.params.index)) as any; - if (!deck) return { name: 'New Deck', cards: [] }; - return { ...deck, cards: JSON.parse(deck.cards || '[]') }; + const deck = db.prepare('SELECT * FROM decks WHERE steam_id = ? AND deck_index = ?').get(steamId, parseInt(idx)) as any; + if (!deck) { + log('GET', `decks/${idx}`, steamId, 'not found, returning empty deck'); + return { name: 'New Deck', cards: [] }; + } + const cards = JSON.parse(deck.cards || '[]'); + log('GET', `decks/${idx}`, steamId, `found deck="${deck.name}" with ${cards.length} cards`); + return { ...deck, cards }; }); route('player/:steamId/decks/:index', ['PUT'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; + const idx = ctx.params.index; const { name, cards } = ctx.body as any; + const cardCount = Array.isArray(cards) ? cards.length : 0; + log('PUT', `decks/${idx}`, steamId, `saving deck="${name || 'unnamed'}" with ${cardCount} cards: ${JSON.stringify(cards?.slice(0, 10))}${cardCount > 10 ? '...' : ''}`); const db = getDb(); - const idx = parseInt(ctx.params.index); db.prepare(` INSERT INTO decks (steam_id, deck_index, name, cards, updated_at) VALUES (?, ?, ?, ?, datetime('now')) ON CONFLICT(steam_id, deck_index) DO UPDATE SET name = ?, cards = ?, updated_at = datetime('now') - `).run(ctx.params.steamId, idx, name || 'My Deck', JSON.stringify(cards || []), name || 'My Deck', JSON.stringify(cards || [])); + `).run(steamId, parseInt(idx), name || 'My Deck', JSON.stringify(cards || []), name || 'My Deck', JSON.stringify(cards || [])); + log('PUT', `decks/${idx}`, steamId, 'saved successfully'); return { success: true }; }); route('player/:steamId/decks/:index', ['DELETE'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; + const idx = ctx.params.index; + log('DELETE', `decks/${idx}`, steamId, 'deleting deck'); const db = getDb(); - const idx = parseInt(ctx.params.index); - db.prepare('DELETE FROM decks WHERE steam_id = ? AND deck_index = ?').run(ctx.params.steamId, idx); + db.prepare('DELETE FROM decks WHERE steam_id = ? AND deck_index = ?').run(steamId, parseInt(idx)); + log('DELETE', `decks/${idx}`, steamId, 'deleted successfully'); return { success: true }; }); route('player/:steamId/decks', ['PUT'], (ctx: HandlerContext) => { + const steamId = ctx.params.steamId; const { decks: decksToSave } = ctx.body as any; if (!decksToSave) throw new HttpError(400, 'decks required'); + const indices = Object.keys(decksToSave); + log('PUT', 'decks (batch)', steamId, `saving ${indices.length} decks: indices=[${indices.join(',')}]`); const db = getDb(); const upsert = db.prepare(` INSERT INTO decks (steam_id, deck_index, name, cards, updated_at) VALUES (?, ?, ?, ?, datetime('now')) @@ -63,9 +94,13 @@ route('player/:steamId/decks', ['PUT'], (ctx: HandlerContext) => { const tx = db.transaction(() => { for (const [indexStr, deck] of Object.entries(decksToSave)) { const d = deck as any; - upsert.run(ctx.params.steamId, parseInt(indexStr), d.name || 'My Deck', JSON.stringify(d.cards || []), d.name || 'My Deck', JSON.stringify(d.cards || [])); + const cards = d.cards || []; + const cardCount = Array.isArray(cards) ? cards.length : 0; + log('PUT', `decks/${indexStr} (batch)`, steamId, `deck="${d.name || 'unnamed'}" with ${cardCount} cards`); + upsert.run(steamId, parseInt(indexStr), d.name || 'My Deck', JSON.stringify(cards), d.name || 'My Deck', JSON.stringify(cards)); } }); tx(); + log('PUT', 'decks (batch)', steamId, `batch save of ${indices.length} decks completed`); return { success: true }; });