freshyo/apps/web-ui/src/routes/home.search.tsx
2026-05-10 16:45:39 +05:30

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>
)
}