/* =====================================================================
aether-police / Ansicht: Strafenkatalog & Anzeigen
Der Katalog liefert einen VORSCHLAG. Die Felder darunter gehören dem
Beamten — er kann sie jederzeit ändern. Weicht er ab, wird das
sichtbar gemacht und eine Begründung verlangt.
===================================================================== */
"use strict";
(() => {
const { sicher, zeit, euro, aufruf, meldung, fenster, bestaetigen, $ } = App;
const z = {
reiter: "erfassen", // erfassen | vorgaenge | katalog
katalog: [],
rechte: {},
auswahl: new Set(), // gewählte Delikt-Kennungen
vorschlag: null, // { delikte, haft, geld, hinweise }
beschuldigter: null, // { id, name }
anzeigen: [],
filterStatus: "",
};
/* ---- Bausteine --------------------------------------------------- */
function reiterLeiste() {
const reiter = [
{ id: "erfassen", name: "Anzeige erfassen", symbol: "✎" },
{ id: "vorgaenge", name: "Vorgänge", symbol: "📋" },
];
if (z.rechte.bearbeiten) reiter.push({ id: "katalog", name: "Katalog pflegen", symbol: "⚙" });
return `
${reiter.map((r) =>
``).join("")}
`;
}
/** Zeigt Minuten als „1 Std 30 Min" */
function haftText(minuten) {
const m = Math.max(0, Math.floor(minuten || 0));
if (m === 0) return "keine Haft";
if (m < 60) return m + " Min";
return Math.floor(m / 60) + " Std " + (m % 60 ? (m % 60) + " Min" : "");
}
/* =====================================================================
ANZEIGE ERFASSEN
===================================================================== */
function katalogAuswahl() {
if (!z.katalog.length) return `
Der Katalog ist leer.
`;
return z.katalog.map((gruppe) => `
${sicher(gruppe.kategorie)}
${gruppe.delikte.map((d) => `
`).join("")}
`).join("");
}
function erfassenAnsicht(behaelter) {
const v = z.vorschlag;
behaelter.innerHTML = `
Anzeige erfassen
Der Katalog schlägt vor — entschieden wird von dir.
${reiterLeiste()}
Strafenkatalog
${katalogAuswahl()}
Vorgang
${z.beschuldigter
? `
Ausgewählt: ${sicher(z.beschuldigter.name)}
`
: `
Ohne Beschuldigten kann keine Anzeige erfasst werden.
`}
${v ? `
Vorschlag des Katalogs${v.delikte.length} Delikt${v.delikte.length === 1 ? "" : "e"}
Haft${haftText(v.haft)}
Geldstrafe${euro(v.geld)}
${v.hinweise.length ? `
${v.hinweise.map((h) => `
ℹ ${sicher(h)}
`).join("")}
` : ""}
Deine Entscheidung
⚠ Du weichst vom Vorschlag ab
ℹ
Der Katalog ist ein Nachschlagewerk. Beide Werte lassen sich frei
anpassen — gespeichert werden Vorschlag und Entscheidung getrennt, damit
nachvollziehbar bleibt, wer was festgelegt hat.
Es wird noch nichts eingezogen und niemand kommt in Haft.
`
: `
Wähle links mindestens ein Delikt aus.
`}
`;
verdrahteErfassen(behaelter);
}
function verdrahteErfassen(behaelter) {
// Delikt an-/abwählen
behaelter.querySelectorAll("[data-delikt]").forEach((k) =>
k.addEventListener("change", async () => {
const kennung = k.dataset.delikt;
if (k.checked) z.auswahl.add(kennung); else z.auswahl.delete(kennung);
await berechneVorschlag();
erfassenAnsicht(behaelter);
}));
// Katalogsuche (nur Anzeige filtern)
const suche = $("an-katalogsuche");
if (suche) suche.addEventListener("input", () => {
const begriff = suche.value.trim().toLowerCase();
behaelter.querySelectorAll(".delikt").forEach((el) => {
const text = el.textContent.toLowerCase();
el.style.display = !begriff || text.includes(begriff) ? "" : "none";
});
behaelter.querySelectorAll(".katalog-gruppe").forEach((g) => {
const sichtbar = [...g.querySelectorAll(".delikt")].some((e) => e.style.display !== "none");
g.style.display = sichtbar ? "" : "none";
});
});
// Person suchen
const personSuche = () => {
const feld = $("an-person");
const begriff = feld.value.trim();
if (begriff.length < 2) { meldung("Bitte mindestens zwei Zeichen.", "fehler"); return; }
personWaehlen(behaelter, begriff);
};
const personKnopf = $("an-personsuche");
if (personKnopf) personKnopf.addEventListener("click", personSuche);
const personFeld = $("an-person");
if (personFeld) personFeld.addEventListener("keydown", (e) => { if (e.key === "Enter") personSuche(); });
// Abweichung sichtbar machen
const pruefeAbweichung = () => {
if (!z.vorschlag) return;
const haft = +($("an-haft") || {}).value || 0;
const geld = +($("an-geld") || {}).value || 0;
const abweichung = haft !== z.vorschlag.haft || geld !== z.vorschlag.geld;
const block = $("an-abweichung");
if (block) block.hidden = !abweichung;
};
["an-haft", "an-geld"].forEach((id) => {
const el = $(id);
if (el) el.addEventListener("input", pruefeAbweichung);
});
// Erfassen
const speichern = $("an-speichern");
if (speichern) speichern.addEventListener("click", async () => {
if (!z.beschuldigter) { meldung("Bitte eine Person auswählen.", "fehler"); return; }
const haft = +($("an-haft") || {}).value || 0;
const geld = +($("an-geld") || {}).value || 0;
const abweichung = haft !== z.vorschlag.haft || geld !== z.vorschlag.geld;
const grund = ($("an-grund") || {}).value || "";
if (abweichung && !z.rechte.abweichen) {
meldung("Dir fehlt die Berechtigung, vom Vorschlag abzuweichen.", "fehler");
return;
}
if (abweichung && grund.trim().length < 5) {
meldung("Bitte begründe die Abweichung.", "fehler");
return;
}
try {
await aufruf("anzeige", "erstellen", {
beschuldigter: z.beschuldigter.id,
delikte: [...z.auswahl],
haft, geld, begruendung: grund,
});
meldung("Als Entwurf erfasst — Bestätigung steht noch aus.", "gut");
z.auswahl.clear(); z.vorschlag = null; z.beschuldigter = null;
z.reiter = "vorgaenge";
rendern(behaelter);
} catch (f) { meldung(f.message, "fehler"); }
});
}
/** Holt den Vorschlag zur aktuellen Auswahl vom Server */
async function berechneVorschlag() {
if (!z.auswahl.size) { z.vorschlag = null; return; }
try {
z.vorschlag = await aufruf("anzeige", "vorschlag", { delikte: [...z.auswahl] });
} catch (f) { meldung(f.message, "fehler"); z.vorschlag = null; }
}
/** Personensuche über das MDT-Modul */
async function personWaehlen(behaelter, begriff) {
try {
const d = await aufruf("mdt", "personSuchen", { begriff });
const treffer = d.treffer || [];
fenster({
titel: "Person auswählen",
inhalt: treffer.length
? `
Die Geldstrafe von ${euro(a.geld_final)} wird eingezogen und
der Staatskasse zugeführt.
🔒
${a.haft_final > 0
? `Die festgelegte Haftdauer von ${haftText(a.haft_final)} wird
vermerkt — eine Einweisung in Gewahrsam erfolgt dadurch nicht.
Das ist ein eigener Schritt.`
: "Es ist keine Haft vorgesehen."}
📄
Der Vorgang wird mit deinem Namen als bestätigend festgehalten.