added pagination
This commit is contained in:
+72
-29
@@ -8,31 +8,48 @@ import { PRODUCT_RANGE } from "~/constants";
|
||||
|
||||
// state
|
||||
|
||||
const route = useRoute();
|
||||
const params: GetProductsFilters = useUrlSearchParams("history", {
|
||||
initialValue: {
|
||||
search: "",
|
||||
sort: "newest",
|
||||
price_gte: PRODUCT_RANGE.min,
|
||||
price_lte: PRODUCT_RANGE.max,
|
||||
in_stock: false,
|
||||
has_discount: false,
|
||||
category: "",
|
||||
page: "1",
|
||||
},
|
||||
});
|
||||
|
||||
const params: GetProductsFilters & { page: number } =
|
||||
useUrlSearchParams("history");
|
||||
const search = ref(params.search ?? "");
|
||||
const searchDebounced = refDebounced(search, 1000);
|
||||
|
||||
// computed
|
||||
// provide / inject
|
||||
|
||||
const page = computed(() => (route.query["page"] ? +route.query["page"] : 1));
|
||||
provide("params", params);
|
||||
|
||||
// queries
|
||||
|
||||
const { data: products, isLoading: productsIsLoading } = useGetProducts(
|
||||
params,
|
||||
page
|
||||
);
|
||||
const { data, isLoading: productsIsLoading } = useGetProducts(params);
|
||||
|
||||
// life-cycle
|
||||
|
||||
onMounted(() => {
|
||||
if (!("range" in params)) {
|
||||
params.range = [];
|
||||
params.range[0] = PRODUCT_RANGE.min;
|
||||
params.range[1] = PRODUCT_RANGE.max;
|
||||
}
|
||||
const products = computed(() => {
|
||||
return data.value?.results.flat();
|
||||
});
|
||||
|
||||
const paginationData = computed(() => {
|
||||
return data!.value?.results.map((_, i: number) => {
|
||||
return { type: "page", value: i };
|
||||
});
|
||||
});
|
||||
|
||||
// watch
|
||||
|
||||
watch(
|
||||
() => searchDebounced.value,
|
||||
(newValue) => {
|
||||
params.search = newValue;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -54,24 +71,50 @@ onMounted(() => {
|
||||
<div class="w-full flex items-center justify-end gap-4">
|
||||
<Input
|
||||
placeholder="جست و جو محصول ..."
|
||||
v-model="search"
|
||||
class="bg-slate-50 !border-slate-200 hover:border-slate-300 focus:!border-slate-800 !rounded-full w-8/12"
|
||||
/>
|
||||
<FilterButton />
|
||||
</div>
|
||||
</div>
|
||||
<ul class="w-full grid grid-cols-3 gap-[1.5rem]">
|
||||
<li v-for="i in 9" :key="i">
|
||||
<ProductCard
|
||||
brand="Samsung"
|
||||
title="Galaxy S20 Ultra"
|
||||
picture="/assets/img/product-1.jpg"
|
||||
:colors="['#0000ff', '#00ff00', 'red']"
|
||||
:price="599"
|
||||
:rate="2.4"
|
||||
tag="New"
|
||||
/>
|
||||
</li>
|
||||
<ul
|
||||
v-if="productsIsLoading"
|
||||
class="w-full grid grid-cols-3 gap-[1.5rem]"
|
||||
>
|
||||
<Skeleton
|
||||
v-for="i in 9"
|
||||
:key="i"
|
||||
class="w-full !h-[31.25rem] !rounded-2xl"
|
||||
/>
|
||||
</ul>
|
||||
<div v-else class="w-full h-max">
|
||||
<div v-if="!products?.length" class="flex flex-grow px-5 w-full">
|
||||
<div
|
||||
class="flex-col flex-grow py-[12rem] gap-6 border-2 border-slate-200 border-dashed size-full rounded-100 flex-center"
|
||||
>
|
||||
<Icon name="bi:search" size="50" class="**:fill-gray-500" />
|
||||
<span class="text-lg text-gray-500">
|
||||
محصولی یافت نشد :(
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-else class="w-full grid grid-cols-3 gap-[1.5rem]">
|
||||
<li v-for="(product, index) in products" :key="index">
|
||||
<ProductCard
|
||||
brand="Samsung"
|
||||
:title="product.name"
|
||||
picture="/assets/img/product-1.jpg"
|
||||
:colors="['#0000ff', '#00ff00', 'red']"
|
||||
:price="product.price"
|
||||
:rate="product.rating"
|
||||
tag="New"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="w-full flex-center py-10">
|
||||
<Pagination :items="paginationData" :total="data?.count" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user