Web: Gruppentabelle auf volle Breite, Karten darunter
Die Seite hatte die Tabelle links und eine feste rechte Spalte (24% der Breite). Seit die Tabelle Obergruppen, Bestand mit Einheit und die Gebinde-Erlaeuterung traegt, war die rechte Spalte teurer als sie half - und sie stand auch dann da, wenn gar keine Gruppe ausgewaehlt war. Jetzt bekommt die Tabelle die volle Breite. "Neue Gruppe" steht darunter, die Karten zur ausgewaehlten Gruppe (EAN-Codes, Mindestbestand) erscheinen beim "verwalten" ebenfalls darunter, nebeneinander. Kein Springen des Layouts beim Auswaehlen, weil die Tabelle ihre Breite nie aendert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -246,55 +246,57 @@ export default function Groups() {
|
||||
</div>
|
||||
{error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}
|
||||
|
||||
<div className="grid-2 wide-aside">
|
||||
<div className="card">
|
||||
<DataTable id="groups" columns={columns} rows={baumZeilen} loading={loading}
|
||||
getRowKey={(g) => g._pfad}
|
||||
tree={{ column: "name", idOf: (g) => g._pfad, parentIdOf: (g) => g._elternPfad }}
|
||||
empty="Noch keine Gruppen." />
|
||||
</div>
|
||||
{/* Die Tabelle bekommt die volle Breite – bei vielen Spalten (Obergruppen,
|
||||
Bestand, Einheit) war die rechte Spalte teurer als sie half. Alles
|
||||
Übrige steht darunter. */}
|
||||
<div className="card">
|
||||
<DataTable id="groups" columns={columns} rows={baumZeilen} loading={loading}
|
||||
getRowKey={(g) => g._pfad}
|
||||
tree={{ column: "name", idOf: (g) => g._pfad, parentIdOf: (g) => g._elternPfad }}
|
||||
empty="Noch keine Gruppen." />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{selected && (
|
||||
<section className="card">
|
||||
<div className="card-head">
|
||||
<Icon name="search" />
|
||||
<h2>EAN-Codes der Gruppe: {selected.name}</h2>
|
||||
</div>
|
||||
<BarcodeList
|
||||
barcodes={selected.barcodes || []}
|
||||
productBarcodes={selected.product_barcodes || []}
|
||||
disabled={!isAdmin}
|
||||
hint={"Codes der zugeordneten Artikel stehen automatisch hier, mit Marke und " +
|
||||
"Artikelnamen; entfernen lassen sie sich nur, indem der Artikel die Gruppe " +
|
||||
"wechselt. Zusätzlich sind Codes möglich, die noch zu keinem Artikel " +
|
||||
"gehören – für die gibt es eine Notiz, weil ihnen der Artikelname fehlt. " +
|
||||
"Wird so ein Code beim Einlagern gescannt, landet der neu angelegte Artikel " +
|
||||
"automatisch hier."}
|
||||
onAdd={async (body) => {
|
||||
try {
|
||||
await api.addGroupBarcode(selected.id, body);
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onEditNote={async (code, note) => {
|
||||
try {
|
||||
await api.updateGroupBarcodeNote(selected.id, code, { note });
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onDelete={async (code) => {
|
||||
try {
|
||||
await api.deleteGroupBarcode(selected.id, code);
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
/>
|
||||
<button className="btn ghost" onClick={() => setSelectedId(null)}>Schließen</button>
|
||||
</section>
|
||||
)}
|
||||
{/* Karten zur AUSGEWÄHLTEN Gruppe – erscheinen erst beim „verwalten". */}
|
||||
{selected && (
|
||||
<div className="grid-2" style={{ marginTop: "var(--sp-3)" }}>
|
||||
<section className="card">
|
||||
<div className="card-head">
|
||||
<Icon name="search" />
|
||||
<h2>EAN-Codes der Gruppe: {selected.name}</h2>
|
||||
</div>
|
||||
<BarcodeList
|
||||
barcodes={selected.barcodes || []}
|
||||
productBarcodes={selected.product_barcodes || []}
|
||||
disabled={!isAdmin}
|
||||
hint={"Codes der zugeordneten Artikel stehen automatisch hier, mit Marke und " +
|
||||
"Artikelnamen; entfernen lassen sie sich nur, indem der Artikel die Gruppe " +
|
||||
"wechselt. Zusätzlich sind Codes möglich, die noch zu keinem Artikel " +
|
||||
"gehören – für die gibt es eine Notiz, weil ihnen der Artikelname fehlt. " +
|
||||
"Wird so ein Code beim Einlagern gescannt, landet der neu angelegte Artikel " +
|
||||
"automatisch hier."}
|
||||
onAdd={async (body) => {
|
||||
try {
|
||||
await api.addGroupBarcode(selected.id, body);
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onEditNote={async (code, note) => {
|
||||
try {
|
||||
await api.updateGroupBarcodeNote(selected.id, code, { note });
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onDelete={async (code) => {
|
||||
try {
|
||||
await api.deleteGroupBarcode(selected.id, code);
|
||||
await load();
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
/>
|
||||
<button className="btn ghost" onClick={() => setSelectedId(null)}>Schließen</button>
|
||||
</section>
|
||||
|
||||
{selected && isAdmin && (
|
||||
{isAdmin && (
|
||||
<section className="card">
|
||||
<div className="card-head">
|
||||
<Icon name="location" />
|
||||
@@ -318,51 +320,52 @@ export default function Groups() {
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{isAdmin && (
|
||||
<form className="card" onSubmit={add}>
|
||||
<div className="card-head"><Icon name="tag" /><h2>Neue Gruppe</h2></div>
|
||||
<label>
|
||||
Name
|
||||
<input placeholder="z.B. Mehl" value={form.name}
|
||||
onChange={(e) => setForm({ ...form, name: e.target.value })} required />
|
||||
</label>
|
||||
<div className="row">
|
||||
<label className="grow">
|
||||
Mindestbestand (optional)
|
||||
<input type="number" step="any" value={form.min_stock}
|
||||
onChange={(e) => setForm({ ...form, min_stock: e.target.value })} placeholder="z.B. 2" />
|
||||
</label>
|
||||
<label className="grow">
|
||||
Einheit
|
||||
<select value={form.min_stock_unit_id}
|
||||
onChange={(e) => setForm({ ...form, min_stock_unit_id: e.target.value })}>
|
||||
<option value="">– Basiseinheit –</option>
|
||||
{units.map((u) => <option key={u.id} value={u.id}>{u.name}</option>)}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<label>
|
||||
Obergruppen (optional)
|
||||
<GroupParentSelect
|
||||
groups={groups}
|
||||
selfId={null}
|
||||
value={form.parent_ids}
|
||||
onChange={(ids) => setForm({ ...form, parent_ids: ids })}
|
||||
/>
|
||||
</label>
|
||||
<button className="btn primary"><Icon name="plus" size={16} />Anlegen</button>
|
||||
<p className="muted small">
|
||||
Bestand und Mindestbestand einer Gruppe zählen auch die Artikel ihrer
|
||||
Untergruppen. Eine Gruppe darf unter mehreren Obergruppen hängen —
|
||||
„Grillwurst“ etwa unter „Wurst“ <em>und</em> unter „Grillgut“.
|
||||
Gezählt werden nur Artikel, die zur gewählten Einheit passen, auch in
|
||||
den Untergruppen. Namen lassen sich in der Tabelle direkt ändern.
|
||||
</p>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isAdmin && (
|
||||
<form className="card" onSubmit={add}
|
||||
style={{ marginTop: "var(--sp-3)", maxWidth: 560 }}>
|
||||
<div className="card-head"><Icon name="tag" /><h2>Neue Gruppe</h2></div>
|
||||
<label>
|
||||
Name
|
||||
<input placeholder="z.B. Mehl" value={form.name}
|
||||
onChange={(e) => setForm({ ...form, name: e.target.value })} required />
|
||||
</label>
|
||||
<div className="row">
|
||||
<label className="grow">
|
||||
Mindestbestand (optional)
|
||||
<input type="number" step="any" value={form.min_stock}
|
||||
onChange={(e) => setForm({ ...form, min_stock: e.target.value })} placeholder="z.B. 2" />
|
||||
</label>
|
||||
<label className="grow">
|
||||
Einheit
|
||||
<select value={form.min_stock_unit_id}
|
||||
onChange={(e) => setForm({ ...form, min_stock_unit_id: e.target.value })}>
|
||||
<option value="">– Basiseinheit –</option>
|
||||
{units.map((u) => <option key={u.id} value={u.id}>{u.name}</option>)}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<label>
|
||||
Obergruppen (optional)
|
||||
<GroupParentSelect
|
||||
groups={groups}
|
||||
selfId={null}
|
||||
value={form.parent_ids}
|
||||
onChange={(ids) => setForm({ ...form, parent_ids: ids })}
|
||||
/>
|
||||
</label>
|
||||
<button className="btn primary"><Icon name="plus" size={16} />Anlegen</button>
|
||||
<p className="muted small">
|
||||
Bestand und Mindestbestand einer Gruppe zählen auch die Artikel ihrer
|
||||
Untergruppen. Eine Gruppe darf unter mehreren Obergruppen hängen —
|
||||
„Grillwurst“ etwa unter „Wurst“ <em>und</em> unter „Grillgut“.
|
||||
Gezählt werden nur Artikel, die zur gewählten Einheit passen, auch in
|
||||
den Untergruppen. Namen lassen sich in der Tabelle direkt ändern.
|
||||
</p>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user