Drei gezielte Mobile-Verbesserungen nach Nutzer-Feedback:
- Audit-Log (bisher .audit-row Flex-Liste mit festen min-width, auf
Handy unlesbar zusammengequetscht) zu einer echten Tabelle mit
class="tw rtable" umgebaut - erbt automatisch das bestehende Karten-
Akkordeon (nur ein Eintrag offen, Rest kompakt gestapelt)
- Neuer Geburtsdatum-Wheel-Picker (Tag/Monat/Jahr-Spalten mit CSS
scroll-snap, openGebDatumPicker/dwConfirm/dwTriggerLabel) ersetzt
natives <input type=date> gezielt nur bei echten Geburtsdatum-Feldern
(Interview-Wizard, Widerspruch-Generator, Musterbrief) - erspart bei
60-100 Jahre zurückliegenden Daten das endlose Monat-für-Monat-
Zurückklicken, auf PC (Mausrad) wie Touch gleich schnell. Andere
Datumsfelder (Antragsdatum, Bescheiddatum etc.) bleiben nativ, da dort
ein normaler Kalender fuer nahe Termine schneller ist. Default-
Scrollposition ist heute-75 Jahre statt heute.
- Schnellzugriff-Kachel wird auf dem Dashboard unter 560px zur
fixierten Bottom-Bar (Icon-Tab-Leiste) statt Teil des scrollbaren
Bento-Grids zu sein - Hauptaktionen immer ohne Scrollen erreichbar
Verifiziert per Playwright: Wheel-Picker-Interaktion (Scroll per
Mausrad, Bestätigen, korrekter ISO-Wert im hidden Input), Audit-Log-
Karten auf 390px, Sticky-Bar sichtbar+fixiert im Viewport-Screenshot,
Widerspruch/Musterbrief-Trigger inkl. Live-Vorschau-Aktualisierung.
Auf Tablet/Handy sollen die Tabellen-zu-Karten-Ansichten weniger
Scrollen erfordern: jetzt ist immer nur eine Karte aufgeklappt, alle
anderen sind auf eine kompakte Kopfzeile reduziert und stapeln sich
eng darunter.
- Neue rtInit()-Helper-Funktion: erste Zeile startet offen, Klick auf
eine Zeile oeffnet sie und schliesst alle anderen (Klicks auf
verschachtelte Buttons/Links/Inputs/.tl loesen die Akkordeon-Logik
nicht aus, damit Aktionen weiter unabhaengig funktionieren)
- Erste data-label-Zelle pro Tabelle als .rt-head markiert (mit
Chevron-Icon), bleibt immer sichtbar; restliche data-label-Zellen
nur bei .rt-open sichtbar. Zellen ohne data-label (Aktions-Buttons)
bleiben immer erreichbar, auch bei zugeklappter Karte.
- rtInit() nach jedem rtable-Render aufgerufen: pgDash, renderPT
(inkl. Filter-Refresh), pgAufgaben, renderAdminDash, loadPat
- Bugfix unterwegs: Chevron-Icon leckte in die normale Desktop/Tablet-
Tabelle (display:none als Basis ergaenzt, nur im 700px-Breakpoint
sichtbar) - vor dem Fix bei 820px Tablet-Breite als stoerendes Icon
unter jedem Namen sichtbar
Verifiziert per Playwright auf 390px (Handy) und 820px (Tablet):
Standardzustand (erste Karte offen), Wechsel beim Klick auf andere
Karte, saubere Tabelle ohne Akkordeon-Artefakte oberhalb 700px.
Nach Nutzer-Feedback ("immer noch zu klinisch, nicht modern") komplett
neu ausgearbeitet statt der vorherigen warmen CSS-Variablen-Anpassung:
- Neues Glass-Design-System (:root): transluzente Cards/Sidebar/Topbar/
Modal/Login mit backdrop-filter:blur, weicher Mehrfarb-Gradient-
Hintergrund (fixed), --bento-*-Farbverlaufstokens fuer Kachelakzente.
Formularfelder bleiben bewusst blickdicht (Lesbarkeit).
- Dashboard strukturell zum echten Bento-Grid umgebaut: 4 farbige
Stat-Kacheln + grosse Patienten-Kachel + Aufgaben- + Schnellzugriff-
Kachel in einem 4-Spalten-Grid mit EXPLIZITER grid-column/grid-row-
Platzierung (Auto-Placement fuellte die letzte Spalte nicht
zuverlaessig auf, siehe CLAUDE.md-Hinweis)
- Neue .rtable-Technik: Tabellen werden unter 700px zu einzelnen
Glass-Cards (Label ueber Wert via data-label + ::before) statt
zusammengequetschter Spalten - angewendet auf Dashboard-Patienten-
tabelle, Patientenliste, Aufgaben, Admin-Dashboard-Konten,
Patientenakte-Antraege
- Login-Screen im gleichen Look neu gestaltet
Verifiziert: JS-Syntax-Check, Playwright auf Desktop/Tablet/Mobile
fuer praktisch alle Seiten (Dashboard, Patientenliste, Patientendetail,
Aufgaben, Katalog, Kalender, Backend, Admin-Dashboard, Interview-
Wizard, Mein Abo, Login). Dabei einen echten Bug gefunden und behoben:
Auto-Placement im Bento-Grid packte die vierte Kachel nicht neben die
dritte - jetzt mit expliziten grid-column/grid-row-Werten geloest.
Ausserdem: stale Flask-Template-Cache bei debug=False identifiziert
(Server muss nach jeder index.html-Aenderung neu gestartet werden,
sonst testet man einen alten Stand) - in CLAUDE.md dokumentiert.
Responsive & Design:
- Sidebar wird unter 900px zum Off-Canvas-Menue (Hamburger-Button,
Backdrop, Auto-Close bei Navigation) statt fix 228px breit zu bleiben
- Formular-/Statistik-Grids brechen bei 900px/560px auf weniger Spalten
um, Modals gehen unter 560px auf Vollbild, iOS-Zoom-Bug bei
Formularfeldern durch font-size:16px auf Mobile vermieden
- Wärmere Optik ausschliesslich über CSS-Variablen (:root): Creme-
Hintergrund, weichere Akzentfarbe, groessere Radien, neuer
--shadow-Token auf Card/Modal - kein Redesign pro Seite noetig, da
die App durchgehend über diese Variablen themt
Abo-/Zahlungsgeruest (Anbieter voraussichtlich PayPal, noch nicht
angebunden):
- nutzer.abo_bis / abo_typ + globaler Schalter einstellungen.abo_pflicht
(Default AUS) - solange PayPal nicht wirklich läuft, sperrt das Gate
niemanden aus
- _hat_aktiven_zugang() zentral in global_auth_check(): blockiert bei
aktiver Zahlungspflicht ohne gueltiges Abo mit 402 Payment Required,
laesst /api/abo/* und /api/auth/logout immer durch
- POST /api/abo/aktivieren ist bewusst ein 501-Stub bis PayPal echt
angebunden ist - kein vorgetaeuschter Erfolg
- Admin-Dashboard: "Freischalten"-Aktion pro Konto (1-12 Monate,
Pflicht-Begruendung, audit-geloggt) - deckt die geforderte
Moeglichkeit ab, Konten kostenlos freizuschalten
(POST /api/admin/nutzer/<uid>/abo-freischalten)
- Backend-Einstellungen: neue Karte "Abo & Zahlung" fuer Preis und
den abo_pflicht-Schalter
- Frontend: neue Seite "Mein Abo" (pgMeinAbo), aboBlockiert-Flag in
initApp() leitet jede Navigation dorthin um, wenn kein Zugang besteht
Verifiziert: JS-Syntax-Check, Playwright-Screenshots auf Desktop/
Tablet/Mobile (Sidebar-Slide-in, Grid-Umbruch, Interview-Wizard auf
Handy), API-Tests fuer das komplette Abo-Gate (Toggle an/aus, 402,
Freischaltung, Stub-Endpoint, Restore auf sicheren Default).
- Neue Seite admindash (pgAdminDash) mit Kontenuebersicht: Status,
Patientenanzahl, Sperren/Entsperren/Loeschen mit Pflicht-Begruendung
- "Loeschen" ist bewusst Soft-Delete: Konto wird gesperrt (aktiv=0) und
alle aktiven Patienten werden ueber die bestehende Archivierungs-
Logik archiviert (10/30 Jahre Aufbewahrungsfrist, § 630f/§ 199 BGB)
statt physisch geloescht zu werden
- Bestehende Hard-Delete-Route (DELETE /api/nutzer/<uid>) lehnt jetzt
ab, solange das Konto noch Patienten besitzt - schliesst die Luecke
verwaister Patientendatensaetze
- nutzer.aktiv wird bei jedem Request geprueft -> Sperren wirkt sofort,
auch bei bereits offener Sitzung, ohne zusaetzlichen Session-Store
- Neue Tabelle admin_audit_log (unveraenderlich, analog notizen_verlauf):
jede Sperr-/Entsperr-/Loesch-/Export-Aktion mit Admin, Zeitstempel,
Ziel und Pflicht-Begruendung protokolliert
- DSGVO-Export (POST /api/admin/patienten/<pid>/dsgvo-export): admin-only,
verlangt Rechtsgrundlage/Aktenzeichen, liefert ZIP mit allen
Datensaetzen (daten.json) plus Dokumenten/Briefen/Fotos, in-memory
ohne Temp-Dateien
- Selbst-Sperrung/-Loeschung durch den handelnden Admin blockiert
(kein Lockout-Risiko)
- GET /api/nutzer liefert jetzt zusaetzlich patienten_anzahl
Verifiziert: API-Tests fuer alle Guards (Begruendung-Pflicht, Self-Lock-
Block, Hard-Delete-Block bei zugeordneten Patienten, sofortige Session-
Sperrung, 403 fuer Nicht-Admins), ZIP-Inhalt geprueft, Audit-Log-Eintraege
korrekt, Dashboard + Modal per Playwright-Screenshot visuell verifiziert.
Dritter und letzter Baustein aus refactoring.md.
- patienten.nutzer_id (FK -> nutzer.id) als neue Migration in init_db()
- _get_owned_patient(pid) und _scope_sql(column) als zentrale Helper,
auf alle patientenbezogenen Routen angewendet (patienten, antraege,
leistungen, aufgaben, pflegetagebuch, dokumente, kalender, dashboard)
- Admin-Rolle bleibt von der Isolation ausgenommen (sieht weiterhin alle)
- Neue Patienten werden automatisch dem anlegenden Nutzer zugeordnet
- aufgaben ohne patient_id: Erstellung durch Nicht-Admins jetzt
patient_id-pflichtig, damit Lese-/Schreibpfad konsistent bleiben
- Verifiziert per End-to-End-Test mit zwei Nutzerkonten + Admin
Erster Baustein aus refactoring.md; Interview-Flow und Admin-Dashboard
folgen nach Rücksprache (siehe CLAUDE.md).
Fixt außerdem UnicodeEncodeError in start.py (▶-Zeichen crashte auf
Windows-Konsolen mit cp1252-Codepage vor app.run()) durch UTF-8-Zwang
auf stdout/stderr.