dok/public/js/quickmenu/events.js
2026-04-06 13:32:28 +01:00

257 lines
8.6 KiB
JavaScript

export async function loadEvents() {
const body = document.getElementById("qm-body-events");
if (!body) return;
/* ================================
CSS einmalig laden
================================ */
if (!document.querySelector('link[href="/css/events.css"]')) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = "/css/events.css";
document.head.appendChild(link);
}
/* ================================
Event-Daten
================================ */
const events = [
{ id: 1, img: "/images/items/runenhaufen.png", label: "Booster Öffnen", type: "booster" },
{ id: 2, img: "/images/items/runenhaufen.png", label: "Textzeile 2" },
{ id: 3, img: "/images/items/runenhaufen.png", label: "Textzeile 3" },
{ id: 4, img: "/images/items/runenhaufen.png", label: "Textzeile 4" },
{ id: 5, img: "/images/items/runenhaufen.png", label: "Textzeile 5" },
];
/* ================================
Haupt-HTML
================================ */
body.innerHTML = `
<div class="events-grid" id="events-grid">
${events.map(ev => `
<div class="event-card" data-event-id="${ev.id}" data-type="${ev.type || ''}">
<div class="event-card-img-wrap">
<img src="${ev.img}" alt="${ev.label}" draggable="false">
</div>
<span class="event-card-label">${ev.label}</span>
</div>`).join("")}
</div>
<!-- Booster Öffnen UI -->
<div id="booster-ui" class="booster-ui" style="display:none;">
<button class="booster-back-btn" id="booster-back-btn">← Zurück</button>
<div class="booster-stage">
<div class="booster-left">
<img id="booster-stapel" src="/images/items/boosterstapel.png" alt="Booster" draggable="false" class="booster-stapel-img">
<span class="booster-stapel-hint" id="booster-hint">Klicken zum Öffnen</span>
</div>
<div class="booster-slots" id="booster-slots">
${Array.from({length: 5}, (_, i) => `
<div class="booster-slot" id="booster-slot-${i}">
<div class="booster-slot-inner">
<img class="booster-slot-img" src="/images/items/rueckseite.png" alt="?" draggable="false">
</div>
<div class="booster-slot-name"></div>
</div>`).join("")}
</div>
</div>
</div>
<!-- Standard Detail-Popup -->
<div id="event-detail-overlay">
<div id="event-detail-popup">
<button class="edp-close" id="edp-close-btn"></button>
<img class="edp-img" id="edp-img" src="" alt="">
<div class="edp-title" id="edp-title"></div>
<div class="edp-body" id="edp-body">Inhalt folgt...</div>
</div>
</div>
`;
/* ================================
Referenzen
================================ */
const overlay = body.querySelector("#event-detail-overlay");
const edpImg = body.querySelector("#edp-img");
const edpTitle = body.querySelector("#edp-title");
const edpBody = body.querySelector("#edp-body");
const boosterUi = body.querySelector("#booster-ui");
const eventsGrid = body.querySelector("#events-grid");
/* ================================
Event-Karten Klick
================================ */
body.querySelectorAll(".event-card").forEach(card => {
card.addEventListener("click", () => {
if (card.dataset.type === "booster") {
eventsGrid.style.display = "none";
boosterUi.style.display = "flex";
resetBooster();
return;
}
const id = Number(card.dataset.eventId);
const ev = events.find(e => e.id === id);
if (!ev) return;
edpImg.src = ev.img;
edpImg.alt = ev.label;
edpTitle.textContent = ev.label;
edpBody.textContent = "Inhalt folgt...";
overlay.classList.add("active");
});
});
/* ================================
Detail-Popup schließen
================================ */
body.querySelector("#edp-close-btn").addEventListener("click", () => overlay.classList.remove("active"));
overlay.addEventListener("click", e => { if (e.target === overlay) overlay.classList.remove("active"); });
/* ================================
Zurück-Button
================================ */
body.querySelector("#booster-back-btn").addEventListener("click", () => {
eventsGrid.style.display = "";
boosterUi.style.display = "none";
clearAllIntervals();
isSpinning = false;
});
document.addEventListener("keydown", e => {
if (e.key === "Escape") {
overlay.classList.remove("active");
eventsGrid.style.display = "";
boosterUi.style.display = "none";
clearAllIntervals();
}
});
/* ================================
Booster Zustand
================================ */
let allCards = [];
let isSpinning = false;
let spinIntervals = [];
function clearAllIntervals() {
spinIntervals.forEach(id => clearInterval(id));
spinIntervals = [];
}
/* ================================
Karten vorladen
================================ */
async function preloadCards() {
if (allCards.length) return;
try {
const res = await fetch("/api/booster/cards");
allCards = await res.json();
} catch (e) {
console.error("Karten laden fehlgeschlagen", e);
}
}
/* ================================
Booster zurücksetzen
================================ */
function resetBooster() {
clearAllIntervals();
isSpinning = false;
for (let i = 0; i < 5; i++) {
const slot = body.querySelector(`#booster-slot-${i}`);
slot.querySelector(".booster-slot-img").src = "/images/items/rueckseite.png";
slot.querySelector(".booster-slot-name").textContent = "";
slot.classList.remove("revealed", "spinning");
}
const stapel = body.querySelector("#booster-stapel");
stapel.classList.remove("used");
stapel.style.opacity = "1";
stapel.style.cursor = "pointer";
body.querySelector("#booster-hint").textContent = "Klicken zum Öffnen";
preloadCards();
}
/* ================================
Slot drehen lassen
================================ */
function startSpinSlot(index) {
const slot = body.querySelector(`#booster-slot-${index}`);
const imgEl = slot.querySelector(".booster-slot-img");
slot.classList.add("spinning");
const iv = setInterval(() => {
if (!allCards.length) return;
const rnd = allCards[Math.floor(Math.random() * allCards.length)];
imgEl.src = rnd.image ? `/images/cards/${rnd.image}` : "/images/items/rueckseite.png";
}, 80);
spinIntervals[index] = iv;
}
/* ================================
Slot enthüllen
================================ */
function revealSlot(index, card) {
clearInterval(spinIntervals[index]);
const slot = body.querySelector(`#booster-slot-${index}`);
const imgEl = slot.querySelector(".booster-slot-img");
const nameEl = slot.querySelector(".booster-slot-name");
slot.classList.remove("spinning");
slot.classList.add("revealed");
imgEl.src = card?.image ? `/images/cards/${card.image}` : "/images/items/rueckseite.png";
nameEl.textContent = card?.name || "???";
}
/* ================================
Booster-Stapel Klick → Öffnen
================================ */
body.querySelector("#booster-stapel").addEventListener("click", async () => {
if (isSpinning) return;
if (!allCards.length) await preloadCards();
if (!allCards.length) return;
isSpinning = true;
const stapel = body.querySelector("#booster-stapel");
stapel.classList.add("used");
stapel.style.opacity = "0.35";
stapel.style.cursor = "default";
body.querySelector("#booster-hint").textContent = "Wird gezogen...";
// 5 Karten vom Server ziehen
let drawnCards = [];
try {
const res = await fetch("/api/booster/open", { method: "POST" });
const data = await res.json();
drawnCards = data.cards || [];
} catch (e) {
console.error("Booster öffnen fehlgeschlagen", e);
resetBooster();
return;
}
// Alle Slots gleichzeitig drehen
for (let i = 0; i < 5; i++) startSpinSlot(i);
// Nacheinander alle 5 Sekunden eine Karte enthüllen
for (let i = 0; i < 5; i++) {
setTimeout(() => revealSlot(i, drawnCards[i]), (i + 1) * 5000);
}
// Nach letzter Karte: Fertig-Meldung
setTimeout(() => {
body.querySelector("#booster-hint").textContent = "Alle Karten enthüllt!";
isSpinning = false;
}, 5 * 5000 + 500);
});
// Karten sofort vorladen
preloadCards();
}