/* ============================================================
public/js/buildings/bazaar.js
============================================================ */
const BAZAAR_PER_PAGE = 18;
let baz_initialized = false;
let baz_page = 1;
let baz_wood = 0, baz_iron = 0, baz_gold = 0, baz_gems = 0;
const BAZ_SVG_RANGE = ``;
const BAZ_SVG_RACE = ``;
const RARITY_CRYSTALS = {
1:"roter-cristal.png",2:"blauer-cristal.png",3:"gelber-cristal.png",
4:"gruener-cristal.png",5:"oranger-cristal.png",6:"violet-cristal.png",7:"pinker-cristal.png"
};
function rarityImgs(rarity, size=11) {
const file = RARITY_CRYSTALS[String(rarity)];
if (!file) return "";
const img = `
`;
return img.repeat(parseInt(rarity)||0);
}
function loadCSS() {
if (!document.querySelector('link[href="/css/bazaar.css"]')) {
const l = document.createElement("link");
l.rel = "stylesheet"; l.href = "/css/bazaar.css";
document.head.appendChild(l);
}
}
function ensurePopup() {
if (document.getElementById("bazaar-popup")) return;
const popup = document.createElement("div");
popup.id = "bazaar-popup";
popup.className = "qm-popup";
popup.innerHTML = `
`;
document.body.appendChild(popup);
popup.querySelector("#bazaar-close").addEventListener("click", closeBazaar);
popup.querySelectorAll(".mp-tab").forEach((btn) => {
btn.addEventListener("click", () => {
popup.querySelectorAll(".mp-tab").forEach(t => t.classList.remove("mp-tab-active"));
popup.querySelectorAll(".mp-panel").forEach(p => p.classList.remove("active"));
btn.classList.add("mp-tab-active");
document.getElementById(btn.dataset.tab)?.classList.add("active");
});
});
/* Drag */
const header = popup.querySelector(".qm-popup-header");
let dragging=false, sx,sy,sl,st;
header.style.cursor="grab";
header.addEventListener("mousedown",(e)=>{
if(e.target.classList.contains("qm-popup-close"))return;
dragging=true; header.style.cursor="grabbing";
const r=popup.getBoundingClientRect();
sx=e.clientX;sy=e.clientY;sl=r.left;st=r.top;
popup.style.transform="none";
popup.style.left=sl+"px";popup.style.top=st+"px";
e.preventDefault();
});
document.addEventListener("mousemove",(e)=>{
if(!dragging)return;
popup.style.left=(sl+(e.clientX-sx))+"px";
popup.style.top=(st+(e.clientY-sy))+"px";
});
document.addEventListener("mouseup",()=>{dragging=false;header.style.cursor="grab";});
}
function updateCurrencyDisplay() {
const fmt = n => n.toLocaleString("de-DE");
const w=document.getElementById("baz-wood"); if(w) w.textContent=fmt(baz_wood);
const i=document.getElementById("baz-iron"); if(i) i.textContent=fmt(baz_iron);
const g=document.getElementById("baz-gold"); if(g) g.textContent=fmt(baz_gold);
const d=document.getElementById("baz-gems"); if(d) d.textContent=fmt(baz_gems);
}
async function loadShopCards() {
const grid = document.getElementById("baz-grid");
const pagination = document.getElementById("baz-pagination");
if (!grid) return;
grid.innerHTML = `Lade KartenâŠ
`;
if (pagination) pagination.innerHTML = "";
try {
const res = await fetch(`/api/bazaar/cards?page=${baz_page}&limit=${BAZAAR_PER_PAGE}`);
if (!res.ok) throw new Error(res.status);
const data = await res.json();
baz_wood=data.wood; baz_iron=data.iron; baz_gold=data.gold; baz_gems=data.gems;
updateCurrencyDisplay();
if (!data.cards.length) {
grid.innerHTML = `Keine Karten verfĂŒgbar.
`;
return;
}
grid.innerHTML = data.cards.map((c) => {
const prices = [
c.price_wood > 0 ? `đȘ” ${c.price_wood}` : "",
c.price_iron > 0 ? `âïž ${c.price_iron}` : "",
c.price_gold > 0 ? `đȘ ${c.price_gold}` : "",
c.price_gems > 0 ? `đ ${c.price_gems}` : "",
].filter(Boolean).join("");
return `

${c.attack != null ? `
${c.attack}` : ""}
${c.defends != null ? `
${c.defends}` : ""}
${c.cooldown != null ? `
${c.cooldown}` : ""}
${c.rarity ? `
${rarityImgs(c.rarity,11)}
` : ""}
${(c.range != null || c.race != null) ? `
${c.range != null ? `${BAZ_SVG_RANGE} ${c.range}` : ""}
${c.race != null ? `${BAZ_SVG_RACE} ${c.race}` : ""}
` : ""}
${prices || "Kostenlos"}
`;
}).join("");
grid.querySelectorAll(".baz-card").forEach((el) => {
el.addEventListener("click", () => {
const card = data.cards.find(c => c.id === parseInt(el.dataset.cardId));
if (card) showBuyConfirm(card);
});
});
renderPagination(pagination, data.totalPages, data.total);
} catch (err) {
grid.innerHTML = `Fehler beim Laden.
`;
console.error("[bazaar]", err);
}
}
function showBuyConfirm(card) {
document.getElementById("baz-confirm-modal")?.remove();
const maxAffordable = Math.max(1, Math.min(99,
card.price_wood > 0 ? Math.floor(baz_wood / card.price_wood) : 99,
card.price_iron > 0 ? Math.floor(baz_iron / card.price_iron) : 99,
card.price_gold > 0 ? Math.floor(baz_gold / card.price_gold) : 99,
card.price_gems > 0 ? Math.floor(baz_gems / card.price_gems) : 99,
));
function calcTotal(qty) {
return {
wood: card.price_wood * qty,
iron: card.price_iron * qty,
gold: card.price_gold * qty,
gems: card.price_gems * qty,
};
}
function priceHtml(qty) {
const t = calcTotal(qty);
return [
t.wood > 0 ? `đȘ” ${t.wood}` : "",
t.iron > 0 ? `âïž ${t.iron}` : "",
t.gold > 0 ? `đȘ ${t.gold}` : "",
t.gems > 0 ? `đ ${t.gems}` : "",
].filter(Boolean).join(" ");
}
function canAffordQty(qty) {
const t = calcTotal(qty);
return baz_wood >= t.wood && baz_iron >= t.iron &&
baz_gold >= t.gold && baz_gems >= t.gems;
}
const modal = document.createElement("div");
modal.id = "baz-confirm-modal";
modal.innerHTML = `
${card.name}
${priceHtml(1) || "Kostenlos"}
â Nicht genug Ressourcen
`;
document.getElementById("bazaar-popup").appendChild(modal);
const qtyInput = modal.querySelector("#baz-qty");
const priceEl = modal.querySelector("#baz-total-price");
const warnEl = modal.querySelector("#baz-afford-warn");
const buyBtn = modal.querySelector("#baz-confirm");
function updateModal() {
const qty = Math.max(1, Math.min(99, parseInt(qtyInput.value) || 1));
qtyInput.value = qty;
priceEl.innerHTML = priceHtml(qty) || "Kostenlos";
const ok = canAffordQty(qty);
warnEl.style.display = ok ? "none" : "";
buyBtn.disabled = !ok;
}
qtyInput.addEventListener("input", updateModal);
modal.querySelector("#baz-qty-minus").onclick = () => {
qtyInput.value = Math.max(1, parseInt(qtyInput.value || 1) - 1); updateModal();
};
modal.querySelector("#baz-qty-plus").onclick = () => {
qtyInput.value = Math.min(99, parseInt(qtyInput.value || 1) + 1); updateModal();
};
modal.querySelector("#baz-qty-max").onclick = () => {
qtyInput.value = maxAffordable; updateModal();
};
updateModal();
modal.querySelector("#baz-cancel").onclick = () => modal.remove();
modal.querySelector(".baz-confirm-backdrop").onclick = () => modal.remove();
buyBtn.onclick = async () => {
const qty = Math.max(1, Math.min(99, parseInt(qtyInput.value) || 1));
buyBtn.disabled = true; buyBtn.textContent = "âŠ";
try {
const res = await fetch("/api/bazaar/buy", {
method:"POST", headers:{"Content-Type":"application/json"},
body: JSON.stringify({ card_id: card.id, quantity: qty }),
});
const data = await res.json();
if (!res.ok) { buyBtn.textContent = data.error||"Fehler"; setTimeout(()=>modal.remove(),2000); return; }
baz_wood=data.wood; baz_iron=data.iron; baz_gold=data.gold; baz_gems=data.gems;
updateCurrencyDisplay();
modal.remove();
showToast(`â
${qty}Ă ${card.name} gekauft!`);
await loadShopCards();
} catch { buyBtn.textContent="Fehler"; setTimeout(()=>modal.remove(),2000); }
};
}
function renderPagination(el, totalPages, total) {
if (!el||!totalPages||totalPages<=1) return;
el.innerHTML = `
${Array.from({length:totalPages},(_,i)=>i+1).map(p=>
``
).join("")}
${total} Karten`;
el.querySelector("#baz-prev")?.addEventListener("click",async()=>{if(baz_page>1){baz_page--;await loadShopCards();}});
el.querySelector("#baz-next")?.addEventListener("click",async()=>{if(baz_pagebtn.addEventListener("click",async()=>{baz_page=parseInt(btn.dataset.page);await loadShopCards();}));
}
function showToast(msg) {
const t=document.createElement("div"); t.className="baz-toast"; t.textContent=msg;
document.body.appendChild(t); setTimeout(()=>t.remove(),2800);
}
function closeBazaar() {
document.getElementById("bazaar-popup")?.classList.remove("active");
document.getElementById("qm-overlay")?.classList.remove("active");
}
export function loadBazaar() {
loadCSS();
ensurePopup();
const popup=document.getElementById("bazaar-popup");
const overlay=document.getElementById("qm-overlay");
popup.style.left="50%"; popup.style.top="50%";
popup.style.transform="translate(-50%, -50%) scale(1)";
popup.classList.add("active");
overlay?.classList.add("active");
if (!baz_initialized) { baz_initialized=true; baz_page=1; loadShopCards(); }
}