feat(ui): UI-004 Dashboard "Was ist jetzt zu tun?"-Karte
CI / backend-tests (push) Successful in 2m0s
CI / frontend-build (push) Successful in 18s

Neue Karte ganz oben fasst offene Fehlbestände, kritische Mängel,
überfällige Prüfungen, abgelaufene Chargen und nie kontrollierte
Objekte zusammen (bereits geladene Daten, keine neuen Endpunkte),
mit Direktlinks - "5-Sekunden-Antwort" auf "was muss ich jetzt tun".
Nebenbei: fehlende .text-success/.text-danger in global.css ergänzt
(waren in AktePage.tsx bereits referenziert, aber nie definiert).

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 13:33:08 +02:00
co-authored by Claude Sonnet 5
parent 79ddb37a36
commit ed9ba29581
3 changed files with 59 additions and 1 deletions
+10 -1
View File
@@ -105,7 +105,16 @@ Aktueller Stand vor Redesign: 39 Seiten-/Komponenten-Dateien, ~7.000 Zeilen, ein
- **Akzeptanzkriterien:** alle geforderten Kennzahlen sichtbar, keine Platzhalter-/
Fake-Werte.
- **Tests:** bestehende Dashboard-Tests bleiben grün.
- **DoD:** offen.
- **DoD:** umgesetzt (2026-09-06). Neue Karte "Was ist jetzt zu tun?" ganz oben
(volle Breite), fasst offene Fehlbestände/kritische Mängel/überfällige
Prüfungen/abgelaufene Chargen/nie kontrollierte Objekte aus bereits
geladenen Daten zusammen, mit Direktlinks - keine neuen Endpunkte, keine
Fake-Daten. Leerzustand "✅ Nichts Dringendes offen." statt leerer Karte.
Restliche Karten (Einsatzbereitschaft mit ReadinessBadge-Chips aus UI-003,
Prüftermine/Ablaufdaten mit InspectionStatus/InventoryStatus, Kennzahlen,
Mängel, Qualifikationsablauf) bleiben als Card-Grid bestehen. Nebenbei
behobene Vorab-Lücke: `.text-success`/`.text-danger` fehlten in
`global.css`, obwohl in `AktePage.tsx` bereits referenziert.
## UI-005 — Objektakte modernisiert
+41
View File
@@ -121,6 +121,30 @@ export function DashboardPage() {
const maengelOffenAnzahl = maengel.filter((m) => m.status !== "erledigt").length;
const maengelKritischAnzahl = maengel.filter((m) => m.status !== "erledigt" && m.prioritaet === "hoch").length;
const maengelOffenListe = maengel.filter((m) => m.status !== "erledigt");
const pruefungenUeberfaellig = prueftermine.filter((p) => p.status === "abgelaufen").length;
const ablaufdatenAbgelaufen = ablaufdaten.filter((a) => a.status === "abgelaufen").length;
// UI-004 (Epic 20): "Was ist einsatzbereit und was muss ich jetzt tun?" in
// 5 Sekunden beantwortbar - eine Aufgaben-Karte statt Zahlen über sechs
// gleichrangige Karten verteilt suchen zu müssen. Keine neuen Daten, nur
// Zusammenfassung der bereits geladenen Kennzahlen mit Direktlinks.
const aufgaben = [
kennzahlen && kennzahlen.anzahl_offener_fehlbestaende > 0
? { text: `${kennzahlen.anzahl_offener_fehlbestaende} offene Fehlbestände`, ziel: "/fehlbestaende" }
: null,
maengelKritischAnzahl > 0
? { text: `${maengelKritischAnzahl} kritische Mängel offen`, ziel: "/maengel" }
: null,
pruefungenUeberfaellig > 0
? { text: `${pruefungenUeberfaellig} Geräteprüfungen überfällig`, ziel: null }
: null,
ablaufdatenAbgelaufen > 0
? { text: `${ablaufdatenAbgelaufen} Chargen abgelaufen`, ziel: null }
: null,
bereitschaft && bereitschaft.unbekannt > 0
? { text: `${bereitschaft.unbekannt} Objekte noch nie kontrolliert`, ziel: "/objekte" }
: null,
].filter((a): a is { text: string; ziel: string | null } => a !== null);
return (
<main className="page-wide">
@@ -129,6 +153,23 @@ export function DashboardPage() {
{laedt && <p className="text-muted">Lade</p>}
{!laedt && bereitschaft && (
<div className="card-grid">
<div className="card" style={{ flexBasis: "100%" }}>
<h3 style={{ marginTop: 0 }}>Was ist jetzt zu tun?</h3>
{aufgaben.length === 0 ? (
<p className="text-success" style={{ fontWeight: 600 }}>
Nichts Dringendes offen.
</p>
) : (
<ul className="card-list">
{aufgaben.map((a, i) => (
<li key={i}>
{a.ziel ? <Link to={a.ziel}>{a.text}</Link> : <span>{a.text}</span>}
</li>
))}
</ul>
)}
</div>
<div className="card">
<h3 style={{ marginTop: 0 }}>Einsatzbereitschaft</h3>
<p className="stat-number">
+8
View File
@@ -541,6 +541,14 @@ select.input:focus {
color: var(--color-text-muted);
}
.text-success {
color: var(--color-success);
}
.text-danger {
color: var(--color-danger);
}
.stack {
display: flex;
flex-direction: column;