128 lines
4.1 KiB
Vue
128 lines
4.1 KiB
Vue
<script lang="ts" setup>
|
|
// import
|
|
|
|
import useGetCategories from "~/composables/api/categories/useGetCategories";
|
|
|
|
// state
|
|
|
|
useSeoMeta({
|
|
title: "دسته بندی ها",
|
|
});
|
|
|
|
const { data: categories, suspense } = useGetCategories();
|
|
|
|
const search = ref("");
|
|
const debouncedSearch = refDebounced(search, 300);
|
|
|
|
const selectedCategory = ref("همه دسته ها");
|
|
|
|
// computed
|
|
|
|
const mainCategoriesMenu = computed(() => {
|
|
const categoriesList = categories.value ? categories.value.map((category) => category.name) : [];
|
|
categoriesList.unshift("همه دسته ها");
|
|
|
|
return categoriesList;
|
|
});
|
|
|
|
const filteredCategories = computed(() => {
|
|
if (categories.value) {
|
|
return categories.value
|
|
.flatMap((mainCategory) => mainCategory.subcategorys)
|
|
.filter((category) => {
|
|
if (selectedCategory.value === "همه دسته ها") {
|
|
return category.name.includes(debouncedSearch.value);
|
|
}
|
|
|
|
return category.name.includes(debouncedSearch.value) && category.parent === selectedCategory.value;
|
|
});
|
|
}
|
|
return [];
|
|
});
|
|
|
|
// ssr
|
|
|
|
const response = await suspense();
|
|
|
|
if (response.isError) {
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: `Error in categories page prefetch`,
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="container">
|
|
<div class="w-full flex flex-col lg:flex-row justify-end items-end py-[3.5rem] lg:py-[5rem] gap-10 lg:gap-5">
|
|
<div class="flex flex-col items-center lg:items-start w-full">
|
|
<h1 class="typo-h-5 lg:typo-h-4 text-black">دسته بندی ها</h1>
|
|
</div>
|
|
|
|
<div class="w-full flex items-center justify-between lg:justify-end gap-4">
|
|
<Input
|
|
placeholder="جست و جو محصول ..."
|
|
v-model="search"
|
|
variant="outlined"
|
|
class="!rounded-xl w-full lg:w-8/12"
|
|
>
|
|
<template #endItem>
|
|
<div class="flex items-center gap-1">
|
|
<Icon
|
|
class="translate-y-[-1px] text-[20px] lg:text-[24px]"
|
|
name="ci:search"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</Input>
|
|
<Select
|
|
class="shrink-0 max-lg:w-[5rem] lg:w-[6.5rem] py-0.5"
|
|
triggerRootClass="!rounded-xl whitespace-nowrap max-sm:w-full shrink-0 "
|
|
:options="mainCategoriesMenu"
|
|
variant="outlined"
|
|
placeholder="انتخاب کنید"
|
|
v-model="selectedCategory"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Transition
|
|
name="fade"
|
|
mode="out-in"
|
|
>
|
|
<div
|
|
v-if="filteredCategories.length > 0"
|
|
v-auto-animate
|
|
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 sm:gap-8 w-full"
|
|
>
|
|
<CategoryCard
|
|
v-for="category in filteredCategories"
|
|
:key="category.id"
|
|
:id="category.id"
|
|
:slug="category.slug"
|
|
:category="category.name"
|
|
:picture="category.image"
|
|
:count="category.product_count"
|
|
:description="category.name"
|
|
dark-layer
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
v-else
|
|
class="flex w-full sm:mt-12"
|
|
>
|
|
<div
|
|
class="flex-col flex-grow py-32 sm:py-[12rem] gap-6 border-2 border-slate-200 border-dashed size-full rounded-100 flex-center"
|
|
>
|
|
<Icon
|
|
name="bi:search"
|
|
class="**:fill-gray-500 size-[40px] sm:size-[50px]"
|
|
/>
|
|
<span class="text-lg text-gray-500"> دسته بندی یافت نشد :( </span>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
</template>
|