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.
This commit is contained in:
Julien Froidefond
2025-09-24 08:11:46 +02:00
parent 7ebc0af3c7
commit 9c8d19fb09

View File

@@ -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<number | undefined>(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
<div className="flex-1 max-w-md">
<Input
type="text"
value={filters.search || ''}
value={localSearch}
onChange={(e) => handleSearchChange(e.target.value)}
placeholder="Rechercher des tâches..."
className="bg-[var(--card)] border-[var(--border)]"