diff --git a/app.js b/app.js index 5c84cd0..a399f79 100644 --- a/app.js +++ b/app.js @@ -443,15 +443,90 @@ app.get("/api/energy", requireLogin, async (req, res) => { const ENERGY_MAX = 40; try { const [[row]] = await db.query( - "SELECT energy FROM account_currency WHERE account_id = ?", + "SELECT energy, energy_bought FROM account_currency WHERE account_id = ?", [userId], ); - res.json({ energy: row?.energy ?? ENERGY_MAX, energy_max: ENERGY_MAX }); + const today = new Date().toISOString().slice(0, 10); + const boughtDate = row?.energy_bought + ? new Date(row.energy_bought).toISOString().slice(0, 10) + : null; + res.json({ + energy: row?.energy ?? ENERGY_MAX, + energy_max: ENERGY_MAX, + bought_today: boughtDate === today, + }); } catch (err) { res.status(500).json({ error: "DB Fehler" }); } }); +/* ======================== + Energie kaufen +======================== */ + +app.post("/api/energy/buy", requireLogin, async (req, res) => { + const userId = req.session.user.id; + const ENERGY_MAX = 40; + const ENERGY_BUY = 10; // Energie die dazugekauft wird + const COST_GEMS = 10; + const COST_GOLD = 200; + const { currency: payWith } = req.body; // "gems" oder "gold" + + if (!["gems", "gold"].includes(payWith)) { + return res.status(400).json({ error: "Ungültige Zahlungsmethode." }); + } + + try { + const today = new Date().toISOString().slice(0, 10); + + const [[row]] = await db.query( + "SELECT energy, gems, gold, energy_bought FROM account_currency WHERE account_id = ?", + [userId], + ); + if (!row) return res.status(404).json({ error: "Account nicht gefunden." }); + + /* Bereits heute gekauft? */ + const boughtDate = row.energy_bought + ? new Date(row.energy_bought).toISOString().slice(0, 10) + : null; + if (boughtDate === today) { + return res.status(400).json({ error: "Du hast heute bereits Energie aufgefüllt." }); + } + + /* Genug Währung? */ + if (payWith === "gems" && row.gems < COST_GEMS) { + return res.status(400).json({ error: `Nicht genug Gems. Benötigt: ${COST_GEMS}.` }); + } + if (payWith === "gold" && row.gold < COST_GOLD) { + return res.status(400).json({ error: `Nicht genug Gold. Benötigt: ${COST_GOLD}.` }); + } + + /* Energie darf max auf ENERGY_MAX steigen */ + const newEnergy = Math.min((row.energy ?? ENERGY_MAX) + ENERGY_BUY, ENERGY_MAX); + + if (payWith === "gems") { + await db.query( + `UPDATE account_currency + SET energy = ?, gems = gems - ?, energy_bought = ? + WHERE account_id = ?`, + [newEnergy, COST_GEMS, today, userId], + ); + } else { + await db.query( + `UPDATE account_currency + SET energy = ?, gold = gold - ?, energy_bought = ? + WHERE account_id = ?`, + [newEnergy, COST_GOLD, today, userId], + ); + } + + res.json({ success: true, energy: newEnergy, energy_max: ENERGY_MAX }); + } catch (err) { + console.error("[Energy Buy]", err); + res.status(500).json({ error: "DB Fehler" }); + } +}); + /* ======================== 404 Handler ======================== */ diff --git a/public/js/hud.js b/public/js/hud.js index 84ef916..cd0e117 100644 --- a/public/js/hud.js +++ b/public/js/hud.js @@ -67,3 +67,201 @@ function formatNumber(n) { if (n === undefined || n === null) return "0"; return Number(n).toLocaleString("de-DE"); } + +/* ════════════════════════════════════════════ + Energie kaufen – Popup beim + Klick +════════════════════════════════════════════ */ + +document.getElementById("hud-energy-plus")?.addEventListener("click", openEnergyBuyPopup); + +async function openEnergyBuyPopup() { + /* Aktuellen Stand laden */ + let hud, energyStatus; + try { + [hud, energyStatus] = await Promise.all([ + fetch("/api/hud").then(r => r.json()), + fetch("/api/energy").then(r => r.json()), + ]); + } catch { + return; + } + + /* Altes Popup entfernen */ + document.getElementById("energy-buy-overlay")?.remove(); + + const alreadyBought = energyStatus.bought_today; + const energyFull = (energyStatus.energy ?? 0) >= (energyStatus.energy_max ?? 40); + const canGems = hud.gems >= 10; + const canGold = hud.gold >= 200; + + const overlay = document.createElement("div"); + overlay.id = "energy-buy-overlay"; + overlay.style.cssText = ` + position:fixed; inset:0; z-index:99999; + background:rgba(0,0,0,.75); + display:flex; align-items:center; justify-content:center;`; + + /* ── Inhalt je nach Status ── */ + let body = ""; + + if (alreadyBought) { + body = ` +
+ Du hast heute bereits Energie dazugekauft.
+ Morgen wieder verfügbar.
+
+ Deine Energie ist bereits auf dem Maximum. +
`; + } else { + const gemBtn = canGems + ? `` + : ``; + + const goldBtn = canGold + ? `` + : ``; + + body = ` ++ +10 Energie · max. 1× täglich +
+Weder genug Gems noch Gold vorhanden.
` + : ""}`; + } + + overlay.innerHTML = ` +${data.error || "Fehler beim Kauf."}
` + ); + overlay.querySelectorAll(".ebtn").forEach(b => { b.disabled = false; b.style.opacity = ""; }); + return; + } + + /* Erfolg: HUD aktualisieren + Popup mit Bestätigung */ + await refreshHud(); + overlay.remove(); + + const confirm = document.createElement("div"); + confirm.style.cssText = ` + position:fixed; inset:0; z-index:99999; + background:rgba(0,0,0,.75); + display:flex; align-items:center; justify-content:center;`; + confirm.innerHTML = ` ++ Energie aufgefüllt auf ${data.energy} / ${data.energy_max} +
+ +