diff --git a/app.js b/app.js index f85d6a0..86c51d1 100644 --- a/app.js +++ b/app.js @@ -151,10 +151,10 @@ app.get("/api/building/:id", requireLogin, async (req, res) => { upgradeCost: nextLevel[0] ? `${nextLevel[0].wood} Holz, ${nextLevel[0].stone} Stein, ${nextLevel[0].gold} Gold` : "Max Level erreicht", - upgradeWood: nextLevel[0]?.wood ?? null, - upgradeStone: nextLevel[0]?.stone ?? null, - upgradeGold: nextLevel[0]?.gold ?? null, - upgradeRequiredPoints: nextLevel[0]?.required_points ?? null, // NEU + upgradeWood: nextLevel[0]?.wood ?? null, + upgradeStone: nextLevel[0]?.stone ?? null, + upgradeGold: nextLevel[0]?.gold ?? null, + upgradeRequiredPoints: nextLevel[0]?.required_points ?? null, // NEU }); } catch (err) { console.error(err); @@ -190,7 +190,9 @@ app.post("/api/building/:id/upgrade", requireLogin, async (req, res) => { ); if (!levelData) { - return res.status(400).json({ error: "Maximales Level bereits erreicht" }); + return res + .status(400) + .json({ error: "Maximales Level bereits erreicht" }); } // Punkte prüfen @@ -210,11 +212,23 @@ app.post("/api/building/:id/upgrade", requireLogin, async (req, res) => { return res.status(400).json({ error: "Keine Währungsdaten gefunden" }); } - if (currency.wood < levelData.wood || currency.stone < levelData.stone || currency.gold < levelData.gold) { + if ( + currency.wood < levelData.wood || + currency.stone < levelData.stone || + currency.gold < levelData.gold + ) { return res.status(400).json({ error: "Nicht genügend Ressourcen", - required: { wood: levelData.wood, stone: levelData.stone, gold: levelData.gold }, - current: { wood: currency.wood, stone: currency.stone, gold: currency.gold }, + required: { + wood: levelData.wood, + stone: levelData.stone, + gold: levelData.gold, + }, + current: { + wood: currency.wood, + stone: currency.stone, + gold: currency.gold, + }, }); } @@ -233,7 +247,11 @@ app.post("/api/building/:id/upgrade", requireLogin, async (req, res) => { res.json({ success: true, newLevel: nextLevel, - cost: { wood: levelData.wood, stone: levelData.stone, gold: levelData.gold }, + cost: { + wood: levelData.wood, + stone: levelData.stone, + gold: levelData.gold, + }, }); } catch (err) { console.error(err); @@ -297,6 +315,42 @@ app.get("/api/buildings", requireLogin, async (req, res) => { } }); +/* ======================== + Cards API +======================== */ + +app.get("/api/cards", requireLogin, async (req, res) => { + const { race, page = 1, limit = 12 } = req.query; + const offset = (page - 1) * limit; + + try { + const [cards] = await db.query( + `SELECT c.*, cg.name AS group_name, cg.color AS group_color, + cl.attack, cl.defense, cl.cooldown + FROM cards c + LEFT JOIN card_groups cg ON cg.id = c.group_id + LEFT JOIN card_levels cl ON cl.card_id = c.id AND cl.level = 1 + WHERE c.race = ? + LIMIT ? OFFSET ?`, + [race, parseInt(limit), parseInt(offset)], + ); + const [[{ total }]] = await db.query( + "SELECT COUNT(*) as total FROM cards WHERE race = ?", + [race], + ); + + res.json({ + cards, + total, + page: parseInt(page), + totalPages: Math.ceil(total / limit), + }); + } catch (err) { + console.error(err); + res.status(500).json({ error: "DB Fehler" }); + } +}); + /* ======================== Body Parser ======================== */ diff --git a/public/images/playcards/Silberklinge.png b/public/images/cards/Silberklinge.png similarity index 100% rename from public/images/playcards/Silberklinge.png rename to public/images/cards/Silberklinge.png diff --git a/public/js/lucky-box.js b/public/js/lucky-box.js new file mode 100644 index 0000000..deb84f8 --- /dev/null +++ b/public/js/lucky-box.js @@ -0,0 +1,337 @@ +const CARDS_PER_PAGE = 12; + +const RACES = [ + { id: "menschen", label: "Menschen", icon: "⚔️" }, + { id: "elfen", label: "Elfen", icon: "🌿" }, + { id: "zwerge", label: "Zwerge", icon: "⛏️" }, + { id: "orks", label: "Orks", icon: "💀" }, + { id: "untote", label: "Untote", icon: "💀" }, + { id: "drachen", label: "Drachen", icon: "🐉" }, +]; + +let currentRace = RACES[0].id; +let currentPage = 1; + +export async function loadLuckyBox() { + const body = document.getElementById("qm-body-glucksbox"); + if (!body) return; + + body.innerHTML = renderShell(); + attachTabEvents(); + await loadCards(); +} + +/* ── HTML-Grundstruktur ─────────────────────── */ +function renderShell() { + const tabs = RACES.map((r, i) => ` + + `).join(""); + + return ` +