276 lines
7.5 KiB
Vue
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>
|