Files
mercadodevida/work/artifacts/F-123/architect.md
2026-08-21 17:36:50 +02:00

3.6 KiB

F-123 — Editor de producto: quitar gate, reorder y selector de peso en gramos

Diagnóstico

F-121 (a40d78d) y F-107 (reorder previo) fueron fixes parciales:

  1. Gate "Guarda primero" sigue activo: ProductEditor.tsx líneas 286 y 374 mantienen los div con el warning. F-121 solo cambió el flujo post-save (router.push → router.replace + setProductId), no eliminó los textos. Bundle live 15z1dcv3uvf3z.js aún contiene "Guarda primero" (1 ocurrencia).
  2. Reorder incompleto: Marca / Canal / Caducidad están en ProductEditor.tsx después de Descripción. El operador quiere esos campos antes de Descripción, justo debajo de Peso unitario.
  3. Peso unitario en kg con input libre: actualmente <input type="text" value={unitWeightKg}> con label "Peso unitario (kg)". El operador quiere:
    • Label "Peso unitario (Gr)"
    • Select dropdown con valores [100, 150, 200, 250, 300, 350, 500, 740, custom]
    • Al elegir "custom" mostrar input libre en gramos
    • Convertir a kg al guardar (dividir por 1000)

Diseño

Cambios

  1. ProductEditor.tsx — Eliminar los dos bloques condicionales {productId ? <Section/> : <Warning/>}. Renderizar siempre:

    • <PriceStockSection productId={productId} /> (productId puede ser undefined)
    • <ImagesSection productId={productId} /> (idem)
  2. PriceStockSection.tsx — Aceptar productId?: string:

    • Si productId es undefined → renderizar el formulario con inputs activos, pero desactivar los botones de guardado y mostrar caption "Se guardará al crear el producto".
    • Si productId definido y la variante aún no carga → mantener el warning actual de "no datos internos de venta".
    • Si productId definido y variante cargada → comportamiento normal.
  3. ImagesSection.tsx — Aceptar productId?: string:

    • Si productId undefined → mostrar UI con inputs/área de drop deshabilitados y caption.
    • Si productId definido → comportamiento normal.

Garantías

  • Sin cambios en backend.
  • Sin cambios en tipos del API client.
  • Los productos ya creados siguen funcionando idéntico (productId siempre truthy → mismo path que antes).
  • Para nuevos productos: el operador puede escribir precio, stock, EAN y planificar imágenes desde el inicio; al pulsar "Crear producto" el bundle se persiste (precio/stock/EAN se guardan con setVariantPrice/setStock/updateVariant tras crear el id; las imágenes vía upload + POST /products/:id/images). El caption avisa que los botones de guardado individual están inactivos hasta tener id.

Riesgos

  • Bajo. Cambios puramente UI. Sin migraciones, sin API, sin tipos.

Plan de implementación

  1. Editar ProductEditor.tsx:
    • Quitar los dos bloques de warning.
    • Renderizar siempre <PriceStockSection> y <ImagesSection>.
    • Mover el bloque Marca/Canal/Caducidad a estar después de <PriceStockSection> y antes de Descripción.
  2. Editar PriceStockSection.tsx:
    • Prop opcional productId?: string + flag pending.
    • Early return si pending → renderizar UI deshabilitada.
    • Reemplazar input libre de peso por <select> con opciones [100,150,200,250,300,350,500,740,custom]. Custom muestra input auxiliar.
    • Convertir gramos → kg al llamar API.
  3. Editar ImagesSection.tsx:
    • Prop opcional productId?: string.
    • Estado pending → renderizar UI deshabilitada con caption.
  4. npx tsc --noEmit en apps/admin.
  5. npm run build en apps/admin.
  6. Reiniciar admin (monolith.sh prod restart).
  7. Verificar bundle servido: curl /products/new | grep "Guarda primero" → 0 ocurrencias; HTML contiene el dropdown.
  8. Cerrar gates.