connected ticket create to api and added validation
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import useGetOrdersList from "~/composables/api/orders/useGetOrdersList";
|
||||
import useCreateTicket, {
|
||||
type CreateTicketRequest,
|
||||
} from "~/composables/api/tickets/useCreateTicket";
|
||||
import useUploadAttachment from "~/composables/api/tickets/useUploadAttachment";
|
||||
import { useToast } from "~/composables/global/useToast";
|
||||
import { QUERY_KEYS } from "~/constants";
|
||||
import useVuelidate from "@vuelidate/core";
|
||||
import { helpers, required, minLength, email } from "@vuelidate/validators";
|
||||
|
||||
// meta
|
||||
|
||||
@@ -71,12 +74,49 @@ const ticketData = ref<CreateTicketRequest>({
|
||||
|
||||
// queries
|
||||
|
||||
const { data: orders, isLoading: ordersIsLoading } = useGetOrdersList();
|
||||
|
||||
const { mutateAsync: createTicket, isPending: createTicketIsPending } =
|
||||
useCreateTicket();
|
||||
|
||||
const { mutate: uploadAttachment, isPending: uploadAttachmentIsPending } =
|
||||
const { mutateAsync: uploadAttachment, isPending: uploadAttachmentIsPending } =
|
||||
useUploadAttachment();
|
||||
|
||||
// computed
|
||||
|
||||
const formRules = computed(() => {
|
||||
return {
|
||||
ticket_category: {
|
||||
required: helpers.withMessage(
|
||||
"فیلد دسته بندی الزامی می باشد",
|
||||
required
|
||||
),
|
||||
},
|
||||
subject: {
|
||||
required: helpers.withMessage(
|
||||
"فیلد عنوان تیکت الزامی می باشد",
|
||||
required
|
||||
),
|
||||
minLength: helpers.withMessage(
|
||||
"فیلد عنوان تیکت حداقل ۵ کرکتر می باشد",
|
||||
minLength(5)
|
||||
),
|
||||
},
|
||||
content: {
|
||||
required: helpers.withMessage(
|
||||
"فیلد متن تیکت الزامی می باشد",
|
||||
required
|
||||
),
|
||||
minLength: helpers.withMessage(
|
||||
"فیلد متن تیکت حداقل ۵ کرکتر می باشد",
|
||||
minLength(5)
|
||||
),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const formValidator$ = useVuelidate(formRules, ticketData);
|
||||
|
||||
// methods
|
||||
|
||||
const handleUploadAttachment = (file: File) => {
|
||||
@@ -101,35 +141,38 @@ const handleUploadAttachment = (file: File) => {
|
||||
);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
createTicket(
|
||||
{ ...ticketData.value },
|
||||
{
|
||||
onSuccess: () => {
|
||||
router.push({ name: "profile-tickets" });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [QUERY_KEYS.tickets],
|
||||
});
|
||||
addToast({
|
||||
message: "تیکت شما با موفقیت ثبت شد",
|
||||
options: {
|
||||
status: "success",
|
||||
description:
|
||||
"پس از بررسی پشتیبانی به شما اطلاع رسانی می شود",
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: () => {
|
||||
addToast({
|
||||
message: "خطایی در ثبت تیکت رخ داد",
|
||||
options: {
|
||||
status: "success",
|
||||
description: "لطفا مجدد تلاش کنید",
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
const handleSubmit = async () => {
|
||||
await formValidator$.value.$validate();
|
||||
if (!formValidator$.value.$errors.length) {
|
||||
createTicket(
|
||||
{ ...ticketData.value },
|
||||
{
|
||||
onSuccess: () => {
|
||||
router.push({ name: "profile-tickets" });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [QUERY_KEYS.tickets],
|
||||
});
|
||||
addToast({
|
||||
message: "تیکت شما با موفقیت ثبت شد",
|
||||
options: {
|
||||
status: "success",
|
||||
description:
|
||||
"پس از بررسی پشتیبانی به شما اطلاع رسانی می شود",
|
||||
},
|
||||
});
|
||||
},
|
||||
onError: () => {
|
||||
addToast({
|
||||
message: "خطایی در ثبت تیکت رخ داد",
|
||||
options: {
|
||||
status: "success",
|
||||
description: "لطفا مجدد تلاش کنید",
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -150,10 +193,16 @@ const handleSubmit = () => {
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5">
|
||||
<DataField id="category" :required="true" label="دسته بندی">
|
||||
<DataField
|
||||
id="category"
|
||||
:required="true"
|
||||
label="دسته بندی"
|
||||
:error="formValidator$.ticket_category"
|
||||
>
|
||||
<Select
|
||||
placeholder="انتخاب کنید"
|
||||
variant="outlined"
|
||||
:error="formValidator$.ticket_category.$error"
|
||||
v-model="ticketData.ticket_category"
|
||||
>
|
||||
<template #content>
|
||||
@@ -186,26 +235,65 @@ const handleSubmit = () => {
|
||||
placeholder="انتخاب کنید"
|
||||
variant="outlined"
|
||||
v-model="ticketData.order"
|
||||
:loading="ordersIsLoading"
|
||||
>
|
||||
<template #trigger>
|
||||
<SelectValue
|
||||
:class="
|
||||
ticketData.order
|
||||
? 'text-black'
|
||||
: 'text-slate-400'
|
||||
"
|
||||
class="font-iran-yekan-x text-sm text-start placeholder-slate-400"
|
||||
>
|
||||
{{
|
||||
ticketData.order
|
||||
? `شماره سفارش : ${ticketData.order}`
|
||||
: "وارد نشده"
|
||||
}}
|
||||
</SelectValue>
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
<SelectGroup>
|
||||
<SelectItem
|
||||
v-for="(
|
||||
category, index
|
||||
) in ticketCategories"
|
||||
v-for="(order, index) in orders"
|
||||
: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"
|
||||
class="text-xs leading-none w-full rounded-sm py-5 flex items-center justify-between h-[25px] px-[12px] shrink-0 relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-slate-300 data-[highlighted]:text-black"
|
||||
:value="order.id"
|
||||
>
|
||||
<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"
|
||||
class="w-full text-end font-iran-yekan-x text-sm flex items-center justify-between"
|
||||
>
|
||||
{{ category.title }}
|
||||
<div class="flex items-center gap-4">
|
||||
<AvatarGroup
|
||||
:items="[
|
||||
'https://c262408.parspack.net/media/profile_photos/Jackie_Robinson_NPG_97_135.jpg?AWSAccessKeyId=mtiSN2JWjWgyfr2u&Signature=mlUzygzyg2gQD7B5STTlgM2N%2FUM%3D&Expires=1740517316',
|
||||
'https://c262408.parspack.net/media/profile_photos/Jackie_Robinson_NPG_97_135.jpg?AWSAccessKeyId=mtiSN2JWjWgyfr2u&Signature=mlUzygzyg2gQD7B5STTlgM2N%2FUM%3D&Expires=1740517316',
|
||||
'https://c262408.parspack.net/media/profile_photos/Jackie_Robinson_NPG_97_135.jpg?AWSAccessKeyId=mtiSN2JWjWgyfr2u&Signature=mlUzygzyg2gQD7B5STTlgM2N%2FUM%3D&Expires=1740517316',
|
||||
]"
|
||||
:max="2"
|
||||
size="32px"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="flex flex-col items-start gap-1 text-[10px]"
|
||||
>
|
||||
<span
|
||||
>{{
|
||||
order.count
|
||||
}}
|
||||
محصول</span
|
||||
>
|
||||
<span>
|
||||
شماره سفارش : {{ order.id }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
{{ order.status }}
|
||||
</span>
|
||||
</SelectItemText>
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
@@ -217,17 +305,26 @@ const handleSubmit = () => {
|
||||
:required="true"
|
||||
label="عنوان تیکت"
|
||||
class="col-span-full"
|
||||
:error="formValidator$.subject"
|
||||
>
|
||||
<Input
|
||||
v-model="ticketData.subject"
|
||||
placeholder="عنوان تیکت را اینجا بنویسید ..."
|
||||
variant="outlined"
|
||||
:error="formValidator$.subject.$error"
|
||||
/>
|
||||
</DataField>
|
||||
<DataField id="message" :required="true" label="متن تیکت">
|
||||
<textarea
|
||||
<DataField
|
||||
id="message"
|
||||
:required="true"
|
||||
label="متن تیکت"
|
||||
:error="formValidator$.content"
|
||||
>
|
||||
<Textarea
|
||||
v-model="ticketData.content"
|
||||
class="w-full bg-white border-[1.5px] border-slate-200 rounded-xl text-xs lg:text-sm p-5 text-black h-[10rem] lg:h-[20rem] transition resize-none outline-none focus:!border-black"
|
||||
:error="formValidator$.content.$error"
|
||||
class="h-[10rem] lg:h-[20rem]"
|
||||
variant="outlined"
|
||||
placeholder="متن تیکت را اینجا بنویسید ..."
|
||||
/>
|
||||
</DataField>
|
||||
@@ -239,10 +336,18 @@ const handleSubmit = () => {
|
||||
</div>
|
||||
</ProfileSection>
|
||||
<div class="w-full flex-center py-5">
|
||||
<Button class="rounded-full px-20" end-icon="bi:send" size="md">
|
||||
<Button
|
||||
@click="handleSubmit"
|
||||
class="rounded-full w-[14rem] h-11"
|
||||
size="md"
|
||||
>
|
||||
<Icon
|
||||
v-if="createTicketIsPending"
|
||||
name="svg-spinners:3-dots-bounce"
|
||||
:name="
|
||||
createTicketIsPending
|
||||
? 'svg-spinners:3-dots-bounce'
|
||||
: 'bi:send'
|
||||
"
|
||||
/>
|
||||
<span v-else>ارسال تیکت</span>
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user