Add MarketFuzzySearch component for enhanced product searching
- Introduced a new MarketFuzzySearch component to provide an advanced search interface with keyboard shortcuts, search suggestions, and recent searches functionality. - Updated MarketPage and StallView to integrate the new fuzzy search component, replacing the previous search input implementations. - Enhanced search capabilities with configurable options for better user experience and product discovery. These changes improve the search functionality across the market module, making it easier for users to find products efficiently.
This commit is contained in:
parent
86d3133978
commit
8aa575ffb1
3 changed files with 470 additions and 34 deletions
|
|
@ -78,14 +78,13 @@
|
|||
<!-- Search and Filter Bar -->
|
||||
<div class="mb-6 flex flex-col sm:flex-row gap-4">
|
||||
<div class="flex-1">
|
||||
<div class="relative">
|
||||
<Search class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
|
||||
<Input
|
||||
v-model="searchQuery"
|
||||
placeholder="Search products in this stall..."
|
||||
class="pl-10"
|
||||
/>
|
||||
</div>
|
||||
<FuzzySearch
|
||||
:data="stallProducts"
|
||||
:options="searchOptions"
|
||||
placeholder="Search products in this stall..."
|
||||
@results="handleSearchResults"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
|
|
@ -166,10 +165,12 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { ArrowLeft, Store, Search, Package, Loader2, X } from 'lucide-vue-next'
|
||||
import { ArrowLeft, Store, Package, Loader2, X } from 'lucide-vue-next'
|
||||
import FuzzySearch from '@/components/ui/fuzzy-search/FuzzySearch.vue'
|
||||
import ProductCard from '../components/ProductCard.vue'
|
||||
import ProductDetailDialog from '../components/ProductDetailDialog.vue'
|
||||
import type { Product, Stall } from '../types/market'
|
||||
import type { FuzzySearchOptions } from '@/composables/useFuzzySearch'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
|
@ -177,13 +178,32 @@ const marketStore = useMarketStore()
|
|||
|
||||
// State
|
||||
const isLoading = ref(false)
|
||||
const searchQuery = ref('')
|
||||
const searchResults = ref<Product[]>([])
|
||||
const sortBy = ref('name')
|
||||
const selectedCategories = ref<string[]>([])
|
||||
const showProductDetail = ref(false)
|
||||
const selectedProduct = ref<Product | null>(null)
|
||||
const logoError = ref(false)
|
||||
|
||||
// Fuzzy search configuration for stall products
|
||||
const searchOptions: FuzzySearchOptions<Product> = {
|
||||
fuseOptions: {
|
||||
keys: [
|
||||
{ name: 'name', weight: 0.8 }, // Product name has highest weight in stall view
|
||||
{ name: 'description', weight: 0.4 }, // Description is important for specific product search
|
||||
{ name: 'categories', weight: 0.3 } // Categories for filtering within stall
|
||||
],
|
||||
threshold: 0.2, // More strict matching since we're within a single stall
|
||||
ignoreLocation: true,
|
||||
findAllMatches: true,
|
||||
minMatchCharLength: 2,
|
||||
shouldSort: true
|
||||
},
|
||||
resultLimit: 100, // Less restrictive limit for stall view
|
||||
minSearchLength: 2,
|
||||
matchAllWhenSearchEmpty: true
|
||||
}
|
||||
|
||||
// Get stall ID from route params
|
||||
const stallId = computed(() => route.params.stallId as string)
|
||||
|
||||
|
|
@ -209,18 +229,12 @@ const stallCategories = computed(() => {
|
|||
// Product count
|
||||
const productCount = computed(() => stallProducts.value.length)
|
||||
|
||||
// Filtered and sorted products
|
||||
// Filtered and sorted products (using fuzzy search results when available)
|
||||
const filteredProducts = computed(() => {
|
||||
let products = [...stallProducts.value]
|
||||
|
||||
// Filter by search query
|
||||
if (searchQuery.value) {
|
||||
const query = searchQuery.value.toLowerCase()
|
||||
products = products.filter(p =>
|
||||
p.name.toLowerCase().includes(query) ||
|
||||
p.description?.toLowerCase().includes(query)
|
||||
)
|
||||
}
|
||||
// Use search results if available, otherwise use all stall products
|
||||
let products = searchResults.value.length > 0 || searchResults.value.length === 0
|
||||
? [...searchResults.value]
|
||||
: [...stallProducts.value]
|
||||
|
||||
// Filter by selected categories
|
||||
if (selectedCategories.value.length > 0) {
|
||||
|
|
@ -264,7 +278,12 @@ const toggleCategoryFilter = (category: string) => {
|
|||
|
||||
const clearFilters = () => {
|
||||
selectedCategories.value = []
|
||||
searchQuery.value = ''
|
||||
searchResults.value = []
|
||||
}
|
||||
|
||||
// Handle fuzzy search results
|
||||
const handleSearchResults = (results: Product[]) => {
|
||||
searchResults.value = results
|
||||
}
|
||||
|
||||
const viewProductDetails = (product: Product) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue