From ea5e3b13cde602b2f98619dd47b4c2fcc6fb3e71 Mon Sep 17 00:00:00 2001 From: Antoine M Date: Fri, 20 Mar 2026 16:53:33 +0100 Subject: [PATCH] FEATURE Handling new features in components like scrolling to filters if page var has query --- resources/js/archives/archives.ts | 261 ++++++++++++++++-------------- 1 file changed, 140 insertions(+), 121 deletions(-) diff --git a/resources/js/archives/archives.ts b/resources/js/archives/archives.ts index 8701a9f..65c27a4 100644 --- a/resources/js/archives/archives.ts +++ b/resources/js/archives/archives.ts @@ -1,140 +1,159 @@ - //post-grid__toolbar-actions export default function archivesInit() { + const isArchivePage = document.querySelector('body.archive'); + if (!isArchivePage) return; - const isArchivePage = document.querySelector('body.archive'); - if (!isArchivePage) return; + const toolbar = document.querySelector('.post-grid__toolbar'); + if (!toolbar) 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); + 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; // É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); + }; + } - // 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 ?? ''; - 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(); + const params = new URLSearchParams({ + etiquette: etiquetteValue, + auteur: auteurValue, + sort_by: sortByValue, + recherche: rechercheValue, + post_type: postTypeValue, }); - etiquettesSelect.addEventListener('change', (e) => { - hydratePosts(); - }); + const url = `/wp-json/carhop-datas/v1/build/posts?${params.toString()}`; - sortBySelect.addEventListener('change', (e) => { - hydratePosts(); // immédiat pour le tri - }); - rechercheInput.addEventListener('input', (e) => { - hydratePostsDebounced(); // debounce pour la saisie rapide - }); - handleFilterPostsBy(); + // 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(); - postGridToolbarActions.addEventListener('click', (e) => { + 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 + }); }); -} \ No newline at end of file + } + + 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(); + }); +} + +function updatePostCount(count: number) { + const postCount = document.querySelector('.post-count__count'); + if (!postCount) return; + postCount.innerHTML = count.toString(); +} + +function scrollToPostsGridIfHasInitialFilter() { + const postsGrid = document.querySelector('.post-grid'); + const hasInitialFilter = postsGrid?.classList.contains('has-initial-filter'); + if (!hasInitialFilter || !postsGrid) return; + + setTimeout(() => { + postsGrid.scrollIntoView({ behavior: 'smooth' }); + }, 200); + setTimeout(() => { + const etiquettesSelect = document.querySelector( + '.post-grid__toolbar-actions select[name="etiquettes"]', + ) as HTMLSelectElement; + if (!etiquettesSelect) return; + etiquettesSelect.focus(); + }, 500); +} + +window.addEventListener('load', () => { + scrollToPostsGridIfHasInitialFilter(); +});