feat: implement client-side state management hooks

- Created useSearch hook for search state and debouncing
- Created useFilters hook for filter state management
- Created useOptimisticUpdate hook for optimistic UI updates
- Created useScrollPosition hook for scroll preservation
- Updated SearchBar, GlobalSearch, and ListDetailView to use new hooks
- Added comprehensive documentation for all hooks

Validates: Requirements 6.4, 7.3, 7.4, 8.3
Task: 9. Implement client-side state management
This commit is contained in:
2025-12-01 20:11:41 +00:00
parent 0143097e69
commit e2e3581d06
10 changed files with 821 additions and 52 deletions

View File

@@ -1,7 +1,7 @@
'use client'
import { useState, useEffect, useCallback } from 'react'
import { Search, X } from 'lucide-react'
import { useSearch } from '@/hooks'
interface SearchBarProps {
onSearch: (query: string) => void
@@ -16,21 +16,10 @@ export default function SearchBar({
debounceMs = 300,
initialValue = ''
}: SearchBarProps) {
const [query, setQuery] = useState(initialValue)
// Debounced search effect
useEffect(() => {
const timer = setTimeout(() => {
onSearch(query)
}, debounceMs)
return () => clearTimeout(timer)
}, [query, debounceMs, onSearch])
const handleClear = useCallback(() => {
setQuery('')
onSearch('')
}, [onSearch])
const { query, setQuery, clearSearch, isDebouncing } = useSearch({
debounceMs,
onSearch
})
return (
<div className="relative">
@@ -48,13 +37,18 @@ export default function SearchBar({
/>
{query && (
<button
onClick={handleClear}
onClick={clearSearch}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors"
aria-label="Clear search"
>
<X size={20} />
</button>
)}
{isDebouncing && (
<div className="absolute right-10 top-1/2 -translate-y-1/2">
<div className="w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" />
</div>
)}
</div>
</div>
)