From c2fa764e2429f6fa49e7c1ed2b10202be7f8f6a3 Mon Sep 17 00:00:00 2001 From: Sam Chau Date: Sun, 12 Jan 2025 02:52:07 +1030 Subject: [PATCH] feat: enhance DataBar and SearchBar components with multi-term search functionality --- .../src/components/ui/DataBar/DataBar.jsx | 37 ++--- .../src/components/ui/DataBar/SearchBar.jsx | 151 +++++++++--------- 2 files changed, 84 insertions(+), 104 deletions(-) diff --git a/frontend/src/components/ui/DataBar/DataBar.jsx b/frontend/src/components/ui/DataBar/DataBar.jsx index 0a59117..5b58285 100644 --- a/frontend/src/components/ui/DataBar/DataBar.jsx +++ b/frontend/src/components/ui/DataBar/DataBar.jsx @@ -17,8 +17,13 @@ const FloatingBar = ({children}) => ( ); const DataBar = ({ - onSearch, searchPlaceholder = 'Search by name or tag...', + searchTerms, + currentInput, + onInputChange, + onAddTerm, + onRemoveTerm, + onClearTerms, filterType, setFilterType, filterValue, @@ -34,43 +39,28 @@ const DataBar = ({ className }) => { const [isFloating, setIsFloating] = useState(false); - const [searchTerm, setSearchTerm] = useState(''); - const [activeSearch, setActiveSearch] = useState(''); useEffect(() => { const handleScroll = () => { setIsFloating(window.scrollY > 64); }; - window.addEventListener('scroll', handleScroll, {passive: true}); return () => window.removeEventListener('scroll', handleScroll); }, []); - const handleSearch = term => { - // First set the search term and trigger the search - setActiveSearch(term); - onSearch(term); - - // Then smoothly scroll to top - window.scrollTo({ - top: 0, - behavior: 'smooth' - }); - }; - const controls = ( <> -
setSortBy(key)} /> - - {showAddButton && !isSelectionMode && ( )} - { const [isFocused, setIsFocused] = useState(false); @@ -17,111 +18,103 @@ const SearchBar = ({ const handleKeyDown = e => { if ((e.ctrlKey || e.metaKey) && e.key === 'f') { e.preventDefault(); - document.querySelector('input[type="text"]').focus(); + document.querySelector('input[type="text"]')?.focus(); } else if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); - clearSearch(); + onClearTerms(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); - }, []); - - const handleChange = e => { - const newValue = e.target.value; - setSearchTerm(newValue); - if (!requireEnter) { - onSearch(newValue); - setActiveSearch(newValue); - } - }; + }, [onClearTerms]); const handleKeyPress = e => { - if (requireEnter && e.key === 'Enter' && searchTerm.trim()) { - onSearch(searchTerm); - setActiveSearch(searchTerm); - setSearchTerm(''); + if (requireEnter && e.key === 'Enter' && currentInput.trim()) { + onAddTerm(currentInput); } }; - const clearSearch = () => { - setSearchTerm(''); - setActiveSearch(''); - onSearch(''); - }; - return (
- {activeSearch ? ( + w-full min-h-10 pl-9 pr-8 rounded-md + transition-all duration-200 ease-in-out + border shadow-sm flex items-center flex-wrap gap-2 p-2 + ${ + isFocused + ? 'border-blue-500 ring-2 ring-blue-500/20 bg-white/5' + : 'border-gray-300 dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-600' + } + bg-white dark:bg-gray-800 + `}> + {searchTerms.map((term, index) => (
+ bg-blue-500/10 dark:bg-blue-500/20 + border border-blue-500/20 dark:border-blue-400/20 + text-blue-600 dark:text-blue-400 + rounded-md shadow-sm + hover:bg-blue-500/15 dark:hover:bg-blue-500/25 + hover:border-blue-500/30 dark:hover:border-blue-400/30 + group/badge + transition-all duration-200'> - {activeSearch} + {term}
- ) : ( - setIsFocused(true)} - onBlur={() => setIsFocused(false)} - placeholder={placeholder} - className='w-full bg-transparent - text-gray-900 dark:text-gray-100 - placeholder:text-gray-500 dark:placeholder:text-gray-400 - focus:outline-none' - /> - )} + ))} + onInputChange(e.target.value)} + onKeyPress={handleKeyPress} + onFocus={() => setIsFocused(true)} + onBlur={() => setIsFocused(false)} + placeholder={ + searchTerms.length + ? 'Add another filter...' + : placeholder + } + className='flex-1 min-w-[200px] bg-transparent + text-gray-900 dark:text-gray-100 + placeholder:text-gray-500 dark:placeholder:text-gray-400 + focus:outline-none' + />
- {searchTerm && !activeSearch && ( + {(searchTerms.length > 0 || currentInput) && ( )}