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

61 lines
3.6 KiB
Markdown

# 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.