- Change the private key field name from "prvkey" to "prvkey_hex" in the CHAT_INTEGRATION.md file for clarity and consistency with expected data formats. feat: Add Fuzzy Search Component and Composable - Introduce a new FuzzySearch component for Vue 3, leveraging Fuse.js for intelligent search capabilities. - Implement a useFuzzySearch composable for flexible search functionality, allowing configuration of search options. - Create demo and README files to showcase usage and features of the fuzzy search implementation. - Update package.json and package-lock.json to include @vueuse/integrations version 13.6.0 for enhanced performance.
116 lines
No EOL
4 KiB
Vue
116 lines
No EOL
4 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import { FuzzySearch, useFuzzySearch } from './index'
|
|
|
|
// Sample data for demonstration
|
|
interface Product {
|
|
id: number
|
|
name: string
|
|
description: string
|
|
category: string
|
|
price: number
|
|
}
|
|
|
|
const products = ref<Product[]>([
|
|
{ id: 1, name: 'Laptop', description: 'High-performance laptop for work and gaming', category: 'Electronics', price: 1200 },
|
|
{ id: 2, name: 'Smartphone', description: 'Latest smartphone with advanced features', category: 'Electronics', price: 800 },
|
|
{ id: 3, name: 'Headphones', description: 'Wireless noise-cancelling headphones', category: 'Audio', price: 200 },
|
|
{ id: 4, name: 'Coffee Maker', description: 'Automatic coffee maker for home use', category: 'Kitchen', price: 150 },
|
|
{ id: 5, name: 'Running Shoes', description: 'Comfortable running shoes for athletes', category: 'Sports', price: 120 },
|
|
{ id: 6, name: 'Backpack', description: 'Durable backpack for travel and daily use', category: 'Travel', price: 80 },
|
|
{ id: 7, name: 'Tablet', description: 'Portable tablet for entertainment and work', category: 'Electronics', price: 500 },
|
|
{ id: 8, name: 'Blender', description: 'High-speed blender for smoothies and shakes', category: 'Kitchen', price: 100 },
|
|
])
|
|
|
|
// Fuzzy search configuration
|
|
const searchOptions = {
|
|
fuseOptions: {
|
|
keys: ['name', 'description', 'category'],
|
|
threshold: 0.3,
|
|
distance: 100,
|
|
ignoreLocation: true,
|
|
useExtendedSearch: false,
|
|
minMatchCharLength: 1,
|
|
shouldSort: true,
|
|
findAllMatches: false,
|
|
location: 0,
|
|
isCaseSensitive: false,
|
|
},
|
|
resultLimit: 10,
|
|
matchAllWhenSearchEmpty: true,
|
|
minSearchLength: 1,
|
|
}
|
|
|
|
// Use the fuzzy search composable
|
|
const {
|
|
searchQuery,
|
|
results,
|
|
filteredItems,
|
|
isSearching,
|
|
resultCount,
|
|
clearSearch
|
|
} = useFuzzySearch(products, searchOptions)
|
|
|
|
// Handle search results
|
|
const handleSearchResults = (results: Product[]) => {
|
|
console.log('Search results:', results)
|
|
}
|
|
|
|
const handleSearch = (query: string) => {
|
|
console.log('Search query:', query)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-6 max-w-4xl mx-auto">
|
|
<h1 class="text-3xl font-bold mb-6">Fuzzy Search Demo</h1>
|
|
|
|
<!-- Fuzzy Search Component -->
|
|
<div class="mb-8">
|
|
<h2 class="text-xl font-semibold mb-4">Search Products</h2>
|
|
<FuzzySearch
|
|
:data="products"
|
|
:options="searchOptions"
|
|
placeholder="Search products by name, description, or category..."
|
|
@search="handleSearch"
|
|
@results="handleSearchResults"
|
|
class="max-w-md"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Search Results -->
|
|
<div class="mb-8">
|
|
<h2 class="text-xl font-semibold mb-4">
|
|
Results ({{ resultCount }} found)
|
|
<span v-if="isSearching" class="text-sm font-normal text-muted-foreground">
|
|
- Searching for "{{ searchQuery }}"
|
|
</span>
|
|
</h2>
|
|
|
|
<div v-if="filteredItems.length === 0 && isSearching" class="text-center py-8 text-muted-foreground">
|
|
No products found matching your search.
|
|
</div>
|
|
|
|
<div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
<div
|
|
v-for="product in filteredItems"
|
|
:key="product.id"
|
|
class="border rounded-lg p-4 hover:shadow-md transition-shadow"
|
|
>
|
|
<h3 class="font-semibold text-lg">{{ product.name }}</h3>
|
|
<p class="text-sm text-muted-foreground mb-2">{{ product.description }}</p>
|
|
<div class="flex justify-between items-center">
|
|
<span class="text-sm bg-secondary px-2 py-1 rounded">{{ product.category }}</span>
|
|
<span class="font-semibold">${{ product.price }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Raw Results (for debugging) -->
|
|
<div v-if="isSearching" class="mt-8 p-4 bg-muted rounded-lg">
|
|
<h3 class="font-semibold mb-2">Raw Search Results (with scoring)</h3>
|
|
<pre class="text-xs overflow-auto">{{ JSON.stringify(results, null, 2) }}</pre>
|
|
</div>
|
|
</div>
|
|
</template> |