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:
co-authored by
Claude Opus 4.8
parent
ffbe33bec4
commit
050496a82d
+27
-28
@@ -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}>
|
||||
|
||||
Reference in New Issue
Block a user