connected to new url param

This commit is contained in:
Mamalizz
2025-10-03 21:40:34 +03:30
parent b60a8962d7
commit 20280b319b
@@ -2,62 +2,44 @@
// imports // imports
import useGetResellersCategories from "~/composables/api/resellers/useGetResellersCategories"; import useGetResellersCategories from "~/composables/api/resellers/useGetResellersCategories";
import useGetResellersProducts, { import useGetResellersProducts from "~/composables/api/resellers/useGetResellersProducts";
type GetResellersProductsFilters, import { useAppParams } from "~/composables/global/useAppParams";
} from "~/composables/api/resellers/useGetResellersProducts"; import { PRODUCT_RANGE, PRODUCTS_SORTS } from "~/constants";
import { PRODUCT_RANGE } from "~/constants";
// state // state
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const params = inject("params") as GetResellersProductsFilters; const { sort, in_stock, has_discount, price_gte, price_lte, search, page, slug } = useAppParams();
const isSideShow = useState("side-modal-resellers-product-filters");
const currentCategory = computed({ const currentCategory = computed({
get: () => { get: () => {
return Array.isArray(route.params.slug) ? route.params.slug[1] ?? undefined : undefined; return Array.isArray(slug.value) ? slug.value[1] ?? undefined : undefined;
}, },
set: (newValue) => { set: (newValue) => {
router.push({ path: `/resellers/category/${newValue}`, query: { ...route.query } }); isSideShow.value = false;
router.push({
name: "resellers-slug",
params: { slug: ["category", `${newValue}`] },
query: { ...route.query },
});
}, },
}); });
const sort_filter = ref([ const sliderValue = ref([price_gte.value ?? PRODUCT_RANGE.min, price_lte.value ?? PRODUCT_RANGE.max]);
{ title: "جدیدترین ها", value: "newest" },
{ title: "گران ترین ها", value: "price" },
{ title: "ارزان ترین ها", value: "-price" },
]);
const sliderValue = ref([params.price_gte ?? PRODUCT_RANGE.min, params.price_lte ?? PRODUCT_RANGE.max]);
const has_discount = ref(Boolean(params.has_discount) ?? false);
const in_stock = ref(Boolean(params.in_stock) ?? false);
const sliderValueDebounced = refDebounced(sliderValue, 1000); const sliderValueDebounced = refDebounced(sliderValue, 1000);
const filtersSuccessMessage = ref<{ title: string; status: string } | null>(null);
// queries // queries
const filters = computed(() => {
return {
sort: params.sort ?? "newest",
search: params.search ?? "",
price_gte: params.price_gte ?? PRODUCT_RANGE.min,
price_lte: params.price_lte ?? PRODUCT_RANGE.max,
in_stock: params.in_stock ?? false,
has_discount: params.has_discount ?? false,
category: currentCategory.value,
page: params.page ?? 1,
};
});
const { data: categories, suspense } = useGetResellersCategories(); const { data: categories, suspense } = useGetResellersCategories();
await suspense(); await suspense();
const { isPending: productsIsPending, status: productsStatus } = useGetResellersProducts(filters); const { isPending: productsIsPending } = useGetResellersProducts();
// computed // computed
@@ -70,48 +52,23 @@ const allCategories = computed(() => {
// methods // methods
const resetFilters = () => { const resetFilters = () => {
params.search = ""; search.value = "";
params.sort = ""; sort.value = "";
sliderValue.value = [PRODUCT_RANGE.min, PRODUCT_RANGE.max]; sliderValue.value = [PRODUCT_RANGE.min, PRODUCT_RANGE.max];
has_discount.value = false; has_discount.value = "false";
in_stock.value = false; in_stock.value = "false";
page.value = 1;
router.push({ path: `/resellers/`, query: { ...route.query } }); isSideShow.value = false;
}; };
// watch
watch( watch(
() => sliderValueDebounced.value, () => sliderValueDebounced.value,
(newValue) => { (newValue) => {
params.price_gte = newValue[0]; price_gte.value = newValue[0];
params.price_lte = newValue[1]; price_lte.value = newValue[1];
}
);
watch(
() => [has_discount.value, in_stock.value],
([newHasDiscount, newInStock]) => {
params.has_discount = newHasDiscount;
params.in_stock = newInStock;
}
);
watch(
() => productsStatus.value,
(nv) => {
if (nv == "success") {
filtersSuccessMessage.value = {
title: "فیلتر اعمال شد",
status: nv,
};
} else if (nv == "error") {
filtersSuccessMessage.value = {
title: "خطایی در اعمال فیلتر رخ داد",
status: nv,
};
}
setTimeout(() => {
filtersSuccessMessage.value = null;
}, 4000);
} }
); );
</script> </script>
@@ -129,13 +86,13 @@ watch(
</div> </div>
<div class="w-full flex items-center gap-2"> <div class="w-full flex items-center gap-2">
<button <button
v-for="(sort, index) in sort_filter" v-for="(sort_filter, index) in PRODUCTS_SORTS"
:key="index" :key="index"
@click="params.sort = sort.value" @click="sort = sort_filter.value"
:class="params.sort == sort.value ? 'bg-black text-white' : 'bg-slate-100'" :class="sort == sort_filter.value ? 'bg-black text-white' : 'bg-slate-100'"
class="py-1 px-3 cursor-pointer text-nowrap transition-all rounded-md text-xs lg:text-sm" class="py-1 px-3 cursor-pointer text-nowrap transition-all rounded-md text-xs lg:text-sm"
> >
{{ sort.title }} {{ sort_filter.title }}
</button> </button>
</div> </div>
</div> </div>
@@ -209,32 +166,31 @@ watch(
</div> </div>
</div> </div>
<div class="w-full flex flex-col items-center gap-5"> <div class="flex items-center gap-4 w-full">
<Button
:disabled="productsIsPending"
variant="primary"
@click="isSideShow = false"
class="w-full rounded-xl py-3 !cursor-pointer disabled:pointer-events-none z-[3]"
>
<Transition <Transition
enter-active-class="animate__animated animate__fadeInUp animate__faster" name="fade"
leave-active-class="animate__animated animate__fadeOutDown animate__faster" mode="out-in"
> >
<div <span class="flex-center gap-3 text-sm">
v-if="!!filtersSuccessMessage" اعمال فیلتر
class="w-max rounded-full py-1.5 px-3 text-xs border flex-center gap-0.5 z-[2]"
:class="
filtersSuccessMessage.status == 'success'
? 'text-success-600 bg-success-100 border-success-600'
: ' text-danger-600 bg-danger-100 border-danger-600'
"
>
<span class="text-sm">{{ filtersSuccessMessage.title }}</span>
<Icon <Icon
:name="filtersSuccessMessage.status == 'success' ? 'bi:check' : 'bi:x'" name="ci:plus"
size="20" size="20"
/> />
</div> </span>
</Transition> </Transition>
</Button>
<Button <Button
:disabled="productsIsPending" :disabled="productsIsPending"
variant="solid" variant="solid"
@click="resetFilters" @click="resetFilters"
class="w-full rounded-full py-4 !cursor-pointer disabled:pointer-events-none z-[3]" class="w-full rounded-xl py-3 !cursor-pointer disabled:pointer-events-none z-[3]"
> >
<Transition <Transition
name="fade" name="fade"
@@ -242,7 +198,7 @@ watch(
> >
<span <span
v-if="productsIsPending" v-if="productsIsPending"
class="flex-center gap-3" class="flex-center gap-3 text-sm"
> >
در حال دریافت اطلاعات در حال دریافت اطلاعات
<Icon <Icon
@@ -252,7 +208,7 @@ watch(
</span> </span>
<span <span
v-else v-else
class="flex-center gap-3" class="flex-center gap-3 text-sm"
> >
بازنشانی به پیش فرض بازنشانی به پیش فرض
<Icon <Icon