diff --git a/js/imageProcessor.js b/js/imageProcessor.js index 6e09245..d8f19d8 100644 --- a/js/imageProcessor.js +++ b/js/imageProcessor.js @@ -1,3 +1,17 @@ +/** + * Traite un tableau d'items avec au plus `concurrency` appels simultanés. + * @param {any[]} items + * @param {(item: any) => Promise} processFn + * @param {number} concurrency + * @returns {Promise} + */ export async function processBatch(items, processFn, concurrency = 3) { - throw new Error('Not implemented'); + const queue = [...items]; + const workers = Array.from({ length: concurrency }, async () => { + while (queue.length > 0) { + const item = queue.shift(); + if (item !== undefined) await processFn(item); + } + }); + await Promise.all(workers); } diff --git a/js/zipExporter.js b/js/zipExporter.js index 5d59811..d377335 100644 --- a/js/zipExporter.js +++ b/js/zipExporter.js @@ -1,3 +1,22 @@ +/** + * Compresse les fichiers en ZIP et déclenche le téléchargement. + * @param {{ name: string, blob: Blob }[]} processedFiles + * @returns {Promise} + */ export async function downloadAllAsZip(processedFiles) { - throw new Error('Not implemented'); + const zip = new JSZip(); + for (const { name, blob } of processedFiles) { + zip.file(name, blob); + } + const zipBlob = await zip.generateAsync({ type: 'blob' }); + const url = URL.createObjectURL(zipBlob); + + const a = document.createElement('a'); + a.href = url; + a.download = `photos-produits-${new Date().toISOString().slice(0, 10)}.zip`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + + setTimeout(() => URL.revokeObjectURL(url), 10_000); }