Filter products using select instead of toggles

This commit is contained in:
2025-12-08 13:23:33 +01:00
parent cdb8e44228
commit 7d9261dd6e
13 changed files with 142 additions and 39 deletions
+31 -19
View File
@@ -6,12 +6,12 @@ import { Product } from '@/types';
import Fuse from 'fuse.js';
import { Input } from '@/components/ui/crm-input'
import { Button } from '@/components/ui/crm-button'
import { Delete, Search, Plus } from "lucide-vue-next"
import { Delete, Search, Plus, CheckIcon, ChevronDown } from "lucide-vue-next"
import PlaceholderPattern from '@/components/PlaceholderPattern.vue';
import { toCurrency, toRoundedCurrency } from '@/lib/utils';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import { Kbd, KbdGroup } from '@/components/ui/kbd'
import { Toggle } from '@/components/ui/toggle'
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, SelectSeparator } from '@/components/ui/select'
interface Props {
productsData: Product[];
@@ -21,6 +21,7 @@ const searchQuery = ref('')
const searchField = ref()
const categoryVisibility = ref<Record<string, boolean>>({});
const selectedCategory = ref<string>("all")
onMounted(() => {
initializeCategoryVisibility();
@@ -40,11 +41,6 @@ const fuse = computed(() => {
})
const filteredProducts = computed(() => {
const visibleCategories = Object.entries(categoryVisibility.value)
.filter(([_, isVisible]) => isVisible)
.map(([categoryName]) => categoryName);
if (visibleCategories.length == 0) return []
let products = props.productsData;
@@ -54,9 +50,12 @@ const filteredProducts = computed(() => {
}
// Filter nach Kategorien
products = products.filter(product =>
product.category?.name && visibleCategories.includes(product.category.name)
);
if (selectedCategory.value !== "all") {
products = products.filter(product =>
product.category?.name &&
product.category.name == selectedCategory.value
);
}
return products;
});
@@ -71,6 +70,7 @@ const categories = computed(() => {
return Array.from(categorySet).sort();
});
const initializeCategoryVisibility = () => {
const visibility: Record<string, boolean> = {};
props.productsData.forEach(product => {
@@ -99,7 +99,26 @@ const toggleAllCategories = () => {
<AppLayout title="Produkte">
<AppHeader>
<template #left></template>
<template #left>
<!-- Category select -->
<Select v-model="selectedCategory">
<SelectTrigger class="w-[180px] bg-background">
<SelectValue placeholder="Kategorie" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="all">
Alle
</SelectItem>
<SelectSeparator />
<SelectItem v-for="category in categories" :value="category">
{{ category }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</template>
<template #middle>
<!-- Search field -->
<Input ref="search-field" id="search" type="text" placeholder="Filtern" class="px-8 bg-background"
@@ -135,19 +154,12 @@ const toggleAllCategories = () => {
</template>
</AppHeader>
<div class="flex items-center justify-center mb-8">
<Toggle :modelValue="allCategoriesVisible" variant="outline" size="sm" aria-label="Alle Kategorien"
@click="toggleAllCategories">Alle</Toggle>
<Toggle v-for="category in categories" v-model="categoryVisibility[category]" variant="outline" size="sm"
:aria-label="'Kategorie ' + category">{{ category }}</Toggle>
</div>
<div class="flex flex-wrap gap-8 lg:gap-12">
<div v-for="product in filteredProducts"
class="w-[calc(50%-4*var(--spacing))] md:w-[calc(33%-5.333*var(--spacing))] lg:w-[calc(25%-9*var(--spacing))] xl:w-[calc(20%-9.6*var(--spacing))] flex flex-col gap-4">
<div class="w-full relative aspect-4/3 overflow-hidden rounded-lg">
<img v-if="product.image" :src="'storage/uploads/products/' + product.image"
class="size-full object-cover" loading="lazy" />
class="size-full object-cover dark:brightness-75" loading="lazy" />
<PlaceholderPattern v-else />
</div>