Files
hossein-por-shop/frontend/pages/contact-us.vue
T

326 lines
12 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>