Files
mercadodevida/work/artifacts/F-082/architect.md
2026-08-20 06:04:22 +02:00

3.5 KiB

F-082 — Architect: /inventory editable fields cannot be saved; Stock UX needs click-to-edit

Root cause

Two views both have inline-edit affordances with subtle UX gaps:

A) Standalone /inventory page (apps/admin/src/app/(dashboard)/inventory/page.tsx)

  • SKU and EAN are already click-to-edit and save on blur/Enter via handleSaveSku/handleSaveEan.
  • Stock opens edit mode on click but the operator still has to click an OK button to persist. Cancel is via ✕. This violates the desired "save on blur or Enter" UX.

B) InventorySection.tsx (inventory tab inside the product editor)

  • Precio neto: opens via ✏️ pencil, saves via OK button (no Enter/blur save).
  • Stock: opens via ✏️ pencil, saves via OK button.
  • SKU and EAN: not editable at all (plain text in the table) — silent loss if anyone tries.

Design

Standardise on click-to-edit + save on blur/Enter for every editable cell. Remove pencil icons and OK buttons where they exist. Pattern:

<button onClick={() => enterEdit(id)}>{value}</button>
   ↳ swaps to
<input autoFocus
       value={editValue}
       onChange={...}
       onBlur={() => save(id)}
       onKeyDown={e => { if (e.key === 'Enter') save(id); if (e.key === 'Escape') cancel(id); }}
       disabled={saving}
/>

Files / changes

  1. apps/admin/src/app/(dashboard)/inventory/page.tsx

    • Stock cell: drop the OK button and ✕ button. Save fires on blur and Enter; cancel on Escape restores the original stock value.
    • Existing msg indicator shows the save state.
    • SKU and EAN unchanged (they already work).
  2. apps/admin/src/features/products/components/sections/InventorySection.tsx

    • Stock: replace ✏️ + OK + ✕ pattern with the same click-to-edit + save on blur/Enter pattern.
    • Precio neto: same — drop OK and ✕, save on Enter/blur.
    • SKU: add inline editing (was plain text). Click cell → input → save on blur/Enter → productsApi.updateVariant(productId, variantId, { sku }).
    • EAN: add inline editing (was plain text). Same mechanism; null when empty.
    • IVA select: stays as-is (already click-to-edit without explicit pencil).

Persistence

All edits call existing PATCH endpoints:

  • productsApi.updateVariant(productId, variantId, { sku | ean })
  • pricingApi.setVariantPrice(variantId, cents, vatRate)
  • inventoryApi.setStock(variantId, qty)

No new endpoints, no schema changes.

Failure handling

  • On API failure the existing inline saveMsg shows Error; cell reverts via cancelEdit* which restores the value from the row state.
  • The previous value is held in state until the API response arrives so the cell can revert cleanly.

Concurrency

A simple saving flag per cell disables the input and prevents double-submit. Last-write-wins on the backend (existing behaviour).

Risk

Low. Pure UX refactor, no API contract change.

Acceptance mapping

  • "Every editable cell in /inventory saves on blur or Enter via PATCH /variants/:id" → all cells adopt the click-to-edit + onBlur/onKeyDown pattern.
  • "Stock cell enters edit mode on a single click; the pencil icon is removed" → button value is the cell value; no pencil.
  • "Successful save shows visual confirmation" → msg chip shows ✓.
  • "Failed save shows inline error and restores the previous value" → saveMsg + cancelEdit path.
  • "No regressions in the existing Prices tab or product editor" → changes scoped to InventorySection + /inventory page.
  • "verify.sh is green" → typecheck + lint clean.