Commit Graph
204 Commits
Author SHA1 Message Date
patrickandClaude Sonnet 5 069a1ee7ee feat(dokumente): DOC-002 feste Dokumenttypen statt Freitext
CI / backend-tests (push) Successful in 2m14s
CI / frontend-build (push) Successful in 36s
Neues Pflichtfeld dokumenttyp (Enum: Prüfprotokoll/Wartungsbericht/
Bedienungsanleitung/Rechnung/Zulassungsdokument/Sonstiges, Migration 0026)
- macht Dokumente kategorisier- und filterbar statt nur per Freitext-
Beschreibung auffindbar zu sein. Backend: Pflichtfeld beim Upload, optionaler
Query-Filter bei GET /dokumente. Frontend: Auswahl-Dropdown beim Upload,
Typ-Badge + Filter-Dropdown in der Liste (DokumentePanel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 10:32:25 +02:00
patrickandClaude Sonnet 5 0619497a1e fix(deps): react-router-dom v6.30.6 -> v7.18.3 (CVE: Open-Redirect/Constructor-Injection)
CI / backend-tests (push) Successful in 2m11s
CI / frontend-build (push) Successful in 32s
GHSA-wrjc-x8rr-h8h6 + GHSA-337j-9hxr-rhxg betrafen die gesamte 6.x-Reihe,
kein gepatchtes 6.x verfügbar - v7 war die einzige Lösung. Projekt nutzt
nur den klassischen Declarative-Router (BrowserRouter/Routes/Route,
useNavigate/useParams/useSearchParams), keine Data-Router-APIs
(loaders/actions) - v7 ist dafür API-kompatibel, keine Code-Änderung nötig.
Typecheck/Build/alle 16 Vitest-Tests grün, npm audit --omit=dev jetzt 0
Vulnerabilities.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 10:16:03 +02:00
patrickandClaude Sonnet 5 e40dd01be9 fix(test): letzten CI-Fund gelöst - Fach-Merge-Test kollidierte mit Auto-Provisionierung
CI / backend-tests (push) Successful in 2m11s
CI / frontend-build (push) Successful in 28s
Per SSH-Debug auf dem Server (Wegwerf-Testdatenbank, echte pytest-Ausführung
- hier lokal ohne venv nicht möglich): erstelle_vorlage() legt für den
Freitext-Fachnamen einer Vorlagenposition bereits automatisch ein Fach an
(services/vorlagen.py). Der Test versuchte danach nochmal explizit ein Fach
mit fast demselben Namen anzulegen ("Reizverschlussfach Gross") - das
kollidierte case-insensitiv mit dem bereits automatisch erzeugten
("Reizverschlussfach gross") und schlug mit 409 fehl, worauf der Rest des
Tests mit falschen Annahmen weiterlief (KeyError 'id').

Fix: das automatisch angelegte Fach wird jetzt per Query als Ziel verwendet
statt nochmal angelegt zu werden. Komplette Suite (164 Tests) läuft auf dem
Server jetzt vollständig grün.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 10:10:23 +02:00
patrickandClaude Sonnet 5 f4fe423559 chore(agents): qa-engineer für MABEA angelegt (nach Vorbild ai-coding-starter-kit)
CI / backend-tests (push) Failing after 2m8s
CI / frontend-build (push) Successful in 28s
Vorlage aus AlexPEClub/ai-coding-starter-kit war Next.js/Supabase-spezifisch
(RLS, Zod) und damit nicht übertragbar - eigene Fassung für den echten
FastAPI/SQLAlchemy+React-Stack, mit Bezug auf reale Stolperfallen dieses
Projekts (z.B. status/ist_status-Tippfehler). Fixt nichts selbst, meldet nur.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 10:02:56 +02:00
patrickandClaude Sonnet 5 bbc8ead2e5 fix(test): CI-Runner-Node hatte Blob ohne .stream() - kein echtes Response mehr
CI / frontend-build (push) Successful in 29s
CI / backend-tests (push) Failing after 2m11s
new Response(new Blob(...)) schlug auf dem Gitea-Runner mit "object.stream
is not a function" fehl (Node-Version dort mit unvollständiger Blob-Impl.),
lokal (Node 22) unauffällig. ladeDokumentAnsehen braucht nur response.ok
und response.blob() - Mock jetzt als einfaches Objekt statt echtem Response.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 10:00:08 +02:00
patrickandClaude Sonnet 5 7a3fd7acda fix(backend): CI war seit mehreren Commits rot - realer Bug + veraltete Tests
CI / backend-tests (push) Failing after 2m10s
CI / frontend-build (push) Failing after 14s
Wichtigster Fund: mein eigener CI-Check hat nur den zuletzt aktualisierten
Task angeschaut statt beide Jobs (backend-tests/frontend-build) einzeln zu
prüfen - dadurch ist die tatsächlich rote backend-tests-Pipeline seit
mehreren Commits unbemerkt geblieben (auch schon deployed).

Echter Bug (von mir eingeführt in SEARCH-002): /suche filterte auf
Objektposition.status, das Feld heißt aber ist_status - AttributeError bei
jeder Materialsuche.

5 veraltete Testerwartungen korrigiert (Logik in dashboard.py ist seit
längerem korrekt und dokumentiert, Tests wurden nie nachgezogen):
"noch_nie_kontrolliert" gilt laut _kategorie_und_gruende() IMMER zusätzlich
zu jedem anderen Grund - test_dashboard.py/test_mangel.py/
test_fahrzeugdetails.py prüften teils das Gegenteil.

1 Typo-Bug in test_kontrolle.py (UUID != str-Vergleich, immer falsch).

Offen/nicht geklärt: test_stammdaten.py::test_fach_verwendung_und_ersetzen_
fuehrt_zusammen (KeyError 'id' bei Fach-Merge-Response) - ohne lokale
Testausführung nicht sicher diagnostizierbar, braucht echten pytest-Lauf.

Nebenbei: FOUND-009/FOUND-011 im Backlog korrigiert (CI existiert bereits
unter .gitea/, vorheriger Abgleich hatte nur .github/ geprüft).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 09:56:01 +02:00
patrickandClaude Sonnet 5 28d8b2957d test(frontend): Vitest-Unit-Tests + CI-Integration, CLAUDE.md ignoriert
CI / backend-tests (push) Failing after 2m18s
CI / frontend-build (push) Failing after 17s
16 Tests ohne Browser-Abhängigkeit (jsdom): useIsDesktop (matchMedia-Reaktion),
client.ts (ApiError, Popup-Blocker-Fix bei ladeDokumentAnsehen), CommandPalette
(Debounce/Escape/Material-Treffer-Hinweis), ObjektListPage (Standort-
Gruppierung, Kacheln-Umschalter, localStorage-Persistenz, Suche). Vitest
separat von vite.config.ts (eigene vitest.config.ts), e2e/*.spec.ts (Playwright)
explizit ausgeschlossen. CI führt `npm run test` jetzt vor dem Build aus.

Nebenbei: CLAUDE.md ins .gitignore aufgenommen (bleibt lokal, nicht Teil des
Repos).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 09:46:35 +02:00
patrickandClaude Sonnet 5 7ce644ac51 refactor(css): global.css (871 Zeilen Monolith) in 15 Dateien aufgeteilt
CI / backend-tests (push) Failing after 2m17s
CI / frontend-build (push) Successful in 22s
Nach Zuständigkeit getrennt (tokens/base/layout/cards/forms/badges/theme-
toggle/command-palette/alert/utilities/scanner/table/split-layout/akte-grid/
responsive) unter frontend/src/styles/global/, größte Datei jetzt 135 statt
871 Zeilen. tailwind.css importiert alle in ursprünglicher Reihenfolge im
selben Layer (global-css) - Cascade-Layer-Reihenfolge unverändert, im
gebauten CSS verifiziert.

Dabei toten Code entfernt: .badge-ready/-limited/-not-ready/-unknown und
.card-grid/.stat-number (Reste von vor der Tailwind-Migration, nirgends
mehr im Code referenziert).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:36:02 +02:00
patrickandClaude Sonnet 5 6f592a1c37 chore(agents): Projekt-Subagenten geschärft (Modell-Konsistenz, Abgrenzung, Projekt-Hinweise)
CI / backend-tests (push) Failing after 2m11s
CI / frontend-build (push) Successful in 21s
model-Feld vereinheitlicht (accessibility-expert/ui-visual-validator liefen
noch mit inherit/sonnet statt claude-sonnet-5). Überschneidung accessibility-
expert vs. ui-visual-validator entschärft (Code-Audit vs. reine Screenshot-
Beurteilung, gegenseitiger Verweis). ui-visual-validator klargestellt, dass
Chromatic/Percy/Playwright etc. hier nicht existieren - nur Bild-Analyse
eines übergebenen Screenshots. tailwind-expert korrigiert (Tailwind v4 ohne
tailwind.config.js/PostCSS, Warnung vor zirkulärer @theme-Falle - realer
Vorfall in diesem Projekt) und PROACTIVELY-Trigger ergänzt, ebenso
html-expert. css-expert von tailwind-expert abgegrenzt (plain CSS vs.
Utility-Klassen).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:29:33 +02:00
patrickandClaude Sonnet 5 dc42b947d0 docs: Backlog gegen echten Code-Stand abgeglichen (Status-Spalte ergänzt)
CI / backend-tests (push) Failing after 2m11s
CI / frontend-build (push) Successful in 22s
Kachel-Liste war seit 2026-09-05 nicht mehr nachgepflegt, obwohl seitdem
viel gebaut wurde. Jede der 111 Kacheln jetzt gegen Endpunkte/Models/
Migrationen/Frontend-Code geprüft: 79 erledigt, 11 teilweise, 21 offen.
Zusammenfassung nach Epic am Dateianfang ergänzt, bestehende Abschnitte
(Epic-Übersicht, Subagenten-Zuordnung, Abhängigkeitsgraph) unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:25:44 +02:00
patrickandClaude Sonnet 5 2475c6a68d feat(search): SEARCH-002 Suchindex auch auf Materialnamen erweitert
CI / backend-tests (push) Failing after 2m11s
CI / frontend-build (push) Successful in 22s
Wer nach einem Material sucht (z.B. "Kompresse"), will die Objekte finden,
die es aktiv führen - nicht nur Objekte, deren eigener Name/Code passt.
GIN-Trigram-Index auf material.name (Migration 0025), /suche joint jetzt
zusätzlich über objektposition (nur status=aktiv) auf material.name.
Direkter Objekt-Treffer hat Vorrang vor Material-Treffer für dasselbe
Objekt. Command Palette zeigt bei Material-Treffern einen Hinweis
("führt „Kompresse“") statt nur dem Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:16:45 +02:00
patrickandClaude Sonnet 5 174cefa595 feat(objekte): Umschalter Kacheln/Gruppierung, useIsDesktop statt CSS-Doppelrender
CI / frontend-build (push) Successful in 20s
CI / backend-tests (push) Failing after 2m10s
Ansicht wird jetzt per Button in der Leiste umgeschaltet (persistiert in
localStorage) statt fest auf Gruppierung. Zusätzlich: Tabelle/Karten-
Umschaltung lief bisher über zwei parallel im DOM liegende, per CSS ein-/
ausgeblendete Blöcke - durch echten useIsDesktop-Hook (matchMedia) ersetzt,
reagiert live auf Resize statt nur beim Neuladen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:12:19 +02:00
patrickandClaude Sonnet 5 fbb9903db4 feat(objekte): Liste nach Standort gruppiert, Desktop-Tabelle statt Karten
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 21s
Objekte-Übersicht war eine flache Karten-Liste ohne Struktur. Jetzt nach
Standort gruppiert (Pflichtfeld, deckt immer alle Objekte ab) mit
Gruppenüberschrift + Anzahl. Ab 900px Breite Tabellen-Ansicht (Code/Name/
Status/letzte Kontrolle/Akte-Link) für mehr Objekte auf einen Blick,
darunter weiterhin die Karten-Ansicht für mobil - beide liegen im DOM,
CSS-Media-Query schaltet um statt JS-Breitenerkennung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 01:07:18 +02:00
patrickandClaude Sonnet 5 707701d897 feat(dokumente): DOC-001 Duplikat-Erkennung + Fix Online-Ansicht (Popup-Blocker)
CI / backend-tests (push) Failing after 2m11s
CI / frontend-build (push) Successful in 20s
Duplikat-Erkennung: SHA-256-Hash je Dokument (Migration 0024), Upload wird
mit 409 abgelehnt, wenn dieselbe Datei bereits an derselben Entität liegt
(Vergleich bewusst pro Entität, nicht global - gleiche Datei an zwei
Objekten ist kein Duplikat). Frontend zeigt die Backend-Fehlermeldung
(Dateiname/Datum des bestehenden Dokuments) statt generischem Text.

Nebenbei gefunden+gefixt: "Ansehen" (PDF/JPG/PNG online statt Download)
funktionierte nicht zuverlässig, weil window.open() erst nach einem await
fetch() aufgerufen wurde - Popup-Blocker werten das nicht mehr als direkte
Nutzeraktion. Jetzt öffnet der Tab sofort synchron, die Blob-URL wird
nachgeladen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 00:59:15 +02:00
patrickandClaude Sonnet 5 307914ccf7 feat(search): pg_trgm-Suchindex + Backend-Endpunkt statt Client-Filter
CI / backend-tests (push) Failing after 2m9s
CI / frontend-build (push) Successful in 21s
Command Palette lud bisher beim Öffnen ALLE Objekte und filterte nur
clientseitig per .includes() - unscharf und würde bei mehr Objekten
langsam werden. Jetzt: GIN-Trigram-Index auf objekt.name/code (Migration
0023), neuer GET /suche?q=-Endpunkt (Ähnlichkeits-Ranking per pg_trgm
similarity()), Frontend debounced (250ms) statt vollständiger Objektliste.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-08 00:44:03 +02:00
patrickandClaude Sonnet 5 c608f06806 fix(a11y): Kontroll-UI - Touch-Targets, Labels, Live-Regions, Dialog-Semantik
CI / backend-tests (push) Failing after 2m12s
CI / frontend-build (push) Successful in 22s
44px-Mindestgröße für Buttons/Inputs (Feldeinsatz mit Handschuhen), echte
Label-Verknüpfung statt reinem placeholder auf allen Kontroll-Eingabefeldern,
aria-live-Statusansagen beim Speichern/Fehler einer Position und beim Öffnen
des Nachfüll-Dialogs, NachfuellDialog jetzt mit role="dialog"/aria-modal,
Fokus beim Öffnen und Esc zum Schließen, Pflichtfeld Begründung mit
aria-required.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 23:30:01 +02:00
patrickandClaude Sonnet 5 7750d49d40 chore(agents): accessibility-expert und ui-visual-validator aus wshobson/agents geladen
CI / backend-tests (push) Failing after 2m7s
CI / frontend-build (push) Successful in 22s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 23:24:49 +02:00
patrickandClaude Sonnet 5 d38c7adbc7 feat(dashboard): Design-Review umgesetzt - EmptyStates, Statuslabel, Monitor-Skalierung
CI / backend-tests (push) Failing after 2m11s
CI / frontend-build (push) Successful in 22s
Einheitliche EmptyState-Komponente statt uneinheitlicher Empty-Texte pro
Kachel, gemeinsames Listen-Pattern (Inline-Styles entfernt, u.a.
KennzahlenTile, MaengelTile, AktivitaetTile, AufgabenTile), Status-Textlabel
im Kachel-Header zusätzlich zur Randfarbe (Kontrast/Distanz/Farbfehlsichtigkeit),
Status-Monitor-Modus jetzt per zoom vergrößert für Wandmonitor-Lesbarkeit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 22:38:36 +02:00
patrickandClaude Sonnet 5 68f0139b3d chore(agents): ui-designer Subagent aus VoltAgent-Repo geladen
CI / backend-tests (push) Failing after 2m8s
CI / frontend-build (push) Successful in 20s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 22:29:42 +02:00
patrickandClaude Sonnet 5 e5ddfde52f feat(ui): 24-Spalten-Dashboard-Raster, einklappbare Sidebar
CI / frontend-build (push) Successful in 20s
CI / backend-tests (push) Failing after 2m7s
Dashboard-Raster von 12 auf 24 Spalten - bei 12 waren Reihen sofort randvoll (3 Kacheln à w:4), kein Spielraum zum Breiter-Ziehen ohne Nachbarkachel zu verkleinern. Layout-localStorage-Key auf v3 gehoben (alte v2-Koordinaten passen nicht mehr zum neuen Raster). Sidebar links jetzt einklappbar (Toggle-Button bleibt sichtbar, Zustand in localStorage) - mehr Platz für breite Dashboard-Raster auf Desktop-Monitoren.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 14:42:19 +02:00
patrickandClaude Sonnet 5 e6eda26eb2 fix(frontend): zirkuläre CSS-Variablen endgültig behoben - kein @theme-Namespace mehr
CI / backend-tests (push) Failing after 2m8s
CI / frontend-build (push) Successful in 21s
Vorheriger Fix (--mabea-* Zwischen-Variablen) hat den Zirkel nur eine Ebene verschoben statt aufgelöst: da @theme weiterhin --color-primary selbst neu definierte (höherer Layer als global.css), zeigte --mabea-primary auf --color-primary, welches wiederum auf --mabea-primary zeigte - derselbe Zirkel, nur indirekt. Coming from CSS-Spec: eine zirkuläre var()-Kette macht die Property zur "guaranteed-invalid value", unabhängig davon über wie viele Zwischenschritte sie läuft.

Echter Fix: kein @theme-Mapping auf --color-* mehr, damit keine Namenskollision mit global.css überhaupt erst entstehen kann. Alle betroffenen Tailwind-Klassen (bg-primary, text-danger, border-l-warning, bg-surface-sunken, text-muted-foreground, ring-primary, etc.) auf Arbitrary-Value-Syntax umgestellt (z.B. bg-[var(--color-primary)]) - referenziert global.css-Variablen direkt, ohne je einen neuen Property-Namen im Theme-Layer zu belegen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 14:35:48 +02:00
patrickandClaude Sonnet 5 adb4aeef46 fix(frontend): kritischer Bug - zirkuläre CSS-Variablen brachen Farben app-weit
CI / backend-tests (push) Failing after 2m7s
CI / frontend-build (push) Successful in 23s
@theme-Mapping in tailwind.css hatte Einträge wie "--color-primary: var(--color-primary)" - gleicher Name wie in global.css, also Selbstreferenz auf dieselbe Custom Property. Laut CSS-Spec wird eine zirkuläre var()-Referenz zur "guaranteed-invalid value" - die Property bricht dadurch komplett weg, nicht nur für neue Tailwind-Utilities, sondern für JEDE Regel im ganzen Projekt, die dieselbe Property liest (z.B. .btn-primary in global.css, .badge-danger, etc.). Betraf: primary, primary-hover, primary-soft, danger, danger-bg, warning, warning-bg, success, success-bg, surface, surface-sunken, border, border-strong - praktisch die gesamte Farbpalette der App, nicht auf Dashboard beschränkt. Sichtbar u.a. als unsichtbarer weißer Text auf weißem "Trotzdem übernehmen"-Button (Kontrolle-Seite bei gesperrtem Objekt). Fix: Zwischen-Variablen mit eigenem Namen (--mabea-*) in tailwind.css, keine Namenskollision mehr.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 14:22:49 +02:00
patrickandClaude Sonnet 5 e3616c1929 fix(auth): Startseite/AdminRoute redirecten bei Reload fälschlich auf Objekte
CI / backend-tests (push) Failing after 2m9s
CI / frontend-build (push) Successful in 24s
Race Condition: bei bereits eingeloggter Session (Direktaufruf/Reload von "/" oder /dashboard/etc.) ist "eingeloggt" sofort true (Token im Storage), "rollen" aber noch [] bis /auth/me durch ist. Startseite/AdminRoute haben in genau diesem kurzen Fenster mit istVerantwortlich=false entschieden und per Navigate replace auf /objekte umgeleitet, bevor die echten Rollen (z.B. "administration") eintrafen - Admin landete dadurch nie auf dem Dashboard, sondern immer auf Objekte. Neues rollenGeladen-Flag im AuthContext, Startseite/AdminRoute warten jetzt darauf statt vorschnell mit rollen=[] zu entscheiden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 14:14:49 +02:00
patrickandClaude Sonnet 5 6db571f5ce fix(dashboard): Resize-Griff war unsichtbar - children-Injection landete in falscher Ebene
CI / backend-tests (push) Failing after 2m7s
CI / frontend-build (push) Successful in 20s
react-grid-layout/react-resizable hängt den Resize-Griff per children-Injection an (cloneElement(child, {}, ...child.props.children, handle)) - erwartet einen DIREKTEN Kindknoten der Grid-Item-Wurzel (CSS ".react-grid-item > .react-resizable-handle"). TileFrame rendere "children" bisher nur verschachtelt in CardContent, die CSS-Regel griff dort nicht - Griff blieb unsichtbar/nicht greifbar. Fix: eigener Kachel-Inhalt läuft jetzt über eine separate "inhalt"-Prop, "children" (das react-grid-layout für den Griff nutzt) wird direkt unter Card gerendert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 14:07:19 +02:00
patrickandClaude Sonnet 5 52936245e1 fix(dashboard): Grid kollabierte auf Content-Breite, Kachel-Titel liefen ab
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 21s
Root Cause (Screenshot-Analyse): .page-wide hatte kein width:100%/flex:1 wie .page - als Flex-Kind von .app-shell schrumpfte es auf reine Content-Breite. react-grid-layout positioniert Kacheln absolut (kein Beitrag zur intrinsischen Breite), dadurch kollabierte der ganze Grid-Container auf ~380px statt volle verfügbare Breite - Kacheln dadurch winzig, Text lief mitten im Wort ab. Fix: .page-wide bekommt flex:1/width:100%. Zusätzlich CardHeader/CardTitle mit min-w-0/truncate gegen abgeschnittene Titel, Einsatzbereitschaft-Vierer-Zeile von sm:grid-cols-4 (reagiert auf Viewport-, nicht Kachel-Breite) auf festes grid-cols-2 - lief in schmalen Kacheln trotz breitem Viewport ineinander.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:57:34 +02:00
patrickandClaude Sonnet 5 a2a44fb780 style(dashboard): Kacheln modernisiert - Karten, Einsatzbereitschaft-Balken, Termin-Listen, Skeleton
CI / backend-tests (push) Failing after 2m8s
CI / frontend-build (push) Successful in 23s
Card: 14px Radius, weicherer Schatten, Hover-Lift über box-shadow (nicht transform, würde von react-grid-layouts Inline-Positionierung überschrieben). Einsatzbereitschaft-Kachel: große Zahl "X/Y einsatzbereit", proportionaler gestapelter Statusbalken, Vierer-Zeile mit Farbpunkten+Zahl, Detail-Liste bleibt aufklappbar. Prüftermine/Ablaufdaten/Qualifikationsablauf: auf 5 Zeilen begrenzt mit "Alle anzeigen", Status-Badge links (überfällig gefüllt rot, bald fällig Outline amber, FristBadge zeigt nur noch Status), Countdown rechts tabular-nums. Neue --status-ok/warn/unknown/critical CSS-Variablen als Alias auf bestehende Farb-Tokens. Skeleton-Platzhalter statt "Lade…"-Text während des initialen Ladens. Keine API-/Datenänderungen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:52:43 +02:00
patrickandClaude Sonnet 5 74ed250ad7 feat(dashboard): echtes freies Grid-Layout mit Resize statt Sortable+Größenstufen
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 20s
@dnd-kit (nur Reihenfolge tauschen) durch react-grid-layout ersetzt - Kacheln lassen sich jetzt frei auf einem 12-Spalten-Raster positionieren (nicht nur umsortieren) UND per Ecke ziehen dynamisch in der Größe ändern (nicht nur zwischen 4 festen Stufen wechseln). Layout-Modell in layout.ts auf x/y/w/h pro Kachel umgestellt (vorher Reihenfolge-Array + Größen-Enum). TileFrame vereinfacht (kein Drag-Griff/Größen-Button mehr nötig, das übernimmt die Grid-Lib direkt an der Kachel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:41:23 +02:00
patrickandClaude Sonnet 5 85df756c3f fix(frontend): Tailwind-Utilities griffen nicht - global.css war unlayered
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 19s
Root Cause fürs "sieht noch alt aus": global.css wurde separat unlayered importiert, Tailwind-Utilities liefen in layer(utilities). Unlayertes CSS gewinnt in der CSS-Kaskade IMMER gegen jeden Layer, unabhängig von Spezifität - die meisten neuen Tailwind-Klassen (text-4xl, rounded-lg, border-l-*, etc.) wurden dadurch von alten global.css-Regeln überstimmt, ohne sichtbaren Effekt. Fix: global.css läuft jetzt selbst in einem eigenen Layer ("global-css"), Layer-Reihenfolge explizit deklariert (global-css < theme < utilities) - Tailwind gewinnt jetzt wie vorgesehen. main.tsx importiert global.css nicht mehr separat, das übernimmt tailwind.css per @import layer(global-css).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:35:26 +02:00
patrickandClaude Sonnet 5 0c448c7ff7 perf(dashboard): React-Review - Memoization, stabile Callbacks, Key-Fixes
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 20s
React.memo auf allen 8 Kachel-Komponenten + TileFrame, damit Interaktionen (Anpassen/Monitor/Größe/Ausblenden) nicht mehr alle Kacheln unnötig neu rendern. Voraussetzung dafür: onAusblendenUmschalten/onGroesseAendern als stabile useCallback-Referenzen mit id-Parameter statt pro Kachel neu erzeugter Closures. Die vier Layout-Mutationsfunktionen (dragEnde/ausblendenUmschalten/groesseAendern/layoutZuruecksetzen) über eine gemeinsame aktualisiereLayout-Helper-Funktion mit funktionalem setState dedupliziert (vermeidet stale-closure-Risiko bei schnellen Interaktionen). Instabile Index-Keys in PrueftermineTile/AufgabenTile durch stabile Keys ersetzt. maengelOffenListe in MaengelTile mit useMemo. Fehler-Anzeige bekommt "Erneut versuchen"-Button. Drag-Griff in TileFrame: type="button" + aria-roledescription für Screenreader.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:27:36 +02:00
patrickandClaude Sonnet 5 726d6e29b1 chore(agents): react/tailwind/css/html-expert Subagenten aus 0xfurai/claude-code-subagents geladen
CI / backend-tests (push) Failing after 2m2s
CI / frontend-build (push) Successful in 19s
Für Dashboard-/UI-Arbeit (Tailwind v4 + shadcn-artige Komponenten seit letztem Commit). Model-ID auf aktuelles Sonnet umgestellt (Quelle referenzierte veraltete claude-sonnet-4-20250514).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 13:22:12 +02:00
patrickandClaude Sonnet 5 c18638a169 feat(dashboard): echtes Drag & Drop statt Pfeil-Buttons, moderneres Kachel-Design
CI / backend-tests (push) Failing after 2m5s
CI / frontend-build (push) Successful in 20s
@dnd-kit statt ↑/↓-Buttons zum Anordnen (Griff-Icon, Tastatur-Fallback inklusive). Card-Komponente auf kleineren Radius umgestellt (weniger "Bubble"-Look). Kennzahlen/Mängel-Kachel zeigen jetzt eine große, fette Kopfzahl mit kleinem Label statt reiner Text-Liste - Inspiration: Resgrid Big Board (Statusfarben statt Deko) und moderne SaaS-Dashboards (Linear/Vercel: große Zahlen, dünne Border, wenig Schatten).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 12:42:33 +02:00
patrickandClaude Sonnet 5 a46897570d feat(dashboard): Tailwind CSS + shadcn/ui eingeführt, Dashboard modernisiert
CI / backend-tests (push) Failing after 2m8s
CI / frontend-build (push) Successful in 20s
Kachel-Größe/Ausblenden-Fix (flexBasis pro Kachel statt nur Aufgaben-Kachel, sichtbare Liste ausgeblendeter Kacheln zum Zurückholen). Tailwind v4 + shadcn-Basiskomponenten (Button/Card/Badge) neu eingeführt, gezielt fürs Dashboard-Redesign genutzt (kein Preflight, global.css bleibt für restliche App unangetastet). TileFrame nutzt jetzt Card mit farbigem Akzentbalken je Kritikalität (Mängel/Prüftermine/Ablaufdaten/Einsatzbereitschaft), ReadinessBadge von Emoji auf CSS-Punkte umgestellt, größere Touch-Ziele im Anpassen-Modus, Kiosk-Look im Status-Monitor (Chrome ausgeblendet), "zuletzt aktualisiert"-Anzeige.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 12:29:54 +02:00
patrickandClaude Sonnet 5 5fc8079df6 feat(dashboard): Dashboard-Start für Verantwortliche, Kachel-Anpassung, Status-Monitor
CI / backend-tests (push) Failing after 2m5s
CI / frontend-build (push) Successful in 19s
Dashboard immer Startseite für Verantwortliche (Mitarbeiter -> Objekte), kaputte Startseiten-Auswahl entfernt. Neu gemeldete Mängel als eigener Hinweis. Kacheln per Anpassen-Modus verschieb-/ausblendbar (localStorage), Status-Monitor-Modus mit Vollbild und Auto-Refresh (60s). DashboardPage dabei in kleine Dateien pro Kachel gesplittet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 12:02:47 +02:00
patrickandClaude Sonnet 5 9b2701e220 feat(kontrolle): Ablaufdatum als nur Monat/Jahr erfassbar
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 19s
Charge zeigt teils nur MM/JJJJ. Checkbox schaltet Eingabe auf Monat um, gespeichert wird Monatsende.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:50:53 +02:00
patrickandClaude Sonnet 5 1c2f2d38e0 refactor(admin): Objekte-Verwaltung entschlackt, Akte statt Redundanz
CI / backend-tests (push) Failing after 2m7s
CI / frontend-build (push) Successful in 18s
Fahrzeugdetails/Dokumente/Positionen-Pflege liefen hier inline parallel
zur neuen Akte-Ansicht (Epic 21) - doppelte Pflege, unübersichtlich
(599 Zeilen, 6 Buttons je Zeile). Jetzt Link "Akte ansehen" statt
eigenem Fahrzeugdetails-Formular/Dokumente-Panel/Positionen-Panel hier.
Verbleibende Verwaltungsaufgaben (Anlegen/Status/Verschieben/Fahrzeug
koppeln/Duplizieren) bleiben. Anlegen-Formular in eigene Komponente
ausgelagert (599 → 340 Zeilen + 145 ausgelagert).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:36:12 +02:00
patrickandClaude Sonnet 5 456fc2963e fix(dashboard): Ablaufdaten zeigen Namen statt roher IDs
CI / backend-tests (push) Failing after 2m5s
CI / frontend-build (push) Successful in 18s
"Bevorstehende Ablaufdaten" zeigte "Objekt #67 – Material #222" statt
lesbarer Bezeichnungen. bevorstehende_ablaufdaten() liefert jetzt
objekt_name/material_name mit, Dashboard nutzt sie.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:27:20 +02:00
patrickandClaude Sonnet 5 06baf03708 feat(material): Material-Dubletten zusammenführen
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 17s
Verwendung je Material einsehbar (Objektposition/Vorlagenposition/
Bestand/Kontrollposition/Fehlbestand/Ausgabe/Nachfüllung/
Materialbewegung), POST /materialien/{id}/ersetzen hängt alle
Referenzen auf ein Ziel-Material um und löscht die Quelle. Bricht bei
Konflikten ab (z.B. dasselbe Objekt hätte danach zwei Positionen für
dasselbe Material) statt Daten stillschweigend zu verlieren. Admin-UI:
"Zusammenführen" je Material zeigt Verwendung + Ziel-Auswahl.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:23:35 +02:00
patrickandClaude Sonnet 5 5f568c365c feat(fach): Duplikate case-insensitiv verhindern, Verwendung anzeigen und ersetzen/zusammenführen
CI / backend-tests (push) Failing after 2m7s
CI / frontend-build (push) Successful in 18s
Anlegen prüft jetzt case-insensitiv auf Duplikate (409 statt "Fach A"
neben "fach a"). Neuer Endpunkt GET /faecher/{id}/objekte zeigt, welche
Objekte ein Fach über ihre Vorlage tatsächlich nutzen. POST
/faecher/{id}/ersetzen benennt um und zieht alle Vorlagenpositionen
mit; landet der neue Name auf einem bereits bestehenden Fach, werden
beide zusammengeführt. Frontend: Fach anklicken öffnet Verwendung +
Ersetzen-Eingabe direkt in der Fächer-Verwaltung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:18:04 +02:00
patrickandClaude Sonnet 5 8e89755385 feat(ui): Fächer-Liste nach Objekttyp filterbar
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 17s
Bei 22 nachgetragenen Fächern über mehrere Objekttypen war die flache
Liste unübersichtlich. Nutzt das bereits vorhandene Objekttyp-Dropdown
(zum Anlegen) auch als Filter für die Liste darunter, statt ein
zusätzliches Element einzuführen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:09:42 +02:00
patrickandClaude Sonnet 5 85ca441216 fix(vorlagen): fehlendes Fach wird beim Anlegen einer Vorlage automatisch ergänzt
CI / backend-tests (push) Failing after 2m2s
CI / frontend-build (push) Successful in 19s
Vorlagenposition.fach ist Freitext ohne FK zur festen Fächer-Liste
(Fach-Tabelle) - beide liefen auseinander: ein Fach tauchte in der
Kontrolle auf ("Güdeltuben"), existierte aber nicht in der
Fächer-Verwaltung des Objekttyps. erstelle_vorlage/neue_version/
aktualisiere_positionen legen fehlende Fächer jetzt automatisch an.
Bestehende Lücken (22 Fächer über mehrere Objekttypen) direkt in
Produktion nachgetragen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-07 00:06:55 +02:00
patrickandClaude Sonnet 5 cc016f09d3 feat(akte): Ablaufdatum in der Beladung-Tabelle
CI / backend-tests (push) Failing after 2m6s
CI / frontend-build (push) Successful in 18s
Bevorstehende Ablaufdaten waren nur im Dashboard und als
Einsatzbereitschafts-Grund sichtbar, nicht direkt an der jeweiligen
Beladungsposition in der Akte. Neue Spalte "Ablauf", rot bei
überfälligem, gelb bei <30 Tagen verbleibender Zeit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:48:31 +02:00
patrickandClaude Sonnet 5 a18ec5bbce fix(kontrolle): Kontrolle bucht Ist-Menge jetzt immer, nicht nur bei Abweichung
CI / backend-tests (push) Failing after 2m1s
CI / frontend-build (push) Successful in 18s
Bisher änderte eine Kontrolle Objektposition.istmenge nur indirekt
über eine anschließende Nachfüllung bei Abweichung. Zählte eine
Kontrolle Ist=Soll (kein Fehlbestand, keine Nachfüllung), blieb der
Wert dauerhaft auf 0 stehen - ein frisch angelegtes, aber vollständig
bestücktes Objekt zeigte in der Beladung nie den echten Bestand.
Kontrolle setzt istmenge jetzt immer auf den gezählten Wert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:38:17 +02:00
patrickandClaude Sonnet 5 300b30e0b1 fix(akte): Beladung zeigt bei Geräten mit SN falsche Ist-Menge
CI / backend-tests (push) Failing after 2m2s
CI / frontend-build (push) Successful in 18s
Objektposition.istmenge bleibt bei materialtyp='geraet_sn' auf 0 -
die tatsächliche Ist-Menge ergibt sich aus der Anzahl einsatzbereiter
geraet_instanz-Zeilen (Karte 14). Die neue Beladung-Karte in der Akte
zeigte den rohen istmenge-Wert, also immer 0 statt z.B. 1 Defibrillator
oder 2 Sauerstoffflaschen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:31:18 +02:00
patrickandClaude Sonnet 5 a12dfb305e fix(ui): Akte-Header und Gründe-Liste überlappten sich
CI / backend-tests (push) Failing after 2m3s
CI / frontend-build (push) Successful in 18s
Beide Elemente trugen die Klasse akte-kopf und damit dasselbe
grid-area - das CSS-Grid platzierte sie übereinander statt
untereinander. Jetzt ein gemeinsamer Container mit einem grid-area.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:24:27 +02:00
patrickandClaude Sonnet 5 2a4d391711 feat(maintenance): MAINT-Epic (Wartungspläne/-aufträge, Werkstatt) + Akte-Redesign
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 18s
Neues Wartungskonzept: Wartungsplan+Position+Intervall (zeit/km/
Betriebsstunden, kombinierbar - fällig sobald ein Kriterium erreicht
ist), Wartungsauftrag mit intern/externer Werkstatt, Status offen/
in_arbeit/erledigt, Kosten, Historie, Dokument-Anhang. Ad-hoc-Aufträge
ohne Plan möglich (z.B. kleinere Reparatur). Admin-Tab "Wartungspläne".

Objektakte-Redesign (Epic 21, Nutzer-Feedback "wirkt nicht modern"):
CSS-Grid statt Karten-Stapel, einspaltig mobil, zweispaltig ab 900px;
Fahrzeug-Objekte zeigen Wartung/Fahrzeugdaten prominent, Geräte/
Rucksäcke die Beladung. Dabei gefundene Lücke: Beladung (Soll/Ist je
Position) fehlte in der Akte komplett, nur über eine laufende
Kontrolle sichtbar - jetzt eigene Karte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:17:39 +02:00
patrickandClaude Sonnet 5 d607a1101d fix(ui): Prüftermine/Ablaufdaten verlinken, Prüfung direkt aus der Akte erfassbar
CI / backend-tests (push) Failing after 2m0s
CI / frontend-build (push) Successful in 17s
Dashboard-Listen "Nächste Prüftermine"/"Bevorstehende Ablaufdaten"
hatten keinen Link zum betroffenen Objekt - ein überfälliger Termin
war nicht erreichbar. Zusätzlich: "Prüfung heute durchgeführt"-Button
je Gerät auf der Akte (PATCH /geraete/{id}), bisher nur über die
Admin-Objektbearbeitung möglich.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 22:50:42 +02:00
patrickandClaude Sonnet 5 9721873088 fix(kontrolle): doppelten Fehlbestand bei Folge-Kontrolle vermieden
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 20s
_synchronisiere_fehlbestand suchte nur nach Fehlbeständen der eigenen
Kontroll-Sitzung. Ein bereits offener Fehlbestand aus einer früheren
Kontrolle für dasselbe Objekt+Material wurde nicht wiedergefunden -
es entstand ein zweiter, paralleler Fehlbestand mit eigener (neuerer)
Sollmenge, der alte blieb mit veralteter Sollmenge offen liegen.
Lookup jetzt über objekt_id+material_id+status=offen statt
kontrolle_id; kontrolle_id am gefundenen Datensatz bleibt unverändert,
damit ein Abbruch der aktuellen Kontrolle ihn nicht fälschlich
mitlöscht. Löst sich die Abweichung über eine andere Kontrolle als
die erzeugende auf, wird der Fehlbestand jetzt sauber als erledigt
markiert (inkl. Mindermenge-Abschluss) statt stillschweigend gelöscht.

Nebenbei: Kommentare mit Kachel-/Datums-Referenzen ("Bug-Fund
2026-09-06", "UI-00X (Epic 20)") aus dem Code dieser Session entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 22:26:57 +02:00
patrickandClaude Sonnet 5 9281840ac1 feat(ui): globaler Aktivitäts-Feed auf dem Dashboard
CI / backend-tests (push) Failing after 2m1s
CI / frontend-build (push) Successful in 19s
Karte "Letzte Aktivität" nutzt GET /historie (kein neuer Endpunkt),
statt Ereignisse nur pro Objekt in der Akte sehen zu können. Lesbare
Ereignis-Labels (EREIGNIS_LABEL) auch in AktePage statt rohem
ereignistyp-String. Angeregt durch Resgrid-Doku (Activity-Log-Panel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 22:03:39 +02:00
patrickandClaude Sonnet 5 65203a039c fix(dashboard): "nie kontrolliert" ging bei zusätzlichen Gründen verloren
CI / backend-tests (push) Failing after 2m3s
CI / frontend-build (push) Successful in 19s
_kategorie_und_gruende() zählte "noch_nie_kontrolliert" bisher nur,
wenn es der EINZIGE Grund war - ein Objekt mit z.B. offenem
Fehlbestand UND nie kontrolliert verlor den Hinweis komplett, landete
nur unter "nicht einsatzbereit" ohne diesen Grund zu nennen. Jetzt
immer als Zusatzgrund angehängt. Neues Feld nie_kontrolliert_gesamt
liefert die tatsächliche Gesamtzahl über alle Kategorien hinweg,
Dashboard nutzt sie statt der (bewusst engeren) "unbekannt"-Kategorie.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 22:00:01 +02:00
patrickandClaude Sonnet 5 9a3eb7d810 feat(ui): UI-008 echte Status-Badges statt badge-neutral, Epic 20 komplett
CI / backend-tests (push) Successful in 2m2s
CI / frontend-build (push) Successful in 18s
FehlbestandListePage, MangelListePage (Status + Prioritäts-Badge statt
Inline-Farbe) und admin/GeraeteInstanzenListe zeigten Status immer als
neutrales Badge statt farblich zu unterscheiden. Letzte hartkodierte
Hex-Fallbacks (NachfuellDialog, BeladungsplanerBoard) auf reine Tokens
umgestellt. Damit ist Epic 20 (UI-Redesign, UI-001..008) vollständig
durchlaufen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 21:45:09 +02:00