diff --git a/web/src/pages/Transfer.jsx b/web/src/pages/Transfer.jsx index a63c2f5..863a7ff 100644 --- a/web/src/pages/Transfer.jsx +++ b/web/src/pages/Transfer.jsx @@ -129,6 +129,23 @@ export default function Transfer() { } } + // Gegenstands-Kategorien als Baum; für die Anzeige, welche Unterkategorien + // durch eine gewählte Oberkategorie automatisch mitkommen. + const objTree = asTree(categories).filter((c) => c.tracking === "object"); + const parentOf = Object.fromEntries(categories.map((c) => [c.id, c.parent_id])); + const nameById = Object.fromEntries(categories.map((c) => [c.id, c.name])); + const hatKinder = (id) => objTree.some((o) => o.parent_id === id); + // Name der nächsten ausgewählten Oberkategorie (oder null) – dann ist diese + // Kategorie „über die Oberkategorie enthalten". + function abgedecktVon(id) { + let p = parentOf[id]; + while (p != null) { + if (selCats.has(p)) return nameById[p]; + p = parentOf[p]; + } + return null; + } + return (
@@ -217,8 +234,9 @@ export default function Transfer() {

Je Einzelstück eine Zeile: QR-Inhalt, UID, Produkt, Marke, Kategorie, Lagerort. In der Etiketten-Software (z.B. P-touch) als Datenbank{" "} - verknüpfen – sie erzeugt QR-Code und Text automatisch. Kategorien wählen - (Unterkategorien sind enthalten); ohne Auswahl kommen alle Einzelstücke. + verknüpfen – sie erzeugt QR-Code und Text automatisch. Ohne Auswahl kommen alle + Einzelstücke. Wählst du eine Kategorie, kommen ihre Unterkategorien + automatisch mit – sie erscheinen unten als „enthalten".

- {asTree(categories).filter((c) => c.tracking === "object").map((c) => ( - - ))} - {asTree(categories).filter((c) => c.tracking === "object").length === 0 && ( + {objTree.map((c) => { + const enthalten = abgedecktVon(c.id); + const direkt = selCats.has(c.id); + return ( + + ); + })} + {objTree.length === 0 && ( Noch keine Gegenstands-Kategorien. )}
diff --git a/web/src/styles.css b/web/src/styles.css index 398c74f..384ac50 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -891,6 +891,8 @@ select.zeitraum:hover { color: var(--text); } .clean-list li { display: flex; align-items: center; gap: var(--sp-2); padding: 6px 8px; background: var(--surface-2); border-radius: 8px; } .check-inline { display: flex; align-items: center; gap: var(--sp-2); } .check-inline input { width: auto; margin: 0; } +/* Über eine gewählte Oberkategorie automatisch enthaltene Unterkategorie. */ +.kat-enthalten { opacity: 0.6; } .feldkopf { display: inline-flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; } tr.row-active { background: var(--surface-2); }