From 916fd6a3f6076f359be7cf792cdee09dd2971864 Mon Sep 17 00:00:00 2001 From: Morgan Wattiez <morgan@zoemp.be> Date: Sun, 25 May 2025 02:47:58 +0200 Subject: [PATCH] filter by age without researching again --- public/index.html | 246 +++++++++++++++++++++++++--------------------- 1 file changed, 132 insertions(+), 114 deletions(-) diff --git a/public/index.html b/public/index.html index 42b46e7..7e0376a 100644 --- a/public/index.html +++ b/public/index.html @@ -123,13 +123,23 @@ badge.textContent = val + '+'; badge.style.background = getAgeColor(val); } - async function search() { + let lastQuery = ''; + let lastResults = []; + + async function search(force = false) { const query = document.getElementById('q').value.trim(); if (!query) return; const maxAge = parseInt(document.getElementById('maxAge').value, 10); window.history.replaceState({}, '', '?q=' + encodeURIComponent(query) + (maxAge < 21 ? `&maxAge=${maxAge}` : '')); const filmsDiv = document.getElementById('films'); filmsDiv.innerHTML = '<p class="loader">Searching...</p>'; + + // Si on a déjà cherché ce terme, et pas force, on ne refait pas le fetch + if (!force && lastQuery === query && lastResults.length) { + renderFilms(filterFilmsByMaxAge(lastResults, maxAge)); + return; + } + try { const base = window.location.origin; const response = await fetch(`${base}/search?q=${encodeURIComponent(query)}`); @@ -138,16 +148,8 @@ return; } let films = await response.json(); - if (!Array.isArray(films) || !films.length) { - filmsDiv.innerHTML = '<p class="no-results">No results. Try another query.</p>'; - return; - } - // Filtres sources inutiles (pas de description et/ou pas d'âge) films = films.map(film => { film.results = film.results.filter(r => { - // On considère valide si : - // - summary ou parentsNeedToKnow ou details.summary >= 8 chars - // - ET un âge existe (age, normalizedMarks, marks, details.ageLegal, etc) let hasDescription = (r.summary && r.summary.length >= 8) || (r.parentsNeedToKnow && r.parentsNeedToKnow.length >= 8) || @@ -159,118 +161,133 @@ return film; }).filter(film => film.results.length > 0); - if (isFinite(maxAge)) { - films = films.filter(film => { - const uniqueResults = []; - const seenSources = new Set(); - film.results.forEach(r => { - if (!seenSources.has(r.source)) { - uniqueResults.push(r); - seenSources.add(r.source); - } - }); - const ages = getAllAges(uniqueResults); - if (ages.length === 0) return true; - return Math.max(...ages) <= maxAge; - }); - } - if (!films.length) { - filmsDiv.innerHTML = '<p class="no-results">No results for this max age.</p>'; - return; - } - let html = `<table class="results-table"> - <thead> - <tr> - <th>Title</th> - <th>Year</th> - <th>Information sources</th> - </tr> - </thead> - <tbody>`; - films.forEach(film => { - const allImgs = film.results.map(r => r.img).filter(Boolean); - const mainImg = allImgs.length ? allImgs[0] : null; - html += `<tr> - <td style="vertical-align:top;"> - <div style="text-align:center;"> - <div style="font-weight:bold;margin-bottom:0.7em;">${film.title || 'Unknown title'}</div> - ${mainImg ? `<img src="${mainImg}" alt="Poster for ${film.title}" style="display:block;margin:auto;max-width:100px;max-height:150px;border-radius:5px;box-shadow:0 2px 8px #0003;margin-bottom:10px;">` : ''} - </div> - </td> - <td class="year" style="vertical-align:top;">${film.year || 'N/A'}</td> - <td>`; - const uniqueResults = []; - const seenSources = new Set(); - film.results.forEach(r => { - if (!seenSources.has(r.source)) { - uniqueResults.push(r); - seenSources.add(r.source); - } - }); - uniqueResults.forEach(r => { - html += `<div class="source-block">`; - html += `<p class="source-name">${r.source.charAt(0).toUpperCase() + r.source.slice(1)}</p>`; - if (r.link) { - html += `<p><a href="${r.link}" target="_blank">View details</a></p>`; - } - if (r.source === 'commonsense') { - html += `<p><b>Recommended age:</b> ${ageBadge(r.age)}</p>`; - html += `<p><b>Summary (CSM):</b> ${shortSummary(r.summary || r.parentsNeedToKnow)}</p>`; - if (r.details && r.details.length) { - html += `<p><b>Details (CSM):</b></p><ul>`; - r.details.forEach(d => { - html += `<li>${d.type}: ${d.score}/5 - ${shortSummary(d.description, 80)}</li>`; - }); - html += `</ul>`; - } - } - else if (r.source === 'cinecheck') { - let numericAges = Array.isArray(r.normalizedMarks) && r.normalizedMarks.length - ? r.normalizedMarks - : (r.marks || []).map(x => { - let n = parseInt((x + '').replace(/\d+/, ''), 10); - return isNaN(n) ? null : n; - }).filter(n => n !== null && !isNaN(n)); - let minAge = numericAges.length ? Math.min(...numericAges) : ''; - html += `<p><b>Age(s) (Cinecheck):</b> ${minAge ? ageBadge(minAge) : ''}${r.marks && r.marks.length ? r.marks.join(', ') : '-'}</p>`; - html += `<p><b>Summary (Cinecheck):</b> ${shortSummary(r.summary)}</p>`; - if (r.details && r.details.length) { - html += `<p><b>Pictograms (Cinecheck):</b> ${r.details.map(d => d.type).join(', ') || '-'}</p>`; - } - } - else if (r.source === 'filmages') { - html += `<p><b>Original title (Filmages):</b> ${r.details.titleOriginalPage || r.details.titleOriginal || '-'}</p>`; - html += `<p><b>Legal age (Filmages):</b> ${ageBadge(r.details.ageLegal)}</p>`; - html += `<p><b>Suggested age (Filmages):</b> ${ageBadge(r.details.ageSuggested)}</p>`; - html += `<p><b>Summary (Filmages):</b> ${shortSummary(r.details.summary)}</p>`; - html += `<p><b>Synthesis (Filmages):</b> ${shortSummary(r.details.synthesis, 100)}</p>`; - if (r.details.indications && r.details.indications.length) { - html += `<p><b>Indications:</b> ${shortSummary(r.details.indications.join(', '), 100)}</p>`; - } - if (r.details.counterIndications && r.details.counterIndications.length) { - html += `<p><b>Contra-indications:</b> ${shortSummary(r.details.counterIndications.join(', '), 100)}</p>`; - } - } - else { - html += `<p><b>Summary:</b> ${shortSummary(r.summary)}</p>`; - html += `<p><b>Age:</b> ${ageBadge(r.age)}</p>`; - } - html += `</div>`; - }); - html += `</td></tr>`; - }); - html += '</tbody></table>'; - filmsDiv.innerHTML = html; + lastQuery = query; + lastResults = films; + renderFilms(filterFilmsByMaxAge(films, maxAge)); } catch (error) { console.error('Search function error:', error); filmsDiv.innerHTML = `<p class="no-results">Search failed. Check the console.</p>`; } } + function filterFilmsByMaxAge(films, maxAge) { + if (!isFinite(maxAge)) return films; + return films.filter(film => { + const uniqueResults = []; + const seenSources = new Set(); + film.results.forEach(r => { + if (!seenSources.has(r.source)) { + uniqueResults.push(r); + seenSources.add(r.source); + } + }); + const ages = getAllAges(uniqueResults); + if (ages.length === 0) return true; + return Math.max(...ages) <= maxAge; + }); + } + + // Extraction de la partie rendering pour pouvoir la réutiliser + function renderFilms(films) { + const filmsDiv = document.getElementById('films'); + if (!films.length) { + filmsDiv.innerHTML = '<p class="no-results">No results for this max age.</p>'; + return; + } + let html = `<table class="results-table"> + <thead> + <tr> + <th>Title</th> + <th>Year</th> + <th>Information sources</th> + </tr> + </thead> + <tbody>`; + films.forEach(film => { + const allImgs = film.results.map(r => r.img).filter(Boolean); + const mainImg = allImgs.length ? allImgs[0] : null; + html += `<tr> + <td style="vertical-align:top;"> + <div style="text-align:center;"> + <div style="font-weight:bold;margin-bottom:0.7em;">${film.title || 'Unknown title'}</div> + ${mainImg ? `<img src="${mainImg}" alt="Poster for ${film.title}" style="display:block;margin:auto;max-width:100px;max-height:150px;border-radius:5px;box-shadow:0 2px 8px #0003;margin-bottom:10px;">` : ''} + </div> + </td> + <td class="year" style="vertical-align:top;">${film.year || 'N/A'}</td> + <td>`; + const uniqueResults = []; + const seenSources = new Set(); + film.results.forEach(r => { + if (!seenSources.has(r.source)) { + uniqueResults.push(r); + seenSources.add(r.source); + } + }); + uniqueResults.forEach(r => { + html += `<div class="source-block">`; + html += `<p class="source-name">${r.source.charAt(0).toUpperCase() + r.source.slice(1)}</p>`; + if (r.link) { + html += `<p><a href="${r.link}" target="_blank">View details</a></p>`; + } + if (r.source === 'commonsense') { + html += `<p><b>Recommended age:</b> ${ageBadge(r.age)}</p>`; + html += `<p><b>Summary (CSM):</b> ${shortSummary(r.summary || r.parentsNeedToKnow)}</p>`; + if (r.details && r.details.length) { + html += `<p><b>Details (CSM):</b></p><ul>`; + r.details.forEach(d => { + html += `<li>${d.type}: ${d.score}/5 - ${shortSummary(d.description, 80)}</li>`; + }); + html += `</ul>`; + } + } + else if (r.source === 'cinecheck') { + let numericAges = Array.isArray(r.normalizedMarks) && r.normalizedMarks.length + ? r.normalizedMarks + : (r.marks || []).map(x => { + let n = parseInt((x + '').replace(/\d+/, ''), 10); + return isNaN(n) ? null : n; + }).filter(n => n !== null && !isNaN(n)); + let minAge = numericAges.length ? Math.min(...numericAges) : ''; + html += `<p><b>Age(s) (Cinecheck):</b> ${minAge ? ageBadge(minAge) : ''}${r.marks && r.marks.length ? r.marks.join(', ') : '-'}</p>`; + html += `<p><b>Summary (Cinecheck):</b> ${shortSummary(r.summary)}</p>`; + if (r.details && r.details.length) { + html += `<p><b>Pictograms (Cinecheck):</b> ${r.details.map(d => d.type).join(', ') || '-'}</p>`; + } + } + else if (r.source === 'filmages') { + html += `<p><b>Original title (Filmages):</b> ${r.details.titleOriginalPage || r.details.titleOriginal || '-'}</p>`; + html += `<p><b>Legal age (Filmages):</b> ${ageBadge(r.details.ageLegal)}</p>`; + html += `<p><b>Suggested age (Filmages):</b> ${ageBadge(r.details.ageSuggested)}</p>`; + html += `<p><b>Summary (Filmages):</b> ${shortSummary(r.details.summary)}</p>`; + html += `<p><b>Synthesis (Filmages):</b> ${shortSummary(r.details.synthesis, 100)}</p>`; + if (r.details.indications && r.details.indications.length) { + html += `<p><b>Indications:</b> ${shortSummary(r.details.indications.join(', '), 100)}</p>`; + } + if (r.details.counterIndications && r.details.counterIndications.length) { + html += `<p><b>Contra-indications:</b> ${shortSummary(r.details.counterIndications.join(', '), 100)}</p>`; + } + } + else { + html += `<p><b>Summary:</b> ${shortSummary(r.summary)}</p>`; + html += `<p><b>Age:</b> ${ageBadge(r.age)}</p>`; + } + html += `</div>`; + }); + html += `</td></tr>`; + }); + html += '</tbody></table>'; + filmsDiv.innerHTML = html; + } + document.getElementById('maxAge').addEventListener('input', function() { updateMaxAgeDisplay(); - search(); + // Pas de fetch, juste filtre en front + const query = document.getElementById('q').value.trim(); + if (!query || !lastResults.length) return; + const maxAge = parseInt(document.getElementById('maxAge').value, 10); + renderFilms(filterFilmsByMaxAge(lastResults, maxAge)); }); + window.addEventListener('DOMContentLoaded', () => { const params = new URLSearchParams(window.location.search); const q = params.get('q'); @@ -281,10 +298,11 @@ } if (q) { document.getElementById('q').value = q; - search(); + search(true); // force fetch initiale } }); - document.getElementById('q').addEventListener('keydown', e => { if (e.key === 'Enter') search(); }); + document.getElementById('q').addEventListener('keydown', e => { if (e.key === 'Enter') search(true); }); + </script> </body> </html>