71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
import { createFileRoute, useNavigate, useSearch } from '@tanstack/react-router'
|
|
import { useState, useMemo } from 'react'
|
|
import Fuse from 'fuse.js'
|
|
import { useCentralProductStore } from '../lib/stores/central-product-store'
|
|
import { MyText, SearchBar, AppContainer, MyTouchableOpacity } from 'web-components'
|
|
|
|
export const Route = createFileRoute('/home/search')({
|
|
component: SearchPage,
|
|
validateSearch: (search: Record<string, string>) => ({
|
|
q: search.q || '',
|
|
}),
|
|
})
|
|
|
|
function SearchPage() {
|
|
const { q } = Route.useSearch()
|
|
const navigate = useNavigate()
|
|
const products = useCentralProductStore((s) => s.products)
|
|
|
|
const fuse = useMemo(
|
|
() =>
|
|
new Fuse(products, {
|
|
keys: ['name', 'category', 'description'],
|
|
threshold: 0.3,
|
|
}),
|
|
[products]
|
|
)
|
|
|
|
const results = useMemo(() => {
|
|
if (!q) return products.slice(0, 20)
|
|
return fuse.search(q).map((r) => r.item)
|
|
}, [q, fuse, products])
|
|
|
|
return (
|
|
<AppContainer>
|
|
<SearchBar
|
|
placeholder="Search products..."
|
|
value={q}
|
|
onChange={(val) => navigate({ to: '/home/search', search: { q: val } })}
|
|
onSearch={(val) => navigate({ to: '/home/search', search: { q: val } })}
|
|
/>
|
|
|
|
<div className="mt-4 grid grid-cols-2 gap-3">
|
|
{results.map((product) => (
|
|
<MyTouchableOpacity
|
|
key={product.id}
|
|
onClick={() =>
|
|
navigate({ to: '/home/product/$id', params: { id: String(product.id) } })
|
|
}
|
|
className="rounded-xl border border-gray-100 bg-white p-3 shadow-sm"
|
|
>
|
|
<div className="mb-2 aspect-square w-full overflow-hidden rounded-lg bg-gray-100">
|
|
{product.images?.[0] && (
|
|
<img
|
|
src={product.images[0].uri}
|
|
alt={product.name}
|
|
className="h-full w-full object-cover"
|
|
/>
|
|
)}
|
|
</div>
|
|
<MyText weight="semibold" className="text-sm" numberOfLines={2}>
|
|
{product.name}
|
|
</MyText>
|
|
<MyText weight="bold" className="mt-1 text-brand-600">
|
|
₹{product.discountedPrice ?? product.price}
|
|
</MyText>
|
|
</MyTouchableOpacity>
|
|
))}
|
|
</div>
|
|
</AppContainer>
|
|
)
|
|
}
|