From 40c8dd9a5e0276391b6761fca3b1618eb0b1be3e Mon Sep 17 00:00:00 2001 From: Cedric Date: Tue, 30 Jun 2026 17:02:03 +0200 Subject: [PATCH] Actualiser js/admin.js --- js/admin.js | 82 ++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/js/admin.js b/js/admin.js index faf0fd2..d9dc19b 100644 --- a/js/admin.js +++ b/js/admin.js @@ -1,20 +1,25 @@ const API_URL = '../api.php'; -let allItems = [], currentAdminTab = 'critique', currentPage = 1, selectedIds = new Set(); +let allItems = []; +let currentAdminTab = 'critique'; +let currentPage = 1; +const itemsPerPage = 12; +let selectedIds = new Set(); +let pendingDeleteAction = null; -// --- Utilitaires --- -const getStarsHTML = (rating) => { - let r = Math.min(Math.max(parseFloat(rating) || 0, 0), 5); - const full = Math.floor(r), hasHalf = (r - full) >= 0.5, empty = Math.max(0, 5 - Math.ceil(r)); - return '★'.repeat(full) + (hasHalf ? '' : '') + `${'☆'.repeat(empty)}`; -}; +function getStarsHTML(rating) { + let r = parseFloat(String(rating).replace(',', '.')) || 0; + r = Math.min(Math.max(r, 0), 5); + const full = Math.floor(r); + const hasHalf = (r - full) >= 0.5; + const empty = Math.max(0, 5 - Math.ceil(r)); + let html = '★'.repeat(full); + if (hasHalf) html += ''; + html += `${'☆'.repeat(empty)}`; + return html; +} function parseCSV(text) { if (text.charCodeAt(0) === 0xFEFF) text = text.slice(1); - - // ✅ NOUVEAU : Détection automatique du séparateur le plus utilisé sur la première ligne - const firstLine = text.split(/[\r\n]+/)[0] || ''; - const sep = (firstLine.match(/;/g) || []).length > (firstLine.match(/,/g) || []).length ? ';' : ','; - const rows = []; let col = '', row = [], inQuotes = false; for (let i = 0; i < text.length; i++) { @@ -26,7 +31,7 @@ function parseCSV(text) { } else col += c; } else { if (c === '"') inQuotes = true; - else if (c === sep) { row.push(col); col = ''; } // ✅ On utilise le séparateur détecté + 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 = ''; @@ -104,9 +109,9 @@ function renderAdminTable() { const searchInput = document.getElementById('search-input'); const currentSearch = searchInput ? searchInput.value.toLowerCase() : ''; const physicalFilter = document.getElementById('admin-physical-checkbox'); - + let filtered = allItems.filter(item => item.type === currentAdminTab); - + if (physicalFilter && physicalFilter.checked) { filtered = filtered.filter(f => { if (f.type === 'critique') { @@ -115,22 +120,22 @@ function renderAdminTable() { return true; }); } - + if (currentSearch) { filtered = filtered.filter(f => f.title.toLowerCase().includes(currentSearch) || (f.director && f.director.toLowerCase().includes(currentSearch)) ); } - + const countLabel = document.getElementById('admin-count-label'); if (countLabel) countLabel.textContent = `${filtered.length} élément(s)`; - + const totalPages = Math.ceil(filtered.length / itemsPerPage) || 1; if (currentPage > totalPages) currentPage = totalPages; const startIdx = (currentPage - 1) * itemsPerPage; const pageItems = filtered.slice(startIdx, startIdx + itemsPerPage); - + pageItems.forEach(f => { const tr = document.createElement('tr'); const isChecked = selectedIds.has(String(f.id)) ? 'checked' : ''; @@ -149,9 +154,9 @@ function renderAdminTable() { `; tbody.appendChild(tr); }); - + renderPagination(totalPages, filtered.length); - + const selectAll = document.getElementById('select-all-checkbox'); if (selectAll) selectAll.checked = pageItems.length > 0 && pageItems.every(f => selectedIds.has(String(f.id))); } @@ -192,21 +197,21 @@ function renderPagination(totalPages, totalItems) { return; } if (totalPages <= 1) return; - + const info = document.createElement('span'); info.className = 'pagination-info'; info.textContent = `Page ${currentPage} sur ${totalPages}`; container.appendChild(info); - + const prevBtn = document.createElement('button'); prevBtn.innerHTML = ''; prevBtn.disabled = currentPage === 1; prevBtn.onclick = () => { currentPage--; renderAdminTable(); }; container.appendChild(prevBtn); - + let startPage = Math.max(1, currentPage - 2); let endPage = Math.min(totalPages, currentPage + 2); - + if (startPage > 1) { const firstBtn = document.createElement('button'); firstBtn.textContent = '1'; @@ -218,7 +223,7 @@ function renderPagination(totalPages, totalItems) { container.appendChild(dots); } } - + for (let i = startPage; i <= endPage; i++) { const btn = document.createElement('button'); btn.textContent = i; @@ -226,7 +231,7 @@ function renderPagination(totalPages, totalItems) { btn.onclick = () => { currentPage = i; renderAdminTable(); }; container.appendChild(btn); } - + if (endPage < totalPages) { if (endPage < totalPages - 1) { const dots = document.createElement('span'); @@ -238,7 +243,7 @@ function renderPagination(totalPages, totalItems) { lastBtn.onclick = () => { currentPage = totalPages; renderAdminTable(); }; container.appendChild(lastBtn); } - + const nextBtn = document.createElement('button'); nextBtn.innerHTML = ''; nextBtn.disabled = currentPage === totalPages; @@ -327,7 +332,6 @@ function openEditModal(id) { function closeAdminModal() { document.getElementById('admin-modal').classList.remove('open'); } -// Nettoyage Config Modal (Suppression Fanart) async function openConfigModal() { document.getElementById('config-modal').classList.add('open'); try { @@ -407,19 +411,20 @@ async function handleCritiqueUpload(input) { loadDashboardData(); } +// ✅ CORRECTION : Retourne l'EAN ET le titre du CSV function normalizeVideothequeRow(row) { let ean = row['ean_isbn13'] || row['EAN'] || row['ean'] || row['Barcode'] || row['UPC'] || row['upc_isbn10'] || ''; if (ean) ean = String(ean).replace(/[^0-9]/g, ''); - // ✅ Tolérance sur le nom de la colonne - let title = row['Title'] || row['title'] || row['Titre'] || row['titre'] || row['Name'] || row['name'] || ''; + // ✅ Récupérer le titre du CSV + let title = row['title'] || row['Title'] || row['Titre'] || ''; title = String(title).trim(); if (!ean && !title) return null; return { ean: ean, - title: title + title: title // ✅ Titre envoyé au backend }; } @@ -432,9 +437,10 @@ function handleVideothequeUpload(input) { const parsed = parseCSV(text); if (!parsed.length) { alert("❌ CSV vide."); return; } - const items = parsed.map(row => normalizeVideothequeRow(row)).filter(Boolean); - - if (!items.length) { alert("❌ Aucun titre ou EAN valide trouvé."); return; } + // ✅ CORRECTION : Utiliser normalizeVideothequeRow qui retourne EAN + titre + const items = parsed.map(row => normalizeVideothequeRow(row)).filter(Boolean); + + if (!items.length) { alert("❌ Aucun titre ou EAN valide trouvé."); return; } showImportModal(items.length, 'videotheque'); let processed = 0, totalImp = 0, totalSkp = 0; @@ -443,8 +449,6 @@ function handleVideothequeUpload(input) { // ✅ Lots de 1 seul pour éviter le blocage Blu-ray.com for (let i = 0; i < items.length; i += 1) { const batch = items.slice(i, i + 1); - // ✅ AJOUTEZ CECI POUR VOIR QUEL FILM BLOQUE - console.log("Tentative d'import de : ", batch[0].title); const res = await fetch(`${API_URL}?action=import_batch`, { method: 'POST', headers: { 'Authorization': localStorage.getItem('token'), 'Content-Type': 'application/json' }, @@ -459,7 +463,7 @@ function handleVideothequeUpload(input) { totalSkp += data.skipped || 0; processed += batch.length; updateImportModal(processed, items.length); - await new Promise(r => setTimeout(r, 500)); // ✅ Délai de 5.5s pour éviter le blocage + await new Promise(r => setTimeout(r, 500)); // Délai de sécurité } input.value = ''; @@ -523,7 +527,7 @@ function updateImportInterface() { const desc = document.getElementById('import-desc'); if (currentAdminTab === 'videotheque') { title.innerHTML = 'Importer ma Vidéothèque'; - desc.textContent = 'Import CSV (EAN seul) : UPCitemdb/UPCMDB pour le physique, TMDB pour l\'affiche, le casting et le synopsis.'; + desc.textContent = 'Import CSV (EAN + Titre) : Blu-ray.com pour le physique, TMDB pour l\'affiche, le casting et le synopsis.'; } else { title.innerHTML = 'Importer Critiques & Notes'; desc.textContent = 'Sélectionnez vos fichiers "ratings.csv" et "reviews.csv" (Letterboxd).';