-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update product filters and store for enhanced functionality
- Loading branch information
oussama.bensalah
committed
Jul 10, 2024
1 parent
06f90ec
commit 2e476ca
Showing
4 changed files
with
134 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,85 @@ | ||
<template> | ||
<div class="join join-vertical w-full"> | ||
<div class="collapse collapse-arrow join-item border-base-300 border"> | ||
<input type="radio" name="my-accordion-3" :checked="true" /> | ||
<div class="collapse-title text-xl font-medium">Price Filter</div> | ||
<div class="collapse-content"> | ||
<div v-for="range in ranges" :key="range.lbl"> | ||
<label :for="range.lbl"> | ||
<input :id="range.lbl" type="radio" :value="{ min: range.min, max: range.max }" name="price" | ||
v-model="selectPrice" class="custom-control-input" @change="filterRangePrice" /> | ||
{{ range.lbl }}</label> | ||
</div> | ||
<div class="mt-3"> | ||
<button class="btn btn-primary" @click="resetAllFilters"> | ||
Reset All | ||
</button> | ||
</div> | ||
</div> | ||
<div class="join join-vertical w-full"> | ||
<div class="collapse collapse-arrow join-item border-base-300 border"> | ||
<input type="radio" name="my-accordion-3" :checked="true" /> | ||
<div class="collapse-title text-xl font-medium">Price Filter</div> | ||
<div class="collapse-content"> | ||
<div v-for="range in ranges" :key="range.lbl"> | ||
<label :for="range.lbl"> | ||
<input | ||
:id="range.lbl" | ||
type="radio" | ||
:value="{ min: range.min, max: range.max }" | ||
name="price" | ||
v-model="selectPrice" | ||
class="custom-control-input" | ||
@change="filterByPriceOrCategory" | ||
/> | ||
{{ range.lbl }}</label | ||
> | ||
</div> | ||
<div class="mt-3"> | ||
<button class="btn btn-primary" @click="resetAllFilters"> | ||
Reset All | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="collapse collapse-arrow join-item border-base-300 border"> | ||
<input type="radio" name="my-accordion-3" /> | ||
<div class="collapse-title text-xl font-medium">Category Filter</div> | ||
<div class="collapse-content"> | ||
<div v-for="category in uniqueCategories" :key="category"> | ||
<label :for="category"> | ||
<input :id="category" type="radio" :value="category" name="category" v-model="selectCategory" | ||
class="custom-control-input" @change="filterByCategory" /> | ||
{{ category }}</label> | ||
</div> | ||
<div class="mt-3"> | ||
<button class="btn btn-primary" @click="resetAllFilters"> | ||
Reset All | ||
</button> | ||
</div> | ||
</div> | ||
<div class="collapse collapse-arrow join-item border-base-300 border"> | ||
<input type="radio" name="my-accordion-3" /> | ||
<div class="collapse-title text-xl font-medium">Category Filter</div> | ||
<div class="collapse-content"> | ||
<div v-for="category in uniqueCategories" :key="category"> | ||
<label :for="category"> | ||
<input | ||
:id="category" | ||
type="radio" | ||
:value="category" | ||
name="category" | ||
v-model="selectCategory" | ||
class="custom-control-input" | ||
@change="filterByPriceOrCategory" | ||
/> | ||
{{ category }}</label | ||
> | ||
</div> | ||
<div class="mt-3"> | ||
<button class="btn btn-primary" @click="resetAllFilters"> | ||
Reset All | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { computed, ref, watch } from "vue" | ||
import { useProductStore } from "../store/product" | ||
import { computed, ref } from "vue"; | ||
import { useProductStore } from "../store/product"; | ||
const emit = defineEmits(["FilterByPrice", "FilterByCategory"]) | ||
const productStore = useProductStore(); | ||
const productStore = useProductStore() | ||
const products = computed(() => productStore.list) | ||
const uniqueCategories = computed(() => productStore.categoriesList); | ||
const uniqueCategories = ref([...new Set(products.value.map(product => product.category))]) | ||
const selectPrice = ref({ min: 0, max: 1000000 }) | ||
const selectCategory = ref() | ||
const selectPrice = ref({ min: 0, max: 1000000 }); | ||
const selectCategory = ref(""); | ||
const ranges = ref([ | ||
{ lbl: 'All', min: 0, max: 1000000 }, | ||
{ lbl: '<=10', min: 0, max: 10 }, | ||
{ lbl: '10 - 100', min: 10, max: 100 }, | ||
{ lbl: '100 - 500', min: 100, max: 500 }, | ||
{ lbl: '>=500', min: 500, max: 1000000 } | ||
]) | ||
watch(() => productStore.loaded, () => { | ||
uniqueCategories.value = [...new Set(products.value.map(product => product.category))] | ||
}) | ||
const filterRangePrice = () => { | ||
emit("FilterByPrice", selectPrice.value) | ||
} | ||
{ lbl: "All", min: 0, max: 1000000 }, | ||
{ lbl: "<=10", min: 0, max: 10 }, | ||
{ lbl: "10 - 100", min: 10, max: 100 }, | ||
{ lbl: "100 - 500", min: 100, max: 500 }, | ||
{ lbl: ">=500", min: 500, max: 1000000 }, | ||
]); | ||
const filterByCategory = () => { | ||
emit("FilterByCategory", selectCategory.value) | ||
} | ||
const filterByPriceOrCategory = () => { | ||
productStore.filterAll(selectCategory.value, selectPrice.value); | ||
}; | ||
const resetAllFilters = () => { | ||
selectCategory.value = undefined | ||
selectPrice.value = { min: 0, max: 1000000 } | ||
emit("FilterByPrice", selectPrice.value) | ||
emit("FilterByCategory", selectCategory.value) | ||
} | ||
</script> | ||
selectCategory.value = '' | ||
selectPrice.value = { min: 0, max: 1000000 } | ||
productStore.filterAll("", { min: 0, max: 1000000 }); | ||
productStore.filtering = false | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,44 @@ | ||
<script setup lang="ts"> | ||
import { computed, ref } from "vue" | ||
import ProductCard from "../components/ProductCard.vue" | ||
import Filters from "../components/Filters.vue" | ||
import ProductCardSkeleton from "../components/ProductCardSkeleton.vue" | ||
import { useProductStore } from "../store/product" | ||
const productStore = useProductStore() | ||
const priceFilter = ref() | ||
const categoryFilter = ref() | ||
const products = computed(() => productStore.list) | ||
const filteredProducts = computed(() => { | ||
let productsList = products.value | ||
if (priceFilter.value) { | ||
productsList = productsList.filter(product => { | ||
return product.price >= priceFilter.value.min && product.price <= priceFilter.value.max | ||
}) | ||
} | ||
if (categoryFilter.value) { | ||
productsList = productsList.filter(product => product.category === categoryFilter.value) | ||
} | ||
return productsList | ||
}) | ||
const filterByPrice = (price: { min: number, max: number }) => { | ||
priceFilter.value = price | ||
} | ||
const filterByCategory = (category: string) => { | ||
categoryFilter.value = category | ||
} | ||
import { computed } from "vue"; | ||
import ProductCard from "../components/ProductCard.vue"; | ||
import Filters from "../components/Filters.vue"; | ||
import ProductCardSkeleton from "../components/ProductCardSkeleton.vue"; | ||
import { useProductStore } from "../store/product"; | ||
const productStore = useProductStore(); | ||
const products = computed(() => { | ||
if (productStore.filtering) return productStore.filteredList; | ||
return productStore.list; | ||
}); | ||
</script> | ||
|
||
<template> | ||
<div class="flex flex-row"> | ||
<aside class="w-full p-6 sm:w-60 md:w-80 lg:w-96 dark:bg-gray-50 dark:text-gray-800"> | ||
<aside class="p-6 sm:w-60 dark:bg-gray-50 dark:text-gray-800"> | ||
<nav class="space-y-8 text-sm"> | ||
<div class="space-y-2"> | ||
<Filters @filter-by-price="filterByPrice" @filter-by-category="filterByCategory" /> | ||
<Filters /> | ||
</div> | ||
</nav> | ||
</aside> | ||
<div class="p-4 max-w-7xl mx-auto"> | ||
<div class="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-3"> | ||
<ProductCardSkeleton v-for="n in 10" v-show="!productStore.loaded" :key="n" /> | ||
<ProductCard v-if="!filteredProducts.length" v-for="product in products" :key="product.id" :product="product" /> | ||
<ProductCard v-if="filteredProducts.length" v-for="product in filteredProducts" :key="product.id" | ||
:product="product" /> | ||
<ProductCardSkeleton | ||
v-for="n in 10" | ||
v-show="!productStore.loaded" | ||
:key="n" | ||
/> | ||
<div v-if="!products.length"> | ||
<h1 class="text-xl">No item Found.</h1> | ||
</div> | ||
<ProductCard | ||
v-if="products.length" | ||
v-for="product in products" | ||
:key="product.id" | ||
:product="product" | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters