From a4ef23c64d2090a7c57c2504c92c1d7b5460bbb4 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 24 Jun 2026 09:10:10 +0200 Subject: [PATCH] Actualiser js/admin.js --- js/admin.js | 92 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/js/admin.js b/js/admin.js index 9a5164c..defd056 100644 --- a/js/admin.js +++ b/js/admin.js @@ -7,14 +7,20 @@ let selectedIds = new Set(); let pendingDeleteAction = null; function getStarsHTML(rating) { + // Gère les virgules (ex: "3,5" -> "3.5") et force un nombre let r = parseFloat(String(rating).replace(',', '.')) || 0; + + // Sécurise la note stricte entre 0 et 5 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)); + const empty = Math.max(0, 5 - Math.ceil(r)); // Empêche une valeur négative fatale + let html = '★'.repeat(full); if (hasHalf) html += ''; html += `${'☆'.repeat(empty)}`; + return html; } @@ -68,7 +74,6 @@ document.addEventListener('DOMContentLoaded', () => { function initEventListeners() { const filmForm = document.getElementById('film-form'); if (filmForm) filmForm.addEventListener('submit', saveFilmForm); - const csvInput = document.getElementById('csv-file'); if (csvInput) { csvInput.addEventListener('change', (e) => { @@ -76,13 +81,10 @@ function initEventListeners() { else handleVideothequeUpload(e.target); }); } - const searchInput = document.getElementById('search-input'); if (searchInput) searchInput.addEventListener('input', () => { currentPage = 1; renderAdminTable(); }); - const selectAll = document.getElementById('select-all-checkbox'); if (selectAll) selectAll.addEventListener('change', (e) => toggleSelectAll(e.target)); - document.addEventListener('click', (e) => { if (e.target.classList.contains('modal-close') || e.target.closest('.modal-close')) { const overlay = e.target.closest('.overlay'); @@ -90,7 +92,6 @@ function initEventListeners() { } if (e.target.classList.contains('overlay')) e.target.classList.remove('open'); }); - const physicalFilter = document.getElementById('admin-physical-checkbox'); if (physicalFilter) physicalFilter.addEventListener('change', () => { currentPage = 1; renderAdminTable(); }); } @@ -111,21 +112,22 @@ function renderAdminTable() { const tbody = document.getElementById('admin-table-body'); if (!tbody) return; tbody.innerHTML = ''; + const searchInput = document.getElementById('search-input'); const currentSearch = searchInput ? searchInput.value.toLowerCase() : ''; - const physicalFilter = document.getElementById('admin-physical-checkbox'); // ✅ 修复了 getElementByI d - - let filtered = allItems.filter(item => item.type === currentAdminTab); // ✅ 修复了 = > - - if (physicalFilter && physicalFilter.checked) { // ✅ 修复了 & & - filtered = filtered.filter(f => { // ✅ 修复了 = > + 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') { return f.streaming && f.streaming.toLowerCase().includes('support physique'); } return true; }); } - + if (currentSearch) { filtered = filtered.filter(f => f.title.toLowerCase().includes(currentSearch) || @@ -134,14 +136,14 @@ function renderAdminTable() { } const countLabel = document.getElementById('admin-count-label'); - if (countLabel) countLabel.textContent = `${filtered.length} élément(s)`; // ✅ 修复了 filtered. length + 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 => { // ✅ 修复了 f = > + pageItems.forEach(f => { const tr = document.createElement('tr'); const isChecked = selectedIds.has(String(f.id)) ? 'checked' : ''; tr.innerHTML = ` @@ -161,9 +163,9 @@ function renderAdminTable() { }); 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))); // ✅ 修复了 check ed, & &, = > + if (selectAll) selectAll.checked = pageItems.length > 0 && pageItems.every(f => selectedIds.has(String(f.id))); } function toggleSingleSelect(id, checkbox) { @@ -197,6 +199,7 @@ function renderPagination(totalPages, totalItems) { const container = document.getElementById('pagination-container'); if (!container) return; container.innerHTML = ''; + if (totalItems === 0) { container.innerHTML = '

Aucun élément trouvé.

'; return; @@ -206,7 +209,7 @@ function renderPagination(totalPages, totalItems) { const info = document.createElement('span'); info.className = 'pagination-info'; info.textContent = `Page ${currentPage} sur ${totalPages}`; - container.appendChild(info); // ✅ 修复了 in fo + container.appendChild(info); const prevBtn = document.createElement('button'); prevBtn.innerHTML = ''; @@ -214,7 +217,8 @@ function renderPagination(totalPages, totalItems) { prevBtn.onclick = () => { currentPage--; renderAdminTable(); }; container.appendChild(prevBtn); - let startPage = Math.max(1, currentPage - 2); // ✅ 修复了 currentP age + // Fenêtre glissante : 2 pages avant, 2 pages après la page courante + let startPage = Math.max(1, currentPage - 2); let endPage = Math.min(totalPages, currentPage + 2); if (startPage > 1) { @@ -244,7 +248,7 @@ function renderPagination(totalPages, totalItems) { dots.textContent = '...'; container.appendChild(dots); } - const lastBtn = document.createElement('button'); // ✅ 修复了 c reateElement + const lastBtn = document.createElement('button'); lastBtn.textContent = totalPages; lastBtn.onclick = () => { currentPage = totalPages; renderAdminTable(); }; container.appendChild(lastBtn); @@ -298,7 +302,7 @@ function switchAdminTab(tabName) { if (wrapper) wrapper.style.display = (tabName === 'videotheque') ? 'none' : 'flex'; document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); document.getElementById(`btn-tab-${tabName}`).classList.add('active'); - updateImportInterface(); + updateImportInterface(); toggleFormFields(); renderAdminTable(); } @@ -409,11 +413,55 @@ async function handleCritiqueUpload(input) { loadDashboardData(); } +function normalizeVideothequeRow(row) { + // Bug 1 : EAN float (ex: 7321950374984.0) → chaîne entière sans décimale + let ean = row['ean_isbn13'] || row['EAN'] || ''; + if (ean !== '') { + const eanNum = parseFloat(ean); + ean = isNaN(eanNum) ? '' : String(Math.round(eanNum)); + } + + // Bug 2 : length float (ex: 245.0) → entier en minutes + let length = row['length'] || ''; + if (length !== '' && length !== null) { + const l = parseFloat(length); + length = isNaN(l) ? '' : String(Math.round(l)); + } + + // Bug 3 : number_of_discs NaN → 1 + let discs = row['number_of_discs'] || ''; + if (discs === '' || discs === null || isNaN(parseFloat(discs))) { + discs = 1; + } else { + discs = Math.round(parseFloat(discs)); + } + + // Bug 4 : creators contient les acteurs dans ce format CSV, + // first_name/last_name pointent vers le 1er acteur, pas le réalisateur. + // On laisse director vide pour que TMDB le remplisse correctement. + const creators = row['creators'] || ''; + const ensemble = row['ensemble'] || ''; + + return Object.assign({}, row, { + ean_isbn13: ean, + length: length, + number_of_discs: discs, + // Ne pas construire de director depuis first_name/last_name (ce sont des acteurs) + first_name: '', + last_name: '', + // Conserver creators/ensemble pour extraction des acteurs côté PHP + creators: creators, + ensemble: ensemble || creators + }); +} + async function handleVideothequeUpload(input) { if (!input.files || input.files.length === 0) return; let allData = []; for (const file of input.files) { try { allData = allData.concat(parseCSV(await file.text())); } catch(e) {} } if (allData.length === 0) { input.value = ''; return alert('❌ Fichier vide.'); } + // Bug 5 : normaliser les données brutes avant envoi + allData = allData.map(normalizeVideothequeRow); showImportModal(allData.length, 'videotheque'); let processed = 0; for (let i = 0; i < allData.length; i += 10) { @@ -435,7 +483,7 @@ function showImportModal(total, type) { document.getElementById('import-modal-desc').textContent = `Traitement de ${total} élément(s)...`; document.getElementById('import-progress-bar').style.width = '0%'; document.getElementById('import-modal-counter').textContent = '0%'; - document.getElementById('import-progress-modal').classList.add('open'); // ✅ 修复了 mo dal + document.getElementById('import-progress-modal').classList.add('open'); } function updateImportModal(current, total) {