Ablaufkarten trennen: "Bald ablaufend" zeigt kein Abgelaufenes mehr

Eine Karte mit dieser Ueberschrift, in der bereits Ueberfaelliges steht,
ist irrefuehrend. KarteAblauf bekommt daher einen Modus soon/expired/alle
statt des bisherigen Schalters "nurAbgelaufen".

Neu ist die Karte "Ablauf-Uebersicht" (alle), die beides zusammen zeigt.
Sie steht auch in der eingebauten Vorgabe, damit dort ohne Zutun weiterhin
Ueberfaelliges sichtbar ist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-23 12:24:30 +02:00
parent 1fd1e89872
commit d6a717e39c
3 changed files with 34 additions and 10 deletions

View File

@@ -54,7 +54,9 @@ ENFORCED_KEY = "dashboard_enforced"
BUILTIN_LAYOUT: list[dict] = [ BUILTIN_LAYOUT: list[dict] = [
{"i": "actions", "x": 0, "y": 0, "w": 4, "h": 3}, {"i": "actions", "x": 0, "y": 0, "w": 4, "h": 3},
{"i": "status", "x": 4, "y": 0, "w": 8, "h": 3}, {"i": "status", "x": 4, "y": 0, "w": 8, "h": 3},
{"i": "expiring", "x": 0, "y": 3, "w": 6, "h": 6}, # Bewusst die kombinierte Karte: "expiring" zeigt nur noch Laufendes, in der
# Vorgabe soll aber auch Ueberfaelliges ohne Zutun sichtbar sein.
{"i": "expiry-all", "x": 0, "y": 3, "w": 6, "h": 6},
{"i": "shopping", "x": 6, "y": 3, "w": 6, "h": 6}, {"i": "shopping", "x": 6, "y": 3, "w": 6, "h": 6},
{"i": "expiry-donut", "x": 0, "y": 9, "w": 4, "h": 6}, {"i": "expiry-donut", "x": 0, "y": 9, "w": 4, "h": 6},
{"i": "category-donut", "x": 4, "y": 9, "w": 4, "h": 6}, {"i": "category-donut", "x": 4, "y": 9, "w": 4, "h": 6},

View File

@@ -155,7 +155,7 @@ def test_layout_faellt_auf_die_eingebaute_zurueck(db, user):
assert antwort.source == "builtin" assert antwort.source == "builtin"
assert antwort.enforced is False assert antwort.enforced is False
assert antwort.has_default is False assert antwort.has_default is False
assert any(k["i"] == "expiring" for k in antwort.layout) assert any(k["i"] == "expiry-all" for k in antwort.layout)
def test_eigene_anordnung_wird_gespeichert(db, user): def test_eigene_anordnung_wird_gespeichert(db, user):

View File

@@ -109,16 +109,32 @@ function KarteEinheiten() {
} }
// ---------------------------------------------------------------- Listen // ---------------------------------------------------------------- Listen
function KarteAblauf({ nurAbgelaufen = false }) { /**
* Ablaufliste in drei Ausprägungen.
*
* "soon" zeigt bewusst NUR das, was noch läuft: Eine Karte mit der Überschrift
* „Bald ablaufend“, in der bereits Abgelaufenes steht, führt in die Irre.
* Wer beides zusammen sehen will, nimmt "alle".
*/
const ABLAUF_LEER = {
soon: "Nichts läuft demnächst ab.",
expired: "Nichts ist abgelaufen.",
alle: "Nichts läuft demnächst ab und nichts ist abgelaufen.",
};
function KarteAblauf({ modus = "alle" }) {
const { formatBestBefore } = useSettings(); const { formatBestBefore } = useSettings();
const { daten, fehler } = useDaten(() => api.expiring()); const { daten, fehler } = useDaten(() => api.expiring());
const zeilen = (daten || []).filter((e) => (nurAbgelaufen ? e.days_left < 0 : true)); const zeilen = (daten || []).filter((e) => {
if (modus === "expired") return e.days_left < 0;
if (modus === "soon") return e.days_left >= 0;
return true;
});
return ( return (
<Zustand fehler={fehler} daten={daten} <Zustand fehler={fehler} daten={daten} leer={ABLAUF_LEER[modus]}>
leer={nurAbgelaufen ? "Nichts ist abgelaufen." : "Nichts läuft demnächst ab."}>
{zeilen.length === 0 ? ( {zeilen.length === 0 ? (
<div className="empty">{nurAbgelaufen ? "Nichts ist abgelaufen." : "Nichts läuft demnächst ab."}</div> <div className="empty">{ABLAUF_LEER[modus]}</div>
) : ( ) : (
<div className="table-wrap"> <div className="table-wrap">
<table className="table"> <table className="table">
@@ -407,15 +423,21 @@ export const KARTEN = {
}, },
expiring: { expiring: {
titel: "Bald ablaufend", icon: "clock", vorschau: "tabelle", titel: "Bald ablaufend", icon: "clock", vorschau: "tabelle",
beschreibung: "Chargen innerhalb der Warnfrist", beschreibung: "Nur Chargen innerhalb der Warnfrist ohne bereits abgelaufene",
standard: { w: 6, h: 6 }, min: { w: 4, h: 4 }, standard: { w: 6, h: 6 }, min: { w: 4, h: 4 },
komponente: () => <KarteAblauf />, komponente: () => <KarteAblauf modus="soon" />,
}, },
expired: { expired: {
titel: "Abgelaufen", icon: "alert", vorschau: "tabelle", titel: "Abgelaufen", icon: "alert", vorschau: "tabelle",
beschreibung: "Nur überfällige Chargen", beschreibung: "Nur überfällige Chargen",
standard: { w: 6, h: 5 }, min: { w: 4, h: 4 }, standard: { w: 6, h: 5 }, min: { w: 4, h: 4 },
komponente: () => <KarteAblauf nurAbgelaufen />, komponente: () => <KarteAblauf modus="expired" />,
},
"expiry-all": {
titel: "Ablauf-Übersicht", icon: "clock", vorschau: "tabelle",
beschreibung: "Abgelaufen und bald ablaufend in einer Liste",
standard: { w: 6, h: 6 }, min: { w: 4, h: 4 },
komponente: () => <KarteAblauf modus="alle" />,
}, },
shopping: { shopping: {
titel: "Einkaufsliste", icon: "cart", vorschau: "tabelle", titel: "Einkaufsliste", icon: "cart", vorschau: "tabelle",