Tabellen entzerrt, EAN-Codes mit Marke und Artikelname, Codes-Block nach unten
EAN-Codes:
- Das Kennzeichen "Artikel" ist weg; stattdessen stehen Marke und Artikelname
zusammen ("Zweifel - Moutarde Original Chips"). Die Marke allein reichte nicht,
um einen Code wiederzuerkennen. Hinweistext entsprechend angepasst.
Produktseite:
- "Weitere EAN-Codes" steht jetzt unterhalb von Formular und Chargen statt als
dritte Spalte dazwischen. Die Codes braucht man selten und sie schoben die
beiden wichtigen Bloecke auseinander.
Tabellen:
- "overflow-wrap: anywhere" galt fuer ALLE Zellen und zerriss Woerter mitten
drin ("PROD UKTE", "555 Gram m"). Jetzt nur noch gezielt per Klasse.
- Kopfzeilen und Zahl-plus-Einheit brechen nicht mehr um.
- Eingaben in Tabellen sind kompakter (kleinere Polsterung, Zahlenfelder 8ch),
Auswahlfelder richten sich nach ihrem Text statt 132px Mindestbreite -
dadurch sind die Zeilen deutlich schlanker.
- Kennzeichen wie "niedrig" oder "abgelaufen" sitzen ueber .cell-row in einer
Zeile mit dem Wert und rutschen nicht mehr je nach Zeilenhoehe herum.
Geprueft: "npm run build" laeuft durch. Backend unveraendert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -105,14 +105,16 @@ export default function Groups() {
|
||||
return (
|
||||
<tr key={g.id}>
|
||||
<td data-label="Gruppe">
|
||||
{isAdmin ? (
|
||||
<input defaultValue={g.name} style={{ marginTop: 0, minWidth: 130 }}
|
||||
onBlur={(e) => {
|
||||
const v = e.target.value.trim();
|
||||
if (v && v !== g.name) patch(g, { name: v });
|
||||
}} />
|
||||
) : <span className="strong">{g.name}</span>}
|
||||
{low && <span className="badge warn" style={{ marginLeft: 6 }}>niedrig</span>}
|
||||
<span className="cell-row">
|
||||
{isAdmin ? (
|
||||
<input defaultValue={g.name} style={{ marginTop: 0, minWidth: 120 }}
|
||||
onBlur={(e) => {
|
||||
const v = e.target.value.trim();
|
||||
if (v && v !== g.name) patch(g, { name: v });
|
||||
}} />
|
||||
) : <span className="strong">{g.name}</span>}
|
||||
{low && <span className="badge warn">niedrig</span>}
|
||||
</span>
|
||||
</td>
|
||||
<td data-label="Produkte" className="num muted">{g.product_count}</td>
|
||||
<td data-label="Bestand" className="num">{fmt(g.stock)} {g.min_stock_unit_name || ""}</td>
|
||||
@@ -173,10 +175,10 @@ export default function Groups() {
|
||||
barcodes={selected.barcodes || []}
|
||||
productBarcodes={selected.product_barcodes || []}
|
||||
disabled={!isAdmin}
|
||||
hint={"Codes der zugeordneten Artikel stehen automatisch hier, gekennzeichnet mit " +
|
||||
"„Artikel“ und der Marke; 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 die Marke fehlt. " +
|
||||
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) => {
|
||||
|
||||
@@ -387,28 +387,6 @@ export default function ProductForm() {
|
||||
{readOnly && <p className="muted small mt-0">Nur Administratoren können Produkte bearbeiten.</p>}
|
||||
</form>
|
||||
|
||||
{!isNew && product && (
|
||||
<section className="card">
|
||||
<div className="card-head"><Icon name="search" /><h2>Weitere EAN-Codes</h2></div>
|
||||
<BarcodeList
|
||||
barcodes={product.barcodes || []}
|
||||
disabled={readOnly}
|
||||
hint="Nützlich, wenn dasselbe Produkt mehrere Codes hat (z.B. Aktionspackung)."
|
||||
onAdd={async (body) => {
|
||||
try {
|
||||
setProduct(await api.addProductBarcode(id, body));
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onDelete={async (code) => {
|
||||
try {
|
||||
await api.deleteProductBarcode(id, code);
|
||||
setProduct(await api.getProduct(id));
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{!isNew && (
|
||||
<LotsCard
|
||||
product={product}
|
||||
@@ -425,6 +403,30 @@ export default function ProductForm() {
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Unterhalb der beiden Spalten: die Codes braucht man selten, sie sollen
|
||||
Formular und Chargen nicht auseinanderschieben. */}
|
||||
{!isNew && product && (
|
||||
<section className="card">
|
||||
<div className="card-head"><Icon name="search" /><h2>Weitere EAN-Codes</h2></div>
|
||||
<BarcodeList
|
||||
barcodes={product.barcodes || []}
|
||||
disabled={readOnly}
|
||||
hint="Nützlich, wenn dasselbe Produkt mehrere Codes hat (z.B. Aktionspackung)."
|
||||
onAdd={async (body) => {
|
||||
try {
|
||||
setProduct(await api.addProductBarcode(id, body));
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
onDelete={async (code) => {
|
||||
try {
|
||||
await api.deleteProductBarcode(id, code);
|
||||
setProduct(await api.getProduct(id));
|
||||
} catch (err) { setError(err.message); }
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,12 +100,14 @@ export default function Products() {
|
||||
: <span className="thumb thumb-fallback"><Icon name="box" size={16} /></span>}
|
||||
</td>
|
||||
<td data-label="Name" className="strong">
|
||||
{p.name}
|
||||
{p.expired_count > 0 && (
|
||||
<span className="badge danger" style={{ marginLeft: 6 }}>
|
||||
<Icon name="alert" size={12} />{p.expired_count} abgelaufen
|
||||
</span>
|
||||
)}
|
||||
<span className="cell-row">
|
||||
<span>{p.name}</span>
|
||||
{p.expired_count > 0 && (
|
||||
<span className="badge danger nowrap">
|
||||
<Icon name="alert" size={12} />{p.expired_count} abgelaufen
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</td>
|
||||
<td data-label="Marke" className="muted">{p.brand || "–"}</td>
|
||||
<td data-label="Kategorie" className="muted">{p.category_name || "–"}</td>
|
||||
@@ -119,10 +121,14 @@ export default function Products() {
|
||||
{fmt(p.stock / (p.unit_factor || 1))} {p.unit_name || unitShort(p.base_unit)}
|
||||
</td>
|
||||
<td data-label="Einheiten" className="num">
|
||||
{fmt(p.stock / unitCount(p))}
|
||||
{p.min_stock != null ? ` / ${fmt(p.min_stock / unitCount(p))}` : ""}{" "}
|
||||
{countLabel(p)}
|
||||
{low && <span className="badge warn" style={{ marginLeft: 6 }}>niedrig</span>}
|
||||
<span className="cell-row" style={{ justifyContent: "flex-end" }}>
|
||||
<span>
|
||||
{fmt(p.stock / unitCount(p))}
|
||||
{p.min_stock != null ? ` / ${fmt(p.min_stock / unitCount(p))}` : ""}{" "}
|
||||
{countLabel(p)}
|
||||
</span>
|
||||
{low && <span className="badge warn">niedrig</span>}
|
||||
</span>
|
||||
</td>
|
||||
<td className="num"><Link to={`/products/${p.id}`}>Details</Link></td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user