feat(marketplace): add functional sort dropdown to ProductSearch
- Add sortBy state with options: price, distance, expiry - Replace static text with interactive select dropdown - Implement sorting logic for each option in groupedProducts memo
This commit is contained in:
parent
1600591f86
commit
299001d8bc
1 changed files with 34 additions and 5 deletions
|
|
@ -22,6 +22,7 @@ const ProductSearch = () => {
|
||||||
const [maxPrice, setMaxPrice] = useState<number | ''>('')
|
const [maxPrice, setMaxPrice] = useState<number | ''>('')
|
||||||
const [minExpiryDays, setMinExpiryDays] = useState<number>(0)
|
const [minExpiryDays, setMinExpiryDays] = useState<number>(0)
|
||||||
const [showAdvancedFilters, setShowAdvancedFilters] = useState(false)
|
const [showAdvancedFilters, setShowAdvancedFilters] = useState(false)
|
||||||
|
const [sortBy, setSortBy] = useState<'price' | 'distance' | 'expiry'>('price')
|
||||||
|
|
||||||
// Modal state
|
// Modal state
|
||||||
const [selectedGroup, setSelectedGroup] = useState<GroupedProduct | null>(null)
|
const [selectedGroup, setSelectedGroup] = useState<GroupedProduct | null>(null)
|
||||||
|
|
@ -89,9 +90,28 @@ const ProductSearch = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by min price
|
// Sort based on selected option
|
||||||
return Object.values(groups).sort((a, b) => a.minPriceCents - b.minPriceCents)
|
const groupsArray = Object.values(groups)
|
||||||
}, [products, user?.id])
|
|
||||||
|
switch (sortBy) {
|
||||||
|
case 'price':
|
||||||
|
return groupsArray.sort((a, b) => a.minPriceCents - b.minPriceCents)
|
||||||
|
case 'distance':
|
||||||
|
return groupsArray.sort((a, b) => {
|
||||||
|
const minDistA = Math.min(...a.offers.map(o => o.distance_km))
|
||||||
|
const minDistB = Math.min(...b.offers.map(o => o.distance_km))
|
||||||
|
return minDistA - minDistB
|
||||||
|
})
|
||||||
|
case 'expiry':
|
||||||
|
return groupsArray.sort((a, b) => {
|
||||||
|
const minExpiryA = Math.min(...a.offers.map(o => new Date(o.expires_at).getTime()))
|
||||||
|
const minExpiryB = Math.min(...b.offers.map(o => new Date(o.expires_at).getTime()))
|
||||||
|
return minExpiryA - minExpiryB
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return groupsArray
|
||||||
|
}
|
||||||
|
}, [products, user?.id, sortBy])
|
||||||
|
|
||||||
const handleLocationSelect = (newLat: number, newLng: number) => {
|
const handleLocationSelect = (newLat: number, newLng: number) => {
|
||||||
setLat(newLat)
|
setLat(newLat)
|
||||||
|
|
@ -237,8 +257,17 @@ const ProductSearch = () => {
|
||||||
<h2 className="text-xl font-semibold text-gray-700">
|
<h2 className="text-xl font-semibold text-gray-700">
|
||||||
{loading ? 'Buscando...' : `${groupedProducts.length} medicamentos (${total} ofertas)`}
|
{loading ? 'Buscando...' : `${groupedProducts.length} medicamentos (${total} ofertas)`}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="text-sm text-gray-500">
|
<div className="flex items-center gap-2 text-sm">
|
||||||
Ordenado por: <span className="font-medium text-gray-800">Menor preço</span>
|
<span className="text-gray-500">Ordenar por:</span>
|
||||||
|
<select
|
||||||
|
value={sortBy}
|
||||||
|
onChange={(e) => setSortBy(e.target.value as 'price' | 'distance' | 'expiry')}
|
||||||
|
className="rounded-md border-gray-300 shadow-sm focus:border-primary focus:ring-primary text-sm p-1.5 border bg-white cursor-pointer"
|
||||||
|
>
|
||||||
|
<option value="price">Menor preço</option>
|
||||||
|
<option value="distance">Mais próximo</option>
|
||||||
|
<option value="expiry">Vencimento (mais próximo)</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue