Files
mohadese namavar ec84dfd222 init git
2024-06-16 00:22:14 +04:30

276 lines
7.5 KiB
Vue

<template>
<aside class="product-filters">
<h2>
<i class="isax isax-setting-5"></i>
<span>{{ $t('filters') }}</span>
</h2>
<PanelMenu :model="categories" v-model:expanded-keys="expandedKeys">
<template #submenuicon="{ active }">
<i :class="'isax isax-arrow-' + (active ? 'up-2' : 'left-2')" />
</template>
</PanelMenu>
<Accordion expand-icon="isax left" collapse-icon="isax up">
<AccordionTab :header="$t('brand')">
<ul>
<li v-for="(brand, i) in data.brands" :key="i">
<Checkbox v-model="brands" :value="brand.link" :input-id="i" />
<label :for="i"> {{ brand.title }} </label>
</li>
</ul>
</AccordionTab>
</Accordion>
<div>
<label>{{ $t('availableInStock') }}</label>
<InputSwitch v-model="stock" />
</div>
<Accordion expand-icon="isax left" collapse-icon="isax up">
<AccordionTab :header="$t('priceRange')">
<ul>
<li>
<span>{{ $t('from') }}</span>
<InputNumber v-model="prices[0]" :sync="true" />
<span>{{ $t('priceUnit') }}</span>
</li>
<li>
<span>{{ $t('until') }}</span>
<InputNumber v-model="prices[1]" :sync="true" />
<span>{{ $t('priceUnit') }}</span>
</li>
<li>
<Slider v-model="prices" :min="1000" :max="200000000" :step="1000" range />
</li>
</ul>
</AccordionTab>
</Accordion>
</aside>
</template>
<script setup>
const { t } = inject('service')
const data = inject('data')
const route = useRoute()
const router = useRouter()
const expandedKeys = reactive()
const catMap = (category) => {
if (!category) return []
const list = []
category.forEach((cat) => {
const temp = {
_id: cat._id,
label: cat.name,
class: route.query.category == cat.link ? 'active' : '',
command: ({ originalEvent }) => {
if (cat.link && originalEvent.target.nodeName == 'SPAN') {
router.push({ query: { ...route.query, category: cat.link } })
}
}
}
if (cat.sub) temp.items = catMap(cat.sub)
list.push(temp)
})
return list
}
const stock = ref('stock' in route.query)
const brands = ref([...(route.query?.brands?.split(',') ?? [])])
const prices = ref([...(route.query?.prices?.split(',').map(i => parseInt(i)) ?? [0, 200000000])])
watch(brands, (v) => {
const query = Object.assign({}, route.query)
if (v?.length > 0)
query.brands = v.join(',')
else
delete query.brands
router.push({ query })
})
watch(stock, (v) => {
const query = Object.assign({}, route.query)
if (v)
query.stock = true
else
delete query.stock
router.push({ query })
})
let timer
watch(prices, (v) => {
clearTimeout(timer)
timer = setTimeout(() => {
const query = Object.assign({}, route.query)
const [$gte, $lte] = v
query.prices = []
if ($gte > 1000 || $lte < 200000000)
query.prices = v.join(',')
else
delete query.prices
router.push({ query })
}, 1000)
}, { deep: true})
const categoriesStroe = useCategoriesStore()
const categories = reactive([
{ label: t('categories'), items: catMap(categoriesStroe.items) }
])
watch(() => route.query, () => (categories[0].items = catMap(categoriesStroe.items)))
</script>
<style lang="scss">
.product-filters {
@apply w-full lg:w-[18.3rem] h-max rounded-[0.6rem] lg:border-2 border-[#EBEBEB];
@apply flex flex-col lg:py-8 shrink-0;
h2 {
@apply flex items-center gap-2 text-[#666666] px-6 mb-8;
span {
@apply text-[1.4em] font-vazir;
}
i {
@apply text-[1.6em];
}
}
&>div:nth-of-type(1)>div {
@apply font-vazir text-lg font-bold flex flex-col px-6 pb-4 border-b-2 border-[#EBEBEB];
&>.p-toggleable-content {
@apply w-[15.6rem] h-[18.8rem] overflow-y-auto pl-0 pt-4 self-end rtl;
&::-webkit-scrollbar-track {
@apply my-6;
}
ul {
@apply pl-0;
}
&>div>ul>li>.p-menuitem-content .p-menuitem-link {
@apply pr-0;
}
.p-menuitem-text {
@apply text-stone-500 text-lg font-bold font-vazir pr-4;
}
.active>.p-menuitem-content .p-menuitem-text {
@apply text-primary-600 #{!important};
}
.p-panelmenu-content {
@apply border-none;
}
}
}
&>div:nth-of-type(2) {
@apply px-6 py-4 border-b-2 border-[#EBEBEB] font-vazir;
.p-accordion-content {
@apply pt-8 pb-4 rtl;
ul {
@apply flex flex-col gap-7;
li {
@apply flex items-center gap-4;
.p-checkbox {
@apply w-6 h-6 p-0.5 rounded border border-neutral-400;
.p-checkbox-box {
@apply w-full h-full border-none;
svg {
@apply hidden;
}
}
}
label {
@apply text-[#666666] text-lg font-bold cursor-pointer select-none;
}
}
}
}
}
&>div:nth-of-type(3) {
@apply flex justify-between p-6 border-b-2 border-[#EBEBEB];
label {
@apply text-[#333333] text-lg font-bold font-vazir;
}
.p-inputswitch {
@apply w-12 h-6 bg-white;
.p-inputswitch-slider::before {
@apply w-4 h-4 -mt-2;
}
}
}
&>div:nth-of-type(4) {
@apply px-6 py-10 font-vazir;
.p-accordion-content {
@apply pt-8 pb-4 rtl border-none;
ul {
@apply flex flex-col gap-6;
li {
@apply flex items-end gap-4 max-w-full;
&>span {
@apply text-[#666666] text-lg font-bold font-vazir grow;
}
input {
box-shadow: none;
@apply text-center w-36 h-10 border-x-0 border-t-0 rounded-none #{!important};
@apply border-b-2 border-[#EBEBEB] text-[#333333] text-[1.4em] font-vazir;
&:focus {
@apply border-primary-600;
}
}
div {
@apply w-full mt-4 rtl #{!important};
.p-slider-handle {
@apply w-4 h-4 border-none bg-primary-600 -mt-2 focus:shadow-none;
}
}
}
}
}
}
}
.p-accordion-header-link {
@apply bg-transparent border-none flex justify-between p-0;
}
.p-panelmenu-header-content {
@apply bg-transparent border-none;
.p-panelmenu-header-action {
@apply flex p-0 justify-between
}
}
</style>