Enhance category filtering in MarketPage and market store
- Added a new function `clearCategoryFilters` in the market store to reset selected category filters. - Updated MarketPage to include an enhanced category filter UI with a clear all button, active filters summary, and improved badge styling for selected categories. - Introduced computed properties for tracking selected categories and their count, improving user experience in managing filters. These changes provide a more intuitive and user-friendly interface for category filtering in the market module.
This commit is contained in:
parent
8aa575ffb1
commit
526caa2689
2 changed files with 93 additions and 9 deletions
|
|
@ -804,6 +804,10 @@ export const useMarketStore = defineStore('market', () => {
|
|||
}
|
||||
}
|
||||
|
||||
const clearCategoryFilters = () => {
|
||||
filterData.value.categories = []
|
||||
}
|
||||
|
||||
const updateSortOptions = (field: string, order: 'asc' | 'desc' = 'asc') => {
|
||||
sortOptions.value = { field, order }
|
||||
}
|
||||
|
|
@ -881,6 +885,7 @@ export const useMarketStore = defineStore('market', () => {
|
|||
updateFilterData,
|
||||
clearFilters,
|
||||
toggleCategoryFilter,
|
||||
clearCategoryFilters,
|
||||
updateSortOptions,
|
||||
formatPrice,
|
||||
addToStallCart,
|
||||
|
|
|
|||
|
|
@ -52,19 +52,84 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Filters -->
|
||||
<!-- Enhanced Category Filters -->
|
||||
<div v-if="marketStore.allCategories.length > 0" class="mb-6">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<Badge
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="text-lg font-semibold text-gray-700">Browse by Category</h3>
|
||||
<Button
|
||||
v-if="selectedCategoriesCount > 0"
|
||||
@click="clearAllCategoryFilters"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="text-sm"
|
||||
>
|
||||
Clear All ({{ selectedCategoriesCount }})
|
||||
<X class="w-4 h-4 ml-1" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<div
|
||||
v-for="category in marketStore.allCategories"
|
||||
:key="category.category"
|
||||
:variant="category.selected ? 'default' : 'secondary'"
|
||||
class="cursor-pointer hover:bg-blue-100"
|
||||
@click="marketStore.toggleCategoryFilter(category.category)"
|
||||
class="group relative cursor-pointer transition-all duration-200 hover:scale-105"
|
||||
>
|
||||
{{ category.category }}
|
||||
<span class="ml-1 text-xs">({{ category.count }})</span>
|
||||
<Badge
|
||||
:variant="category.selected ? 'default' : 'outline'"
|
||||
class="px-4 py-2 text-sm font-medium transition-all duration-200"
|
||||
:class="{
|
||||
'bg-primary text-primary-foreground shadow-md': category.selected,
|
||||
'hover:bg-primary/10 hover:border-primary': !category.selected,
|
||||
'ring-2 ring-primary ring-offset-1': category.selected
|
||||
}"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<span>{{ category.category }}</span>
|
||||
<div
|
||||
class="px-2 py-0.5 rounded-full text-xs font-bold transition-colors"
|
||||
:class="category.selected
|
||||
? 'bg-primary-foreground/20 text-primary-foreground'
|
||||
: 'bg-secondary text-secondary-foreground'"
|
||||
>
|
||||
{{ category.count }}
|
||||
</div>
|
||||
</div>
|
||||
</Badge>
|
||||
|
||||
<!-- Selection indicator -->
|
||||
<div
|
||||
v-if="category.selected"
|
||||
class="absolute -top-1 -right-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white shadow-sm"
|
||||
>
|
||||
<Check class="w-2 h-2 text-white absolute top-0.5 left-0.5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Filters Summary -->
|
||||
<div v-if="selectedCategoriesCount > 0" class="mt-4 p-3 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<Filter class="w-4 h-4 text-blue-600" />
|
||||
<span class="text-sm font-medium text-blue-800">
|
||||
Active Filters:
|
||||
</span>
|
||||
<div class="flex gap-1">
|
||||
<Badge
|
||||
v-for="category in selectedCategories"
|
||||
:key="category"
|
||||
variant="secondary"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ category }}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-blue-600">
|
||||
{{ productsToDisplay.length }} products found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -107,7 +172,7 @@ import { config } from '@/lib/config'
|
|||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
|
||||
import { ShoppingCart } from 'lucide-vue-next'
|
||||
import { ShoppingCart, X, Check, Filter } from 'lucide-vue-next'
|
||||
import MarketFuzzySearch from '../components/MarketFuzzySearch.vue'
|
||||
import ProductCard from '../components/ProductCard.vue'
|
||||
import type { Product } from '../types/market'
|
||||
|
|
@ -232,6 +297,20 @@ const handleCategoryFilter = (category: string) => {
|
|||
marketStore.toggleCategoryFilter(category)
|
||||
}
|
||||
|
||||
// Computed properties for enhanced category filtering
|
||||
const selectedCategoriesCount = computed(() => {
|
||||
return marketStore.filterData.categories.length
|
||||
})
|
||||
|
||||
const selectedCategories = computed(() => {
|
||||
return marketStore.filterData.categories
|
||||
})
|
||||
|
||||
// Clear all category filters
|
||||
const clearAllCategoryFilters = () => {
|
||||
marketStore.clearCategoryFilters()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Only load market if it hasn't been preloaded
|
||||
if (needsToLoadMarket.value) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue