diff --git a/js/public.js b/js/public.js index 7bee936..c0007b6 100644 --- a/js/public.js +++ b/js/public.js @@ -7,40 +7,34 @@ let searchQuery = ''; let currentPage = 1; const itemsPerPage = 12; -async function loadPublicData() { - try { - const response = await fetch(`${API_URL}?action=get_films`); - films = await response.json(); - generateStreamingSelect(); // Remplit le menu déroulant - renderPublicGrid(); - } catch (error) { - console.error("Erreur de récupération :", error); - } +// ── GÉNÉRATEUR D'ÉTOILES ─ +function getStarsHTML(rating) { + const r = parseFloat(rating) || 0; + const full = Math.floor(r); + const hasHalf = (r - full) >= 0.5; + const empty = 5 - Math.ceil(r); + let html = '★'.repeat(full); + if (hasHalf) html += ''; + html += `${'☆'.repeat(empty)}`; + return html; } -// ── GÉNÉRATION DU MENU DÉROULANT STREAMING ── +// ── GÉNÉRATION MENU STREAMING ── function generateStreamingSelect() { const select = document.getElementById('pub-streaming-select'); if (!select) return; - - // Extraire toutes les plateformes uniques const platforms = new Set(); films.forEach(f => { if (f.type === 'critique' && f.streaming && f.streaming !== 'Disponible en support physique ou Cinéma' && f.streaming.trim() !== '') { - // Séparer par virgule si plusieurs plateformes f.streaming.split(',').forEach(p => { const platform = p.trim(); if (platform.length > 0) platforms.add(platform); }); } }); - - // Trier alphabétiquement const sortedPlatforms = Array.from(platforms).sort(); - - // Conserver l'option "Toutes" et ajouter les plateformes select.innerHTML = ''; sortedPlatforms.forEach(platform => { const option = document.createElement('option'); @@ -48,8 +42,6 @@ function generateStreamingSelect() { option.textContent = platform; select.appendChild(option); }); - - // Écouteur d'événement select.addEventListener('change', (e) => { activeStreamingFilter = e.target.value; currentPage = 1; @@ -57,38 +49,43 @@ function generateStreamingSelect() { }); } +// ── CHARGEMENT ── +async function loadPublicData() { + try { + const response = await fetch(`${API_URL}?action=get_films`); + films = await response.json(); + generateStreamingSelect(); + renderPublicGrid(); + } catch (error) { + console.error("Erreur de récupération :", error); + } +} + +// ── NAVIGATION ONGLETS ── function switchPubTab(tabName) { currentPubTab = tabName; activeRatingFilter = 0; activeStreamingFilter = ''; currentPage = 1; - - // Reset le select const select = document.getElementById('pub-streaming-select'); if (select) select.value = ''; - const ratingBar = document.getElementById('rating-filter-bar'); - if(ratingBar) ratingBar.style.display = (tabName === 'critique') ? 'flex' : 'none'; - - // Cacher le select sur l'onglet vidéothèque + if (ratingBar) ratingBar.style.display = (tabName === 'critique') ? 'flex' : 'none'; if (select) select.style.display = (tabName === 'critique') ? 'block' : 'none'; - document.querySelectorAll('.rating-filter-btn').forEach(btn => { btn.classList.remove('active'); btn.querySelectorAll('.rf-star').forEach(s => s.classList.remove('filled')); }); - document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active')); const activeBtn = document.getElementById(`tab-pub-${tabName}s`); - if(activeBtn) activeBtn.classList.add('active'); - + if (activeBtn) activeBtn.classList.add('active'); renderPublicGrid(); } +// ── FILTRE PAR NOTE (regroupement : 5★ = 4.5+5, 4★ = 3.5+4, etc.) ── function filterByRating(stars) { if (currentPubTab !== 'critique') return; activeRatingFilter = (activeRatingFilter === stars) ? 0 : stars; - document.querySelectorAll('.rating-filter-btn').forEach(btn => { const n = parseInt(btn.dataset.stars); btn.classList.toggle('active', n === activeRatingFilter); @@ -99,6 +96,7 @@ function filterByRating(stars) { renderPublicGrid(); } +// ── RENDU GRILLE ── function renderPublicGrid() { const grid = document.getElementById('grid'); const emptyState = document.getElementById('empty-state'); @@ -106,10 +104,8 @@ function renderPublicGrid() { if (!grid) return; grid.innerHTML = ''; - // 1. Filtrage par type let filtered = films.filter(f => f.type === currentPubTab); - // Filtre par note (regroupement : 5★ inclut 4.5, 4★ inclut 3.5, etc.) if (currentPubTab === 'critique' && activeRatingFilter > 0) { filtered = filtered.filter(f => { const rating = parseFloat(f.rating) || 0; @@ -117,18 +113,15 @@ function renderPublicGrid() { }); } - // 3. Filtre par plateforme (avec normalisation) if (currentPubTab === 'critique' && activeStreamingFilter) { const filterLower = activeStreamingFilter.toLowerCase(); filtered = filtered.filter(f => { if (!f.streaming || f.streaming === 'Disponible en support physique ou Cinéma') return false; - // On vérifie si la plateforme sélectionnée est présente dans le champ streaming const platforms = f.streaming.split(',').map(p => p.trim().toLowerCase()); return platforms.includes(filterLower); }); } - // 4. Recherche textuelle if (searchQuery) { const q = searchQuery.toLowerCase(); filtered = filtered.filter(f => @@ -148,13 +141,11 @@ function renderPublicGrid() { } if (emptyState) emptyState.style.display = 'none'; - // 5. Pagination 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); - // 6. Rendu pageItems.forEach(f => { const card = document.createElement('div'); card.className = 'card'; @@ -169,17 +160,12 @@ function renderPublicGrid() { if (f.streaming && f.streaming !== 'Disponible en support physique ou Cinéma') { streamingBadge = `
📺 ${f.streaming.split(',')[0]}
`; } else { - streamingBadge = `
️ Physique / Cinéma
`; + streamingBadge = `
🎟️ Physique / Cinéma
`; } } if (f.type === 'critique') { - const rating = parseFloat(f.rating) || 0; - const fullStars = Math.floor(rating); - const emptyStars = 5 - Math.ceil(rating); - const starsHTML = '★'.repeat(fullStars) + `${'☆'.repeat(emptyStars)}`; - const ratingNum = `${rating.toFixed(1)}`; - + const starsHTML = getStarsHTML(f.rating) + `${parseFloat(f.rating).toFixed(1)}`; card.innerHTML = ` ${posterHTML} ${streamingBadge} @@ -187,7 +173,7 @@ function renderPublicGrid() {

${f.title}

${f.director || 'Réalisateur inconnu'}

${f.year || '-'}

-
${starsHTML}${ratingNum}
+
${starsHTML}
`; } else { card.innerHTML = ` @@ -208,11 +194,11 @@ function renderPublicGrid() { renderPagination(totalPages); } +// ── PAGINATION ── function renderPagination(totalPages) { const container = document.getElementById('pub-pagination'); if (!container) return; container.innerHTML = ''; - if (totalPages <= 1) return; const info = document.createElement('span'); @@ -232,7 +218,6 @@ function renderPagination(totalPages) { if (endPage - startPage + 1 < maxButtons) { startPage = Math.max(1, endPage - maxButtons + 1); } - if (startPage > 1) { container.appendChild(createPubPageBtn(1)); if (startPage > 2) container.appendChild(createPubEllipsis()); @@ -244,7 +229,6 @@ function renderPagination(totalPages) { if (endPage < totalPages - 1) container.appendChild(createPubEllipsis()); container.appendChild(createPubPageBtn(totalPages)); } - const nextBtn = document.createElement('button'); nextBtn.innerHTML = ''; nextBtn.disabled = currentPage === totalPages; @@ -268,6 +252,7 @@ function createPubEllipsis() { return span; } +// ── DÉTAIL ── function openDetail(id) { const f = films.find(item => item.id == id); if (!f) return; @@ -296,12 +281,9 @@ function openDetail(id) { if (dBody) { if (f.type === 'critique') { - const rating = parseFloat(f.rating) || 0; - const fullStars = Math.floor(rating); - const emptyStars = 5 - Math.ceil(rating); - const stars = '★'.repeat(fullStars) + `${'☆'.repeat(emptyStars)}`; + const stars = getStarsHTML(f.rating) + `${parseFloat(f.rating).toFixed(1)}/5`; dBody.innerHTML = ` -
${stars} ${rating.toFixed(1)}/5
+
${stars}

${f.review ? f.review : 'Aucun texte rédigé pour le moment.'}

@@ -344,9 +326,9 @@ function closeDetail() { if (detailOverlay) detailOverlay.classList.remove('open'); } +// ── INITIALISATION ── document.addEventListener('DOMContentLoaded', () => { loadPublicData(); - const searchInput = document.getElementById('pub-search-input'); if (searchInput) { searchInput.addEventListener('input', (e) => {