Web: Kategorie-Filter - Oberkategorie subtil + als eigener Eintrag waehlbar
Die DataTable kann jetzt je Spalte mehrere Filter-Werte pro Zeile (filterValues/Tokens) und eine eigene Option-Darstellung (filterOptionLabel). Die Kategorie-Spalte liefert als Tokens jede Ebene kumuliert (Klamotten, Klamotten -> kurze Hosen); so erscheint die Oberkategorie als eigener, anklickbarer Eintrag und selektiert alle Unterkategorien. Ober-Ebenen werden in Zelle und Dropdown kleiner/gedaempft dargestellt (CategoryPathLabel), das Blatt normal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,8 @@ import Icon from "../components/Icon";
|
||||
import DataTable from "../components/DataTable";
|
||||
import { ProduktThumb } from "../components/ProduktBild";
|
||||
import { locationOptions, locationPathById } from "../locationPath";
|
||||
import { categoryPathMap } from "../categoryPath";
|
||||
import { categoryInfoMap } from "../categoryPath";
|
||||
import CategoryPathLabel, { pathParts } from "../components/CategoryPathLabel";
|
||||
|
||||
/**
|
||||
* Liste aller Einzelstücke (physische Exemplare, jedes mit eigener UID/Lagerort) –
|
||||
@@ -31,8 +32,9 @@ export default function ItemList() {
|
||||
}
|
||||
useEffect(() => { load(); }, []);
|
||||
|
||||
// Kategorie als voller Pfad, damit "Klamotten" auch die Unterkategorien findet.
|
||||
const catPfad = useMemo(() => categoryPathMap(categories), [categories]);
|
||||
// Kategorie als Pfad + Tokens (jede Ebene), damit "Klamotten" auch die
|
||||
// Unterkategorien findet und die Oberkategorie im Filter wählbar ist.
|
||||
const catInfo = useMemo(() => categoryInfoMap(categories), [categories]);
|
||||
|
||||
async function patch(it, body) {
|
||||
try { await api.updateItem(it.id, body); await load(); }
|
||||
@@ -53,8 +55,11 @@ export default function ItemList() {
|
||||
{ key: "brand", header: "Marke", width: 140, filterText: (it) => it.product_brand || "",
|
||||
render: (it) => <span className="muted">{it.product_brand || "–"}</span> },
|
||||
{ key: "category", header: "Kategorie", width: 200,
|
||||
filterText: (it) => catPfad.get(it.category_id) || it.category_name || "",
|
||||
render: (it) => <span className="muted">{catPfad.get(it.category_id) || it.category_name || "–"}</span> },
|
||||
filterText: (it) => catInfo.get(it.category_id)?.path || it.category_name || "",
|
||||
filterValues: (it) => catInfo.get(it.category_id)?.tokens || (it.category_name ? [it.category_name] : [""]),
|
||||
filterOptionLabel: (v) => (v === "" ? "(Leere)" : <CategoryPathLabel parts={pathParts(v)} />),
|
||||
sortValue: (it) => catInfo.get(it.category_id)?.path || it.category_name || "",
|
||||
render: (it) => <CategoryPathLabel parts={catInfo.get(it.category_id)?.parts} fallback={it.category_name || "–"} /> },
|
||||
{ key: "location", header: "Lagerort", width: 220,
|
||||
filterText: (it) => locationPathById(it.location_id, locations),
|
||||
render: (it) => (isAdmin ? (
|
||||
|
||||
Reference in New Issue
Block a user