Actualiser js/admin.js
This commit is contained in:
+12
-35
@@ -42,11 +42,10 @@ function parseCSV(text) {
|
|||||||
}
|
}
|
||||||
if (col !== '' || row.length > 0) { row.push(col); rows.push(row); }
|
if (col !== '' || row.length > 0) { row.push(col); rows.push(row); }
|
||||||
if (rows.length === 0) return [];
|
if (rows.length === 0) return [];
|
||||||
|
|
||||||
const headers = rows[0].map(h => h.trim());
|
const headers = rows[0].map(h => h.trim());
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let i = 1; i < rows.length; i++) {
|
for (let i = 1; i < rows.length; i++) {
|
||||||
if (rows[i].length === 1 && rows[i][0].trim() === '') continue; // Ignore les lignes 100% vides
|
if (rows[i].length === 1 && rows[i][0].trim() === '') continue;
|
||||||
const obj = {};
|
const obj = {};
|
||||||
headers.forEach((h, idx) => {
|
headers.forEach((h, idx) => {
|
||||||
obj[h] = rows[i][idx] !== undefined ? rows[i][idx] : '';
|
obj[h] = rows[i][idx] !== undefined ? rows[i][idx] : '';
|
||||||
@@ -71,7 +70,6 @@ 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) csvInput.addEventListener('change', (e) => handleCsvUpload(e.target));
|
if (csvInput) csvInput.addEventListener('change', (e) => handleCsvUpload(e.target));
|
||||||
|
|
||||||
@@ -84,9 +82,7 @@ function initEventListeners() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectAll = document.getElementById('select-all-checkbox');
|
const selectAll = document.getElementById('select-all-checkbox');
|
||||||
if (selectAll) {
|
if (selectAll) selectAll.addEventListener('change', (e) => toggleSelectAll(e.target));
|
||||||
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')) {
|
||||||
@@ -123,7 +119,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');
|
||||||
@@ -184,7 +179,6 @@ function toggleSingleSelect(id, checkbox) {
|
|||||||
if (checkbox.checked) selectedIds.add(String(id));
|
if (checkbox.checked) selectedIds.add(String(id));
|
||||||
else selectedIds.delete(String(id));
|
else selectedIds.delete(String(id));
|
||||||
updateBulkBar();
|
updateBulkBar();
|
||||||
|
|
||||||
const filtered = allItems.filter(item => item.type === currentAdminTab);
|
const filtered = allItems.filter(item => item.type === currentAdminTab);
|
||||||
const selectAll = document.getElementById('select-all-checkbox');
|
const selectAll = document.getElementById('select-all-checkbox');
|
||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
@@ -222,7 +216,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;
|
||||||
@@ -345,7 +338,6 @@ function switchAdminTab(tabName) {
|
|||||||
selectedIds.clear();
|
selectedIds.clear();
|
||||||
const searchInput = document.getElementById('search-input');
|
const searchInput = document.getElementById('search-input');
|
||||||
if (searchInput) searchInput.value = '';
|
if (searchInput) searchInput.value = '';
|
||||||
|
|
||||||
const physicalFilter = document.getElementById('admin-physical-checkbox');
|
const physicalFilter = document.getElementById('admin-physical-checkbox');
|
||||||
if (physicalFilter) physicalFilter.checked = false;
|
if (physicalFilter) physicalFilter.checked = false;
|
||||||
|
|
||||||
@@ -446,13 +438,11 @@ async function saveFilmForm(e) {
|
|||||||
} catch (err) { console.error('Erreur sauvegarde :', err); }
|
} catch (err) { console.error('Erreur sauvegarde :', err); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- FONCTION D'IMPORT INTELLIGENTE ---
|
// --- FONCTION D'IMPORT INTELLIGENTE (CORRIGÉE) ---
|
||||||
async function handleCsvUpload(input) {
|
async function handleCsvUpload(input) {
|
||||||
if (!input.files || input.files.length === 0) return;
|
if (!input.files || input.files.length === 0) return;
|
||||||
|
|
||||||
let allData = [];
|
let allData = [];
|
||||||
|
|
||||||
// 1. Lecture de tous les fichiers (supporte le multi-upload)
|
|
||||||
for (const file of input.files) {
|
for (const file of input.files) {
|
||||||
try {
|
try {
|
||||||
const text = await file.text();
|
const text = await file.text();
|
||||||
@@ -463,15 +453,13 @@ async function handleCsvUpload(input) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input.value = ''; // Reset l'input file
|
input.value = '';
|
||||||
|
|
||||||
if (allData.length === 0) {
|
if (allData.length === 0) {
|
||||||
alert('❌ Fichiers vides ou mal formatés.');
|
alert('❌ Fichiers vides ou mal formatés.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Fusion et Dédoublonnage en mémoire
|
|
||||||
// Utilise une Map pour regrouper les données par "Titre|Année"
|
|
||||||
const mergedMap = new Map();
|
const mergedMap = new Map();
|
||||||
allData.forEach(row => {
|
allData.forEach(row => {
|
||||||
const title = (row['Title'] || row['Name'] || '').trim();
|
const title = (row['Title'] || row['Name'] || '').trim();
|
||||||
@@ -483,7 +471,6 @@ async function handleCsvUpload(input) {
|
|||||||
mergedMap.set(key, { ...row });
|
mergedMap.set(key, { ...row });
|
||||||
} else {
|
} else {
|
||||||
const existing = mergedMap.get(key);
|
const existing = mergedMap.get(key);
|
||||||
// Fusion des notes et critiques si présentes
|
|
||||||
if ((row['Rating'] || row['rating']) && !existing['Rating']) existing['Rating'] = row['Rating'];
|
if ((row['Rating'] || row['rating']) && !existing['Rating']) existing['Rating'] = row['Rating'];
|
||||||
if ((row['Review'] || row['review']) && !existing['Review']) existing['Review'] = row['Review'];
|
if ((row['Review'] || row['review']) && !existing['Review']) existing['Review'] = row['Review'];
|
||||||
}
|
}
|
||||||
@@ -491,7 +478,7 @@ async function handleCsvUpload(input) {
|
|||||||
|
|
||||||
let finalData = Array.from(mergedMap.values());
|
let finalData = Array.from(mergedMap.values());
|
||||||
|
|
||||||
// 3. Protection : Ne pas écraser les données BDD existantes
|
// 🔥 CORRECTION : Mapping des champs CSV vers les champs attendus par le Backend
|
||||||
finalData = finalData.map(row => {
|
finalData = finalData.map(row => {
|
||||||
const title = (row['Title'] || row['Name'] || '').trim();
|
const title = (row['Title'] || row['Name'] || '').trim();
|
||||||
const dateStr = (row['Date'] || row['Year'] || row['year'] || '').toString();
|
const dateStr = (row['Date'] || row['Year'] || row['year'] || '').toString();
|
||||||
@@ -503,20 +490,18 @@ async function handleCsvUpload(input) {
|
|||||||
f.type === currentAdminTab
|
f.type === currentAdminTab
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingDb) {
|
|
||||||
return {
|
return {
|
||||||
...row,
|
...row, // Garde les données brutes au cas où
|
||||||
'Rating': (row['Rating'] || row['rating']) || existingDb.rating,
|
// Mappe vers les noms de colonnes BDD
|
||||||
'Review': (row['Review'] || row['review']) || existingDb.review
|
title: title,
|
||||||
|
year: year,
|
||||||
|
rating: (row['Rating'] || row['rating']) || (existingDb ? existingDb.rating : ''),
|
||||||
|
review: (row['Review'] || row['review']) || (existingDb ? existingDb.review : '')
|
||||||
};
|
};
|
||||||
}
|
|
||||||
return row;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Lancement de la modale de progression stylisée
|
|
||||||
showImportModal(finalData.length, currentAdminTab);
|
showImportModal(finalData.length, currentAdminTab);
|
||||||
|
|
||||||
// 5. Envoi par lots de 10
|
|
||||||
const batchSize = 10;
|
const batchSize = 10;
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
|
|
||||||
@@ -538,7 +523,6 @@ async function handleCsvUpload(input) {
|
|||||||
updateImportModal(processed, finalData.length);
|
updateImportModal(processed, finalData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Finalisation
|
|
||||||
closeImportModal();
|
closeImportModal();
|
||||||
alert(`✅ Import terminé ! ${finalData.length} élément(s) traité(s).`);
|
alert(`✅ Import terminé ! ${finalData.length} élément(s) traité(s).`);
|
||||||
loadDashboardData();
|
loadDashboardData();
|
||||||
@@ -604,17 +588,12 @@ function showImportModal(total, type) {
|
|||||||
const modal = document.getElementById('import-progress-modal');
|
const modal = document.getElementById('import-progress-modal');
|
||||||
const title = document.getElementById('import-modal-title');
|
const title = document.getElementById('import-modal-title');
|
||||||
const desc = document.getElementById('import-modal-desc');
|
const desc = document.getElementById('import-modal-desc');
|
||||||
|
|
||||||
// Adaptation selon le contexte
|
|
||||||
title.innerHTML = type === 'critique'
|
title.innerHTML = type === 'critique'
|
||||||
? '<i class="ti ti-star"></i> Import des Critiques'
|
? '<i class="ti ti-star"></i> Import des Critiques'
|
||||||
: '<i class="ti ti-video"></i> Import Vidéothèque';
|
: '<i class="ti ti-video"></i> Import Vidéothèque';
|
||||||
|
|
||||||
desc.textContent = `Traitement de ${total} élément(s)...`;
|
desc.textContent = `Traitement de ${total} élément(s)...`;
|
||||||
|
|
||||||
document.getElementById('import-progress-bar').style.width = '0%';
|
document.getElementById('import-progress-bar').style.width = '0%';
|
||||||
document.getElementById('import-modal-counter').textContent = '0%';
|
document.getElementById('import-modal-counter').textContent = '0%';
|
||||||
|
|
||||||
modal.classList.add('open');
|
modal.classList.add('open');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +611,6 @@ async function fetchInfoFromEAN() {
|
|||||||
const eanInput = document.getElementById('f-ean');
|
const eanInput = document.getElementById('f-ean');
|
||||||
const ean = eanInput.value.trim();
|
const ean = eanInput.value.trim();
|
||||||
if (!ean || ean.length < 8) { alert("Veuillez saisir un code EAN valide."); return; }
|
if (!ean || ean.length < 8) { alert("Veuillez saisir un code EAN valide."); return; }
|
||||||
|
|
||||||
const btn = eanInput.nextElementSibling;
|
const btn = eanInput.nextElementSibling;
|
||||||
const originalHtml = btn.innerHTML;
|
const originalHtml = btn.innerHTML;
|
||||||
btn.innerHTML = '<i class="ti ti-loader"></i>';
|
btn.innerHTML = '<i class="ti ti-loader"></i>';
|
||||||
@@ -656,7 +634,7 @@ async function fetchInfoFromEAN() {
|
|||||||
if (d.aspect_ratio) document.getElementById('f-aspect').value = d.aspect_ratio;
|
if (d.aspect_ratio) document.getElementById('f-aspect').value = d.aspect_ratio;
|
||||||
} else { alert("Aucune information trouvée pour ce code EAN."); }
|
} else { alert("Aucune information trouvée pour ce code EAN."); }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Erreur de recherche EAN:", e);
|
console.error("Erreur de recherche EAN: ", e);
|
||||||
alert("Erreur réseau lors de la recherche du code EAN.");
|
alert("Erreur réseau lors de la recherche du code EAN.");
|
||||||
} finally {
|
} finally {
|
||||||
btn.innerHTML = originalHtml;
|
btn.innerHTML = originalHtml;
|
||||||
@@ -667,7 +645,6 @@ async function fetchInfoFromEAN() {
|
|||||||
function updateImportInterface() {
|
function updateImportInterface() {
|
||||||
const title = document.getElementById('import-title');
|
const title = document.getElementById('import-title');
|
||||||
const desc = document.getElementById('import-desc');
|
const desc = document.getElementById('import-desc');
|
||||||
|
|
||||||
if (currentAdminTab === 'critique') {
|
if (currentAdminTab === 'critique') {
|
||||||
title.innerHTML = '<strong>Importer Critiques & Notes</strong>';
|
title.innerHTML = '<strong>Importer Critiques & Notes</strong>';
|
||||||
desc.textContent = 'Glissez-déposez vos fichiers "ratings.csv" et "reviews.csv" (Letterboxd).';
|
desc.textContent = 'Glissez-déposez vos fichiers "ratings.csv" et "reviews.csv" (Letterboxd).';
|
||||||
|
|||||||
Reference in New Issue
Block a user