import { showNotification } from "../notification.js"; import { refreshHud } from "../hud.js"; /* ── Einstiegspunkt ─────────────────────────────── */ export async function loadMine(buildingId) { const actionsTab = document.getElementById("tab-actions"); if (!actionsTab) return; actionsTab.innerHTML = `
Lade Mineninfo...
`; await renderMineStatus(buildingId); } /* ───────────────────────────────────────────────── Haupt-Render-Funktion ───────────────────────────────────────────────── */ 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 = "

" + data.error + "

"; return; } actionsTab.innerHTML = "
" + renderHeader(data) + renderDivider() + // Ressource wählen (nur wenn noch keine aktive Session) (!data.selected_resource ? renderResourceSelector(data, buildingId) : renderActiveSession(data, buildingId) ) + "
"; if (data.selected_resource) { startCountdown(buildingId, data); } } catch (err) { console.error("Mine Fehler:", err); actionsTab.innerHTML = "

Fehler beim Laden der Mineninfo.

"; } } /* ───────────────────────────────────────────────── Header ───────────────────────────────────────────────── */ function renderHeader(data) { let cycleText = "Keine Ressource gewählt"; if (data.selected_resource) { if (data.is_full) cycleText = "Voll – bitte abholen!"; else if (data.cycles > 0) cycleText = data.cycles + "x Zyklus abgeschlossen"; else cycleText = "Läuft..."; } return ( "
" + "Level " + data.level + "" + "" + cycleText + "" + "
" ); } /* ───────────────────────────────────────────────── Ressourcen-Auswahl (Startscreen ohne aktive Session) ───────────────────────────────────────────────── */ function renderResourceSelector(data, buildingId) { return ( "

Ressource wählen

" + "

Wähle eine Ressource für die nächsten " + data.session_hours + "h.

" + renderResourceGrid(data.production, null, buildingId, "select") ); } /* ───────────────────────────────────────────────── Aktive Session (mit Timer, Queue, Collect-Button) ───────────────────────────────────────────────── */ function renderActiveSession(data, buildingId) { return ( // Aktuelle Produktion renderCurrentProduction(data) + renderDivider() + // Warteschlangen-Bereich renderQueueSection(data, buildingId) + renderDivider() + // Abholen-Button renderCollectSection(data, buildingId) ); } /* ───────────────────────────────────────────────── Aktuelle Produktion ───────────────────────────────────────────────── */ function renderCurrentProduction(data) { const minutesLeft = Math.floor(data.next_cycle_in_seconds / 60); const secondsLeft = data.next_cycle_in_seconds % 60; const progressPct = Math.min(100, Math.round((data.cycles / data.max_cycles) * 100)); return ( "

Aktuelle Session – " + data.session_hours + "h

" + "
" + "" + resourceIcon(data.selected_resource) + "" + "" + resourceLabel(data.selected_resource) + "" + "" + data.available_amount + "" + "
" + "
" + "
" + "
" + "
" + "" + (data.is_full ? "Zeit abgelaufen!" : "Nächster Zyklus in") + "" + (data.is_full ? "VOLL" : "" + minutesLeft + "m " + secondsLeft + "s" ) + "
" ); } /* ───────────────────────────────────────────────── Warteschlangen-Bereich – zeigt belegte Slots als Ressourcen-Badges – zeigt freie Slots als aufklappbare Auswahl ───────────────────────────────────────────────── */ function renderQueueSection(data, buildingId) { const { loop_queue, loop_slots_free, loop_slots_used, loop_cost_gems, can_afford_loop, player_gems } = data; let html = "

Warteschlange" + " (" + loop_slots_used + "/4)

"; // Belegte Slots loop_queue.forEach((res, i) => { html += "
" + "" + (i + 1) + "." + "" + resourceIcon(res) + "" + "" + resourceLabel(res) + "" + "" + data.session_hours + "h" + "
"; }); // Freie Slots (kaufbar) if (loop_slots_free > 0) { const nextPos = loop_slots_used + 1; html += "
" + "" + // Resource-Picker (standardmäßig versteckt) "" + "
"; } if (loop_slots_free === 0) { html += "

Warteschlange voll – 4 Schleifen aktiv.

"; } return html; } /* ───────────────────────────────────────────────── Ressourcen-Raster (wiederverwendbar für select + loop) mode: "select" | "loop" ───────────────────────────────────────────────── */ function renderResourceGrid(production, activeResource, buildingId, mode) { const buttons = production.map(r => { const isActive = r.resource === activeResource; return ( "" ); }).join(""); return "
" + buttons + "
"; } /* ───────────────────────────────────────────────── Collect-Button ───────────────────────────────────────────────── */ function renderCollectSection(data, buildingId) { return ( "
" + "" + "
" ); } function renderDivider() { return "
"; } /* ───────────────────────────────────────────────── Event: Toggle Schleifenpicker ───────────────────────────────────────────────── */ document.addEventListener("click", (e) => { const btn = e.target.closest("#mine-queue-toggle"); if (!btn || btn.disabled) return; const picker = document.getElementById("mine-loop-picker"); if (!picker) return; const isOpen = picker.style.display !== "none"; picker.style.display = isOpen ? "none" : "block"; btn.classList.toggle("mine-btn-add-loop-open", !isOpen); }); /* ───────────────────────────────────────────────── Event: Ressource wählen (select) oder Schleife buchen (loop) ───────────────────────────────────────────────── */ document.addEventListener("click", async (e) => { const btn = e.target.closest(".mine-res-btn"); if (!btn || btn.disabled || btn.classList.contains("mine-res-btn-active")) return; const resource = btn.dataset.resource; const buildingId = btn.dataset.building; const mode = btn.dataset.mode; // "select" | "loop" document.querySelectorAll(".mine-res-btn").forEach(b => (b.disabled = true)); const endpoint = mode === "loop" ? "/api/mine/" + buildingId + "/loop" : "/api/mine/" + buildingId + "/select"; try { const res = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ resource }), }); if (!res.ok) throw new Error("API Fehler"); const data = await res.json(); if (data.error) { showNotification(data.error, "Mine", "⛏️"); await renderMineStatus(buildingId); return; } if (mode === "loop") { showNotification( "Schleife hinzugefügt!\n" + resourceLabel(resource) + " – 5h\n" + "Noch " + data.loop_slots_free + " Slot(s) frei.", "Mine", "💎" ); } else { showNotification( resourceLabel(resource) + " ausgewählt.\n5h Session startet jetzt.", "Mine", "⛏️" ); } await renderMineStatus(buildingId); if (mode === "loop") await refreshHud(); } catch (err) { console.error("Mine Fehler:", err); await renderMineStatus(buildingId); } }); /* ───────────────────────────────────────────────── Event: Abholen ───────────────────────────────────────────────── */ 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 ? "Noch nicht bereit.\nBereit in: " + data.ready_in_display : data.error, "Mine", "⛏️" ); await renderMineStatus(buildingId); return; } const c = data.collected; let msg = "Abgeholt!\n" + resourceLabel(c.resource) + ": +" + c.amount; if (data.next_resource) { msg += "\n\nNächste Session: " + resourceLabel(data.next_resource) + " (5h)"; } else { msg += "\n\nKeine weiteren Schleifen – neue Ressource wählen."; } showNotification(msg, "Mine", "⛏️"); await renderMineStatus(buildingId); await refreshHud(); } catch (err) { console.error("Abholen Fehler:", err); showNotification("Fehler beim Abholen. Bitte erneut versuchen.", "Fehler", "⚠️"); await renderMineStatus(buildingId); } }); /* ───────────────────────────────────────────────── Countdown-Timer ───────────────────────────────────────────────── */ let countdownInterval = null; function startCountdown(buildingId, data) { if (countdownInterval) clearInterval(countdownInterval); if (data.is_full) return; 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; el.textContent = Math.floor(secs / 60) + "m " + (secs % 60) + "s"; if (secs === 0) { clearInterval(countdownInterval); renderMineStatus(buildingId); } }, 1000); } /* ───────────────────────────────────────────────── Icons & Labels ───────────────────────────────────────────────── */ function resourceIcon(resource) { const imgMap = { iron: "/images/items/eisen.png", gold: "/images/items/goldmuenze.png", wood: "/images/items/holz.png", stone: "/images/items/stein.png", }; if (imgMap[resource]) { return ( "" + "" + "" ); } return "📦"; } function resourceLabel(resource) { const map = { gold: "Gold", iron: "Eisen", stone: "Stein", wood: "Holz" }; return map[resource] || resource; }