326 lines
12 KiB
Vue
326 lines
12 KiB
Vue
<script setup lang="ts">
|
||
// imports
|
||
|
||
import useVuelidate from "@vuelidate/core";
|
||
import { email, helpers, minLength, required } from "@vuelidate/validators";
|
||
import useCreateContactUsTicket, {
|
||
type CreateContactUsTicketRequest,
|
||
} from "~/composables/api/tickets/useCreateContactUsTicket";
|
||
import { useToast } from "~/composables/global/useToast";
|
||
|
||
// types
|
||
|
||
type ContactInfoForm = Omit<CreateContactUsTicketRequest, "type"> & {
|
||
type: string | undefined;
|
||
};
|
||
|
||
type RequestTypeOption = {
|
||
title: string;
|
||
value: CreateContactUsTicketRequest["type"];
|
||
};
|
||
|
||
// state
|
||
|
||
useSeoMeta({
|
||
title: "ارتباط با ما",
|
||
});
|
||
|
||
const { addToast } = useToast();
|
||
|
||
const contactInfo = ref<ContactInfoForm>({
|
||
full_name: "",
|
||
email: "",
|
||
phone: "",
|
||
type: undefined,
|
||
message: "",
|
||
});
|
||
|
||
const requestTypes = ref<RequestTypeOption[]>([
|
||
{
|
||
title: "انتقادات",
|
||
value: "COMPLAINT",
|
||
},
|
||
{
|
||
title: "پیشنهادات",
|
||
value: "SUGGESTION",
|
||
},
|
||
{
|
||
title: "پیگیری سفارش",
|
||
value: "ORDER_FOLLOW_UP",
|
||
},
|
||
]);
|
||
|
||
const contactWays = ref<{ title: string; ways: { type: "text" | "link"; title: string; path?: string }[] }[]>([
|
||
{
|
||
title: "آدرس",
|
||
ways: [
|
||
{
|
||
type: "text",
|
||
title: `استان فارس,شهرستان شيراز,بخش مركزى, شهر
|
||
شيراز, گلستان، بلوار سما,خيابان شهيد طهماسبى ،پلاك ١٩٨ ,طبقه همكف`,
|
||
},
|
||
{
|
||
type: "text",
|
||
title: "کد پستی :7145746584",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: "شماره تماس",
|
||
ways: [
|
||
{
|
||
type: "link",
|
||
title: "09026663488",
|
||
path: "tell:09026663488",
|
||
},
|
||
{
|
||
type: "link",
|
||
title: "09022202311",
|
||
path: "tell:09022202311",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: "ایمیل شرکت",
|
||
ways: [
|
||
{
|
||
type: "link",
|
||
title: "npsayna@gmail.com",
|
||
path: "mailto:npsayna@gmail.com",
|
||
},
|
||
],
|
||
},
|
||
]);
|
||
|
||
const { mutateAsync: createContactUsTicket, isPending: createTicketIsPending } = useCreateContactUsTicket();
|
||
|
||
// computed
|
||
|
||
const requestTypeOptions = computed(() => requestTypes.value.map((item) => item.title));
|
||
|
||
const formRules = computed(() => {
|
||
return {
|
||
full_name: {
|
||
required: helpers.withMessage("فیلد نام و نام خانوادگی الزامی می باشد", required),
|
||
minLength: helpers.withMessage("فیلد نام و نام خانوادگی حداقل ۳ کرکتر می باشد", minLength(3)),
|
||
},
|
||
email: {
|
||
required: helpers.withMessage("فیلد پست الکترونیکی الزامی می باشد", required),
|
||
email: helpers.withMessage("پست الکترونیکی وارد شده معتبر نمی باشد", email),
|
||
},
|
||
phone: {
|
||
required: helpers.withMessage("فیلد شماره تلفن الزامی می باشد", required),
|
||
},
|
||
type: {
|
||
required: helpers.withMessage("فیلد نوع درخواست الزامی می باشد", required),
|
||
},
|
||
message: {
|
||
required: helpers.withMessage("فیلد پیغام شما الزامی می باشد", required),
|
||
minLength: helpers.withMessage("فیلد پیغام شما حداقل ۵ کرکتر می باشد", minLength(5)),
|
||
},
|
||
};
|
||
});
|
||
|
||
const formValidator$ = useVuelidate(formRules, contactInfo);
|
||
|
||
// methods
|
||
|
||
const resetForm = () => {
|
||
contactInfo.value = {
|
||
full_name: "",
|
||
email: "",
|
||
phone: "",
|
||
type: undefined,
|
||
message: "",
|
||
};
|
||
formValidator$.value.$reset();
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
await formValidator$.value.$validate();
|
||
|
||
if (!formValidator$.value.$errors.length && contactInfo.value.type) {
|
||
const selectedType = requestTypes.value.find((item) => item.title === contactInfo.value.type)?.value;
|
||
|
||
if (!selectedType) {
|
||
addToast({
|
||
message: "نوع درخواست معتبر نیست",
|
||
options: {
|
||
status: "error",
|
||
description: "لطفا نوع درخواست را مجدد انتخاب کنید",
|
||
},
|
||
});
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await createContactUsTicket({
|
||
full_name: contactInfo.value.full_name,
|
||
email: contactInfo.value.email,
|
||
phone: contactInfo.value.phone,
|
||
type: selectedType,
|
||
message: contactInfo.value.message,
|
||
});
|
||
|
||
addToast({
|
||
message: "پیغام شما با موفقیت ارسال شد",
|
||
options: {
|
||
status: "success",
|
||
description: "پس از بررسی با شما تماس می گیریم",
|
||
},
|
||
});
|
||
|
||
resetForm();
|
||
} catch (error) {
|
||
addToast({
|
||
message: "خطایی در ارسال پیغام رخ داد",
|
||
options: {
|
||
status: "error",
|
||
description: "لطفا مجدد تلاش کنید",
|
||
},
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<template>
|
||
<div class="w-full container flex flex-col">
|
||
<div class="w-full flex-center py-[5rem]">
|
||
<div class="flex flex-col items-center gap-3 text-black w-full">
|
||
<h1 class="typo-h-6 max-sm:text-xl md:typo-h-5 lg:typo-h-4">ارتباط با ما</h1>
|
||
<p class="text-slate-500 text-center max-w-[750px] max-lg:text-sm leading-[175%]">
|
||
ما اینجا هستیم تا کمک کنیم. برای پشتیبانی، بازخورد یا هر سوالی که ممکن است داشته باشید تماس بگیرید.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="w-full flex flex-col-reverse max-lg:-mt-14 lg:flex-row items-start justify-between">
|
||
<div class="w-full lg:w-8/12 flex flex-col items-start gap-10">
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-[.6rem] w-full">
|
||
<DataField
|
||
label="نام و نام خانوادگی"
|
||
:required="true"
|
||
:error="formValidator$.full_name"
|
||
>
|
||
<Input
|
||
class="w-full"
|
||
v-model="contactInfo.full_name"
|
||
placeholder="نام و نام خانوادگی"
|
||
:error="formValidator$.full_name.$error"
|
||
/>
|
||
</DataField>
|
||
|
||
<DataField
|
||
label="پست الکترونیکی"
|
||
:required="true"
|
||
:error="formValidator$.email"
|
||
>
|
||
<Input
|
||
class="w-full"
|
||
v-model="contactInfo.email"
|
||
placeholder="پست الکترونیکی"
|
||
:error="formValidator$.email.$error"
|
||
/>
|
||
</DataField>
|
||
|
||
<DataField
|
||
label="شماره تلفن"
|
||
:required="true"
|
||
:error="formValidator$.phone"
|
||
>
|
||
<Input
|
||
class="w-full"
|
||
v-model="contactInfo.phone"
|
||
placeholder="شماره تلفن"
|
||
dir="ltr"
|
||
:error="formValidator$.phone.$error"
|
||
/>
|
||
</DataField>
|
||
|
||
<DataField
|
||
label="نوع درخواست"
|
||
:required="true"
|
||
:error="formValidator$.type"
|
||
>
|
||
<Select
|
||
v-model="contactInfo.type"
|
||
placeholder="نوع درخواست"
|
||
:options="requestTypeOptions"
|
||
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 "
|
||
/>
|
||
</DataField>
|
||
|
||
<DataField
|
||
label="پیغام شما"
|
||
:required="true"
|
||
:error="formValidator$.message"
|
||
class="col-span-1 md:col-span-2"
|
||
>
|
||
<textarea
|
||
v-model="contactInfo.message"
|
||
placeholder="پیغام شما"
|
||
:class="[
|
||
'w-full flex items-center resize-none bg-slate-50 h-[10rem] max-h-[12rem] text-black justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-3.5 selection:bg-slate-100 rounded-100 outline-none flex-1 !text-sm placeholder-slate-400 placeholder:text-xs lg:placeholder:text-sm placeholder:font-normal',
|
||
formValidator$.message.$error
|
||
? 'border-danger-600'
|
||
: 'border-slate-200 hover:border-black focus:border-black',
|
||
]"
|
||
></textarea>
|
||
</DataField>
|
||
</div>
|
||
|
||
<div class="w-full flex-center pb-10 border-b border-slate-200">
|
||
<Button
|
||
class="rounded-full w-[14rem] h-11"
|
||
size="md"
|
||
:loading="createTicketIsPending"
|
||
@click="handleSubmit"
|
||
>
|
||
<span>ارسال پیغام</span>
|
||
</Button>
|
||
</div>
|
||
|
||
<div class="flex max-sm:flex-col gap-8 w-full lg:gap-20">
|
||
<div
|
||
v-for="(way, index) in contactWays"
|
||
:key="index"
|
||
class="flex flex-col gap-3"
|
||
>
|
||
<span class="text-slate-500 max-lg:text-sm">
|
||
{{ way.title }}
|
||
</span>
|
||
<div
|
||
v-for="(item, index) in way.ways"
|
||
:key="index"
|
||
class="flex flex-col"
|
||
>
|
||
<a
|
||
v-if="item.type === 'link'"
|
||
:href="item.path!"
|
||
class="text-black underline max-lg:text-xs lg:text-sm"
|
||
>
|
||
{{ item.title }}
|
||
</a>
|
||
<p
|
||
v-else
|
||
class="leading-[175%]! max-lg:text-xs lg:text-sm max-w-100"
|
||
>
|
||
{{ item.title }}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="w-full lg:w-4/12 h-full flex-center">
|
||
<NuxtImg
|
||
src="/img/heymlz/heymlz-contact-us.gif"
|
||
class="size-2/3 -mt-5 lg:scale-150 drop-shadow-2xl"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped></style>
|