From b6efa3f37eaced1433869a6973ae935a0dcd2514 Mon Sep 17 00:00:00 2001 From: chamiakJ Date: Mon, 7 Jul 2025 05:52:07 +0530 Subject: [PATCH] feat(task-filters): enhance search filter functionality and UI interactions - Implemented synchronization of local search value with external value prop to maintain expanded state during searches. - Updated button styles for better visibility in dark mode and improved user experience. - Refactored search handling to ensure consistent use of taskReducer for search actions across different views. - Enhanced filter section visibility logic to improve user interaction during data loading. --- .../task-management/improved-task-filters.tsx | 77 +++++++++++-------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/worklenz-frontend/src/components/task-management/improved-task-filters.tsx b/worklenz-frontend/src/components/task-management/improved-task-filters.tsx index dce52dce..6e2fd1eb 100644 --- a/worklenz-frontend/src/components/task-management/improved-task-filters.tsx +++ b/worklenz-frontend/src/components/task-management/improved-task-filters.tsx @@ -605,6 +605,15 @@ const SearchFilter: React.FC<{ const [localValue, setLocalValue] = useState(value); const inputRef = useRef(null); + // Sync local value with external value prop + useEffect(() => { + setLocalValue(value); + // Keep expanded if there's a search value + if (value) { + setIsExpanded(true); + } + }, [value]); + const handleToggle = useCallback(() => { setIsExpanded(!isExpanded); if (!isExpanded) { @@ -623,7 +632,6 @@ const SearchFilter: React.FC<{ const handleClear = useCallback(() => { setLocalValue(''); onChange(''); - setIsExpanded(false); }, [onChange]); // Redux selectors for theme and other state @@ -631,7 +639,7 @@ const SearchFilter: React.FC<{ return (
- {!isExpanded ? ( + {!isExpanded && !value ? ( @@ -681,11 +693,19 @@ const SearchFilter: React.FC<{ + onClick={() => { + setLocalValue(''); + onChange(''); + setIsExpanded(false); + }} + className={`px-2.5 py-1.5 text-xs font-medium transition-colors duration-200 ${ + isDarkMode + ? 'text-gray-400 hover:text-gray-200' + : 'text-gray-600 hover:text-gray-800' + }`} + > + {t('cancel')} + )}
@@ -871,9 +891,14 @@ const ImprovedTaskFilters: React.FC = ({ position, cla // Use the filter data loader hook useFilterDataLoader(); + // Get search value from Redux based on position + const taskReducerSearch = useAppSelector(state => state.taskReducer?.search || ''); + const kanbanSearch = useAppSelector(state => state.enhancedKanbanReducer?.search || ''); + + const searchValue = position === 'board' ? kanbanSearch : taskReducerSearch; + // Local state for filter sections const [filterSections, setFilterSections] = useState([]); - const [searchValue, setSearchValue] = useState(''); const [openDropdown, setOpenDropdown] = useState(null); const [activeFiltersCount, setActiveFiltersCount] = useState(0); const [clearingFilters, setClearingFilters] = useState(false); @@ -890,8 +915,9 @@ const ImprovedTaskFilters: React.FC = ({ position, cla const filterSectionsData = useFilterData(position); // Check if data is loaded - memoize this computation + // Keep filters visible even during refetch if we have any filter sections const isDataLoaded = useMemo(() => { - return filterSectionsData.some(section => section.options.length > 0); + return filterSectionsData.length > 0; }, [filterSectionsData]); // Initialize filter sections from data - memoize this to prevent unnecessary updates @@ -948,12 +974,8 @@ const ImprovedTaskFilters: React.FC = ({ position, cla // Debounced search change function debouncedSearchChangeRef.current = createDebouncedFunction( (projectId: string, value: string) => { - // Dispatch search action based on current view - if (projectView === 'list') { - dispatch(setSearch(value)); - } else { - dispatch(setKanbanSearch(value)); - } + // Always use taskReducer search for list view since that's what we read from + dispatch(setSearch(value)); // Trigger task refetch with new search value dispatch(fetchTasksV3(projectId)); @@ -1084,8 +1106,6 @@ const ImprovedTaskFilters: React.FC = ({ position, cla const handleSearchChange = useCallback( (value: string) => { - setSearchValue(value); - if (!projectId) return; if (position === 'board') { @@ -1094,7 +1114,7 @@ const ImprovedTaskFilters: React.FC = ({ position, cla dispatch(fetchEnhancedKanbanGroups(projectId)); } } else { - // Use debounced search + // Use debounced search for list view if (projectId) { debouncedSearchChangeRef.current?.(projectId, value); } @@ -1116,9 +1136,6 @@ const ImprovedTaskFilters: React.FC = ({ position, cla // Batch all state updates together to prevent multiple re-renders const batchUpdates = () => { - // Clear local state immediately for UI feedback - setSearchValue(''); - // Update local filter sections state immediately setFilterSections(prev => prev.map(section => ({ @@ -1133,12 +1150,8 @@ const ImprovedTaskFilters: React.FC = ({ position, cla // Prepare all Redux actions to be dispatched together const reduxUpdates = () => { - // Clear search based on view - if (projectView === 'list') { - dispatch(setSearch('')); - } else { - dispatch(setKanbanBoardSearch('')); - } + // Clear search - always use taskReducer for list view + dispatch(setSearch('')); // Clear label filters const clearedLabels = currentTaskLabels.map(label => ({ @@ -1298,7 +1311,6 @@ const ImprovedTaskFilters: React.FC = ({ position, cla "{searchValue}"