Actualiser js/admin.js

This commit is contained in:
2026-06-24 09:21:09 +02:00
parent d68aac965e
commit 000a8b89bd
+11 -31
View File
@@ -7,20 +7,14 @@ let selectedIds = new Set();
let pendingDeleteAction = null; let pendingDeleteAction = null;
function getStarsHTML(rating) { function getStarsHTML(rating) {
// Gère les virgules (ex: "3,5" -> "3.5") et force un nombre
let r = parseFloat(String(rating).replace(',', '.')) || 0; let r = parseFloat(String(rating).replace(',', '.')) || 0;
// Sécurise la note stricte entre 0 et 5
r = Math.min(Math.max(r, 0), 5); r = Math.min(Math.max(r, 0), 5);
const full = Math.floor(r); const full = Math.floor(r);
const hasHalf = (r - full) >= 0.5; const hasHalf = (r - full) >= 0.5;
const empty = Math.max(0, 5 - Math.ceil(r)); // Empêche une valeur négative fatale const empty = Math.max(0, 5 - Math.ceil(r));
let html = '★'.repeat(full); let html = '★'.repeat(full);
if (hasHalf) html += '<span class="half-star">★</span>'; if (hasHalf) html += '<span class="half-star">★</span>';
html += `<span class="stars-muted">${'☆'.repeat(empty)}</span>`; html += `<span class="stars-muted">${'☆'.repeat(empty)}</span>`;
return html; return html;
} }
@@ -74,6 +68,7 @@ document.addEventListener('DOMContentLoaded', () => {
function initEventListeners() { function initEventListeners() {
const filmForm = document.getElementById('film-form'); const filmForm = document.getElementById('film-form');
if (filmForm) filmForm.addEventListener('submit', saveFilmForm); if (filmForm) filmForm.addEventListener('submit', saveFilmForm);
const csvInput = document.getElementById('csv-file'); const csvInput = document.getElementById('csv-file');
if (csvInput) { if (csvInput) {
csvInput.addEventListener('change', (e) => { csvInput.addEventListener('change', (e) => {
@@ -81,10 +76,13 @@ function initEventListeners() {
else handleVideothequeUpload(e.target); else handleVideothequeUpload(e.target);
}); });
} }
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
if (searchInput) searchInput.addEventListener('input', () => { currentPage = 1; renderAdminTable(); }); if (searchInput) searchInput.addEventListener('input', () => { currentPage = 1; renderAdminTable(); });
const selectAll = document.getElementById('select-all-checkbox'); const selectAll = document.getElementById('select-all-checkbox');
if (selectAll) selectAll.addEventListener('change', (e) => toggleSelectAll(e.target)); if (selectAll) selectAll.addEventListener('change', (e) => toggleSelectAll(e.target));
document.addEventListener('click', (e) => { document.addEventListener('click', (e) => {
if (e.target.classList.contains('modal-close') || e.target.closest('.modal-close')) { if (e.target.classList.contains('modal-close') || e.target.closest('.modal-close')) {
const overlay = e.target.closest('.overlay'); const overlay = e.target.closest('.overlay');
@@ -92,6 +90,7 @@ function initEventListeners() {
} }
if (e.target.classList.contains('overlay')) e.target.classList.remove('open'); if (e.target.classList.contains('overlay')) e.target.classList.remove('open');
}); });
const physicalFilter = document.getElementById('admin-physical-checkbox'); const physicalFilter = document.getElementById('admin-physical-checkbox');
if (physicalFilter) physicalFilter.addEventListener('change', () => { currentPage = 1; renderAdminTable(); }); if (physicalFilter) physicalFilter.addEventListener('change', () => { currentPage = 1; renderAdminTable(); });
} }
@@ -112,7 +111,6 @@ function renderAdminTable() {
const tbody = document.getElementById('admin-table-body'); const tbody = document.getElementById('admin-table-body');
if (!tbody) return; if (!tbody) return;
tbody.innerHTML = ''; tbody.innerHTML = '';
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
const currentSearch = searchInput ? searchInput.value.toLowerCase() : ''; const currentSearch = searchInput ? searchInput.value.toLowerCase() : '';
const physicalFilter = document.getElementById('admin-physical-checkbox'); const physicalFilter = document.getElementById('admin-physical-checkbox');
@@ -199,7 +197,6 @@ function renderPagination(totalPages, totalItems) {
const container = document.getElementById('pagination-container'); const container = document.getElementById('pagination-container');
if (!container) return; if (!container) return;
container.innerHTML = ''; container.innerHTML = '';
if (totalItems === 0) { if (totalItems === 0) {
container.innerHTML = '<p style="color:var(--muted); text-align:center; width:100%;">Aucun élément trouvé.</p>'; container.innerHTML = '<p style="color:var(--muted); text-align:center; width:100%;">Aucun élément trouvé.</p>';
return; return;
@@ -217,7 +214,6 @@ function renderPagination(totalPages, totalItems) {
prevBtn.onclick = () => { currentPage--; renderAdminTable(); }; prevBtn.onclick = () => { currentPage--; renderAdminTable(); };
container.appendChild(prevBtn); container.appendChild(prevBtn);
// Fenêtre glissante : 2 pages avant, 2 pages après la page courante
let startPage = Math.max(1, currentPage - 2); let startPage = Math.max(1, currentPage - 2);
let endPage = Math.min(totalPages, currentPage + 2); let endPage = Math.min(totalPages, currentPage + 2);
@@ -226,7 +222,6 @@ function renderPagination(totalPages, totalItems) {
firstBtn.textContent = '1'; firstBtn.textContent = '1';
firstBtn.onclick = () => { currentPage = 1; renderAdminTable(); }; firstBtn.onclick = () => { currentPage = 1; renderAdminTable(); };
container.appendChild(firstBtn); container.appendChild(firstBtn);
if (startPage > 2) { if (startPage > 2) {
const dots = document.createElement('span'); const dots = document.createElement('span');
dots.textContent = '...'; dots.textContent = '...';
@@ -413,45 +408,28 @@ async function handleCritiqueUpload(input) {
loadDashboardData(); loadDashboardData();
} }
// 🔥 NETTOYAGE DES DONNÉES CSV VIDÉOTHÈQUE (Collectorz / CLZ)
function normalizeVideothequeRow(row) { function normalizeVideothequeRow(row) {
// Bug 1 : EAN float (ex: 7321950374984.0) → chaîne entière sans décimale
let ean = row['ean_isbn13'] || row['EAN'] || ''; let ean = row['ean_isbn13'] || row['EAN'] || '';
if (ean !== '') { if (ean !== '') {
const eanNum = parseFloat(ean); const eanNum = parseFloat(ean);
ean = isNaN(eanNum) ? '' : String(Math.round(eanNum)); ean = isNaN(eanNum) ? '' : String(Math.round(eanNum));
} }
// Bug 2 : length float (ex: 245.0) → entier en minutes
let length = row['length'] || ''; let length = row['length'] || '';
if (length !== '' && length !== null) { if (length !== '' && length !== null) {
const l = parseFloat(length); const l = parseFloat(length);
length = isNaN(l) ? '' : String(Math.round(l)); length = isNaN(l) ? '' : String(Math.round(l));
} }
// Bug 3 : number_of_discs NaN → 1
let discs = row['number_of_discs'] || ''; let discs = row['number_of_discs'] || '';
if (discs === '' || discs === null || isNaN(parseFloat(discs))) { if (discs === '' || discs === null || isNaN(parseFloat(discs))) {
discs = 1; discs = 1;
} else { } else {
discs = Math.round(parseFloat(discs)); 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, { return Object.assign({}, row, {
ean_isbn13: ean, ean_isbn13: ean,
length: length, length: length,
number_of_discs: discs, 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
}); });
} }
@@ -460,8 +438,10 @@ async function handleVideothequeUpload(input) {
let allData = []; let allData = [];
for (const file of input.files) { try { allData = allData.concat(parseCSV(await file.text())); } catch(e) {} } 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.'); } if (allData.length === 0) { input.value = ''; return alert('❌ Fichier vide.'); }
// Bug 5 : normaliser les données brutes avant envoi
// 🔥 Application du nettoyage avant envoi au serveur
allData = allData.map(normalizeVideothequeRow); allData = allData.map(normalizeVideothequeRow);
showImportModal(allData.length, 'videotheque'); showImportModal(allData.length, 'videotheque');
let processed = 0; let processed = 0;
for (let i = 0; i < allData.length; i += 10) { for (let i = 0; i < allData.length; i += 10) {