From 9c8d19fb09e8c109061e4d7d194401cf6dbf6bae Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Wed, 24 Sep 2025 08:11:46 +0200 Subject: [PATCH] feat: implement debounced search functionality in KanbanFilters - Added local state for search input to improve user experience with immediate feedback. - Introduced a debounced search function to optimize filter updates, reducing unnecessary renders. - Ensured synchronization of local search state with external filter changes and cleaned up timeouts on component unmount. --- src/components/kanban/KanbanFilters.tsx | 36 ++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/kanban/KanbanFilters.tsx b/src/components/kanban/KanbanFilters.tsx index 7ac40b4..36e5bbc 100644 --- a/src/components/kanban/KanbanFilters.tsx +++ b/src/components/kanban/KanbanFilters.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect, useRef, useMemo } from 'react'; +import { useState, useEffect, useRef, useMemo, useCallback } from 'react'; import { createPortal } from 'react-dom'; import { TaskPriority, TaskStatus } from '@/lib/types'; import { Button } from '@/components/ui/Button'; @@ -74,10 +74,40 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH } }, [isSortExpanded, isSwimlaneModeExpanded]); + // État local pour la recherche pour une saisie fluide + const [localSearch, setLocalSearch] = useState(filters.search || ''); + const searchTimeoutRef = useRef(undefined); + + // Fonction debouncée pour mettre à jour les filtres + const debouncedSearchChange = useCallback((search: string) => { + if (searchTimeoutRef.current) { + window.clearTimeout(searchTimeoutRef.current); + } + + searchTimeoutRef.current = window.setTimeout(() => { + onFiltersChange({ ...filters, search: search || undefined }); + }, 300); + }, [filters, onFiltersChange]); + const handleSearchChange = (search: string) => { - onFiltersChange({ ...filters, search: search || undefined }); + setLocalSearch(search); + debouncedSearchChange(search); }; + // Synchroniser l'état local quand les filtres changent de l'extérieur + useEffect(() => { + setLocalSearch(filters.search || ''); + }, [filters.search]); + + // Nettoyer le timeout au démontage + useEffect(() => { + return () => { + if (searchTimeoutRef.current) { + window.clearTimeout(searchTimeoutRef.current); + } + }; + }, []); + const handleTagToggle = (tagName: string) => { const currentTags = filters.tags || []; const newTags = currentTags.includes(tagName) @@ -195,7 +225,7 @@ export function KanbanFilters({ filters, onFiltersChange, hiddenStatuses: propsH
handleSearchChange(e.target.value)} placeholder="Rechercher des tâches..." className="bg-[var(--card)] border-[var(--border)]"