257 lines
8.6 KiB
JavaScript
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();
|
|
}
|