# F-135 — Drop zone funcional en estado pending + cola de subida ## Cambios ### `apps/admin/src/features/products/components/sections/ImagesSection.tsx` #### Estado nuevo ```ts const [pendingFiles, setPendingFiles] = useState([]); const prevProductIdRef = useRef(productId); ``` #### `handleFileInput` actualizado - Si hay `productId` → llama `uploadFile(file)` directamente - Si no hay `productId` → encola con `queueFile(file)` #### `handleDrop` actualizado - Acepta múltiples archivos: `Array.from(e.dataTransfer.files).filter(f => f.type.startsWith('image/'))` - Si hay `productId` → sube en serie (para evitar carreras) - Si no hay `productId` → encola todos en `pendingFiles` #### Nuevo `queueFile` ```ts const queueFile = (file: File) => { setPendingFiles(prev => [...prev, file]); }; ``` #### Nuevo efecto de drenaje ```ts useEffect(() => { const prev = prevProductIdRef.current; prevProductIdRef.current = productId; if (!productId || prev === productId) return; if (pendingFiles.length === 0) return; const queue = pendingFiles; setPendingFiles([]); void (async () => { for (const f of queue) { await uploadFile(f); } })(); }, [productId]); ``` Cuando `productId` pasa de `undefined` a un UUID (es decir, el padre creó el producto y llamó `setProductId(saved.id)`), el efecto dispara la subida automática de todos los archivos encolados. Se ejecuta **una sola vez** por transición (gracias al ref que guarda el valor anterior). #### Bloque pending rediseñado La zona de drop **ahora tiene los handlers `onDragOver` / `onDragLeave` / `onDrop`** (antes no los tenía). Visualmente: - Cambia color al hacer drag-over (verde marca) - Si hay archivos encolados, muestra caption: `N imagen(es) en cola — se subirán al crear el producto` ## Comportamiento resultante ### `/products/new` (sin productId) 1. Operador arrastra imágenes → se encolan localmente 2. Operador rellena nombre y pulsa "Crear producto" 3. Backend responde con `saved.id`, ProductEditor llama `setProductId(saved.id)` 4. El efecto dispara: sube todos los archivos encolados → backend los adjunta al producto 5. La lista de imágenes aparece populated ### `/products/[id]` (con productId) - Drag-drop y file picker funcionan igual que antes (subida inmediata) ## Verificación - `cd apps/admin && npx tsc --noEmit` → exit 0. - `cd apps/admin && NEXT_PUBLIC_API_URL=http://192.168.18.93:3000 npm run build` → exit 0. ## Notas - El caption del header cambió de "Se guardarán al crear el producto" a "Se subirán al crear el producto" (más preciso ahora que las imágenes sí se suben). - Sin cambios en backend ni en `uploadFile`/`addImageByUrl` — reusan la lógica existente. - Operador reinicia admin (`./scripts/monolith.sh prod restart`) para desplegar.