refactor: (4) enhance MarketSearchBar with internal query handling and debouncing

- Introduced an internal query state to improve UI responsiveness during search input.
- Implemented a debounced search function to optimize performance and reduce unnecessary emissions.
- Updated conditions for displaying keyboard hints and clear button based on the new internal query.
- Ensured both internal and actual search queries are cleared appropriately.

These changes enhance the user experience by providing immediate feedback while typing and optimizing search operations.
This commit is contained in:
padreug 2025-09-27 18:44:02 +02:00
parent 1f321dce4a
commit b3428c2905

View file

@ -8,7 +8,7 @@
<Input
ref="searchInputRef"
:model-value="searchQuery"
:model-value="internalQuery || searchQuery"
@update:model-value="handleSearchChange"
@keydown="handleKeydown"
@focus="handleFocus"
@ -21,13 +21,13 @@
<!-- Enhanced Features (keyboard hints, clear button) -->
<div class="absolute inset-y-0 right-0 pr-3 flex items-center gap-2">
<!-- Keyboard Shortcuts Hint (only for enhanced mode on desktop) -->
<div v-if="showEnhancements && showKeyboardHints && !searchQuery && isDesktop" class="text-xs text-muted-foreground flex items-center gap-1">
<div v-if="showEnhancements && showKeyboardHints && !internalQuery && !searchQuery && isDesktop" class="text-xs text-muted-foreground flex items-center gap-1">
<Badge variant="outline" class="px-1 py-0 text-xs"> K</Badge>
</div>
<!-- Clear Button -->
<Button
v-if="searchQuery"
v-if="internalQuery || searchQuery"
variant="ghost"
size="sm"
@click="handleClear"
@ -89,7 +89,7 @@ import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Search, X } from 'lucide-vue-next'
import { useLocalStorage, useBreakpoints, breakpointsTailwind } from '@vueuse/core'
import { useLocalStorage, useBreakpoints, breakpointsTailwind, useDebounceFn } from '@vueuse/core'
import type { Product } from '../types/market'
// Conditional imports for enhanced mode
@ -265,20 +265,35 @@ const searchSuggestions = computed(() => {
})
// Methods
const handleSearchChange = (value: string | number) => {
const stringValue = String(value)
setSearchQuery(stringValue)
emit('update:modelValue', stringValue)
emit('search', stringValue)
// Internal search query for immediate UI updates
const internalQuery = ref('')
// Debounced search function for performance optimization
const debouncedSearch = useDebounceFn((value: string) => {
setSearchQuery(value)
emit('search', value)
emit('results', filteredItems.value)
// Add to recent searches when user finishes typing (enhanced mode only)
if (props.showEnhancements && stringValue.trim() && stringValue.length >= 3) {
addToRecentSearches(stringValue.trim())
if (props.showEnhancements && value.trim() && value.length >= 3) {
addToRecentSearches(value.trim())
}
}, 300)
const handleSearchChange = (value: string | number) => {
const stringValue = String(value)
// Update internal query immediately for responsive UI
internalQuery.value = stringValue
emit('update:modelValue', stringValue)
// Debounce the actual search computation
debouncedSearch(stringValue)
}
const handleClear = () => {
// Clear both internal and actual search queries
internalQuery.value = ''
clearSearch()
emit('update:modelValue', '')
emit('search', '')
@ -297,7 +312,7 @@ const handleKeydown = (event: KeyboardEvent) => {
// Handle basic Escape key for simple mode
if (event.key === 'Escape') {
event.preventDefault()
if (searchQuery.value) {
if (internalQuery.value || searchQuery.value) {
handleClear()
}
return
@ -307,7 +322,7 @@ const handleKeydown = (event: KeyboardEvent) => {
if (useSearchKeyboardShortcuts.value && handleSearchKeydown) {
const shouldClear = handleSearchKeydown(event)
if (shouldClear) {
if (searchQuery.value) {
if (internalQuery.value || searchQuery.value) {
handleClear()
} else {
blurSearchInput()
@ -318,15 +333,18 @@ const handleKeydown = (event: KeyboardEvent) => {
const filterByCategory = (category: string) => {
emit('filter-category', category)
internalQuery.value = category
setSearchQuery(category)
}
const applySuggestion = (suggestion: string) => {
internalQuery.value = suggestion
setSearchQuery(suggestion)
addToRecentSearches(suggestion)
}
const applyRecentSearch = (recent: string) => {
internalQuery.value = recent
setSearchQuery(recent)
}