171 lines
5.5 KiB
JavaScript
171 lines
5.5 KiB
JavaScript
/* ============================================================
|
||
routes/bazaar.route.js
|
||
============================================================ */
|
||
|
||
const express = require("express");
|
||
const router = express.Router();
|
||
const db = require("../database/database");
|
||
const { getMaxRarity } = require("../utils/rarity");
|
||
|
||
function requireLogin(req, res, next) {
|
||
if (!req.session?.user)
|
||
return res.status(401).json({ error: "Nicht eingeloggt" });
|
||
next();
|
||
}
|
||
|
||
/* ════════════════════════════════════════════
|
||
GET /api/bazaar/cards?page=1&limit=18
|
||
════════════════════════════════════════════ */
|
||
router.get("/bazaar/cards", requireLogin, async (req, res) => {
|
||
const userId = req.session.user.id;
|
||
const page = parseInt(req.query.page) || 1;
|
||
const limit = parseInt(req.query.limit) || 18;
|
||
const offset = (page - 1) * limit;
|
||
|
||
try {
|
||
const [[account]] = await db.query(
|
||
"SELECT level FROM accounts WHERE id = ?",
|
||
[userId],
|
||
);
|
||
const maxRarity = getMaxRarity(account?.level ?? 1);
|
||
|
||
const [cards] = await db.query(
|
||
`SELECT
|
||
c.id, c.name, c.image, c.rarity,
|
||
c.attack, c.defends, c.cooldown, c.\`range\`, c.\`race\`,
|
||
COALESCE(p.price_wood, 0) AS price_wood,
|
||
COALESCE(p.price_iron, 0) AS price_iron,
|
||
COALESCE(p.price_gold, 0) AS price_gold,
|
||
COALESCE(p.price_gems, 0) AS price_gems
|
||
FROM cards c
|
||
LEFT JOIN card_shop_prices p ON p.rarity = c.rarity
|
||
WHERE c.rarity <= ?
|
||
ORDER BY c.rarity ASC, c.name ASC
|
||
LIMIT ? OFFSET ?`,
|
||
[maxRarity, limit, offset],
|
||
);
|
||
|
||
const [[{ total }]] = await db.query(
|
||
"SELECT COUNT(*) AS total FROM cards WHERE rarity <= ?",
|
||
[maxRarity],
|
||
);
|
||
|
||
const [[currency]] = await db.query(
|
||
"SELECT wood, iron, gold, gems FROM account_currency WHERE account_id = ?",
|
||
[userId],
|
||
);
|
||
|
||
res.json({
|
||
cards,
|
||
total,
|
||
page,
|
||
totalPages: Math.ceil(total / limit),
|
||
wood: currency?.wood || 0,
|
||
iron: currency?.iron || 0,
|
||
gold: currency?.gold || 0,
|
||
gems: currency?.gems || 0,
|
||
});
|
||
} catch (err) {
|
||
console.error("[bazaar/cards]", err);
|
||
res.status(500).json({ error: "DB Fehler" });
|
||
}
|
||
});
|
||
|
||
/* ════════════════════════════════════════════
|
||
POST /api/bazaar/buy { card_id }
|
||
════════════════════════════════════════════ */
|
||
router.post("/bazaar/buy", requireLogin, async (req, res) => {
|
||
const userId = req.session.user.id;
|
||
const { card_id, quantity } = req.body;
|
||
if (!card_id) return res.status(400).json({ error: "card_id fehlt." });
|
||
const qty = Math.max(1, Math.min(99, parseInt(quantity) || 1));
|
||
|
||
try {
|
||
const [[card]] = await db.query(
|
||
`SELECT c.id, c.name, c.rarity,
|
||
COALESCE(p.price_wood, 0) AS price_wood,
|
||
COALESCE(p.price_iron, 0) AS price_iron,
|
||
COALESCE(p.price_gold, 0) AS price_gold,
|
||
COALESCE(p.price_gems, 0) AS price_gems
|
||
FROM cards c
|
||
LEFT JOIN card_shop_prices p ON p.rarity = c.rarity
|
||
WHERE c.id = ?`,
|
||
[card_id],
|
||
);
|
||
if (!card) return res.status(404).json({ error: "Karte nicht gefunden." });
|
||
|
||
const [[account]] = await db.query(
|
||
"SELECT level FROM accounts WHERE id = ?",
|
||
[userId],
|
||
);
|
||
if (parseInt(card.rarity) > getMaxRarity(account?.level ?? 1)) {
|
||
return res
|
||
.status(403)
|
||
.json({ error: "Dein Level reicht für diese Karte nicht aus." });
|
||
}
|
||
|
||
const [[currency]] = await db.query(
|
||
"SELECT wood, iron, gold, gems FROM account_currency WHERE account_id = ?",
|
||
[userId],
|
||
);
|
||
if (!currency)
|
||
return res.status(400).json({ error: "Keine Währungsdaten gefunden." });
|
||
|
||
const checks = [
|
||
{ key: "wood", label: "Holz" },
|
||
{ key: "iron", label: "Eisen" },
|
||
{ key: "gold", label: "Gold" },
|
||
{ key: "gems", label: "Gems" },
|
||
];
|
||
for (const { key, label } of checks) {
|
||
const need = card[`price_${key}`] * qty;
|
||
if (need > 0 && (currency[key] || 0) < need) {
|
||
return res.status(400).json({
|
||
error: `Nicht genug ${label}. Benötigt: ${need} (${qty}×), Vorhanden: ${currency[key] || 0}`,
|
||
});
|
||
}
|
||
}
|
||
|
||
await db.query(
|
||
`UPDATE account_currency
|
||
SET wood = wood - ?,
|
||
iron = iron - ?,
|
||
gold = gold - ?,
|
||
gems = gems - ?
|
||
WHERE account_id = ?`,
|
||
[
|
||
card.price_wood * qty,
|
||
card.price_iron * qty,
|
||
card.price_gold * qty,
|
||
card.price_gems * qty,
|
||
userId,
|
||
],
|
||
);
|
||
|
||
await db.query(
|
||
`INSERT INTO user_cards (user_id, card_id, amount) VALUES (?, ?, ?)
|
||
ON DUPLICATE KEY UPDATE amount = amount + ?`,
|
||
[userId, card_id, qty, qty],
|
||
);
|
||
|
||
const [[updated]] = await db.query(
|
||
"SELECT wood, iron, gold, gems FROM account_currency WHERE account_id = ?",
|
||
[userId],
|
||
);
|
||
|
||
res.json({
|
||
success: true,
|
||
card: { id: card.id, name: card.name },
|
||
wood: updated?.wood || 0,
|
||
iron: updated?.iron || 0,
|
||
gold: updated?.gold || 0,
|
||
gems: updated?.gems || 0,
|
||
});
|
||
} catch (err) {
|
||
console.error("[bazaar/buy]", err);
|
||
res.status(500).json({ error: "DB Fehler" });
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|