Chargen: Anzeige und Bearbeitung in derselben Einheit + Zweitangabe
- Chargen werden in der Produkteinheit angezeigt, darunter die Zweitangabe (Basiseinheit falls abweichend und/oder Packungen). - Bearbeiten laeuft jetzt ebenfalls in der Produkteinheit (mit Einheit neben dem Feld) und rechnet beim Speichern in die Basiseinheit um - vorher zeigte die Bearbeitung einen anderen Wert als die Anzeige. - Produktkopf zeigt den Bestand zusaetzlich in Packungen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -206,6 +206,7 @@ export default function ProductForm() {
|
||||
{!isNew && product && (
|
||||
<div className="sub">
|
||||
Bestand: {fmt(product.stock / (product.unit_factor || 1))} {product.unit_name}
|
||||
{product.package_size ? ` · ${fmt(product.stock / product.package_size)} Pkg` : ""}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -287,7 +288,7 @@ export default function ProductForm() {
|
||||
|
||||
{!isNew && (
|
||||
<LotsCard
|
||||
productId={id}
|
||||
product={product}
|
||||
lots={lots}
|
||||
baseShort={baseShort}
|
||||
warnDays={warnDays}
|
||||
@@ -305,20 +306,31 @@ export default function ProductForm() {
|
||||
);
|
||||
}
|
||||
|
||||
/** Chargen-Karte mit Bearbeiten/Löschen. */
|
||||
function LotsCard({ productId, lots, baseShort, warnDays, isAdmin, imageUrl, onChanged, onError }) {
|
||||
/** Chargen-Karte mit Bearbeiten/Löschen. Bearbeitet wird in der Produkteinheit. */
|
||||
function LotsCard({ product, lots, baseShort, warnDays, isAdmin, imageUrl, onChanged, onError }) {
|
||||
const [editId, setEditId] = useState(null);
|
||||
const [draft, setDraft] = useState({ quantity: "", best_before: "" });
|
||||
|
||||
const factor = product?.unit_factor || 1;
|
||||
const unitName = product?.unit_name || baseShort;
|
||||
const pkgSize = product?.package_size || 0;
|
||||
// Zweitangabe: Basiseinheit (falls abweichend) und/oder Packungen.
|
||||
function secondary(qty) {
|
||||
const parts = [];
|
||||
if (factor !== 1) parts.push(`${fmt(qty)} ${baseShort}`);
|
||||
if (pkgSize > 0) parts.push(`${fmt(qty / pkgSize)} Pkg`);
|
||||
return parts.join(" · ");
|
||||
}
|
||||
|
||||
function startEdit(l) {
|
||||
setEditId(l.id);
|
||||
setDraft({ quantity: l.quantity, best_before: l.best_before || "" });
|
||||
setDraft({ quantity: l.quantity / factor, best_before: l.best_before || "" });
|
||||
}
|
||||
|
||||
async function saveEdit(l) {
|
||||
try {
|
||||
await api.updateLot(l.id, {
|
||||
quantity: Number(draft.quantity),
|
||||
quantity: Number(draft.quantity) * factor,
|
||||
best_before: draft.best_before || null,
|
||||
});
|
||||
setEditId(null);
|
||||
@@ -361,11 +373,19 @@ function LotsCard({ productId, lots, baseShort, warnDays, isAdmin, imageUrl, onC
|
||||
<tr key={l.id} className={cls}>
|
||||
<td className="num">
|
||||
{editing ? (
|
||||
<div className="field-inline" style={{ justifyContent: "flex-end" }}>
|
||||
<input type="number" step="any" min="0" value={draft.quantity}
|
||||
onChange={(e) => setDraft({ ...draft, quantity: e.target.value })}
|
||||
style={{ maxWidth: 100, marginTop: 0 }} />
|
||||
style={{ maxWidth: 90, marginTop: 0 }} />
|
||||
<span className="muted small">{unitName}</span>
|
||||
</div>
|
||||
) : (
|
||||
<>{fmt(l.quantity)} {baseShort}</>
|
||||
<>
|
||||
{fmt(l.quantity / factor)} {unitName}
|
||||
{secondary(l.quantity) && (
|
||||
<div className="muted small">{secondary(l.quantity)}</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
@@ -406,7 +426,10 @@ function LotsCard({ productId, lots, baseShort, warnDays, isAdmin, imageUrl, onC
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="muted small">Mengen sind in der Basiseinheit ({baseShort}) angegeben.</p>
|
||||
<p className="muted small">
|
||||
Mengen in {unitName}
|
||||
{pkgSize > 0 ? `; 1 Packung = ${fmt(pkgSize)} ${baseShort}` : ""}.
|
||||
</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user