From f49f7fd6973af1de6773b4337dc4b41249221990 Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 16 Mar 2026 10:12:24 +0100 Subject: [PATCH] FEATURE Handling Javascript archive filters --- resources/js/app.ts | 2 + resources/js/archives/archives.ts | 140 ++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 resources/js/archives/archives.ts diff --git a/resources/js/app.ts b/resources/js/app.ts index 6497659..4a0de39 100644 --- a/resources/js/app.ts +++ b/resources/js/app.ts @@ -5,6 +5,7 @@ import handleInsidePageScrolling from './page-scrolling'; import alternatePictures from './alternate-pictures'; import { searchBarInit } from './search-bar'; import singlesInit from './singles/singles'; +import archivesInit from './archives/archives'; window.addEventListener('load', function () { menuInit(); @@ -14,4 +15,5 @@ window.addEventListener('load', function () { alternatePictures(); searchBarInit(); singlesInit(); + archivesInit(); }); diff --git a/resources/js/archives/archives.ts b/resources/js/archives/archives.ts new file mode 100644 index 0000000..8701a9f --- /dev/null +++ b/resources/js/archives/archives.ts @@ -0,0 +1,140 @@ + +//post-grid__toolbar-actions + +export default function archivesInit() { + + const isArchivePage = document.querySelector('body.archive'); + if (!isArchivePage) return; + + + const toolbar = document.querySelector('.post-grid__toolbar'); + if (!toolbar) return; + + const postGridToolbarActions = toolbar.querySelector('.post-grid__toolbar-actions'); + const currentPostType = postGridToolbarActions?.getAttribute('data-post-type') as string; + const etiquettesSelect = toolbar.querySelector('select[name="etiquettes"]') as HTMLSelectElement; + const auteursSelect = toolbar.querySelector('select[name="auteurs"]') as HTMLSelectElement; + const sortBySelect = toolbar.querySelector('select[name="sort_by"]') as HTMLSelectElement; + const rechercheInput = toolbar.querySelector('.search-bar input') as HTMLInputElement; + + console.log('currentPostType', currentPostType); + console.log('etiquettesSelect', etiquettesSelect); + console.log('auteursSelect', auteursSelect); + console.log('sortBySelect', sortBySelect); + console.log('rechercheInput', rechercheInput); + + // Évite les courses: annule les requêtes précédentes et ignore les réponses obsolètes + let currentAbortController: AbortController | null = null; + let lastRequestId = 0; + + + // Debounce simple pour la recherche + function debounce void>(fn: T, waitMs: number) { + let timeoutId: number | undefined; + return (...args: Parameters) => { + if (timeoutId) window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => fn(...args), waitMs); + }; + } + + async function hydratePosts() { + + const etiquetteValue = etiquettesSelect?.value ?? ''; + const auteurValue = auteursSelect?.value ?? ''; + const sortByValue = sortBySelect?.value ?? ''; + const rechercheValue = rechercheInput?.value ?? ''; + const postTypeValue = currentPostType ?? ''; + + + const params = new URLSearchParams({ + etiquette: etiquetteValue, + auteur: auteurValue, + sort_by: sortByValue, + recherche: rechercheValue, + post_type: postTypeValue, + }); + console.log(params.toString()); + const url = `/wp-json/carhop-datas/v1/build/posts?${params.toString()}`; + + + // Annule la précédente et prépare un nouvel identifiant + if (currentAbortController) currentAbortController.abort(); + currentAbortController = new AbortController(); + const requestId = ++lastRequestId; + + try { + const response = await fetch(url, { signal: currentAbortController.signal }); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + const data = await response.json(); + + console.log('data', data); + + // Ignore si une requête plus récente a été envoyée + if (requestId !== lastRequestId) return; + + const articlesContainer = document.querySelector('.post-grid__list'); + if (!articlesContainer) return; + articlesContainer.innerHTML = data.html_template; + + updatePostCount(data.post_count); + } catch (error) { + if ((error as any)?.name === 'AbortError') return; + console.error('Erreur lors de la récupération des articles:', error); + } + } + + const hydratePostsDebounced = debounce(hydratePosts, 150); + + function resetCurrentFilters() { + if (!etiquettesSelect || !auteursSelect || !rechercheInput) return; + + etiquettesSelect.value = ''; + auteursSelect.value = ''; + rechercheInput.value = ''; + } + + function setFilterByActivebutton(button: HTMLButtonElement) { + const filterByButtons = document.querySelectorAll('.search-by button'); + if (!filterByButtons) return; + filterByButtons.forEach((button) => { + button.setAttribute('aria-selected', 'false'); + }); + button.setAttribute('aria-selected', 'true'); + } + + + + function handleFilterPostsBy() { + const filterByButtons = document.querySelectorAll('.search-by button'); + if (!filterByButtons) return; + filterByButtons.forEach((button) => { + button.addEventListener('click', (e) => { + e.preventDefault(); + setFilterByActivebutton(button as HTMLButtonElement); + resetCurrentFilters(); + hydratePosts(); // immédiat sur action explicite + }); + }); + } + + auteursSelect.addEventListener('change', (e) => { + hydratePosts(); + }); + + etiquettesSelect.addEventListener('change', (e) => { + hydratePosts(); + }); + + sortBySelect.addEventListener('change', (e) => { + hydratePosts(); // immédiat pour le tri + }); + rechercheInput.addEventListener('input', (e) => { + hydratePostsDebounced(); // debounce pour la saisie rapide + }); + handleFilterPostsBy(); + + + postGridToolbarActions.addEventListener('click', (e) => { + e.preventDefault(); + }); +} \ No newline at end of file