diff --git a/js/admin.js b/js/admin.js index 5257b56..424924e 100644 --- a/js/admin.js +++ b/js/admin.js @@ -412,15 +412,15 @@ async function handleCritiqueUpload(input) { } function normalizeVideothequeRow(row) { + // Recherche de l'EAN dans plusieurs colonnes possibles let ean = row['ean_isbn13'] || row['EAN'] || row['ean'] || row['Barcode'] || row['UPC'] || row['upc_isbn10'] || ''; ean = String(ean).replace(/[^0-9]/g, ''); - // Essayer plusieurs clés pour le titre + // Recherche du titre dans plusieurs colonnes let title = row['title'] || row['Title'] || row['Titre'] || row['titre'] || row['nom'] || row['Nom'] || ''; title = String(title).trim(); - // Si on a un EAN mais pas de titre, on peut utiliser le titre du fichier ? Non, on laisse vide mais on ne skip pas. - // On retourne quand même l'objet si l'EAN est valide, même sans titre (pour tenter de récupérer via Blu-ray.com) + // Si on n'a ni EAN ni titre, on ignore if (!ean && !title) return null; return { ean, title }; @@ -429,52 +429,86 @@ function normalizeVideothequeRow(row) { function handleVideothequeUpload(input) { const file = input.files[0]; if (!file) return; + const reader = new FileReader(); reader.onload = async (e) => { const text = e.target.result; const parsed = parseCSV(text); - if (!parsed.length) { alert("❌ CSV vide."); return; } - - // ✅ CORRECTION : Utiliser normalizeVideothequeRow qui retourne EAN + titre + if (!parsed.length) { + alert("❌ CSV vide ou mal formaté."); + input.value = ''; + return; + } + + // Transformer chaque ligne en objet {ean, title} const items = parsed.map(row => normalizeVideothequeRow(row)).filter(Boolean); - console.log('Lignes parsées :', parsed.length); - console.log('Items valides :', items.length); - console.log('Premier item :', items[0]); - if (!items.length) { alert("❌ Aucun titre ou EAN valide trouvé."); return; } - + if (!items.length) { + alert("❌ Aucun titre ou EAN valide trouvé dans le CSV."); + input.value = ''; + return; + } + + console.log(`Lignes parsées : ${parsed.length}, items valides : ${items.length}`); + + // Ouvrir la modale de progression showImportModal(items.length, 'videotheque'); - let processed = 0, totalImp = 0, totalSkp = 0; + let processed = 0; + let totalImported = 0; + let totalSkipped = 0; + + // Taille du lot : 10 films par requête + const BATCH_SIZE = 10; try { - // ✅ Lots de 1 seul pour éviter le blocage Blu-ray.com - const batchSize = 5; // ou 10 selon la puissance du serveur - for (let i = 0; i < items.length; i += batchSize) { - const batch = items.slice(i, i + batchSize); - const res = await fetch(`${API_URL}?action=import_batch`, { + for (let i = 0; i < items.length; i += BATCH_SIZE) { + const batch = items.slice(i, i + BATCH_SIZE); + const response = await fetch(`${API_URL}?action=import_batch`, { method: 'POST', - headers: { 'Authorization': localStorage.getItem('token'), 'Content-Type': 'application/json' }, + headers: { + 'Authorization': localStorage.getItem('token'), + 'Content-Type': 'application/json' + }, body: JSON.stringify({ type: 'videotheque', items: batch }) }); - // ... traitement de la réponse - // Petit délai optionnel (100 ms) pour éviter de saturer le serveur - await new Promise(r => setTimeout(r, 100)); - } - - input.value = ''; - closeImportModal(); - const msg = totalSkp > 0 ? ` (${totalSkp} ignoré(s))` : ''; - showSuccessModal(`${totalImp} édition(s) importée(s).${msg}`); - loadDashboardData(); - } catch (err) { - console.error(err); - closeImportModal(); - alert("❌ Échec import : " + err.message); - input.value = ''; - } - }; - reader.readAsText(file); + + if (!response.ok) { + throw new Error(`Erreur HTTP ${response.status} - ${response.statusText}`); + } + + const result = await response.json(); + if (!result.success) { + throw new Error(result.error || "Erreur inconnue lors de l'import."); + } + + totalImported += result.imported || 0; + totalSkipped += result.skipped || 0; + processed += batch.length; + + // Mise à jour de la barre de progression + updateImportModal(processed, items.length); + + // Petit délai pour éviter de saturer le serveur + await new Promise(resolve => setTimeout(resolve, 200)); } + // Fermer la modale + closeImportModal(); + input.value = ''; + + const msg = totalSkipped > 0 ? ` (${totalSkipped} ignoré(s))` : ''; + showSuccessModal(`${totalImported} film(s) importé(s) avec succès.${msg}`); + loadDashboardData(); + + } catch (err) { + console.error(err); + closeImportModal(); + alert(`❌ Échec de l'import : ${err.message}`); + input.value = ''; + } + }; + reader.readAsText(file); +} + function showImportModal(total, type) { document.getElementById('import-modal-title').innerHTML = type === 'critique' ? ' Import Critiques' : ' Import Vidéothèque'; document.getElementById('import-modal-desc').textContent = `Traitement de ${total} élément(s)...`;