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
This commit is contained in:
2026-09-06 21:45:09 +02:00
co-authored by Claude Sonnet 5
parent 30e2db63ae
commit 9a3eb7d810
7 changed files with 42 additions and 9 deletions
+1 -1
View File
@@ -272,7 +272,7 @@ eigenes Modul (MAINT-\*, MABEA hat nur Prüfung, keine Wartung)**.
| `17_zustaendigkeit.md` | ZUST-001 … ZUST-002 (vollständig, nachträglich ergänzt) |
| `18_notifications.md` | NOTIF-001 … NOTIF-002 (vollständig, nachträglich ergänzt) |
| `19_satelliten_server.md` | SAT-001 (Platzhalter, nachträglich ergänzt, bewusst zurückgestellt) |
| `20_ui_redesign.md` | UI-001 … UI-008 (vollständig, nachträglich ergänzt, in Umsetzung) |
| `20_ui_redesign.md` | UI-001 … UI-008 (vollständig umgesetzt, 2026-09-06) |
**Alle 20 Epics durchgegangen** (16 ursprüngliche + 17 Zuständigkeit/18 Notifications/19
Satelliten-Server/20 UI-Redesign, nachträglich ergänzt). Detaillierungsphase
+8 -1
View File
@@ -207,7 +207,14 @@ Aktueller Stand vor Redesign: 39 Seiten-/Komponenten-Dateien, ~7.000 Zeilen, ein
- **Rechte:** keine Änderung
- **Akzeptanzkriterien:** keine Seite mehr im alten Stil.
- **Tests:** bestehende Tests bleiben grün.
- **DoD:** offen.
- **DoD:** umgesetzt (2026-09-06). Rest-Audit über alle Seiten/Komponenten
(`grep` nach Hex-Farben, `badge-neutral` auf echten Status-Feldern): letzte
hartkodierte Hex-Fallbacks (`NachfuellDialog.tsx`, `BeladungsplanerBoard.tsx`)
auf reine Tokens umgestellt. `FehlbestandListePage`, `MangelListePage`
(Status UND Prioritäts-Badge statt Inline-Farbe) und
`GeraeteInstanzenListe.tsx` (Admin) bekamen echte Status-Farben statt immer
`badge-neutral`. Damit ist Epic 20 (UI-Redesign, UI-001..008) vollständig
durchlaufen.
---
+11 -1
View File
@@ -4,6 +4,16 @@ import { apiRequest } from "../api/client";
import { useAuth } from "../auth/AuthContext";
import type { Fehlbestand, Material, Objekt } from "../api/types";
// UI-008 (Epic 20): Status war bisher immer badge-neutral, unabhängig vom
// tatsächlichen Zustand - andere Listen (Mängel, Ausgabe) unterscheiden längst
// visuell zwischen offen/erledigt.
const STATUS_BADGE: Record<string, string> = {
offen: "badge-warning",
in_bearbeitung: "badge-warning",
nachgefuellt_teilweise: "badge-warning",
erledigt: "badge-success",
};
// Eigenständige Abarbeitung offener Fehlbestände (Nutzer-Vorgabe): Nachfüllen/
// Mindermenge-Genehmigung sollen ohne komplette Kontrolle möglich sein - Backend
// (GET /fehlbestaende, POST .../nachfuellungen, POST .../mindermenge) existierte
@@ -112,7 +122,7 @@ export function FehlbestandListePage() {
<span>
<strong>{objektName(fb.objekt_id)}</strong> {materialName(fb.material_id)}
</span>
<span className="badge badge-neutral">{fb.status}</span>
<span className={`badge ${STATUS_BADGE[fb.status] ?? "badge-neutral"}`}>{fb.status}</span>
</div>
<div className="text-muted" style={{ margin: "0.4rem 0" }}>
Soll {fb.sollmenge} / Ist {fb.istmenge} Fehlmenge {fb.fehlmenge}
+11 -2
View File
@@ -14,6 +14,15 @@ const STATUS_LABEL: Record<MangelStatus, string> = {
erledigt: "Erledigt",
};
// UI-008 (Epic 20): Status-Badge war immer neutral, unabhängig vom Zustand.
const STATUS_BADGE: Record<MangelStatus, string> = {
neu: "badge-warning",
in_bearbeitung: "badge-warning",
ersatzteil_bestellt: "badge-warning",
reparatur_geplant: "badge-warning",
erledigt: "badge-success",
};
const STATUS_OPTIONEN: MangelStatus[] = [
"neu",
"in_bearbeitung",
@@ -150,9 +159,9 @@ export function MangelListePage() {
<div className="row-between">
<span>
<strong>{objektName(m.objekt_id)}</strong>
{m.prioritaet === "hoch" && <span style={{ color: "var(--color-danger)" }}> hoch</span>}
{m.prioritaet === "hoch" && <span className="badge badge-danger" style={{ marginLeft: "0.4rem" }}> hoch</span>}
</span>
<span className="badge badge-neutral">{STATUS_LABEL[m.status]}</span>
<span className={`badge ${STATUS_BADGE[m.status]}`}>{STATUS_LABEL[m.status]}</span>
</div>
<div style={{ margin: "0.4rem 0" }}>{m.beschreibung}</div>
{darfStatusAendern && m.status !== "erledigt" && (
@@ -80,7 +80,7 @@ export function BeladungsplanerBoard({ zeilen, onZeilenChange, materialien, faec
marginBottom: "0.4rem",
padding: "0.35rem 0.5rem",
cursor: "pointer",
outline: ausgewaehlt === m.id ? "2px solid var(--color-primary, #2563eb)" : "none",
outline: ausgewaehlt === m.id ? "2px solid var(--color-primary)" : "none",
}}
>
{m.name}
@@ -99,7 +99,7 @@ export function BeladungsplanerBoard({ zeilen, onZeilenChange, materialien, faec
flex: "0 0 14rem",
minHeight: "8rem",
cursor: ausgewaehlt !== null ? "pointer" : "default",
borderColor: ausgewaehlt !== null ? "var(--color-primary, #2563eb)" : undefined,
borderColor: ausgewaehlt !== null ? "var(--color-primary)" : undefined,
}}
onClick={() => zuordnen(spalte)}
>
@@ -15,6 +15,13 @@ const STATUS_LABEL: Record<GeraetInstanz["status"], string> = {
in_reparatur: "In Reparatur",
};
// UI-008 (Epic 20): Status-Badge war immer neutral, unabhängig vom Zustand.
const STATUS_BADGE: Record<GeraetInstanz["status"], string> = {
einsatzbereit: "badge-success",
defekt: "badge-danger",
in_reparatur: "badge-warning",
};
/** Karte 14: löst das Einzelfeld objektposition.seriennummer ab - beliebig
* viele Geräte-Exemplare pro Position (z.B. 2 Pulsoxymeter im selben
* Rucksack), je mit eigenem Prüfdatum/Status. */
@@ -103,7 +110,7 @@ export function GeraeteInstanzenListe({ objektpositionId, pruefintervallMonate,
<div className="row-between">
<span>
{instanz.status === "einsatzbereit" ? "✓" : "✗"} {instanz.seriennummer}{" "}
<span className="badge badge-neutral">{STATUS_LABEL[instanz.status]}</span>{" "}
<span className={`badge ${STATUS_BADGE[instanz.status]}`}>{STATUS_LABEL[instanz.status]}</span>{" "}
{instanz.naechste_pruefung && (
<span className="text-muted">nächste Prüfung: {instanz.naechste_pruefung}</span>
)}
@@ -26,7 +26,7 @@ export function NachfuellDialog({
const [begruendung, setBegruendung] = useState("");
return (
<div className="card" style={{ borderColor: "var(--color-warning, #b45309)", marginTop: "0.6rem" }}>
<div className="card" style={{ borderColor: "var(--color-warning)", marginTop: "0.6rem" }}>
<div className="card-subtitle">
Fehlmenge bei {materialName} jetzt aus Lager nachfüllen?
</div>