# 2026-10-31

## SwimMonitor-Oberfläche 2.0

**Was:** Alle beauftragten SwimMonitor-Seiten und ihre Unterseiten nutzen das neue Layout `templates/swimmonitor/base.html.twig` im Messgeräte-Stil (hell, dunkel, automatisch): `/api-data`, `/container/{id}`, `/admin/user` mit Anlegen und Bearbeiten, `/admin/settings`, `/changelog`, `/admin/todo`, `/admin/inspection-templates`, `/admin/lilian-labs` (Übersicht, Konfiguration, Messwerte), `/admin/water-comparison` (mit Details), `/calendar` (alle Container und `/calendar/container/{id}`), `/admin/appointment-types`, `/signage` mit allen Unterseiten, `/appointments/privacy`, `/appointments/imprint`. Das Menü zeigt nur noch diese Bereiche. Lilian Labs steht unter „Wasser“.

**Warum:** Auftrag des Nutzers: einheitlicher, moderner Stil ohne „KI-Look“, kein Inline-CSS, kein Inline-JavaScript, kein CDN. Nicht genannte Seiten bleiben unverändert und unter ihrer URL erreichbar, nur die Menülinks sind weg.

**Festlegungen:**
- Regeln, Tokens und Bausteine stehen in `docs/SWIMMONITOR-STYLE.md` (Kopie im Branding-Ordner `branding/swimmonitor-style/`).
- Verhalten über `data-*`-Attribute und Dateien unter `public/js/pages/`; URLs mit ID als `__ID__`-Platzhalter. Frei gewählte Farben (Terminarten, To-Do-Tags) über `data-sm-color`, Breiten und Positionen über `data-sm-width`/`-left`/`-grow`; beides setzt `swimmonitor.js` per CSSOM, das bleibt mit `style-src 'self'` erlaubt.
- Bibliotheken lokal: Bootstrap 5.3.3, Font Awesome 6.7.2, Leaflet 1.9.4, FullCalendar 5.11.3, Chart.js 4.4.0. SortableJS (CDN) im Vorlagen-Editor durch natives Drag-and-drop ersetzt.
- Signage behält seine Bausteine `.sg-*` in `public/css/admin/signage.css`. Deren Variablen zeigen jetzt auf die `--sm-*`-Tokens; Farbverläufe, Pillen und Schatten sind entfernt. Die Bereichsnavigation steht als Tabs im Seitenkopf.
- Changelog-Inhalt kommt aus `config/swimmonitor/changelog.yaml`, Release 2.0.0 beschreibt diesen Umbau.
- `privacy_content.html.twig` binden auch die Buchungsseiten ein; die Datei ist unverändert, die Anpassung läuft über `.sm-legal`.

**Nebenbei behoben:**
- Termine wurden beim Verschieben als UTC gespeichert (`toISOString`) und lagen dann daneben; jetzt Ortszeit (Kalender und Container-Seite).
- Der Container-Kalender zeigte einen festen Beispieltermin statt der echten Termine.
- Lilian-Labs-Synchronisierung nutzte fest 30 Tage statt des eingestellten Zeitraums; die Messwert-Anzahl ignorierte den Standortfilter; ein abgelaufener Token stand mit negativen Tagen da; der Token stand offen im Formular.
- Die Fehlerantwort des Wasservergleichs enthielt einen Stacktrace.
- Terminarten ließen sich per GET-Link ohne CSRF-Schutz löschen; jetzt POST mit Token.
- Prüfungsliste lieferte bei Prüfungen ohne Durchführung eine PHP-Warnung statt JSON; `isOnline` liegt jetzt im `ContainerApiService`.
- Signage-Karten in Rastern standen versetzt (`.sg-card + .sg-card` setzte auch dort einen oberen Abstand).
- Entfernt: Platzhalter-Tabs „Diagnosen“ und „Anlagenkataster“ auf der Container-Seite sowie die nicht mehr genutzten `public/js/container/show.js` und `anlagendaten.js`.

**Auffällig, nicht geändert:**
- `/calendar` ist in `security.yaml` öffentlich, die Termin-API verlangt `ROLE_USER`. Ohne Anmeldung zeigt die Seite jetzt einen Hinweis statt eines scheinbar leeren, bearbeitbaren Kalenders.
- Lilian-Labs-Token abgelaufen, letzte Synchronisierung 18.04.2026. Die Labordaten enthalten Ausreißer (pH und Chlor mit 1000).
- Der Wasservergleich über 365 Tage braucht etwa 25 s.

**Geänderte Dateien (Auswahl):** `templates/swimmonitor/*`, `templates/base.html.twig` (nur Menü), die Templates der genannten Seiten, `templates/signage/**`, `templates/privacy.html.twig`, `templates/imprint.html.twig`, `public/css/swimmonitor.css`, `public/css/admin/signage.css`, `public/css/admin/inspection-templates.css`, `public/js/swimmonitor.js`, `public/js/pages/*.js`, `public/js/admin/inspection-templates.js`, `public/js/admin/signage-media.js`, `src/Twig/SwimMonitorExtension.php`, `src/Controller/{Changelog,Calendar,Container,Api}Controller.php`, `src/Controller/Admin/{AppointmentType,LilianLabs,WaterDataComparison}Controller.php`, `src/Controller/Api/ContainerInspectionController.php`, `src/Service/ContainerApiService.php`, `config/swimmonitor/changelog.yaml`. Die offenen Signage-Änderungen vom 30.10. (Browser-Wiedergabe) sind mitgeführt; in `templates/signage/device/show.html.twig` wurden nur `style=`-Attribute ersetzt und FullCalendar lokal eingebunden.

**Prüfung:** Alle betroffenen Seiten über einen lokalen Vorschau-Server gerendert und das ausgelieferte HTML auf `style=`, `on…=`, Inline-`<script>`/`<style>` und externe Quellen geprüft: ohne Befund (die Symfony-Debug-Toolbar im Dev-Modus ausgenommen). Eingebundene Skripte auf erzeugte `style=`/`on…`-Attribute und externe URLs geprüft. Screenshots hell und dunkel, 390 px ohne horizontalen Überlauf. `lint:twig`, `lint:yaml`, `php -l`, `node --check`. Im Browser geprüft: Kalender lädt die echten Termine, Termin-Modal, Icon-Auswahl der Terminarten, Vorschau-Modal der Inspektionsvorlagen, Signage-Zeitplan mit FullCalendar. Datenverändernde Aktionen wurden bewusst nicht ausgeführt. Nichts committet, nichts deployt.
