/* ===================================================================== aether-police / Ansicht: Dashboard Zeigt die Lage der Dienststelle. Sämtliche Zahlen kommen bei jedem Aufruf frisch vom Server — nichts ist fest hinterlegt. Die Ansicht bewertet nichts und löst keine Maßnahme aus. ===================================================================== */ "use strict"; (() => { const { sicher, zeit, dauer, aufruf, meldung, anClient } = App; /** Zwischenspeicher der zuletzt geladenen Daten (für Auffrischungen) */ let letzteDaten = null; /* ---- Bausteine --------------------------------------------------- */ function kennzahl(titel, wert, zusatz, art) { return `
${sicher(titel)}
${sicher(wert)}
${zusatz ? `
${sicher(zusatz)}
` : ""}
`; } /** Übersetzt eine Prioritätszahl in eine Streifenklasse */ const prioKlasse = (p) => "p" + Math.min(4, Math.max(1, p || 3)); function warnungen(liste) { if (!liste || !liste.length) return ""; const symbol = { hoch: "⚠", normal: "ℹ", niedrig: "•" }; return liste.map((w) => `
${symbol[w.prioritaet] || "•"} ${sicher(w.text)}
` ).join(""); } function beamtenListe(beamte) { if (!beamte.length) return `
Niemand im Dienst.
`; const statusFarbe = { verfuegbar: "gut", einsatz: "warn", pause: "neutral", nicht: "kritisch", }; return `
${beamte.map((b) => `
${sicher(b.dienstnummer)}
${sicher(b.name)}${b.leitstelle ? ' Leitstelle' : ""}
${sicher(b.rolleName)} · ${sicher(b.abteilung)}
${dauer((Date.now() / 1000) - b.seit)}
`).join("")}
`; } function einsatzListe(einsaetze) { if (!einsaetze.length) return `
Keine offenen Einsätze.
`; return `
${einsaetze.map((e) => `
${sicher(e.titel)}
${sicher(e.nummer)} · ${sicher(e.ort || "Ort unbekannt")} · ${zeit(e.erstellt_am)}
${sicher(e.status)} ${e.pos_x ? `` : ""}
`).join("")}
`; } function gewahrsamListe(eintraege) { if (!eintraege.length) return `
Niemand in Gewahrsam.
`; return `
${eintraege.map((g) => { const rest = Number(g.rest) || 0; const abgelaufen = rest <= 0; return `
${sicher(g.firstname + " " + g.lastname)}
${sicher(g.grund || "—")}${g.zelle ? " · Zelle " + sicher(g.zelle) : ""}
${abgelaufen ? "Frist abgelaufen" : rest + " Min"}
`; }).join("")}
`; } function fahndungsListe(fahndungen) { if (!fahndungen.length) return `
Keine aktiven Fahndungen.
`; const gefahrKlasse = { gefaehrlich: "kritisch", bewaffnet: "warn", normal: "neutral" }; return `
${fahndungen.map((f) => `
${sicher(f.bezeichnung)}
${sicher(f.grund)}
${sicher(f.gefahr)}
`).join("")}
`; } function mitteilungsListe(mitteilungen) { if (!mitteilungen.length) return `
Keine Mitteilungen.
`; return `
${mitteilungen.map((m) => `
${sicher(m.betreff || "Mitteilung")}
${sicher((m.firstname || "") + " " + (m.lastname || ""))} · ${zeit(m.gesendet)}
`).join("")}
`; } /* ---- Aufbau ------------------------------------------------------ */ function zeichne(behaelter, d) { const k = d.kennzahlen; behaelter.innerHTML = `

Übersicht

Lage der Dienststelle — Stand ${new Date().toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" })}

${warnungen(d.warnungen)}
${kennzahl("Im Dienst", k.imDienst, `${k.verfuegbar} verfügbar`, k.imDienst > 0 ? "gut" : "")} ${kennzahl("Offene Einsätze", k.einsaetzeOffen, null, k.einsaetzeOffen > 0 ? "warn" : "")} ${kennzahl("Anzeigen (Entwurf)", k.anzeigenOffen, "warten auf Bestätigung")} ${kennzahl("Fahndungen", k.fahndungen)} ${kennzahl("In Gewahrsam", k.gefangene, k.haftAbgelaufen > 0 ? `${k.haftAbgelaufen} Frist abgelaufen` : null, k.haftAbgelaufen > 0 ? "hoch" : "")} ${kennzahl("Dienstfahrzeuge", `${k.fahrzeugeEinsatz}/${k.fahrzeugeGesamt}`, "im Einsatz")}
Offene Einsätze ${d.einsaetze.length}
${einsatzListe(d.einsaetze)}
Beamte im Dienst ${d.beamte.length}
${beamtenListe(d.beamte)}
Gewahrsam ${d.gewahrsam.length}
${gewahrsamListe(d.gewahrsam)}
ℹ
Fristen dienen nur der Erinnerung. Eine Entlassung erfolgt ausschließlich manuell durch einen Beamten.
Aktive Fahndungen ${d.fahndungen.length}
${fahndungsListe(d.fahndungen)}
Meine offenen Berichte ${d.berichte.length}
${d.berichte.length ? `
${d.berichte.map((b) => `
${sicher(b.titel)}
${sicher(b.nummer)} · ${zeit(b.erstellt_am)}
Entwurf
`).join("")}
` : `
Keine offenen Berichte.
`}
Neueste Mitteilungen
${mitteilungsListe(d.mitteilungen)}
`; // Aktualisieren App.$("db-aktualisieren").addEventListener("click", () => laden(behaelter)); // Route zu einem Einsatzort setzen behaelter.querySelectorAll("[data-weg]").forEach((b) => { b.addEventListener("click", () => { const [x, y] = b.dataset.weg.split(",").map(Number); anClient("wegpunkt", { x, y }); }); }); } /* ---- Laden ------------------------------------------------------- */ async function laden(behaelter) { try { const daten = await aufruf("dashboard", "laden", {}); letzteDaten = daten; App.zustand.hinweise = daten.hinweise || []; zeichne(behaelter, daten); } catch (fehler) { behaelter.innerHTML = `

Übersicht

Die Daten konnten nicht geladen werden: ${sicher(fehler.message)}

`; } } /* ---- Registrierung ----------------------------------------------- */ App.registriereAnsicht("dashboard", { rendern: (behaelter) => laden(behaelter), // Wird aufgerufen, wenn sich im Hintergrund etwas geändert hat aktualisieren: () => { const behaelter = App.$("inhalt"); if (App.zustand.aktivesModul === "dashboard" && behaelter) laden(behaelter); }, }); })();