Files
Todo/components/SearchBar.tsx
Paul Bailey 87f91ecbe0 feat: implement performance optimizations
- Add database indexes for frequently queried fields (listId, completed, priority, dueDate, createdAt)
- Add compound indexes for common query patterns (listId+completed, listId+priority)
- Implement pagination support in getItemsByFilter with configurable page size (default 50)
- Optimize components with React.memo (ItemCard, ListCard, FilterPanel, SearchBar, SearchResults, EmptyState)
- Configure Next.js for better bundle optimization:
  - Enable optimizePackageImports for lucide-react
  - Enable SWC minification
  - Remove console logs in production (except errors/warnings)
  - Optimize images with AVIF/WebP formats
  - Enable compression
  - Disable production source maps for smaller bundles
- Loading states already implemented to prevent layout shift

Task 18 complete - all performance optimizations implemented
2025-12-01 21:29:50 +00:00

59 lines
1.7 KiB
TypeScript

'use client'
import { memo } from 'react'
import { Search, X } from 'lucide-react'
import { useSearch } from '@/hooks'
interface SearchBarProps {
onSearch: (query: string) => void
placeholder?: string
debounceMs?: number
initialValue?: string
}
function SearchBar({
onSearch,
placeholder = 'Search tasks...',
debounceMs = 300,
initialValue = ''
}: SearchBarProps) {
const { query, setQuery, clearSearch, isDebouncing } = useSearch({
debounceMs,
onSearch
})
return (
<div className="relative">
<div className="relative">
<Search
className="absolute left-3 sm:left-4 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none"
size={20}
/>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={placeholder}
className="w-full pl-10 sm:pl-12 pr-10 sm:pr-12 py-3 sm:py-3.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm sm:text-base transition-shadow"
/>
{query && (
<button
onClick={clearSearch}
className="absolute right-3 sm:right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 active:text-gray-700 transition-colors tap-target-sm"
aria-label="Clear search"
>
<X size={20} />
</button>
)}
{isDebouncing && (
<div className="absolute right-12 sm:right-14 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>
)
}
export default memo(SearchBar)