fix(11): address code-review findings in catalog inline-edit

- WR-01: remove blur-commit on EditableCell toggle (onChange already saves+closes; prevents double updateServiceField)
- WR-02: skip server action when cell value unchanged (commit + new commitOnBlur dirty-check)
- WR-03: on blur, revert required-empty field via cancel() instead of leaving the cell stuck in error state
- WR-04: normalize it-IT price input (1.234,50) before parse; Number() rejects trailing garbage
- IN-01: render row error in its own <tr> instead of an invalid 7th <td> in a 6-column row

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 21:02:50 +02:00
parent 8d62207ccb
commit 42c16e1bab
3 changed files with 45 additions and 9 deletions
+10 -2
View File
@@ -93,8 +93,16 @@ export async function updateServiceField(
const s = String(value).trim();
await db.update(services).set({ category: s || null }).where(eq(services.id, serviceId));
} else if (fieldName === "unit_price") {
const num = parseFloat(String(value));
if (isNaN(num) || num < 0) throw new Error("Prezzo invalido");
// Normalize locale-formatted input (WR-04): the cell displays it-IT (€1.234,50),
// so an admin may type "1.234,50". When a comma is present, treat "." as thousands
// separators and "," as the decimal mark; otherwise parse "." as the decimal mark.
// Number() (not parseFloat) rejects trailing garbage like "12abc".
const rawInput = String(value).trim();
const normalized = rawInput.includes(",")
? rawInput.replace(/\./g, "").replace(",", ".")
: rawInput;
const num = Number(normalized);
if (!Number.isFinite(num) || num < 0) throw new Error("Prezzo invalido");
await db.update(services).set({ unit_price: num.toFixed(2) }).where(eq(services.id, serviceId));
} else if (fieldName === "active") {
const boolValue = typeof value === "boolean" ? value : value === "true";