/* ===================================================================== aether-police / Ansicht: Fuhrpark Zeigt Standort, Tankstand, Zustand und letzten Fahrer — das sind gemeldete Tatsachen. Zuweisung, Status und Wartung setzt immer ein Beamter; es gibt keine automatische Fahrzeugvergabe. ===================================================================== */ "use strict"; (() => { const { sicher, zeit, aufruf, meldung, fenster, bestaetigen, $, anClient } = App; const z = { daten: null, offen: null, filterAbteilung: "", filterStatus: "", filterWartung: "", suche: "", }; const statusArt = { verfuegbar: "gut", im_einsatz: "warn", werkstatt: "kritisch", ausser_dienst: "neutral", }; const wartungArt = { ok: "gut", faellig: "warn", werkstatt: "kritisch" }; /* ---- Bausteine --------------------------------------------------- */ /** Balken für Tank oder Zustand */ function balken(anteil, art) { const wert = Math.max(0, Math.min(100, anteil)); const farbe = wert < 20 ? "var(--kritisch)" : wert < 50 ? "var(--warn)" : "var(--gut)"; return `
`; } function statusName(id) { return (z.daten.statusliste && z.daten.statusliste[id]) || id; } function wartungName(id) { return (z.daten.wartungsliste && z.daten.wartungsliste[id]) || id; } function abteilungName(id) { const treffer = (z.daten.abteilungen || []).find((a) => a.id === id); return treffer ? treffer.name : id; } /* ---- Übersicht ---------------------------------------------------- */ function uebersicht(behaelter) { const d = z.daten; behaelter.innerHTML = `

Fuhrpark

Standort, Tank und Zustand werden gemeldet — Zuweisung und Status setzt ein Beamter.

${d.rechte.wartung ? `` : ""}
Verfügbar
${d.bestand.verfuegbar || 0}
Im Einsatz
${d.bestand.im_einsatz || 0}
Werkstatt
${d.bestand.werkstatt || 0}
Wartung offen
${d.wartungFaellig}
${d.fahrzeuge.length ? `
${d.fahrzeuge.map((f) => `
${sicher(f.kennzeichen)}
${sicher(f.bezeichnung)} ${f.wartung !== "ok" ? `${sicher(wartungName(f.wartung))}` : ""}
${sicher(f.modell)} · ${sicher(abteilungName(f.abteilung))} ${f.z_nummer ? " · zugewiesen: " + sicher(f.z_nummer) : ""}
⛽ ${Math.round(f.tank)} %${balken(f.tank, "Tank")} 🔧 ${Math.round(f.zustand / 10)} %${balken(f.zustand / 10, "Zustand")}
${sicher(statusName(f.status))} ${f.pos_x ? `` : ""}
`).join("")}
` : `
Kein Fahrzeug im Fuhrpark.
`}
`; const neu = $("fz-neu"); if (neu) neu.addEventListener("click", () => anlegenDialog(behaelter)); const suchfeld = $("fz-suche"); suchfeld.addEventListener("keydown", (e) => { if (e.key === "Enter") { z.suche = suchfeld.value.trim(); rendern(behaelter); } }); $("fz-abteilung").addEventListener("change", (e) => { z.filterAbteilung = e.target.value; rendern(behaelter); }); $("fz-status").addEventListener("change", (e) => { z.filterStatus = e.target.value; rendern(behaelter); }); // Standort auf der Karte markieren, ohne die Zeile zu öffnen behaelter.querySelectorAll("[data-weg]").forEach((b) => b.addEventListener("click", (e) => { e.stopPropagation(); const [x, y] = b.dataset.weg.split(",").map(Number); anClient("wegpunkt", { x, y }); })); behaelter.querySelectorAll("[data-fahrzeug]").forEach((el) => el.addEventListener("click", () => oeffne(behaelter, +el.dataset.fahrzeug))); } /* ---- Einzelansicht ------------------------------------------------ */ function einzelAnsicht(behaelter, d) { const f = d.fahrzeug; behaelter.innerHTML = `

${sicher(f.bezeichnung)}

${sicher(f.kennzeichen)} · ${sicher(f.modell)} · ${sicher(abteilungName(f.abteilung))}

${f.pos_x ? `` : ""} ${d.rechte.zuweisen ? `` : ""} ${d.rechte.wartung ? `` : ""} ${d.rechte.zuweisen ? `` : ""}
${f.wartung !== "ok" ? `
🔧 ${sicher(wartungName(f.wartung))} — das Fahrzeug sollte vor dem nächsten Einsatz geprüft werden.
` : ""}
Zustand ${sicher(statusName(f.status))}
⛽ Tankstand ${Math.round(f.tank)} %
${balken(f.tank, "Tank")}
🔧 Karosserie ${Math.round(f.zustand / 10)} %
${balken(f.zustand / 10, "Zustand")}
Wartung${sicher(wartungName(f.wartung))} Zugewiesen an${f.z_nummer ? sicher(f.z_nummer + " " + (f.z_vorname || "") + " " + (f.z_nachname || "")) : "— frei —"} Letzter Fahrer${f.l_nummer ? sicher(f.l_nummer + " " + (f.l_vorname || "") + " " + (f.l_nachname || "")) : "— nicht erfasst —"} Standort${f.pos_x ? `${Math.round(f.pos_x)}, ${Math.round(f.pos_y)}` : "— nicht gemeldet —"}
ℹ
Tank, Zustand, Standort und letzter Fahrer werden vom Fahrzeug gemeldet. Status, Zuweisung und Wartung setzt ausschließlich ein Beamter.
Verwaltung ${d.rechte.wartung && !f.zugewiesen_an ? `` : ""}
${f.zugewiesen_an ? `
${sicher(f.z_nummer || "")}
${sicher((f.z_vorname || "") + " " + (f.z_nachname || ""))}
Fahrzeug ist dieser Person zugewiesen
${d.rechte.zuweisen ? `` : ""}
` : `
Das Fahrzeug ist keiner Person zugewiesen.
`}
Vorgangshistorie
${d.historie.length ? `
${d.historie.map((h) => `
${sicher(h.aktion)}
${sicher(h.dienstnummer || "")} ${sicher((h.firstname || "") + " " + (h.lastname || ""))} · ${zeit(h.am)} ${h.grund ? " · " + sicher(h.grund) : ""}
`).join("")}
` : `
Keine Einträge.
`}
`; verdrahteEinzel(behaelter, d); } function verdrahteEinzel(behaelter, d) { const f = d.fahrzeug; $("fz-zurueck").addEventListener("click", () => { z.offen = null; rendern(behaelter); }); const standort = $("fz-standort"); if (standort) standort.addEventListener("click", () => anClient("wegpunkt", { x: f.pos_x, y: f.pos_y })); const zuweisen = $("fz-zuweisen"); if (zuweisen) zuweisen.addEventListener("click", () => { const beamte = d.beamteImDienst || []; fenster({ titel: "Fahrzeug zuweisen", inhalt: `

${sicher(f.bezeichnung)} (${sicher(f.kennzeichen)})

${beamte.length ? `
${beamte.map((b) => `
${sicher(b.dienstnummer)}
${sicher(b.name)}
${sicher(b.rolleName)} · ${sicher(b.abteilung)}
`).join("")}
` : `
Niemand im Dienst.
`}
`, nachOeffnen: (el) => { el.querySelectorAll("[data-wahl]").forEach((zeile) => zeile.addEventListener("click", async () => { try { await aufruf("fahrzeug", "zuweisen", { id: f.id, charakterId: +zeile.dataset.wahl, grund: el.querySelector("#fzz-grund").value.trim(), }); el.remove(); meldung("Zugewiesen.", "gut"); oeffne(behaelter, f.id); } catch (fehler) { meldung(fehler.message, "fehler"); } })); }, }); }); const freigeben = $("fz-freigeben"); if (freigeben) freigeben.addEventListener("click", async () => { try { await aufruf("fahrzeug", "zuweisen", { id: f.id, freigeben: true }); meldung("Zuweisung aufgehoben."); oeffne(behaelter, f.id); } catch (fehler) { meldung(fehler.message, "fehler"); } }); const statusSetzen = $("fz-status-setzen"); if (statusSetzen) statusSetzen.addEventListener("click", () => { fenster({ titel: "Status setzen", inhalt: `
`, knoepfe: [ { text: "Abbrechen", klick: (_, zu) => zu() }, { text: "Speichern", klick: async (el, zu) => { try { await aufruf("fahrzeug", "status", { id: f.id, status: el.querySelector("#fzs-status").value, grund: el.querySelector("#fzs-grund").value.trim(), }); zu(); meldung("Status gesetzt.", "gut"); oeffne(behaelter, f.id); } catch (fehler) { meldung(fehler.message, "fehler"); } }}, ], }); }); const wartung = $("fz-wartung"); if (wartung) wartung.addEventListener("click", () => { fenster({ titel: "Wartungsstatus", inhalt: `
`, knoepfe: [ { text: "Abbrechen", klick: (_, zu) => zu() }, { text: "Speichern", klick: async (el, zu) => { try { await aufruf("fahrzeug", "wartung", { id: f.id, wartung: el.querySelector("#fzw-wartung").value, vermerk: el.querySelector("#fzw-vermerk").value.trim(), }); zu(); meldung("Wartungsstatus gesetzt.", "gut"); oeffne(behaelter, f.id); } catch (fehler) { meldung(fehler.message, "fehler"); } }}, ], }); }); const entfernen = $("fz-entfernen"); if (entfernen) entfernen.addEventListener("click", () => { bestaetigen({ titel: "Fahrzeug ausmustern", gefahr: true, inhalt: `

${sicher(f.bezeichnung)} (${sicher(f.kennzeichen)}) wird aus dem Fuhrpark entfernt. Der Vorgang bleibt im Protokoll sichtbar.

`, bestaetigenText: "Ausmustern", bestaetigt: async (el, zu) => { try { await aufruf("fahrzeug", "entfernen", { id: f.id, grund: el.querySelector("#fze-grund").value.trim(), }); zu(); meldung("Ausgemustert."); z.offen = null; rendern(behaelter); } catch (fehler) { meldung(fehler.message, "fehler"); } }, }); }); } /* ---- Anlegen ------------------------------------------------------ */ function anlegenDialog(behaelter) { fenster({ titel: "Fahrzeug aufnehmen", inhalt: `
Das Kennzeichen muss mit dem im Spiel übereinstimmen — nur dann können Tank, Zustand und Standort gemeldet werden.
`, knoepfe: [ { text: "Abbrechen", klick: (_, zu) => zu() }, { text: "Aufnehmen", klick: async (el, zu) => { try { const ergebnis = await aufruf("fahrzeug", "anlegen", { kennzeichen: el.querySelector("#fn-kz").value.trim(), modell: el.querySelector("#fn-modell").value.trim(), bezeichnung: el.querySelector("#fn-bez").value.trim(), abteilung: el.querySelector("#fn-abteilung").value, }); zu(); meldung("Fahrzeug aufgenommen.", "gut"); oeffne(behaelter, ergebnis.id); } catch (fehler) { meldung(fehler.message, "fehler"); } }}, ], }); } /* ---- Laden -------------------------------------------------------- */ async function oeffne(behaelter, fahrzeugId) { try { const d = await aufruf("fahrzeug", "oeffnen", { id: fahrzeugId }); z.offen = fahrzeugId; einzelAnsicht(behaelter, d); } catch (f) { meldung(f.message, "fehler"); } } async function rendern(behaelter) { try { z.daten = await aufruf("fahrzeug", "liste", { abteilung: z.filterAbteilung, status: z.filterStatus, wartung: z.filterWartung, begriff: z.suche, }); if (z.offen) await oeffne(behaelter, z.offen); else uebersicht(behaelter); } catch (f) { behaelter.innerHTML = `

Fuhrpark

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

`; } } App.registriereAnsicht("fahrzeug", { rendern }); App.registriereSuche(async (begriff) => { try { const d = await aufruf("fahrzeug", "liste", { begriff }); return (d.fahrzeuge || []).slice(0, 5).map((f) => ({ bereich: "Dienstfahrzeug", titel: f.bezeichnung, unter: f.kennzeichen + " · " + f.modell, })); } catch (e) { return []; } }); })();