/* =====================================================================
aether-police / Ansicht: MDT
Drei Reiter: Personen, Fahrzeuge, Akten.
Die Ansicht zeigt und dokumentiert — sie bewertet nichts und löst
keine Maßnahme aus. Jede Änderung verlangt eine Bestätigung.
===================================================================== */
"use strict";
(() => {
const { sicher, zeit, aufruf, meldung, fenster, bestaetigen, $, anClient } = App;
/* Zustand der Ansicht */
const z = {
reiter: "personen", // personen | fahrzeuge | akten
suche: "",
treffer: [],
offenePerson: null, // geladene Personenakte
offenesFahrzeug: null,
offeneAkte: null,
akteFilter: { typ: "", status: "" },
stammdaten: null, // Aktenarten, Beteiligtenrollen
};
/* ---- kleine Bausteine ------------------------------------------- */
const gefahrText = ["keine", "gering", "erhöht", "hoch"];
/** Marke für die Gefahrenstufe einer Person */
function gefahrMarke(stufe) {
const s = Number(stufe) || 0;
if (s === 0) return "";
const art = s >= 3 ? "kritisch" : s === 2 ? "warn" : "neutral";
return `Gefahr: ${gefahrText[s]} `;
}
function reiterLeiste() {
const reiter = [
{ id: "personen", name: "Personen", symbol: "👤" },
{ id: "fahrzeuge", name: "Fahrzeuge", symbol: "🚗" },
{ id: "akten", name: "Akten", symbol: "🗂" },
];
return `
${reiter.map((r) =>
`
${r.symbol} ${r.name}
`).join("")}
`;
}
/* =====================================================================
PERSONEN
===================================================================== */
function personenTrefferListe() {
if (!z.treffer.length) {
return `${z.suche ? "Keine Treffer." : "Suchbegriff eingeben — Name, Geburtsdatum oder Telefonnummer."}
`;
}
return `${z.treffer.map((p) =>
`
${sicher(p.firstname + " " + p.lastname)}
${p.fahndung > 0 ? 'Fahndung ' : ""}
${gefahrMarke(p.gefahrenstufe)}
geb. ${sicher(String(p.dob || "").slice(0, 10))}
${p.telefon ? " · ☎ " + sicher(p.telefon) : ""}
${p.job ? " · " + sicher(p.job) : ""}
Akte öffnen
`).join("")}
`;
}
/** Zeichnet eine vollständige Personenakte */
function personenAkte(d) {
const p = d.person;
const lizenzName = {
perso: "Personalausweis", fs: "Führerschein", ws: "Waffenschein",
gk: "Gesundheitskarte", vk: "Visitenkarte",
};
return `
${p.lichtbild
? `
`
: `
Kein Lichtbild `}
${sicher(p.firstname + " " + p.lastname)}
Geboren ${sicher(String(p.dob || "").slice(0, 10))}
Geschlecht ${sicher(p.gender || "—")}
Herkunft ${sicher(p.nationality || "—")}
Beruf ${sicher(p.job || "—")}
Telefon ${sicher(d.telefon || "—")}
Fingerabdruck ${sicher(p.fingerabdruck || "nicht erfasst")}
DNA ${sicher(p.dna || "nicht erfasst")}
+ Notiz
⚠ Warnhinweis
🔬 ED-Daten
🗂 Akte anlegen
${p.warnhinweis ? `
⚠
Warnhinweis: ${sicher(p.warnhinweis)} — Gefahrenstufe ${gefahrText[Number(p.gefahrenstufe) || 0]}
` : ""}
${d.fahndung ? `
🔍
Zur Fahndung ausgeschrieben: ${sicher(d.fahndung.grund)}
(${sicher(d.fahndung.gefahr)})
` : ""}
${d.gewahrsam ? `
🔒
In Gewahrsam — ${sicher(d.gewahrsam.grund || "ohne Grundangabe")};
Frist ${Number(d.gewahrsam.rest) <= 0 ? "abgelaufen" : "noch " + d.gewahrsam.rest + " Minuten"}.
Eine Entlassung entscheidet ein Beamter.
` : ""}
Dokumente & Lizenzen
${d.lizenzen.length ? `
${d.lizenzen.map((l) =>
`
${sicher(lizenzName[l.typ] || l.typ)}
${l.nummer ? sicher(l.nummer) : "—"}
${l.klassen ? " · Klassen " + sicher(l.klassen.join(", ")) : ""}
${l.gueltigBis ? " · gültig bis " + sicher(l.gueltigBis) : ""}
${l.entzogen ? "entzogen" : l.gueltig ? "gültig" : "abgelaufen"}
`).join("")}
`
: `
Keine Dokumente hinterlegt.
`}
Bekannte Fahrzeuge
${d.fahrzeuge.length ? `
${d.fahrzeuge.map((f) =>
`
${sicher(f.name || f.model)}
${f.fahndung > 0 ? 'Fahndung ' : ""}
${sicher(f.plate)} · ${sicher(f.state === "impound" ? "sichergestellt" : f.state === "out" ? "unterwegs" : "eingeparkt")}
`).join("")}
`
: `
Keine Fahrzeuge zugeordnet.
`}
Vorgänge & Anzeigen
${d.anzeigen.length}
${d.anzeigen.length ? `
${d.anzeigen.map((a) =>
`
${sicher((a.delikte || []).map((x) => x.name).join(", ") || "Anzeige")}
${zeit(a.erstellt_am)}
${a.status === "bestaetigt" ? ` · ${a.haft_final} Min · ${App.euro(a.geld_final)}` : ""}
${sicher(a.status)}
`).join("")}
`
: `
Keine Vorgänge erfasst.
`}
Verknüpfte Akten
${d.akten.length ? `
${d.akten.map((a) =>
`
${sicher(a.titel)}
${sicher(a.aktenzeichen)} · ${sicher(a.typ)}
${a.rolle ? " · " + sicher(a.rolle) : ""}
${sicher(a.status)}
`).join("")}
`
: `
Keine Akten verknüpft.
`}
Bekannte Kontakte
${d.kontakte.length ? `
${d.kontakte.map((k) =>
`
${sicher(k.name)}
☎ ${sicher(k.number)}
${k.charakterId ? '
bekannt ' : ""}
`).join("")}
`
: `
Keine Kontakte bekannt.
`}
Notizen
${d.notizen.length}
${d.notizen.length ? `
${d.notizen.map((n) =>
`
${sicher(n.text)}
${sicher((n.firstname || "") + " " + (n.lastname || ""))} · ${zeit(n.am)}
✕
`).join("")}
`
: `
Keine Notizen.
`}
`;
}
/* ---- Aktionen an der Personenakte -------------------------------- */
function verdrahtePersonenakte(behaelter, charakterId) {
// Notiz hinzufügen
const notizKnopf = $("p-notiz");
if (notizKnopf) notizKnopf.addEventListener("click", () => {
fenster({
titel: "Notiz hinzufügen",
inhalt: `
Vermerk
Notizen sind für alle Beamten sichtbar und werden protokolliert.
`,
knoepfe: [
{ text: "Abbrechen", klick: (_, zu) => zu() },
{ text: "Speichern", art: "", klick: async (el, zu) => {
const text = el.querySelector("#nz-text").value.trim();
if (text.length < 3) { meldung("Bitte einen Text eingeben.", "fehler"); return; }
try {
await aufruf("mdt", "personNotiz", { charakterId, text });
zu(); meldung("Notiz gespeichert.", "gut");
oeffnePerson(behaelter, charakterId);
} catch (f) { meldung(f.message, "fehler"); }
}},
],
});
});
// Notiz entfernen
behaelter.querySelectorAll("[data-notiz-weg]").forEach((b) => {
b.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await aufruf("mdt", "personNotizLoeschen", { id: +b.dataset.notizWeg });
oeffnePerson(behaelter, charakterId);
} catch (f) { meldung(f.message, "fehler"); }
});
});
// Warnhinweis setzen
const warnKnopf = $("p-warn");
if (warnKnopf) warnKnopf.addEventListener("click", () => {
const p = z.offenePerson.person;
bestaetigen({
titel: "Warnhinweis festlegen",
inhalt: `
Hinweis (leer = entfernen)
Gefahrenstufe
${[0, 1, 2, 3].map((s) =>
`${s} — ${gefahrText[s]} `
).join("")}
Begründung
`,
bestaetigenText: "Warnhinweis setzen",
bestaetigt: async (el, zu) => {
try {
await aufruf("mdt", "personWarnhinweis", {
charakterId,
hinweis: el.querySelector("#wh-text").value.trim(),
stufe: +el.querySelector("#wh-stufe").value,
grund: el.querySelector("#wh-grund").value.trim(),
});
zu(); meldung("Warnhinweis aktualisiert.", "gut");
oeffnePerson(behaelter, charakterId);
} catch (f) { meldung(f.message, "fehler"); }
},
});
});
// Erkennungsdienstliche Daten
const edKnopf = $("p-ed");
if (edKnopf) edKnopf.addEventListener("click", () => {
const p = z.offenePerson.person;
fenster({
titel: "Erkennungsdienstliche Daten",
inhalt: `
Fingerabdruck-Kennung
DNA-Kennung
`,
knoepfe: [
{ text: "Abbrechen", klick: (_, zu) => zu() },
{ text: "Speichern", klick: async (el, zu) => {
try {
await aufruf("mdt", "personStammdaten", {
charakterId,
fingerabdruck: el.querySelector("#ed-finger").value.trim(),
dna: el.querySelector("#ed-dna").value.trim(),
lichtbild: el.querySelector("#ed-bild").value.trim(),
});
zu(); meldung("Daten gespeichert.", "gut");
oeffnePerson(behaelter, charakterId);
} catch (f) { meldung(f.message, "fehler"); }
}},
],
});
});
// Akte direkt zu dieser Person anlegen
const akteKnopf = $("p-akte-neu");
if (akteKnopf) akteKnopf.addEventListener("click", () =>
akteAnlegenDialog(behaelter, { typ: "person", id: charakterId }));
// Sprünge in andere Akten
behaelter.querySelectorAll("[data-akte]").forEach((el) =>
el.addEventListener("click", () => { z.reiter = "akten"; oeffneAkte(behaelter, +el.dataset.akte); }));
behaelter.querySelectorAll("[data-fahrzeug]").forEach((el) =>
el.addEventListener("click", () => { z.reiter = "fahrzeuge"; oeffneFahrzeug(behaelter, el.dataset.fahrzeug); }));
behaelter.querySelectorAll("[data-person]").forEach((el) =>
el.addEventListener("click", () => oeffnePerson(behaelter, +el.dataset.person)));
}
async function oeffnePerson(behaelter, charakterId) {
try {
const daten = await aufruf("mdt", "personAkte", { charakterId });
z.offenePerson = daten;
z.reiter = "personen";
zeichne(behaelter, personenAkte(daten), () => verdrahtePersonenakte(behaelter, charakterId), true);
} catch (f) { meldung(f.message, "fehler"); }
}
/* =====================================================================
FAHRZEUGE
===================================================================== */
function fahrzeugTrefferListe() {
if (!z.treffer.length) {
return `${z.suche ? "Keine Treffer." : "Kennzeichen, Modell oder Halter eingeben."}
`;
}
return `${z.treffer.map((f) =>
`
${sicher(f.plate)}
${sicher(f.name || f.model)}
${f.fahndung > 0 ? 'Fahndung ' : ""}
${f.state === "impound" ? 'sichergestellt ' : ""}
Halter: ${sicher((f.firstname || "unbekannt") + " " + (f.lastname || ""))}
Details
`).join("")}
`;
}
function fahrzeugAkte(d) {
const f = d.fahrzeug;
const zustandText = { in: "eingeparkt", out: "unterwegs", impound: "sichergestellt" };
return `
${sicher(f.plate)}
${sicher(f.name || f.model)}
Modell ${sicher(f.model)}
Klasse ${sicher(f.klasse || "—")}
Farbe ${f.farbe ? ` ${sicher(f.farbe)}` : "—"}
Status ${sicher(zustandText[f.state] || f.state)}
Standort ${sicher(f.garage || "—")}
Kilometerstand ${sicher(f.mileage || 0)} km
${f.owner ? `👤 Halterakte ` : ""}
🗂 Akte anlegen
${d.fahndung ? `
🔍
Fahrzeug zur Fahndung ausgeschrieben: ${sicher(d.fahndung.grund)}
` : ""}
Halter
${f.owner ? `
${sicher((f.firstname || "") + " " + (f.lastname || ""))}
geb. ${sicher(String(f.dob || "").slice(0, 10))}
Akte öffnen
`
: `
Kein Halter eingetragen.
`}
Verknüpfte Akten
${d.akten.length ? `
${d.akten.map((a) =>
`
${sicher(a.titel)}
${sicher(a.aktenzeichen)} · ${sicher(a.typ)}
`).join("")}
`
: `
Keine Akten verknüpft.
`}
Historie
${d.historie.length ? `
${d.historie.map((h) =>
`
${sicher(h.aktion)}
${sicher((h.firstname || "") + " " + (h.lastname || ""))}
${h.dienstnummer ? " · " + sicher(h.dienstnummer) : ""} · ${zeit(h.am)}
${h.grund ? " · " + sicher(h.grund) : ""}
`).join("")}
`
: `
Keine dokumentierten Vorgänge.
`}
`;
}
async function oeffneFahrzeug(behaelter, kennzeichen) {
try {
const daten = await aufruf("mdt", "fahrzeugAkte", { kennzeichen });
z.offenesFahrzeug = daten;
z.reiter = "fahrzeuge";
zeichne(behaelter, fahrzeugAkte(daten), () => {
behaelter.querySelectorAll("[data-person]").forEach((el) =>
el.addEventListener("click", () => oeffnePerson(behaelter, +el.dataset.person)));
behaelter.querySelectorAll("[data-akte]").forEach((el) =>
el.addEventListener("click", () => oeffneAkte(behaelter, +el.dataset.akte)));
const neu = $("v-akte-neu");
if (neu) neu.addEventListener("click", () =>
akteAnlegenDialog(behaelter, { typ: "fahrzeug", id: daten.fahrzeug.plate }));
}, true);
} catch (f) { meldung(f.message, "fehler"); }
}
/* =====================================================================
AKTEN
===================================================================== */
function aktenListe(akten) {
if (!akten.length) return `Keine Akten gefunden.
`;
const statusArt = { offen: "warn", pruefung: "info", geschlossen: "neutral" };
return `${akten.map((a) =>
`
${sicher(a.typ)}
${sicher(a.titel)}
${sicher(a.aktenzeichen)} ·
${sicher((a.firstname || "") + " " + (a.lastname || ""))} · ${zeit(a.erstellt_am)}
${a.version > 1 ? ` · Version ${a.version}` : ""}
${sicher(a.status)}
`).join("")}
`;
}
function akteAnsicht(d) {
const a = d.akte;
const statusArt = { offen: "warn", pruefung: "info", geschlossen: "neutral" };
return `
${sicher(a.titel)}
Aktenzeichen ${sicher(a.aktenzeichen)}
Art ${sicher(a.typ)}
Angelegt von ${sicher((a.firstname || "") + " " + (a.lastname || ""))}
Angelegt am ${zeit(a.erstellt_am)}
Version ${sicher(a.version)}
${sicher(a.status)}
${d.darfBearbeiten ? `✎ Bearbeiten ` : ""}
${d.darfBearbeiten ? `🔗 Verknüpfen ` : ""}
${d.darfSchliessen && a.status !== "geschlossen"
? `Akte schließen ` : ""}
Sachverhalt
${a.inhalt ? sicher(a.inhalt).replace(/\n/g, " ") : "Kein Inhalt hinterlegt. "}
Verknüpfungen
${d.verknuepfungen.length}
${d.verknuepfungen.length ? `
${d.verknuepfungen.map((v) =>
`
${sicher(v.typ)}
${sicher(v.bezeichnung || v.ziel_id)}
${v.rolle ? `
${sicher(v.rolle)}
` : ""}
${d.darfBearbeiten ? `
✕ ` : ""}
`).join("")}
`
: `
Nichts verknüpft.
`}
Änderungshistorie
${d.versionen.length ? `
${d.versionen.map((v) =>
`
v${sicher(v.version)}
${sicher(v.grund || "ohne Angabe")}
${sicher((v.firstname || "") + " " + (v.lastname || ""))} · ${zeit(v.geaendert_am)}
`).join("")}
`
: `
Keine Änderungen.
`}
`;
}
async function oeffneAkte(behaelter, akteId) {
try {
const daten = await aufruf("mdt", "akteOeffnen", { id: akteId });
z.offeneAkte = daten;
z.reiter = "akten";
zeichne(behaelter, akteAnsicht(daten), () => verdrahteAkte(behaelter, daten), true);
} catch (f) { meldung(f.message, "fehler"); }
}
function verdrahteAkte(behaelter, d) {
const a = d.akte;
const bearbeiten = $("a-bearbeiten");
if (bearbeiten) bearbeiten.addEventListener("click", () => {
fenster({
titel: "Akte bearbeiten",
inhalt: `
Titel
Sachverhalt
`,
knoepfe: [
{ text: "Abbrechen", klick: (_, zu) => zu() },
{ text: "Speichern", klick: async (el, zu) => {
try {
await aufruf("mdt", "akteBearbeiten", {
id: a.id,
titel: el.querySelector("#ab-titel").value.trim(),
inhalt: el.querySelector("#ab-inhalt").value,
grund: el.querySelector("#ab-grund").value.trim(),
});
zu(); meldung("Akte gespeichert.", "gut");
oeffneAkte(behaelter, a.id);
} catch (f) { meldung(f.message, "fehler"); }
}},
],
});
});
const verknuepfen = $("a-verknuepfen");
if (verknuepfen) verknuepfen.addEventListener("click", () => {
const rollen = (z.stammdaten && z.stammdaten.rollen) || [];
fenster({
titel: "Verknüpfung hinzufügen",
inhalt: `
Art
Person (Charakter-ID)
Fahrzeug (Kennzeichen)
Beweis (Kennung)
Einsatz (Nummer)
Kennung
Beteiligung
— keine Angabe —
${rollen.map((r) => `${sicher(r.name)} `).join("")}
`,
knoepfe: [
{ text: "Abbrechen", klick: (_, zu) => zu() },
{ text: "Verknüpfen", klick: async (el, zu) => {
try {
await aufruf("mdt", "akteVerknuepfen", {
akteId: a.id,
typ: el.querySelector("#vk-typ").value,
zielId: el.querySelector("#vk-ziel").value.trim(),
rolle: el.querySelector("#vk-rolle").value || null,
});
zu(); meldung("Verknüpfung angelegt.", "gut");
oeffneAkte(behaelter, a.id);
} catch (f) { meldung(f.message, "fehler"); }
}},
],
});
});
behaelter.querySelectorAll("[data-vk-weg]").forEach((b) =>
b.addEventListener("click", async () => {
try {
await aufruf("mdt", "akteVerknuepfungLoesen", { id: +b.dataset.vkWeg });
oeffneAkte(behaelter, a.id);
} catch (f) { meldung(f.message, "fehler"); }
}));
const schliessen = $("a-schliessen");
if (schliessen) schliessen.addEventListener("click", () => {
bestaetigen({
titel: "Akte schließen",
gefahr: true,
inhalt: `
Die Akte ${sicher(a.aktenzeichen)} wird als abgeschlossen gekennzeichnet.
Es wird festgehalten, dass du diese Entscheidung getroffen hast.
Grund
`,
bestaetigenText: "Akte schließen",
bestaetigt: async (el, zu) => {
try {
await aufruf("mdt", "akteStatus", {
id: a.id, status: "geschlossen",
grund: el.querySelector("#as-grund").value.trim(),
});
zu(); meldung("Akte geschlossen.", "gut");
oeffneAkte(behaelter, a.id);
} catch (f) { meldung(f.message, "fehler"); }
},
});
});
behaelter.querySelectorAll("[data-person]").forEach((el) =>
el.addEventListener("click", () => oeffnePerson(behaelter, +el.dataset.person)));
behaelter.querySelectorAll("[data-fahrzeug]").forEach((el) =>
el.addEventListener("click", () => oeffneFahrzeug(behaelter, el.dataset.fahrzeug)));
}
/** Dialog zum Anlegen einer Akte, optional gleich verknüpft */
function akteAnlegenDialog(behaelter, verknuepfung) {
const arten = (z.stammdaten && z.stammdaten.aktenarten) || [];
const rollen = (z.stammdaten && z.stammdaten.rollen) || [];
fenster({
titel: "Akte anlegen",
inhalt: `
Aktenart
${arten.map((a) => `${sicher(a.name)} `).join("")}
Titel
Sachverhalt
${verknuepfung ? `
Beteiligung der verknüpften ${verknuepfung.typ === "person" ? "Person" : "Sache"}
— keine Angabe —
${rollen.map((r) => `${sicher(r.name)} `).join("")}
` : ""}`,
knoepfe: [
{ text: "Abbrechen", klick: (_, zu) => zu() },
{ text: "Akte anlegen", klick: async (el, zu) => {
try {
const ergebnis = await aufruf("mdt", "akteErstellen", {
typ: el.querySelector("#an-typ").value,
titel: el.querySelector("#an-titel").value.trim(),
inhalt: el.querySelector("#an-inhalt").value,
verknuepfeTyp: verknuepfung && verknuepfung.typ,
verknuepfeId: verknuepfung && verknuepfung.id,
verknuepfeRolle: verknuepfung ? (el.querySelector("#an-rolle") || {}).value : null,
});
zu();
meldung("Akte " + ergebnis.aktenzeichen + " angelegt.", "gut");
oeffneAkte(behaelter, ergebnis.id);
} catch (f) { meldung(f.message, "fehler"); }
}},
],
});
}
/* =====================================================================
Gerüst
===================================================================== */
/**
* Zeichnet den MDT-Rahmen mit Inhalt.
* @param {boolean} detail Wenn true, wird ein Zurück-Knopf gezeigt.
*/
function zeichne(behaelter, inhalt, nachher, detail) {
const suchfeld = {
personen: "Name, Geburtsdatum oder Telefonnummer …",
fahrzeuge: "Kennzeichen, Modell oder Halter …",
akten: "Aktenzeichen oder Titel …",
}[z.reiter];
behaelter.innerHTML = `
MDT Personen, Fahrzeuge und Akten
${z.reiter === "akten"
? `
+ Neue Akte ` : ""}
${reiterLeiste()}
${detail
? `‹ Zurück zur Suche `
: `
Suchen
${z.reiter === "akten" ? `
Alle Arten
${((z.stammdaten && z.stammdaten.aktenarten) || []).map((a) =>
`${sicher(a.name)} `).join("")}
Alle Status
Offen
In Prüfung
Geschlossen
` : ""}
`}
${inhalt}
`;
// Reiter wechseln
behaelter.querySelectorAll("[data-reiter]").forEach((b) =>
b.addEventListener("click", () => {
z.reiter = b.dataset.reiter;
z.suche = ""; z.treffer = [];
rendern(behaelter);
}));
const zurueck = $("mdt-zurueck");
if (zurueck) zurueck.addEventListener("click", () => rendern(behaelter));
const neueAkte = $("mdt-akte-neu");
if (neueAkte) neueAkte.addEventListener("click", () => akteAnlegenDialog(behaelter, null));
// Suche
const suchfeldEl = $("mdt-suche");
if (suchfeldEl) {
const suchen = () => { z.suche = suchfeldEl.value.trim(); ausfuehrenSuche(behaelter); };
suchfeldEl.addEventListener("keydown", (e) => { if (e.key === "Enter") suchen(); });
$("mdt-suchen").addEventListener("click", suchen);
}
["mdt-filter-typ", "mdt-filter-status"].forEach((id) => {
const el = $(id);
if (el) el.addEventListener("change", () => {
z.akteFilter.typ = ($("mdt-filter-typ") || {}).value || "";
z.akteFilter.status = ($("mdt-filter-status") || {}).value || "";
ausfuehrenSuche(behaelter);
});
});
if (nachher) nachher();
}
/** Führt die Suche des aktiven Reiters aus */
async function ausfuehrenSuche(behaelter) {
try {
if (z.reiter === "personen") {
if (!z.suche) { z.treffer = []; zeichne(behaelter, personenTrefferListe(), () => verdrahteTreffer(behaelter)); return; }
const d = await aufruf("mdt", "personSuchen", { begriff: z.suche });
z.treffer = d.treffer;
zeichne(behaelter, personenTrefferListe(), () => verdrahteTreffer(behaelter));
} else if (z.reiter === "fahrzeuge") {
if (!z.suche) { z.treffer = []; zeichne(behaelter, fahrzeugTrefferListe(), () => verdrahteTreffer(behaelter)); return; }
const d = await aufruf("mdt", "fahrzeugSuchen", { begriff: z.suche });
z.treffer = d.treffer;
zeichne(behaelter, fahrzeugTrefferListe(), () => verdrahteTreffer(behaelter));
} else {
const d = await aufruf("mdt", "aktenListe", {
begriff: z.suche, typ: z.akteFilter.typ, status: z.akteFilter.status,
});
zeichne(behaelter, aktenListe(d.akten), () => verdrahteTreffer(behaelter));
}
} catch (f) { meldung(f.message, "fehler"); }
}
function verdrahteTreffer(behaelter) {
behaelter.querySelectorAll("[data-person]").forEach((el) =>
el.addEventListener("click", () => oeffnePerson(behaelter, +el.dataset.person)));
behaelter.querySelectorAll("[data-fahrzeug]").forEach((el) =>
el.addEventListener("click", () => oeffneFahrzeug(behaelter, el.dataset.fahrzeug)));
behaelter.querySelectorAll("[data-akte]").forEach((el) =>
el.addEventListener("click", () => oeffneAkte(behaelter, +el.dataset.akte)));
}
async function rendern(behaelter) {
// Stammdaten einmalig holen (Aktenarten, Beteiligtenrollen)
if (!z.stammdaten) {
try { z.stammdaten = await aufruf("mdt", "stammdaten", {}); } catch (f) { z.stammdaten = {}; }
}
/* Sprungziel eines anderen Moduls auswerten, z. B. aus einer Fahndung.
Es gilt nur einmal und wird danach verworfen. */
const ziel = App.zustand.modulZiel;
if (ziel) {
App.zustand.modulZiel = null;
if (ziel.person) { await oeffnePerson(behaelter, +ziel.person); return; }
if (ziel.fahrzeug) { await oeffneFahrzeug(behaelter, ziel.fahrzeug); return; }
if (ziel.akte) { await oeffneAkte(behaelter, +ziel.akte); return; }
}
await ausfuehrenSuche(behaelter);
}
/* ---- Registrierung ----------------------------------------------- */
App.registriereAnsicht("mdt", { rendern });
/* Globale Suche bedienen */
App.registriereSuche(async (begriff) => {
const treffer = [];
try {
const personen = await aufruf("mdt", "personSuchen", { begriff });
(personen.treffer || []).slice(0, 5).forEach((p) => treffer.push({
bereich: "Person", titel: p.firstname + " " + p.lastname,
unter: "geb. " + String(p.dob || "").slice(0, 10),
}));
} catch (e) { /* Bereich überspringen */ }
try {
const fahrzeuge = await aufruf("mdt", "fahrzeugSuchen", { begriff });
(fahrzeuge.treffer || []).slice(0, 5).forEach((f) => treffer.push({
bereich: "Fahrzeug", titel: f.plate + " · " + (f.name || f.model),
unter: "Halter: " + ((f.firstname || "unbekannt") + " " + (f.lastname || "")),
}));
} catch (e) { /* Bereich überspringen */ }
try {
const akten = await aufruf("mdt", "aktenListe", { begriff });
(akten.akten || []).slice(0, 5).forEach((a) => treffer.push({
bereich: "Akte", titel: a.titel, unter: a.aktenzeichen + " · " + a.typ,
}));
} catch (e) { /* Bereich überspringen */ }
return treffer;
});
})();