Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -135,7 +135,7 @@ watch(
|
||||
class="rounded-full"
|
||||
>
|
||||
<span class="whitespace-pre">
|
||||
{{ !!address ? "ویرایش آدرس" : "افزودن آدرس" }}
|
||||
{{ !!address ? "ویرایش" : "افزودن آدرس" }}
|
||||
</span>
|
||||
</Button>
|
||||
</template>
|
||||
@@ -260,6 +260,7 @@ watch(
|
||||
:disabled="createAddressIsPending"
|
||||
@click="addNew"
|
||||
class="rounded-full px-10"
|
||||
size="md"
|
||||
>
|
||||
<Icon
|
||||
v-if="createAddressIsPending"
|
||||
@@ -268,7 +269,11 @@ watch(
|
||||
<span v-else>ثبت</span>
|
||||
</Button>
|
||||
<DialogClose aria-label="Close">
|
||||
<Button variant="outlined" class="rounded-full px-10">
|
||||
<Button
|
||||
variant="outlined"
|
||||
class="rounded-full px-10"
|
||||
size="md"
|
||||
>
|
||||
انصراف
|
||||
</Button>
|
||||
</DialogClose>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
import useGetCartOrders from "~/composables/api/orders/useGetCartOrders";
|
||||
import useSubmitDiscountCode from "~/composables/api/orders/useSubmitDiscountCode";
|
||||
import { useToast } from "~/composables/global/useToast";
|
||||
import { QUERY_KEYS } from "~/constants";
|
||||
@@ -15,7 +15,7 @@ const discountCode = ref("");
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart, isLoading: cartIsLoading } = useGetOrdersCart();
|
||||
const { data: cart, isLoading: cartIsLoading } = useGetCartOrders();
|
||||
|
||||
const { addToast } = useToast();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import useGetAccount from "~/composables/api/account/useGetAccount";
|
||||
import { useAuth } from "~/composables/api/auth/useAuth";
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
import useGetCartOrders from "~/composables/api/orders/useGetCartOrders";
|
||||
import { NAV_LINKS } from "~/constants";
|
||||
|
||||
// state
|
||||
@@ -16,7 +16,7 @@ const isSideDrawerOpen = ref(false);
|
||||
|
||||
const { data: account } = useGetAccount();
|
||||
|
||||
const { data: cart } = useGetOrdersCart();
|
||||
const { data: cart } = useGetCartOrders();
|
||||
|
||||
// computed
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import { usePersianTimeAgo } from "~/composables/global/usePersianTimeAgo";
|
||||
|
||||
// types
|
||||
|
||||
type Props = {
|
||||
data: Order;
|
||||
};
|
||||
|
||||
// props
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const { data } = toRefs(props);
|
||||
|
||||
// computed
|
||||
|
||||
const createdTimeAgo = usePersianTimeAgo(new Date(data.value.created_at));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tr
|
||||
class="odd:bg-white even:bg-gray-50 last:border-none border-b border-slate-200"
|
||||
>
|
||||
<td
|
||||
scope="row"
|
||||
class="w-3/12 px-6 py-6 font-medium whitespace-nowrap"
|
||||
:class="data.order_id ? 'text-cyan-500' : 'text-black'"
|
||||
>
|
||||
{{ data.order_id ? `${data.order_id}#` : "--" }}
|
||||
</td>
|
||||
<td class="w-3/12 px-6 py-6">
|
||||
{{ data.created_at ? createdTimeAgo : "--" }}
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
{{ data.count ? data.count : "--" }}
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
{{ data.final_price ? data.final_price : "--" }}
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
<div
|
||||
class="w-max rounded-full py-1.5 px-3 text-xs border"
|
||||
:class="{
|
||||
'text-warning-600 bg-warning-100 border-warning-600': [
|
||||
'ADMIN_PENDING',
|
||||
'PENDING',
|
||||
].includes(data.status),
|
||||
'text-success-600 bg-success-100 border-success-600': [
|
||||
'POSTED',
|
||||
'RECEIVED',
|
||||
].includes(data.status),
|
||||
'text-danger-600 bg-danger-100 border-danger-600': [
|
||||
'CANCELED',
|
||||
'REFUND',
|
||||
].includes(data.status),
|
||||
}"
|
||||
>
|
||||
{{ data.verbose_status ? data.verbose_status : "--" }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="w-1/12 px-6 py-6">
|
||||
<NuxtLink
|
||||
:to="{
|
||||
name: 'profile-purchases-and-orders-id',
|
||||
params: { id: data.id },
|
||||
}"
|
||||
>
|
||||
<button
|
||||
class="size-10 flex-center border border-slate-200 rounded-md"
|
||||
>
|
||||
<Icon
|
||||
name="ci:eye-open"
|
||||
class="**:stroke-black"
|
||||
size="20"
|
||||
/>
|
||||
</button>
|
||||
</NuxtLink>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<tr
|
||||
class="odd:bg-white even:bg-gray-50 last:border-none border-b border-slate-200"
|
||||
>
|
||||
<td
|
||||
scope="row"
|
||||
class="w-3/12 px-6 py-6 font-medium whitespace-nowrap text-black"
|
||||
>
|
||||
<Skeleton class="w-full !h-10 !rounded-sm" />
|
||||
</td>
|
||||
<td class="w-3/12 px-6 py-6">
|
||||
<Skeleton class="w-full !h-10 !rounded-sm" />
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
<Skeleton class="w-full !h-10 !rounded-sm" />
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
<Skeleton class="w-full !h-10 !rounded-sm" />
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
<Skeleton class="w-full !h-10 !rounded-sm" />
|
||||
</td>
|
||||
<td class="w-1/12 px-6 py-6">
|
||||
<Skeleton class="!size-10 !rounded-sm" />
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -17,7 +17,8 @@ const { data } = toRefs(props);
|
||||
|
||||
// computed
|
||||
|
||||
const timeAgo = usePersianTimeAgo(new Date(data.value.created_at));
|
||||
const createdTimeAgo = usePersianTimeAgo(new Date(data.value.created_at));
|
||||
const updatedTimeAgo = usePersianTimeAgo(new Date(data.value.updated_at));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -33,8 +34,13 @@ const timeAgo = usePersianTimeAgo(new Date(data.value.created_at));
|
||||
<td class="w-3/12 px-6 py-6">
|
||||
{{ data.subject ? data.subject : "--" }}
|
||||
</td>
|
||||
<td class="w-3/12 px-6 py-6">
|
||||
{{ data.created_at ? timeAgo : "--" }}
|
||||
<td class="w-3/12 px-6 py-6 flex flex-col gap-3 text-sm">
|
||||
<span class="w-full whitespace-pre">
|
||||
ایجاد : {{ data.created_at ? createdTimeAgo : "--" }}
|
||||
</span>
|
||||
<span class="w-full whitespace-pre">
|
||||
بروزرسانی : {{ data.updated_at ? updatedTimeAgo : "--" }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="w-2/12 px-6 py-6">
|
||||
<div
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// imports
|
||||
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { API_ENDPOINTS, QUERY_KEYS } from "~/constants";
|
||||
|
||||
// types
|
||||
|
||||
export type GetAllOrdersResponse = ApiPaginated<Order>;
|
||||
|
||||
export type GetAllOrdersRequest = {
|
||||
sort: string | undefined;
|
||||
status: string | undefined;
|
||||
page: string | string[];
|
||||
};
|
||||
|
||||
const useGetAllOrders = (params: ComputedRef<GetAllOrdersRequest>) => {
|
||||
// state
|
||||
|
||||
const { $axios: axios } = useNuxtApp();
|
||||
|
||||
// methods
|
||||
|
||||
const handleGetAllOrders = async (params: GetAllOrdersRequest) => {
|
||||
const { data } = await axios.get<GetAllOrdersResponse>(
|
||||
API_ENDPOINTS.orders.get_all,
|
||||
{
|
||||
params: {
|
||||
sort: params.sort,
|
||||
filter: params.status,
|
||||
offset: Number(params.page) * 7 - 7,
|
||||
limit: 7,
|
||||
},
|
||||
}
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
return useQuery({
|
||||
queryKey: [QUERY_KEYS.orders, params],
|
||||
queryFn: () => handleGetAllOrders(params.value),
|
||||
});
|
||||
};
|
||||
|
||||
export default useGetAllOrders;
|
||||
+6
-6
@@ -5,17 +5,17 @@ import { API_ENDPOINTS, QUERY_KEYS } from "~/constants";
|
||||
|
||||
// types
|
||||
|
||||
export type GetOrdersCartResponse = Cart;
|
||||
export type GetCartOrdersResponse = Cart;
|
||||
|
||||
const useGetOrdersCart = () => {
|
||||
const useGetCartOrders = () => {
|
||||
// state
|
||||
|
||||
const { $axios: axios } = useNuxtApp();
|
||||
|
||||
// methods
|
||||
|
||||
const handleGetOrdersCart = async () => {
|
||||
const { data } = await axios.get<GetOrdersCartResponse>(
|
||||
const handleGetCartOrders = async () => {
|
||||
const { data } = await axios.get<GetCartOrdersResponse>(
|
||||
API_ENDPOINTS.orders.cart.get_all
|
||||
);
|
||||
return data;
|
||||
@@ -23,8 +23,8 @@ const useGetOrdersCart = () => {
|
||||
|
||||
return useQuery({
|
||||
queryKey: [QUERY_KEYS.cart],
|
||||
queryFn: () => handleGetOrdersCart(),
|
||||
queryFn: () => handleGetCartOrders(),
|
||||
});
|
||||
};
|
||||
|
||||
export default useGetOrdersCart;
|
||||
export default useGetCartOrders;
|
||||
@@ -1,30 +0,0 @@
|
||||
// imports
|
||||
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { API_ENDPOINTS, QUERY_KEYS } from "~/constants";
|
||||
|
||||
// types
|
||||
|
||||
export type GetOrdersAllResponse = Order[];
|
||||
|
||||
const useGetOrdersAll = () => {
|
||||
// state
|
||||
|
||||
const { $axios: axios } = useNuxtApp();
|
||||
|
||||
// methods
|
||||
|
||||
const handleGetOrdersAll = async () => {
|
||||
const { data } = await axios.get<GetOrdersAllResponse>(
|
||||
API_ENDPOINTS.orders.get_all
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
return useQuery({
|
||||
queryKey: [QUERY_KEYS.orders],
|
||||
queryFn: () => handleGetOrdersAll(),
|
||||
});
|
||||
};
|
||||
|
||||
export default useGetOrdersAll;
|
||||
@@ -7,28 +7,28 @@ import { API_ENDPOINTS, QUERY_KEYS } from "~/constants";
|
||||
|
||||
export type GetAllTicketsResponse = ApiPaginated<Omit<Ticket, "messages">>;
|
||||
|
||||
export type GetAllTicketsFilters = {
|
||||
export type GetAllTicketsRequest = {
|
||||
sort: string | undefined;
|
||||
status: string | undefined;
|
||||
page: string | string[];
|
||||
};
|
||||
|
||||
const useGetAllTickets = (params: Ref<GetAllTicketsFilters>) => {
|
||||
const useGetAllTickets = (params: ComputedRef<GetAllTicketsRequest>) => {
|
||||
// state
|
||||
|
||||
const { $axios: axios } = useNuxtApp();
|
||||
|
||||
// methods
|
||||
|
||||
const handleGetAllTickets = async (params: GetAllTicketsFilters) => {
|
||||
const handleGetAllTickets = async (params: GetAllTicketsRequest) => {
|
||||
const { data } = await axios.get<GetAllTicketsResponse>(
|
||||
API_ENDPOINTS.tickets.get_all,
|
||||
{
|
||||
params: {
|
||||
sort: params.sort,
|
||||
filter: params.status,
|
||||
offset: Number(params.page) * 7 - 7,
|
||||
limit: 7,
|
||||
offset: Number(params.page) * 10 - 10,
|
||||
limit: 10,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
import useGetCartOrders from "~/composables/api/orders/useGetCartOrders";
|
||||
|
||||
// state
|
||||
|
||||
@@ -12,7 +12,7 @@ const prevPage = computed(() => route.meta.prevPage);
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart } = useGetOrdersCart();
|
||||
const { data: cart } = useGetCartOrders();
|
||||
|
||||
// computed
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import useGetOrdersCart from "~/composables/api/orders/useGetOrdersCart";
|
||||
import useGetCartOrders from "~/composables/api/orders/useGetCartOrders";
|
||||
|
||||
// meta
|
||||
|
||||
@@ -15,7 +15,7 @@ definePageMeta({
|
||||
|
||||
// queries
|
||||
|
||||
const { data: cart, isLoading: cartIsLoading, suspense } = useGetOrdersCart();
|
||||
const { data: cart, isLoading: cartIsLoading, suspense } = useGetCartOrders();
|
||||
|
||||
await suspense();
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
// meta
|
||||
|
||||
definePageMeta({
|
||||
middleware: "check-is-logged-in",
|
||||
layout: "profile",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full flex flex-col gap-5">
|
||||
<ProfilePageTitle title="خرید ها و سفارش های شما" icon="bi:cart" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,256 @@
|
||||
<script setup lang="ts">
|
||||
import useGetAllOrders, {
|
||||
type GetAllOrdersRequest,
|
||||
} from "~/composables/api/orders/useGetAllOrders";
|
||||
|
||||
// meta
|
||||
|
||||
definePageMeta({
|
||||
middleware: "check-is-logged-in",
|
||||
layout: "profile",
|
||||
});
|
||||
|
||||
// state
|
||||
|
||||
const params: GetAllOrdersRequest = useUrlSearchParams("history");
|
||||
|
||||
const filters = computed(() => {
|
||||
return {
|
||||
sort: params.sort ?? "created_at",
|
||||
status: params.status ?? "",
|
||||
page: params.page ?? 1,
|
||||
};
|
||||
});
|
||||
|
||||
const tableHeads = ref([
|
||||
"شماره سفارش",
|
||||
"تاریخ ثبت",
|
||||
"تعداد اقلام",
|
||||
"مبلغ",
|
||||
"وضعیت",
|
||||
"عملیات",
|
||||
]);
|
||||
|
||||
const sortFilters = ref([
|
||||
{
|
||||
title: "جدید ترین",
|
||||
value: "created_at",
|
||||
},
|
||||
{
|
||||
title: "قدیمی ترین",
|
||||
value: "-created_at",
|
||||
},
|
||||
{
|
||||
title: "گران ترین",
|
||||
value: "final_price",
|
||||
},
|
||||
{
|
||||
title: "ارزان ترین",
|
||||
value: "-final_price",
|
||||
},
|
||||
]);
|
||||
|
||||
const statusFilters = ref([
|
||||
{
|
||||
title: "در انتظار تایید",
|
||||
value: "ADMIN_PENDING",
|
||||
},
|
||||
{
|
||||
title: "در حال پردازش",
|
||||
value: "PENDING",
|
||||
},
|
||||
{
|
||||
title: "ارسال شده",
|
||||
value: "POSTED",
|
||||
},
|
||||
{
|
||||
title: "تحویل داده شده",
|
||||
value: "RECEIVED",
|
||||
},
|
||||
{
|
||||
title: "لغو شده",
|
||||
value: "CANCELED",
|
||||
},
|
||||
{
|
||||
title: "مرجوع شده",
|
||||
value: "REFUND",
|
||||
},
|
||||
]);
|
||||
|
||||
// provide / inject
|
||||
|
||||
provide("params", params);
|
||||
|
||||
// queries
|
||||
|
||||
const { data, isPending: purchasesIsPending } = useGetAllOrders(filters);
|
||||
|
||||
// computed
|
||||
|
||||
const purchases = computed(() => {
|
||||
return data.value?.results.flat();
|
||||
});
|
||||
|
||||
const hasPurchases = computed(() => data.value?.count > 0);
|
||||
|
||||
const hasFilters = computed(() =>
|
||||
Object.keys(params)
|
||||
.filter((key) => key != "page")
|
||||
.some((key) => params[key] != undefined)
|
||||
);
|
||||
|
||||
const paginationData = computed(() => {
|
||||
return data.value?.results.map((_, i: number) => {
|
||||
return { type: "page", value: i };
|
||||
});
|
||||
});
|
||||
|
||||
// methods
|
||||
|
||||
const clearFilters = () => {
|
||||
params.sort = undefined;
|
||||
params.status = undefined;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full flex flex-col gap-5">
|
||||
<ProfilePageTitle title="خرید ها و سفارش های شما" icon="bi:cart" />
|
||||
|
||||
<div class="w-full flex flex-col gap-5">
|
||||
<div class="w-full flex items-center justify-between px-5">
|
||||
<div class="flex items-center justify-start gap-8">
|
||||
<div class="flex items-center justify-start gap-3">
|
||||
<span class="text-sm">ترتیب بر اساس</span>
|
||||
<Select
|
||||
v-model="params.sort!"
|
||||
triggerRootClass="!py-2.5"
|
||||
class="w-[6rem]"
|
||||
>
|
||||
<template #content>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
v-for="(category, index) in sortFilters"
|
||||
:key="index"
|
||||
class="text-xs leading-none w-full rounded-sm py-5 flex items-center justify-between h-[25px] pr-[12px] relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-slate-300 data-[highlighted]:text-black"
|
||||
:value="category.value"
|
||||
>
|
||||
<SelectItemIndicator
|
||||
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
|
||||
>
|
||||
<Icon name="bi:check" size="20" />
|
||||
</SelectItemIndicator>
|
||||
<SelectItemText
|
||||
class="text-end font-iran-yekan-x text-sm"
|
||||
>
|
||||
{{ category.title }}
|
||||
</SelectItemText>
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</template>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="flex items-center justify-start gap-3">
|
||||
<span class="text-sm">وضعیت</span>
|
||||
<Select
|
||||
v-model="params.status!"
|
||||
triggerRootClass="!py-2.5"
|
||||
class="w-[6rem]"
|
||||
>
|
||||
<template #content>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
v-for="(
|
||||
category, index
|
||||
) in statusFilters"
|
||||
:key="index"
|
||||
class="text-xs leading-none w-full rounded-sm py-5 flex items-center justify-between h-[25px] pr-[12px] relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-slate-300 data-[highlighted]:text-black"
|
||||
:value="category.value"
|
||||
>
|
||||
<SelectItemIndicator
|
||||
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
|
||||
>
|
||||
<Icon name="bi:check" size="20" />
|
||||
</SelectItemIndicator>
|
||||
<SelectItemText
|
||||
class="text-end font-iran-yekan-x text-sm"
|
||||
>
|
||||
{{ category.title }}
|
||||
</SelectItemText>
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</template>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-center gap-4">
|
||||
<Button
|
||||
v-if="hasFilters"
|
||||
end-icon="bi:x"
|
||||
@click="clearFilters"
|
||||
size="md"
|
||||
class="rounded-full"
|
||||
>
|
||||
<span class="whitespace-pre"> حذف فیلتر ها </span>
|
||||
</Button>
|
||||
|
||||
<NuxtLink :to="{ name: 'products' }">
|
||||
<Button
|
||||
end-icon="bi:plus"
|
||||
size="md"
|
||||
class="rounded-full"
|
||||
>
|
||||
<span class="whitespace-pre"> خرید جدید </span>
|
||||
</Button>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Placeholder
|
||||
v-if="!hasPurchases && !purchasesIsPending"
|
||||
class="!w-full !py-[5rem]"
|
||||
icon="bi:cart"
|
||||
title="خرید یا سفارشی یافت نشد"
|
||||
/>
|
||||
|
||||
<Table v-else>
|
||||
<template #thead>
|
||||
<th
|
||||
v-for="(tableHead, index) in tableHeads"
|
||||
:key="index"
|
||||
scope="col"
|
||||
:class="
|
||||
[0, 1].includes(index)
|
||||
? 'w-3/12'
|
||||
: tableHeads.length - 1 == index
|
||||
? 'w-1/2'
|
||||
: 'w-2/12'
|
||||
"
|
||||
class="px-6 py-5 text-sm font-normal"
|
||||
>
|
||||
{{ tableHead }}
|
||||
</th>
|
||||
</template>
|
||||
<template #tbody>
|
||||
<template v-if="purchasesIsPending">
|
||||
<PurchasesTableRowLoading v-for="i in 5" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<PurchasesTableRow
|
||||
v-for="(purchase, index) in purchases"
|
||||
:key="index"
|
||||
:data="purchase"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</Table>
|
||||
|
||||
<div v-if="data?.count > 10" class="w-full flex-center py-10">
|
||||
<Pagination :items="paginationData" :total="data?.count" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -2,7 +2,7 @@
|
||||
// imports
|
||||
|
||||
import useGetAllTickets, {
|
||||
type GetAllTicketsFilters,
|
||||
type GetAllTicketsRequest,
|
||||
} from "~/composables/api/tickets/useGetAllTickets";
|
||||
|
||||
// meta
|
||||
@@ -14,7 +14,7 @@ definePageMeta({
|
||||
|
||||
// state
|
||||
|
||||
const params: GetAllTicketsFilters = useUrlSearchParams("history");
|
||||
const params: GetAllTicketsRequest = useUrlSearchParams("history");
|
||||
|
||||
const filters = computed(() => {
|
||||
return {
|
||||
@@ -74,11 +74,24 @@ const tickets = computed(() => {
|
||||
|
||||
const hasTickets = computed(() => data.value?.count > 0);
|
||||
|
||||
const hasFilters = computed(() =>
|
||||
Object.keys(params)
|
||||
.filter((key) => key != "page")
|
||||
.some((key) => params[key] != undefined)
|
||||
);
|
||||
|
||||
const paginationData = computed(() => {
|
||||
return data.value?.results.map((_, i: number) => {
|
||||
return { type: "page", value: i };
|
||||
});
|
||||
});
|
||||
|
||||
// methods
|
||||
|
||||
const clearFilters = () => {
|
||||
params.sort = undefined;
|
||||
params.status = undefined;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -152,11 +165,27 @@ const paginationData = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NuxtLink :to="{ name: 'profile-tickets-new' }">
|
||||
<Button end-icon="bi:plus" size="md" class="rounded-full">
|
||||
<span class="whitespace-pre"> تیکت جدید </span>
|
||||
<div class="flex-center gap-4">
|
||||
<Button
|
||||
v-if="hasFilters"
|
||||
end-icon="bi:x"
|
||||
@click="clearFilters"
|
||||
size="md"
|
||||
class="rounded-full"
|
||||
>
|
||||
<span class="whitespace-pre"> حذف فیلتر ها </span>
|
||||
</Button>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink :to="{ name: 'profile-tickets-new' }">
|
||||
<Button
|
||||
end-icon="bi:plus"
|
||||
size="md"
|
||||
class="rounded-full"
|
||||
>
|
||||
<span class="whitespace-pre"> تیکت جدید </span>
|
||||
</Button>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Placeholder
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import useGetOrdersAll from "~/composables/api/orders/useGetOrdersAll";
|
||||
import useGetAllOrders from "~/composables/api/orders/useGetAllOrders";
|
||||
import useCreateTicket, {
|
||||
type CreateTicketRequest,
|
||||
} from "~/composables/api/tickets/useCreateTicket";
|
||||
@@ -74,7 +74,7 @@ const ticketData = ref<CreateTicketRequest>({
|
||||
|
||||
// queries
|
||||
|
||||
const { data: orders, isLoading: ordersIsLoading } = useGetOrdersAll();
|
||||
const { data: orders, isLoading: ordersIsLoading } = useGetAllOrders();
|
||||
|
||||
const { mutateAsync: createTicket, isPending: createTicketIsPending } =
|
||||
useCreateTicket();
|
||||
|
||||
Vendored
+11
-4
@@ -172,11 +172,18 @@ declare global {
|
||||
id: number;
|
||||
count: number;
|
||||
images: string[];
|
||||
discount_code: string | null;
|
||||
status: string;
|
||||
status:
|
||||
| "ADMIN_PENDING"
|
||||
| "PENDING"
|
||||
| "POSTED"
|
||||
| "RECEIVED"
|
||||
| "CANCELED"
|
||||
| "REFUND";
|
||||
verbose_status: string;
|
||||
is_paid: boolean;
|
||||
created_at: string | null;
|
||||
address: Address | null;
|
||||
created_at: string;
|
||||
final_price: string;
|
||||
order_id: number;
|
||||
};
|
||||
|
||||
type DiscountCode = {
|
||||
|
||||
Reference in New Issue
Block a user