Web: Produkte in Lebensmittel/Gegenstaende getrennt; Spalten-Labels; Produktformular aufgeraeumt

1) Zwei getrennte Sidebar-Eintraege 'Lebensmittel' und 'Gegenstaende' (Products mit fixedType) statt einem 'Produkte' mit Umschalter - so vermischt sich nichts. 2) Spalten-Waehler zeigt sprechende Labels ('Bild' statt 'thumb', 'Aktionen', ...). 3) Produktformular: leerer Grow-Platzhalter unter 'Typ' entfernt und 'Neue Kategorie' direkt neben das Kategorie-Dropdown gruppiert; Formular wieder auf Lesebreite (kein content--wide), da das Layout-Problem intern war.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 18:26:41 +02:00
parent 4aa6d9597b
commit 01a3528227
9 changed files with 35 additions and 26 deletions

View File

@@ -26,7 +26,7 @@ function einheitText(p) {
: basis;
}
export default function Products() {
export default function Products({ fixedType = null }) {
const { isAdmin } = useAuth();
const [products, setProducts] = useState([]);
const [categories, setCategories] = useState([]);
@@ -43,10 +43,15 @@ export default function Products() {
// 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]);
const sichtbar = products.filter((p) => !typ || p.tracking === typ);
// Zwei getrennte Seiten (Lebensmittel/Gegenstände) fixieren den Typ; sonst der
// Umschalter oben.
const activeTyp = fixedType || typ;
const sichtbar = products.filter((p) => !activeTyp || p.tracking === activeTyp);
const titel = fixedType === "food" ? "Lebensmittel"
: fixedType === "object" ? "Gegenstände" : "Produkte";
const columns = [
{ key: "thumb", header: "", fixed: true, width: 56,
{ key: "thumb", header: "", label: "Bild", fixed: true, width: 56,
render: (p) => <ProduktThumb productId={p.id} alt={p.name} /> },
{ key: "name", header: "Name", grow: true, min: 200,
filterText: (p) => p.name, sortValue: (p) => p.name,
@@ -88,7 +93,7 @@ export default function Products() {
</span>
);
} },
{ key: "details", header: "", fixed: true, width: 84, align: "num",
{ key: "details", header: "", label: "Details", fixed: true, width: 84, align: "num",
render: (p) => <Link to={`/products/${p.id}`}>Details</Link> },
];
@@ -96,9 +101,9 @@ export default function Products() {
<div>
<div className="page-head">
<div>
<h1>Produkte</h1>
<h1>{titel}</h1>
<div className="sub">
{sichtbar.length} Produkte{typ ? (typ === "food" ? " · Lebensmittel" : " · Gegenstände") : " im Katalog"}
{sichtbar.length} {fixedType ? titel : `Produkte${activeTyp ? (activeTyp === "food" ? " · Lebensmittel" : " · Gegenstände") : " im Katalog"}`}
</div>
</div>
{isAdmin && (
@@ -108,14 +113,16 @@ export default function Products() {
{error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}
<div className="segmented" style={{ marginBottom: "var(--sp-3)" }}>
<button type="button" className={typ === "" ? "active" : ""} onClick={() => setTyp("")}>Alle</button>
<button type="button" className={typ === "food" ? "active" : ""} onClick={() => setTyp("food")}>Lebensmittel</button>
<button type="button" className={typ === "object" ? "active" : ""} onClick={() => setTyp("object")}>Gegenstände</button>
</div>
{!fixedType && (
<div className="segmented" style={{ marginBottom: "var(--sp-3)" }}>
<button type="button" className={typ === "" ? "active" : ""} onClick={() => setTyp("")}>Alle</button>
<button type="button" className={typ === "food" ? "active" : ""} onClick={() => setTyp("food")}>Lebensmittel</button>
<button type="button" className={typ === "object" ? "active" : ""} onClick={() => setTyp("object")}>Gegenstände</button>
</div>
)}
<div className="card">
<DataTable id="products" columns={columns} rows={sichtbar}
<DataTable id={fixedType ? `products-${fixedType}` : "products"} columns={columns} rows={sichtbar}
getRowKey={(p) => p.id} empty="Keine Produkte gefunden." />
</div>
</div>