diff --git a/js/admin.js b/js/admin.js index d346e46..956298b 100644 --- a/js/admin.js +++ b/js/admin.js @@ -260,36 +260,110 @@ async function saveFilmForm(e) { } catch (err) { console.error('Erreur sauvegarde :', err); } } -// ── IMPORT CSV ── +// ── PARSER CSV (Gère les virgules dans les titres entre guillemets) ── +function parseCSV(text) { + if (text.charCodeAt(0) === 0xFEFF) text = text.slice(1); // Supprime le BOM UTF-8 + const rows = []; + let col = '', row = [], inQuotes = false; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (inQuotes) { + if (c === '"') { + if (text[i+1] === '"') { col += '"'; i++; } + else inQuotes = false; + } else col += c; + } else { + if (c === '"') inQuotes = true; + else if (c === ',') { row.push(col); col = ''; } + else if (c === '\n' || c === '\r') { + if (c === '\r' && text[i+1] === '\n') i++; + row.push(col); col = ''; + if (row.length > 1 || row[0] !== '') rows.push(row); + row = []; + } else col += c; + } + } + if (col !== '' || row.length > 0) { row.push(col); rows.push(row); } + + if (rows.length === 0) return []; + const headers = rows[0].map(h => h.trim()); + const data = []; + for (let i = 1; i < rows.length; i++) { + if (rows[i].length === headers.length) { + const obj = {}; + headers.forEach((h, idx) => obj[h] = rows[i][idx]); + data.push(obj); + } + } + return data; +} + +// ── GESTION UI BARRE DE PROGRESSION ── +function showProgressModal(total) { + document.getElementById('progress-text').textContent = 'Traitement des films et récupération TMDB...'; + document.getElementById('progress-bar').style.width = '0%'; + document.getElementById('progress-count').textContent = `0 / ${total}`; + document.getElementById('progress-overlay').classList.add('open'); +} +function updateProgressModal(current, total) { + const pct = Math.round((current / total) * 100); + document.getElementById('progress-bar').style.width = pct + '%'; + document.getElementById('progress-count').textContent = `${current} / ${total}`; +} +function closeProgressModal() { + document.getElementById('progress-overlay').classList.remove('open'); +} + +// ── IMPORT CSV (Lecture locale + Envoi par lots) ── async function handleCsvUpload(input) { if (!input.files || input.files.length === 0) return; const file = input.files[0]; - const formData = new FormData(); - formData.append('csv_file', file); - formData.append('type', currentAdminTab); + input.value = ''; // Reset l'input file try { - const res = await fetch(`${API_URL}?action=import_csv`, { - method: 'POST', - headers: { 'Authorization': localStorage.getItem('token') }, - body: formData - }); + // 1. Lecture du fichier en texte par le navigateur + const text = await file.text(); + const allData = parseCSV(text); - const data = await res.json(); - - // 🚨 Vérification de l'erreur serveur - if (!res.ok || data.error) { - alert('❌ Erreur import : ' + (data.error || 'Erreur serveur inconnue')); + if (allData.length === 0) { + alert('❌ Le fichier CSV est vide ou mal formaté.'); return; } - - input.value = ''; - closeConfigModal(); - alert(`✅ Import réussi ! ${data.imported || 0} élément(s) traité(s).`); + + closeConfigModal(); // Ferme la modale de config + showProgressModal(allData.length); + + // 2. Envoi par lots de 5 films pour éviter les timeouts et avoir une barre fluide + const batchSize = 5; + let processed = 0; + + for (let i = 0; i < allData.length; i += batchSize) { + const batch = allData.slice(i, i + batchSize); + + try { + await fetch(`${API_URL}?action=import_batch`, { + method: 'POST', + headers: { + 'Authorization': localStorage.getItem('token'), + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ items: batch, type: currentAdminTab }) + }); + } catch (err) { + console.error('Erreur sur un lot:', err); + } + + processed += batch.length; + updateProgressModal(processed, allData.length); + } + + closeProgressModal(); + alert(`✅ Import terminé ! ${allData.length} élément(s) traité(s).`); loadDashboardData(); - } catch (err) { - console.error('Erreur import CSV :', err); - alert('❌ Erreur de communication avec le serveur.'); + } catch (err) { + console.error('Erreur lecture CSV :', err); + closeProgressModal(); + alert('❌ Impossible de lire le fichier CSV.'); } }