/* ===================================================================== aether-medical / Ansicht: Übersicht Der Lagebericht der Klinik. Jede Zahl kommt frisch vom Server; keine ist fest verdrahtet. Die Warnungen betreffen ausschliesslich Bestände, Fristen und Besetzung — nie den Zustand eines Patienten, den das System selbst bewertet hätte. ===================================================================== */ "use strict"; (() => { const { sicher, zeit, minuten, aufruf, meldung } = App; const z = { daten: null, behaelter: null }; /* ---- Bausteine ------------------------------------------------------ */ /** * Kennzahlkachel * @param {string|number} wert Angezeigter Wert * @param {string} titel Beschriftung * @param {string} zusatz Zusatzzeile * @param {string} art "", "gut", "warn", "hoch" * @param {string} ziel Modul, in das ein Klick springt */ function kachel(wert, titel, zusatz, art, ziel) { return `
${sicher(titel)}
${sicher(wert)}
${zusatz ? `
${sicher(zusatz)}
` : ""}
`; } /** Waagerechter Belegungsbalken */ function belegungsBalken(name, belegt, gesamt) { const anteil = gesamt > 0 ? Math.round((belegt / gesamt) * 100) : 0; // Je voller, desto dringlicher die Farbe const farbe = anteil >= 90 ? "var(--kritisch)" : anteil >= 70 ? "var(--warn)" : "var(--gut)"; return `
${sicher(name)}
${belegt}/${gesamt}
`; } /** Name einer Station anhand ihrer Kennung */ function stationsName(id) { const treffer = (App.zustand.stationen || []).find((s) => s.id === id); return treffer ? treffer.name : (id || "—"); } /* ---- Zeichnen -------------------------------------------------------- */ function zeichne(behaelter) { const d = z.daten; const dienst = d.dienst, ein = d.einsaetze, pat = d.patienten; const bel = d.belegung, offen = d.offen; behaelter.innerHTML = `

Übersicht

Stand der Klinik. Alle Zahlen sind Momentaufnahmen — sie lösen nichts aus und ersetzen keine Einschätzung am Patienten.

${zeit(new Date().toISOString())}
${d.warnungen.length ? `
${d.warnungen.map((w) => `
${w.art === "kritisch" ? "⚠" : "❗"}
${sicher(w.titel)} — ${sicher(w.text)}
`).join("")}
` : ""}
${kachel(dienst.imDienst, "Im Dienst", dienst.leitstelle ? "Leitstelle: " + dienst.leitstelle : "Leitstelle unbesetzt", dienst.imDienst === 0 ? "hoch" : "gut")} ${kachel(dienst.notaerzte, "Notärzte", dienst.aufRtw + " auf RTW · " + dienst.imOp + " im OP")} ${kachel(ein.offen, "Offene Notrufe", ein.laufend + " laufend · " + ein.dringend + " dringend", ein.offen > 0 ? "warn" : "", "leitstelle")} ${kachel(pat.aufgenommen, "Patienten im Haus", pat.wartend + " warten auf Aufnahme", "", "patienten")}
${kachel(pat.intensiv, "Intensivpatienten", pat.kritisch + " als kritisch eingetragen", pat.kritisch > 0 ? "hoch" : "", "intensiv")} ${kachel(bel.opLaufend + "/" + bel.opSaeleGesamt, "OP-Säle belegt", bel.opGeplant + " geplant", "", "operation")} ${kachel(bel.bettenFrei, "Freie Betten", "von " + bel.bettenGesamt + " insgesamt", bel.bettenFrei === 0 ? "hoch" : bel.bettenFrei <= 2 ? "warn" : "gut", "klinik")} ${kachel(bel.behandlungFrei, "Freie Behandlungsräume", "von " + bel.behandlungGesamt + " insgesamt", bel.behandlungFrei === 0 ? "warn" : "", "klinik")}
${kachel(offen.dokumentationen, "Offene Dokumentationen", offen.eigeneDoku + " davon von dir", offen.eigeneDoku > 0 ? "warn" : "", "behandlung")} ${kachel(offen.laborOffen, "Laboraufträge offen", offen.laborUnbefundet + " warten auf Bewertung", "", "labor")} ${kachel(offen.berichteEntwurf, "Eigene Berichtsentwürfe", "noch nicht eingereicht", offen.berichteEntwurf > 0 ? "warn" : "", "bericht")} ${kachel(pat.laengsteWartezeit > 0 ? minuten(pat.laengsteWartezeit) : "—", "Längste Wartezeit", pat.wartend + " Patienten warten", pat.laengsteWartezeit >= 30 ? "hoch" : pat.laengsteWartezeit >= 10 ? "warn" : "", "patienten")}
Wartende Patienten Aufnahme entscheidet ein Mediziner
${pat.warteliste.length ? pat.warteliste.map((p) => `
${sicher(p.firstname)} ${sicher(p.lastname)}
${sicher(String(p.grund).slice(0, 70))}
wartet ${minuten(p.wartet)}
`).join("") : `
Niemand wartet auf Aufnahme.
`}
Offene und laufende Einsätze Zuweisung durch die Leitstelle
${ein.liste.length ? ein.liste.map((e) => `
${sicher(e.nummer)}
${sicher(e.titel)}
${sicher(e.ort || "Ort offen")}
${e.status === "offen" ? "offen" : "laufend"}
`).join("") : `
Keine offenen Einsätze.
`}
Belegung
${belegungsBalken("Betten", bel.bettenBelegt, bel.bettenGesamt)} ${belegungsBalken("Behandlungsräume", bel.behandlungGesamt - bel.behandlungFrei, bel.behandlungGesamt)} ${belegungsBalken("OP-Säle", bel.opLaufend, bel.opSaeleGesamt)}
Kollegen im Dienst ${dienst.imDienst} anwesend
${dienst.liste.length ? dienst.liste.slice(0, 8).map((m) => `
${sicher(m.personalnummer)}
${sicher(m.name)}
${sicher(m.rolleName)} · ${sicher(stationsName(m.station))}
${m.leitstelle ? `Leitstelle` : ""} ${sicher(funktionsName(m.funktion))}
`).join("") : `
Niemand im Dienst.
`}
Das System unterstützt medizinische Entscheidungen — es trifft niemals selbst welche. Es nimmt niemanden auf, entlässt niemanden, stellt keine Diagnose, gibt kein Medikament aus und stellt keinen Tod fest. Wartezeiten und Fristen laufen ab, ohne dass etwas passiert, bis ein Mediziner entscheidet.
`; verdrahte(behaelter); } /** Farbe zum Dienststatus aus der Konfiguration */ function farbeZuStatus(status) { const treffer = (App.zustand.status || []).find((s) => s.id === status); return treffer ? treffer.farbe : "var(--flaeche-3)"; } /** Klartextname einer Dienstfunktion */ function funktionsName(funktion) { const treffer = (App.zustand.funktionen || []).find((f) => f.id === funktion); return treffer ? treffer.name : (funktion || "—"); } function verdrahte(behaelter) { // Kacheln und Warnungen springen in das zuständige Modul behaelter.querySelectorAll("[data-springe]").forEach((el) => { el.addEventListener("click", () => { const ziel = el.dataset.springe; if (!App.zustand.module.some((m) => m.id === ziel)) { meldung("Dieses Modul steht dir nicht zur Verfügung.", "fehler"); return; } App.oeffneModul(ziel); }); }); } /* ---- Laden ------------------------------------------------------------ */ async function rendern(behaelter) { z.behaelter = behaelter; try { z.daten = await aufruf("dashboard", "laden", {}); // Hinweise aus dem ersten Laden in den Kern übernehmen App.zustand.hinweise = z.daten.hinweise || []; zeichne(behaelter); } catch (f) { behaelter.innerHTML = `

Übersicht

Konnte nicht geladen werden: ${sicher(f.message)}

`; } } App.registriereAnsicht("dashboard", { rendern, // Wird gerufen, wenn sich Dienstliste oder Einsätze ändern aktualisieren() { if (z.behaelter && App.zustand.aktivesModul === "dashboard") rendern(z.behaelter); }, }); })();