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)...`;