Frontend-Komponenten & Benutzeroberfläche
Das SMARTKRIS-Dashboard ist als Single-Page-Application (SPA) innerhalb des Next.js App Routers konzipiert. Es bietet den städtischen Mitarbeitern eine interaktive, kartenbasierte und echtzeitfähige Benutzeroberfläche.
Dieses Kapitel erklärt die zentralen UI-Komponenten aus zwei Perspektiven: der Bedienersicht (Wie nutze ich die Funktion richtig?) und der Entwicklersicht (Wie ist es gebaut und wie kann ich es erweitern?).
1. Zentrales State-Management (DataContext.tsx)
Das gesamte Dashboard wird von einem globalen React Context (DataContext) umschlossen.
-
Wenn eine neue Komponente gebaut wird, sollte sie Stammdaten (Kategorien, Eskalationsstufen, Gebiete) immer über den Hook
const { categories } = useData()beziehen und nicht selbst von der API laden. Auch Mutationen (Erstellen, Bearbeiten, Löschen) sollten bevorzugt über die im Context bereitgestellten Funktionen (z.B.createMessageInState) ausgeführt werden. Diese Funktionen rufen die API (client-api.ts) auf, aktualisieren bei Erfolg sofort den lokalen React-State (verhindert Flimmern/Neuladen der Seite), aktualisieren die Zähler-Statistiken im Hintergrund und feuern eine Toast-Benachrichtigung.
2. Listen-Ansichten (Dashboard, Archiv, Pending)
Die Hauptnavigation teilt sich in verschiedene Ansichten auf (Dashboard.tsx, SituationsComponent.tsx, MessageComponent.tsx, Archive.tsx, Pending.tsx). Alle diese Ansichten nutzen unter der Haube dieselben UI-Konzepte, filtern die Daten aber unterschiedlich.
-
Die Listen sind hierarchisch aufgebaut. Eine Haupt-Lage (Parent) enthält ihre direkten Meldungen und aufklappbar ihre Einsatzschwerpunkte (Children), welche wiederum eigene Meldungen haben. Über die dynamischen Filterleisten (
Header.tsx) kann die Ansicht nach Status, Typ oder Gebiet eingegrenzt werden. * Die Komponenten laden ihre spezifischen Daten überloadData()und berechnen den Hierarchie-Baum im Frontend (groupedItemsmituseMemo). Die HilfsfunktionhydrateTree()sorgt dafür, dass, wenn das Backend z. B. nur eine gefilterte Meldung zurückgibt, das Frontend automatisch die fehlenden Parent-Situationen nachlädt, damit der visuelle Baum im UI nicht zerbricht.
3. Interaktive Karten (react-leaflet)
Karten sind ein zentrales Element von SMARTKRIS und in zwei Hauptbereichen zu finden: als Übersicht (Map.tsx) und als Auswahl-Werkzeug in Formularen (MapSelector.tsx).
-
Auf der großen Karte können Lagen und Feedbacks visuell erfasst werden. Durch Klick auf einen Marker öffnet sich in der rechten Bildschirmhälfte ein Detail-Panel (
MapDetails.tsx) mit allen Informationen und direktem Bearbeitungszugriff. Lagen-Marker zeigen farblich die Eskalationsstufe und das Kategorie-Icon. * Die Basiskarte (BaseMap.tsx) nutzt entweder einen konfigurierten WMS-Tile-Server (NEXT_PUBLIC_TILE_SERVER_URL) oder fällt auf Standard-OpenStreetMap zurück. Marker werden inmapUtils.tsdynamisch als HTML (DivIcon) gerendert. Das erlaubt aufwendige CSS-Animationen (Pulsieren bei Selektion) und die Einbettung externer SVGs über die Proxy-Routen. Die Geometrien der Gebiete (Areas) werden alsGeoJSONaus der Datenbank gelesen und direkt als Polygon-Layer auf die Karte gelegt.
4. Formulardialoge & Vorschau-Modus
Das Erstellen von Lagen (SituationFormModal.tsx) und Meldungen (MessageFormModal.tsx) ist der wichtigste Prozess im System.
Adressen & Koordinaten (Nominatim)
-
Sobald man in das Adressfeld tippt, schlägt das System Adressen in der konfigurierten Stadt vor. Alternativ kann man einen Punkt auf der Karte anklicken.
-
Dies wird über den
AddressInputund denMapSelectorgesteuert. Beide kommunizieren mit der Nominatim-API. Setzt man einen Pin auf der Karte, wird per Reverse-Geocoding automatisch das Adressformular ausgefüllt. Tippt man eine Adresse, verschiebt Forward-Geocoding den Pin.
Live-Vorschau (Preview.tsx)
-
Klickt man oben rechts im Formular auf das Auge-Symbol, teilt sich der Dialog. Man sieht nun exakt, wie der getippte Text später auf der Webseite (Ticker-Ansicht) oder auf dem Smartphone (Push-Benachrichtigung mit Sperrbildschirm-Simulation) aussehen wird.
-
Die Vorschau-Komponente reagiert live auf State-Änderungen des Formulars. Die Mobile-Preview berechnet dynamisch CSS-Gradienten und Schatten basierend auf dem Hex-Code der gewählten Eskalationsstufe, um kritische Warnungen visuell bedrohlicher wirken zu lassen (rotes Glühen).
Autorisierungs-Flow
-
Normalerweise werden erstellte Elemente im Status "Wartend" gespeichert und müssen von einem Vorgesetzten freigegeben werden. Setzt man im Formular den Haken bei "Sofort autorisieren", erscheint ein PIN-Feld. Stimmt der PIN, geht die Meldung sofort live.
-
Der State
authorizeImmediatelyfügt denauthorizationPinzum Payload hinzu und ändert das Ziel-Status-Flag des API-Calls vonPENDING_AUTHORIZATIONaufACTIVE.
5. Card Actions & PIN-Modal (CardActionsMenu.tsx)
Jede Karte (Lage/Meldung) besitzt ein Kontextmenü (Drei-Punkte-Icon) oder direkte Aktions-Buttons (Bearbeiten, Freigeben, Löschen).
-
Bestimmte kritische Aktionen (Freigeben, Archivieren, Löschen) erfordern eine Bestätigung. Es öffnet sich das PIN-Modal (
PinModal.tsx). Erst nach Eingabe der korrekten 4 Ziffern wird die Aktion ausgeführt. -
Das
CardActionsMenukapselt diese Logik vollständig. Es entscheidet anhand des aktuellenview-Prop (pending,active,archive), welche Buttons gerendert werden. Wird eine kritische Aktion geklickt, wird deractionStategesetzt, dasPinModalöffnet sich, und beim CallbackhandlePinConfirmwird der API-Aufruf mit dem PIN abgesetzt.
6. Feedback-Kanban-Board (FeedbackComponent.tsx)
-
Bürger-Rückmeldungen landen in einem Kanban-Board. Spalten repräsentieren den Bearbeitungsstatus (z. B. "Neu", "In Bearbeitung"). Feedbacks können per Drag & Drop von einer Spalte in die andere gezogen werden. Mit Klick auf "Antworten" kann ein Dialog mit dem Bürger gestartet werden.
-
Die Komponente nutzt die native HTML5 Drag & Drop API (
draggable,onDragStart,onDrop). Beim Loslassen (handleDrop) wird die Ziel-Spalten-ID ausgelesen und sofort der API-CallhandleStatusChangeausgelöst, um das Backend zu aktualisieren.
7. Audit-Log Viewer (AuditLogComponent.tsx)
-
In dieser Ansicht lässt sich forensisch nachvollziehen, wer wann was geändert hat. Ein Klick auf einen Eintrag öffnet die Details.
-
Die Komponente
AuditLogCard.tsxberechnet visuelle Diffs. Sie vergleichtoldStateundnewStatedes Backends. Geänderte Felder werden farblich hervorgehoben (rot für alt, grün für neu). Besonders wichtig: Das Frontend prüft das FlagisCompromised. Ist diestrue(Signatur in der Datenbank fehlerhaft), rendert das UI eine prominente rote Sicherheitswarnung, dass dieser Datensatz potenziell manipuliert wurde.
8. Entwickler-Hinweis: Neue Komponenten hinzufügen
Um das System um neue Stammdaten zu erweitern, sind folgende Schritte im Frontend nötig:
1. Types: Die Interfaces in types/index.ts ergänzen.
2. Client-API: Die CRUD-Funktionen in lib/client-api.ts hinzufügen.
3. BFF-Routen: Entsprechende Route-Handler in app/api/… anlegen.
4. Context: Den State und die Mutationsfunktionen im DataContext.tsx registrieren.
5. Settings: In der SettingsComponent.tsx das Mapping im entityConfig-Objekt hinzufügen – das UI generiert die dazugehörige Verwaltungstabelle und das Edit-Modal danach weitgehend generisch.