fix(ui): line-item number inputs — allow clearing the 0 (store raw string, coerce at totals/save), unify value alignment, widen Množství column
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -141,9 +141,13 @@ interface OrderItem {
|
||||
_key: string;
|
||||
description: string;
|
||||
item_description: string;
|
||||
quantity: number;
|
||||
// Held as the raw typed string while editing so the field can be cleared
|
||||
// (empty renders fine in a type="number" input). Coerced via Number(x) || 0
|
||||
// only where used (live totals + save payload). vat_rate stays numeric: it
|
||||
// is edited via a Select, never a free-text number input.
|
||||
quantity: string | number;
|
||||
unit: string;
|
||||
unit_price: number;
|
||||
unit_price: string | number;
|
||||
vat_rate: number;
|
||||
}
|
||||
|
||||
@@ -284,10 +288,8 @@ function SortableOrderRow({
|
||||
<TextField
|
||||
label="Množství"
|
||||
type="number"
|
||||
value={item.quantity}
|
||||
onChange={(e) =>
|
||||
onUpdate(index, "quantity", Number(e.target.value))
|
||||
}
|
||||
value={item.quantity ?? ""}
|
||||
onChange={(e) => onUpdate(index, "quantity", e.target.value)}
|
||||
slotProps={{ htmlInput: { min: "0", step: "any" } }}
|
||||
InputProps={{ readOnly }}
|
||||
/>
|
||||
@@ -301,10 +303,8 @@ function SortableOrderRow({
|
||||
<TextField
|
||||
label="Jedn. cena"
|
||||
type="number"
|
||||
value={item.unit_price}
|
||||
onChange={(e) =>
|
||||
onUpdate(index, "unit_price", Number(e.target.value))
|
||||
}
|
||||
value={item.unit_price ?? ""}
|
||||
onChange={(e) => onUpdate(index, "unit_price", e.target.value)}
|
||||
slotProps={{ htmlInput: { step: "any" } }}
|
||||
InputProps={{ readOnly }}
|
||||
/>
|
||||
@@ -401,8 +401,8 @@ function SortableOrderRow({
|
||||
<TableCell>
|
||||
<TextField
|
||||
type="number"
|
||||
value={item.quantity}
|
||||
onChange={(e) => onUpdate(index, "quantity", Number(e.target.value))}
|
||||
value={item.quantity ?? ""}
|
||||
onChange={(e) => onUpdate(index, "quantity", e.target.value)}
|
||||
slotProps={{ htmlInput: { min: "0", step: "any" } }}
|
||||
InputProps={{ readOnly }}
|
||||
sx={{ "& input": { textAlign: "center" } }}
|
||||
@@ -420,10 +420,8 @@ function SortableOrderRow({
|
||||
<TableCell>
|
||||
<TextField
|
||||
type="number"
|
||||
value={item.unit_price}
|
||||
onChange={(e) =>
|
||||
onUpdate(index, "unit_price", Number(e.target.value))
|
||||
}
|
||||
value={item.unit_price ?? ""}
|
||||
onChange={(e) => onUpdate(index, "unit_price", e.target.value)}
|
||||
slotProps={{ htmlInput: { step: "any" } }}
|
||||
InputProps={{ readOnly }}
|
||||
sx={{ "& input": { textAlign: "right" } }}
|
||||
@@ -740,9 +738,11 @@ export default function IssuedOrderDetail() {
|
||||
.map((it, i) => ({
|
||||
description: it.description,
|
||||
item_description: it.item_description,
|
||||
quantity: it.quantity,
|
||||
// Coerce the raw typed strings back to numbers so an empty/partial
|
||||
// field never reaches the server as NaN (mirrors the totals math).
|
||||
quantity: Number(it.quantity) || 0,
|
||||
unit: it.unit,
|
||||
unit_price: it.unit_price,
|
||||
unit_price: Number(it.unit_price) || 0,
|
||||
vat_rate: it.vat_rate,
|
||||
position: i,
|
||||
})),
|
||||
@@ -1135,7 +1135,7 @@ export default function IssuedOrderDetail() {
|
||||
#
|
||||
</TableCell>
|
||||
<TableCell>Popis</TableCell>
|
||||
<TableCell sx={{ width: "5.5rem" }} align="center">
|
||||
<TableCell sx={{ width: "7rem" }} align="center">
|
||||
Množství
|
||||
</TableCell>
|
||||
<TableCell sx={{ width: "5.5rem" }} align="center">
|
||||
|
||||
Reference in New Issue
Block a user