Web: Kategorien (Baum), Gruppen, Einheiten, Gebinde auf DataTable

Restliche Tabellenseiten auf die filterbare DataTable umgestellt. Kategorien nutzen den neuen Tree-Modus (ein-/ausklappbar wie bisher; sobald gefiltert/sortiert wird, flache Liste). Inline-Bearbeitung (Namen, Art, uebergeordnet, Mindestbestand, Gebinde-Formen) bleibt in den Zell-Renderern erhalten; Seiten-Formulare/Panels unveraendert. Damit haben Produkte, Einzelstuecke, Kategorien, Gruppen, Einheiten und Gebinde die gleiche Filter-/Spalten-Bedienung.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 15:10:00 +02:00
co-authored by Claude Opus 4.8
parent ffbe33bec4
commit 050496a82d
6 changed files with 254 additions and 281 deletions
+27 -28
View File
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import { api } from "../api";
import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import DataTable from "../components/DataTable";
import { fmt } from "../units";
const KIND_LABEL = { count: "Anzahl (Stück)", weight: "Gewicht (Basis: Gramm)", volume: "Volumen (Basis: Milliliter)" };
@@ -52,6 +53,28 @@ export default function Units() {
const baseUnitOfKind = { count: "Stück", weight: "Gramm", volume: "Milliliter" };
const columns = [
{ key: "name", header: "Name", grow: true, min: 160,
filterText: (u) => u.name, sortValue: (u) => u.name,
render: (u) => (
<span className="cell-row">
<span className="strong">{u.name}</span>
{u.is_builtin && <span className="badge nowrap">eingebaut</span>}
</span>
) },
{ key: "kind", header: "Art", width: 230, filterText: (u) => KIND_LABEL[u.kind] || u.kind,
render: (u) => <span className="muted">{KIND_LABEL[u.kind] || u.kind}</span> },
{ key: "factor", header: "Faktor", width: 150, align: "num", sortValue: (u) => u.factor,
filterText: (u) => `${fmt(u.factor)} ${baseUnitOfKind[u.kind]}`,
render: (u) => `${fmt(u.factor)} ${baseUnitOfKind[u.kind]}` },
{ key: "actions", header: "", fixed: true, width: 56, align: "num",
render: (u) => (!u.is_builtin && (
<button className="btn-icon danger" onClick={() => remove(u)} title="Löschen">
<Icon name="trash" size={16} />
</button>
)) },
];
return (
<div>
<div className="page-head">
@@ -62,34 +85,10 @@ export default function Units() {
</div>
{error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}
<div className="grid-2">
<div className="card" style={{ padding: 0 }}>
<div className="table-wrap">
<table className="table">
<thead><tr><th>Name</th><th>Art</th><th className="num">Faktor</th><th></th></tr></thead>
<tbody>
{units.map((u) => (
<tr key={u.id}>
<td data-label="Name" className="strong">
<span className="cell-row">
<span>{u.name}</span>
{u.is_builtin && <span className="badge nowrap">eingebaut</span>}
</span>
</td>
<td data-label="Art" className="muted">{KIND_LABEL[u.kind] || u.kind}</td>
<td data-label="Faktor" className="num">{fmt(u.factor)} {baseUnitOfKind[u.kind]}</td>
<td className="num">
{!u.is_builtin && (
<button className="btn-icon danger" onClick={() => remove(u)} title="Löschen">
<Icon name="trash" size={16} />
</button>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="grid-2 wide-aside">
<div className="card">
<DataTable id="units" columns={columns} rows={units}
getRowKey={(u) => u.id} empty="Noch keine Einheiten." />
</div>
<form className="card" onSubmit={add}>