74 lines
2.8 KiB
Markdown
74 lines
2.8 KiB
Markdown
# 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<File[]>([]);
|
|
const prevProductIdRef = useRef<string | undefined>(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. |