208 lines
6.1 KiB
JavaScript
208 lines
6.1 KiB
JavaScript
/* ================================
|
||
Mine – Frontend
|
||
Lädt den Aktionen-Tab mit
|
||
Produktionsanzeige + Abholen-Button
|
||
================================ */
|
||
|
||
/* showNotification() kommt aus dem globalen Scope (launcher.ejs) */
|
||
|
||
export async function loadMine(buildingId) {
|
||
const actionsTab = document.getElementById("tab-actions");
|
||
if (!actionsTab) return;
|
||
|
||
actionsTab.innerHTML = `<div class="mine-loading">⛏️ Lade Mineninfo...</div>`;
|
||
|
||
await renderMineStatus(buildingId);
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
Status rendern
|
||
───────────────────────────────────────── */
|
||
async function renderMineStatus(buildingId) {
|
||
const actionsTab = document.getElementById("tab-actions");
|
||
|
||
try {
|
||
const res = await fetch(`/api/mine/${buildingId}/status`);
|
||
if (!res.ok) throw new Error("API Fehler");
|
||
const data = await res.json();
|
||
|
||
if (data.error) {
|
||
actionsTab.innerHTML = `<p class="mine-error">⚠️ ${data.error}</p>`;
|
||
return;
|
||
}
|
||
|
||
const minutesLeft = Math.floor(data.next_cycle_in_seconds / 60);
|
||
const secondsLeft = data.next_cycle_in_seconds % 60;
|
||
|
||
/* Ressourcen-Zeilen */
|
||
const resourceRows = data.available
|
||
.map((r) => {
|
||
const icon = resourceIcon(r.resource);
|
||
const label = resourceLabel(r.resource);
|
||
const ready = data.ready;
|
||
return `
|
||
<div class="mine-resource-row ${ready ? "mine-resource-ready" : ""}">
|
||
<span class="mine-resource-icon">${icon}</span>
|
||
<span class="mine-resource-label">${label}</span>
|
||
<span class="mine-resource-amount">${r.amount}</span>
|
||
</div>`;
|
||
})
|
||
.join("");
|
||
|
||
actionsTab.innerHTML = `
|
||
<div class="mine-panel">
|
||
|
||
<div class="mine-header-row">
|
||
<span class="mine-level-badge">⛏️ Level ${data.level}</span>
|
||
<span class="mine-cycles">${data.cycles > 0 ? `${data.cycles}× Zyklus abgeschlossen` : "Läuft..."}</span>
|
||
</div>
|
||
|
||
<div class="mine-divider"></div>
|
||
|
||
<p class="mine-section-title">Abgebaut</p>
|
||
<div class="mine-resources">
|
||
${resourceRows}
|
||
</div>
|
||
|
||
<div class="mine-divider"></div>
|
||
|
||
<div class="mine-timer-row">
|
||
<span class="mine-timer-label">Nächster Zyklus in</span>
|
||
<span class="mine-timer" id="mine-countdown"
|
||
data-seconds="${data.next_cycle_in_seconds}">
|
||
${minutesLeft}m ${secondsLeft}s
|
||
</span>
|
||
</div>
|
||
|
||
<div class="mine-actions">
|
||
<button
|
||
class="mine-btn-collect ${data.ready ? "" : "mine-btn-disabled"}"
|
||
id="mine-collect-btn"
|
||
data-building="${buildingId}"
|
||
${data.ready ? "" : "disabled"}
|
||
>
|
||
${data.ready ? "⛏️ Abholen" : "⏳ Noch nicht bereit"}
|
||
</button>
|
||
</div>
|
||
|
||
</div>`;
|
||
|
||
startCountdown(buildingId);
|
||
|
||
} catch (err) {
|
||
console.error("Mine Fehler:", err);
|
||
actionsTab.innerHTML = `<p class="mine-error">⚠️ Fehler beim Laden der Mineninfo.</p>`;
|
||
}
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
Abholen-Klick
|
||
───────────────────────────────────────── */
|
||
document.addEventListener("click", async (e) => {
|
||
const btn = e.target.closest("#mine-collect-btn");
|
||
if (!btn || btn.disabled) return;
|
||
|
||
const buildingId = btn.dataset.building;
|
||
|
||
btn.disabled = true;
|
||
btn.textContent = "⏳ Wird abgeholt...";
|
||
|
||
try {
|
||
const res = await fetch(`/api/mine/${buildingId}/collect`, { method: "POST" });
|
||
if (!res.ok) throw new Error("API Fehler");
|
||
const data = await res.json();
|
||
|
||
if (data.error) {
|
||
showNotification(
|
||
data.ready_in_display
|
||
? `Die Mine ist noch nicht bereit.\nBereit in: ${data.ready_in_display}`
|
||
: data.error,
|
||
"Mine",
|
||
"⛏️"
|
||
);
|
||
await renderMineStatus(buildingId);
|
||
return;
|
||
}
|
||
|
||
/* Erfolg – was wurde abgeholt? */
|
||
const lines = data.collected
|
||
.map((c) => `${resourceIcon(c.resource)} ${resourceLabel(c.resource)}: +${c.amount}`)
|
||
.join("\n");
|
||
|
||
showNotification(
|
||
`Erfolgreich abgeholt!\n\n${lines}`,
|
||
"Mine",
|
||
"⛏️"
|
||
);
|
||
|
||
await renderMineStatus(buildingId);
|
||
|
||
} catch (err) {
|
||
console.error("Abholen Fehler:", err);
|
||
showNotification(
|
||
"Fehler beim Abholen. Bitte erneut versuchen.",
|
||
"Fehler",
|
||
"⚠️"
|
||
);
|
||
await renderMineStatus(buildingId);
|
||
}
|
||
});
|
||
|
||
/* ─────────────────────────────────────────
|
||
Countdown-Timer (live)
|
||
───────────────────────────────────────── */
|
||
let countdownInterval = null;
|
||
|
||
function startCountdown(buildingId) {
|
||
if (countdownInterval) clearInterval(countdownInterval);
|
||
|
||
countdownInterval = setInterval(() => {
|
||
const el = document.getElementById("mine-countdown");
|
||
if (!el) {
|
||
clearInterval(countdownInterval);
|
||
return;
|
||
}
|
||
|
||
let secs = parseInt(el.dataset.seconds, 10) - 1;
|
||
if (secs < 0) secs = 0;
|
||
el.dataset.seconds = secs;
|
||
|
||
const m = Math.floor(secs / 60);
|
||
const s = secs % 60;
|
||
el.textContent = `${m}m ${s}s`;
|
||
|
||
/* Zyklus abgeschlossen → UI neu laden */
|
||
if (secs === 0) {
|
||
clearInterval(countdownInterval);
|
||
renderMineStatus(buildingId);
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
Hilfsfunktionen
|
||
───────────────────────────────────────── */
|
||
function resourceIcon(resource) {
|
||
const map = {
|
||
gold: "🪙",
|
||
copper: "🟤",
|
||
silver: "⚪",
|
||
iron: "⚙️",
|
||
stone: "🪨",
|
||
wood: "🪵",
|
||
};
|
||
return map[resource] ?? "📦";
|
||
}
|
||
|
||
function resourceLabel(resource) {
|
||
const map = {
|
||
gold: "Gold",
|
||
copper: "Kupfer",
|
||
silver: "Silber",
|
||
iron: "Eisen",
|
||
stone: "Stein",
|
||
wood: "Holz",
|
||
};
|
||
return map[resource] ?? resource;
|
||
}
|