323 lines
12 KiB
Vue
323 lines
12 KiB
Vue
<script setup lang="ts">
|
|
// imports
|
|
|
|
import useVuelidate from "@vuelidate/core";
|
|
import { helpers, required, minLength, email } from "@vuelidate/validators";
|
|
import useGetAccount from "~/composables/api/account/useGetAccount";
|
|
import useUpdateAccount, {
|
|
type UpdateAccountRequest,
|
|
} from "~/composables/api/account/useUpdateAccount";
|
|
import { useObjectTrack } from "~/composables/global/useObjectTrack";
|
|
import { useToast } from "~/composables/global/useToast";
|
|
import { QUERY_KEYS } from "~/constants";
|
|
|
|
// meta
|
|
|
|
definePageMeta({
|
|
middleware: "check-is-logged-in",
|
|
layout: "profile",
|
|
});
|
|
|
|
// state
|
|
|
|
const { data: account } = useGetAccount();
|
|
|
|
const { $queryClient: queryClient } = useNuxtApp();
|
|
|
|
const { addToast } = useToast();
|
|
|
|
const personalData = ref<UpdateAccountRequest>({
|
|
profile_photo: null,
|
|
first_name: account.value?.first_name ?? "",
|
|
last_name: account.value?.last_name ?? "",
|
|
phone: account.value?.phone ?? "",
|
|
gender: account.value?.gender ?? undefined,
|
|
email: account.value?.email ?? "",
|
|
birth_date: account.value?.birth_date ?? "",
|
|
});
|
|
|
|
const profilePictureModalIsShow = ref(false);
|
|
|
|
const { isNotEqual, clear: clearObjectTracker } = useObjectTrack(personalData);
|
|
|
|
const alises = ref([
|
|
"شکارچی",
|
|
"آیفون باز",
|
|
"خوش سلیقه",
|
|
"دست و دلباز",
|
|
"چرم باز",
|
|
]);
|
|
|
|
// queries
|
|
|
|
const { mutateAsync: updateAccount, isPending: updateAccountIsPending } =
|
|
useUpdateAccount();
|
|
|
|
// computed
|
|
|
|
const formRules = computed(() => {
|
|
return {
|
|
first_name: {
|
|
required: helpers.withMessage("فیلد نام الزامی می باشد", required),
|
|
minLength: helpers.withMessage(
|
|
"فیلد نام حداقل ۳ کرکتر می باشد",
|
|
minLength(3)
|
|
),
|
|
},
|
|
last_name: {
|
|
required: helpers.withMessage(
|
|
"فیلد نام خانوادگی الزامی می باشد",
|
|
required
|
|
),
|
|
minLength: helpers.withMessage(
|
|
"فیلد نام خانوادگی حداقل ۳ کرکتر می باشد",
|
|
minLength(3)
|
|
),
|
|
},
|
|
phone: {
|
|
required: helpers.withMessage(
|
|
"فیلد شماره تلفن الزامی می باشد",
|
|
required
|
|
),
|
|
phoneValidator: helpers.withMessage(
|
|
"شماره تلفن وارد شده معتبر نمی باشد",
|
|
helpers.regex(/^0?[1-9][0-9]{9}$/)
|
|
),
|
|
},
|
|
gender: {
|
|
required: helpers.withMessage(
|
|
"فیلد جنسیت الزامی می باشد",
|
|
required
|
|
),
|
|
},
|
|
email: {
|
|
required: helpers.withMessage(
|
|
"فیلد حساب الکترونیکی الزامی می باشد",
|
|
required
|
|
),
|
|
email: helpers.withMessage(
|
|
"حساب الکترونیکی وارد شده معتبر نمی باشد",
|
|
email
|
|
),
|
|
},
|
|
birth_date: {
|
|
required: helpers.withMessage(
|
|
"فیلد تاریخ تولد الزامی می باشد",
|
|
required
|
|
),
|
|
},
|
|
};
|
|
});
|
|
|
|
const formValidator$ = useVuelidate(formRules, personalData as any);
|
|
|
|
// methods
|
|
|
|
const updateData = () => {
|
|
updateAccount(
|
|
{ ...personalData.value },
|
|
{
|
|
onSuccess: (data) => {
|
|
queryClient.invalidateQueries({
|
|
queryKey: [QUERY_KEYS.account],
|
|
});
|
|
|
|
addToast({
|
|
message: "اطلاعات با موفقیت تغییر یافت",
|
|
options: {
|
|
status: "success",
|
|
},
|
|
});
|
|
clearObjectTracker();
|
|
},
|
|
onError: () => {
|
|
addToast({
|
|
message: "خطایی در تغییر اطلاعات رخ داد",
|
|
options: {
|
|
status: "error",
|
|
},
|
|
});
|
|
},
|
|
}
|
|
);
|
|
};
|
|
|
|
const handleSubmit = (withValidation: boolean) => {
|
|
if (withValidation) {
|
|
formValidator$.value.$validate();
|
|
if (!formValidator$.value.$errors.length) {
|
|
updateData();
|
|
}
|
|
} else {
|
|
updateData();
|
|
profilePictureModalIsShow.value = false;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="w-full flex flex-col gap-5">
|
|
<ProfilePageTitle title="پروفایل" icon="bi:person-vcard" />
|
|
|
|
<div class="flex flex-col gap-6">
|
|
<div
|
|
class="w-full flex items-center justify-between border p-6 rounded-xl border-slate-200"
|
|
>
|
|
<div class="flex items-center justify-start gap-5 w-8/12">
|
|
<div
|
|
class="relative shrink-0 rounded-full flex-center"
|
|
>
|
|
<Avatar
|
|
class="!size-32"
|
|
:src="account!.profile_photo"
|
|
:alt="
|
|
account?.first_name && account?.last_name
|
|
? `${account?.first_name.charAt(
|
|
0
|
|
)} ${account?.last_name.charAt(0)}`
|
|
: 'بدون نام کاربری'
|
|
"
|
|
/>
|
|
|
|
<ProfilePictureModal
|
|
v-model:is-show="profilePictureModalIsShow"
|
|
v-model="personalData.profile_photo!"
|
|
@update:model-value="() => handleSubmit(false)"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-3">
|
|
<span class="typo-sub-h-lg"
|
|
>{{ account?.first_name }}
|
|
{{ account?.last_name }}</span
|
|
>
|
|
<span class="typo-sub-h-sm font-light text-slate-600">
|
|
با اولین خریدتون هوش مصنوعی وبسایتمون واستون یک
|
|
بایوگرافی درست میکنه :)
|
|
</span>
|
|
<div
|
|
class="flex-center border border-yellow-500 pe-3.5 ps-1 w-max rounded-full"
|
|
>
|
|
<div class="rounded-full p-2">
|
|
<Icon
|
|
name="bi:patch-check"
|
|
class="**:fill-yellow-400"
|
|
size="20"
|
|
/>
|
|
</div>
|
|
<span class="text-xs text-yellow-500"
|
|
>جزو ۳ مشتری برتر</span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col items-start gap-3 w-4/12">
|
|
<span class="typo-sub-h-lg">لقب های شما</span>
|
|
<span class="flex w-full flex-wrap gap-2">
|
|
<span
|
|
v-for="(alise, index) in alises"
|
|
:key="index"
|
|
class="flex-center bg-slate-50 border border-slate-200 py-2 px-3 w-max rounded-full"
|
|
>
|
|
<span class="text-xs text-black">{{ alise }}</span>
|
|
</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<ProfileSection title="اطلاعات شما">
|
|
<template #button>
|
|
<Button
|
|
v-if="isNotEqual"
|
|
:loading="updateAccountIsPending"
|
|
class="rounded-full w-[6.5rem]"
|
|
@click="handleSubmit(true)"
|
|
size="md"
|
|
>
|
|
<Icon
|
|
v-if="updateAccountIsPending"
|
|
name="svg-spinners:3-dots-bounce"
|
|
/>
|
|
<span v-else> ثبت تغییرات </span>
|
|
</Button>
|
|
</template>
|
|
<div
|
|
class="w-full grid grid-cols-1 lg:grid-cols-2 gap-x-3 gap-y-5"
|
|
>
|
|
<DataField
|
|
id="personal-data-name"
|
|
label="نام"
|
|
:error="formValidator$.first_name"
|
|
>
|
|
<Input
|
|
v-model="personalData.first_name!"
|
|
variant="outlined"
|
|
:error="formValidator$.first_name.$error"
|
|
/>
|
|
</DataField>
|
|
<DataField
|
|
id="personal-data-last-name"
|
|
label="نام خانوادگی"
|
|
:error="formValidator$.last_name"
|
|
>
|
|
<Input
|
|
v-model="personalData.last_name!"
|
|
variant="outlined"
|
|
:error="formValidator$.last_name.$error"
|
|
/>
|
|
</DataField>
|
|
<DataField
|
|
id="personal-data-gender"
|
|
label="جنسیت"
|
|
:error="formValidator$.gender"
|
|
>
|
|
<Select
|
|
v-model="personalData.gender!"
|
|
:options="['مرد', 'زن']"
|
|
variant="outlined"
|
|
:error="formValidator$.gender.$error"
|
|
/>
|
|
</DataField>
|
|
<DataField
|
|
id="personal-data-birth-date"
|
|
label="تاریخ تولد"
|
|
:error="formValidator$.birth_date"
|
|
>
|
|
<Datepicker
|
|
v-model="personalData.birth_date!"
|
|
:error="formValidator$.birth_date.$error"
|
|
/>
|
|
</DataField>
|
|
<DataField
|
|
id="personal-data-phone"
|
|
label="تلفن همراه"
|
|
:error="formValidator$.phone"
|
|
>
|
|
<Input
|
|
v-model="personalData.phone!"
|
|
variant="outlined"
|
|
:error="formValidator$.phone.$error"
|
|
/>
|
|
</DataField>
|
|
<DataField
|
|
id="personal-email"
|
|
label="حساب الکترونیکی"
|
|
:error="formValidator$.email"
|
|
>
|
|
<Input
|
|
v-model="personalData.email!"
|
|
variant="outlined"
|
|
:error="formValidator$.email.$error"
|
|
/>
|
|
</DataField>
|
|
</div>
|
|
</ProfileSection>
|
|
</div>
|
|
<!-- <div class="w-fill grid grid-cols-1 lg:grid-cols-2">
|
|
|
|
</div> -->
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|