added validation for address modal

This commit is contained in:
Mamalizz
2025-04-18 19:49:42 +03:30
parent 90c3f6dbec
commit 56e41fa169
@@ -5,6 +5,8 @@ import useCreateOrUpdateAddress from "~/composables/api/account/useCreateOrUpdat
import useGetAccount from "~/composables/api/account/useGetAccount"; import useGetAccount from "~/composables/api/account/useGetAccount";
import { QUERY_KEYS } from "~/constants"; import { QUERY_KEYS } from "~/constants";
import { useToast } from "~/composables/global/useToast"; import { useToast } from "~/composables/global/useToast";
import useVuelidate from "@vuelidate/core";
import { helpers, required, minLength } from "@vuelidate/validators";
// types // types
@@ -42,6 +44,35 @@ const addressData = ref({
is_main: address.value?.is_main ?? false, is_main: address.value?.is_main ?? false,
}); });
// computed
const formRules = computed(() => {
return {
province: {
required: helpers.withMessage("فیلد استان سکونت الزامی می باشد", required),
minLength: helpers.withMessage("فیلد استان سکونت حداقل 2 کرکتر می باشد", minLength(2)),
},
city: {
required: helpers.withMessage("فیلد شهر سکونت الزامی می باشد", required),
minLength: helpers.withMessage("فیلد شهر سکونت حداقل 2 کرکتر می باشد", minLength(2)),
},
postal_code: {
required: helpers.withMessage("فیلد کد پستی الزامی می باشد", required),
minLength: helpers.withMessage("فیلد کد پستی حداقل 10 کرکتر می باشد", minLength(10)),
},
address: {
required: helpers.withMessage("فیلد آدرس کامل الزامی می باشد", required),
minLength: helpers.withMessage("فیلد آدرس کامل حداقل 2 کرکتر می باشد", minLength(2)),
},
phone: {
required: helpers.withMessage("فیلد تلفن همراه الزامی می باشد", required),
minLength: helpers.withMessage("فیلد تلفن همراه حداقل 10 کرکتر می باشد", minLength(10)),
},
};
});
const formValidator$ = useVuelidate(formRules, addressData);
// queries // queries
const { data: account } = useGetAccount(); const { data: account } = useGetAccount();
@@ -64,35 +95,42 @@ const closeModal = () => {
is_main: false, is_main: false,
}; };
} }
formValidator$.value.$reset();
isShow.value = false; isShow.value = false;
}; };
const addNew = () => { const handleSubmit = async () => {
createOrUpdateAddress( await formValidator$.value.$validate();
{ ...addressData.value }, if (!formValidator$.value.$errors.length) {
{ createOrUpdateAddress(
onSuccess: () => { { ...addressData.value },
queryClient.invalidateQueries({ {
queryKey: [QUERY_KEYS.addresses], onSuccess: () => {
}); queryClient.invalidateQueries({
closeModal(); queryKey: [QUERY_KEYS.addresses],
addToast({ });
message: isEditing.value ? "آدرس با موفقیت ویرایش شد" : "آدرس با موفقیت اضافه شد", queryClient.invalidateQueries({
options: { queryKey: [QUERY_KEYS.cart],
status: "success", });
}, closeModal();
}); addToast({
}, message: isEditing.value ? "آدرس با موفقیت ویرایش شد" : "آدرس با موفقیت اضافه شد",
onError: () => { options: {
addToast({ status: "success",
message: isEditing.value ? "آدرس با موفقیت ویرایش شد" : "مشکلی در افزودن آدرس رخ داد", },
options: { });
status: "error", },
}, onError: () => {
}); addToast({
}, message: isEditing.value ? "آدرس با موفقیت ویرایش شد" : "مشکلی در افزودن آدرس رخ داد",
} options: {
); status: "error",
},
});
},
}
);
}
}; };
watch( watch(
@@ -122,9 +160,9 @@ watch(
<Button <Button
:end-icon="!!address ? 'bi:pen' : 'ci:plus'" :end-icon="!!address ? 'bi:pen' : 'ci:plus'"
size="md" size="md"
class="rounded-full" class="rounded-full transition-all"
:variant="!!address ? 'ghost' : 'solid'" :variant="!!address ? 'ghost' : 'solid'"
:class="!!address ? '!bg-transparent !underline' : ''" :class="!!address ? '!bg-transparent !underline underline-offset-4' : ''"
> >
<span class="whitespace-pre max-lg:text-xs"> <span class="whitespace-pre max-lg:text-xs">
{{ !!address ? "ویرایش" : "افزودن آدرس" }} {{ !!address ? "ویرایش" : "افزودن آدرس" }}
@@ -138,115 +176,111 @@ watch(
dir="rtl" dir="rtl"
> >
<div class="grid w-full grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3"> <div class="grid w-full grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
<div class="flex flex-col gap-2"> <DataField
<label id="name"
for="name" label="نام پیش فرض"
class="text-xs font-semibold lg:text-sm text-gray-900" >
>نام پیش فرض <span class="text-sm text-red-500">*</span></label
>
<Input <Input
id="name" id="name"
type="text" type="text"
placeholder="اینجا وارد کنید ..." placeholder="اینجا وارد کنید ..."
v-model="addressData.name!" v-model="addressData.name!"
/> />
</div> </DataField>
<div class="flex flex-col gap-2">
<label
for="province"
class="text-xs font-semibold lg:text-sm text-gray-900"
>
آدرس شما؟
<span class="text-sm text-red-500"> * </span>
</label>
<DataField
id="for_me"
label="آدرس شما؟"
:required="true"
>
<Select <Select
id="for_me"
:options="['بله', 'خیر']" :options="['بله', 'خیر']"
placeholder="انتخاب کنید" placeholder="انتخاب کنید"
v-model="addressData.for_me as string" v-model="addressData.for_me as string"
/> />
</div> </DataField>
<div class="flex flex-col gap-2">
<label
for="phone"
class="text-xs font-semibold lg:text-sm text-gray-900"
>شماره تلفن <span class="text-sm text-red-500">*</span></label
>
<DataField
id="phone"
label="تلفن همراه"
:required="true"
:error="formValidator$.phone"
>
<Input <Input
id="phone" id="phone"
type="text" type="text"
placeholder="اینجا وارد کنید ..." placeholder="اینجا وارد کنید ..."
:error="formValidator$.phone.$error"
v-model="addressData.phone!" v-model="addressData.phone!"
/> />
</div> </DataField>
<div class="flex flex-col gap-2">
<label
for="province"
class="text-xs font-semibold lg:text-sm text-gray-900"
>استان
<span class="text-sm text-red-500">*</span>
</label>
<DataField
id="province"
label="استان"
:required="true"
:error="formValidator$.province"
>
<Input <Input
id="province" id="province"
type="text" type="text"
placeholder="اینجا وارد کنید ..." placeholder="اینجا وارد کنید ..."
:error="formValidator$.province.$error"
v-model="addressData.province!" v-model="addressData.province!"
/> />
</div> </DataField>
<div class="flex flex-col gap-2"> <DataField
<label id="city"
for="city" label="شهر"
class="text-xs font-semibold lg:text-sm text-gray-900" :required="true"
>شهر <span class="text-sm text-red-500">*</span></label :error="formValidator$.city"
> >
<Input <Input
id="city" id="city"
type="text" type="text"
placeholder="اینجا وارد کنید ..." placeholder="اینجا وارد کنید ..."
:error="formValidator$.city.$error"
v-model="addressData.city!" v-model="addressData.city!"
/> />
</div> </DataField>
<div class="flex flex-col gap-2"> <DataField
<label id="postal_code"
for="post" label="کد پستی"
class="text-xs font-semibold lg:text-sm text-gray-900" :required="true"
>کد پستی <span class="text-sm text-red-500">*</span></label :error="formValidator$.postal_code"
> >
<Input <Input
id="post" id="postal_code"
type="text" type="text"
placeholder="اینجا وارد کنید ..." placeholder="اینجا وارد کنید ..."
:error="formValidator$.postal_code.$error"
v-model="addressData.postal_code!" v-model="addressData.postal_code!"
/> />
</div> </DataField>
</div> </div>
<div class="flex flex-col w-full gap-2"> <DataField
<label id="address"
for="address" label="آدرس کامل"
class="text-xs font-semibold lg:text-sm text-gray-900" :required="true"
>آدرس کامل <span class="text-sm text-red-500">*</span></label :error="formValidator$.address"
> >
<textarea <Textarea
id="address" id="address"
placeholder="آدرس خود را بنویسید" placeholder="آدرس خود را بنویسید"
v-model="addressData.address" v-model="addressData.address"
class="flex items-center field-sizing-content resize-none bg-slate-50 border-slate-200 hover:border-black focus:border-black max-h-[10rem] text-black justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-1.5 lg:py-3.5 selection:bg-slate-100 rounded-md lg:rounded-100 outline-none flex-1 text-xs lg:!text-sm placeholder-slate-400 placeholder:text-xs lg:placeholder:text-sm placeholder:font-normal" :error="formValidator$.address.$error"
></textarea> class="flex items-center field-sizing-content resize-none bg-slate-50 border-slate-200 hover:border-black focus:border-black max-h-[10rem] text-black justify-between cursor-text transition-all border-[1.5px] gap-3 typo-label-md px-4 py-2.5 lg:py-3 leading-[175%] selection:bg-slate-100 rounded-md lg:rounded-100 outline-none max-lg:h-[5rem] lg:flex-1 text-xs lg:!text-sm placeholder-slate-400 placeholder:text-xs lg:placeholder:text-sm placeholder:font-normal"
</div> ></Textarea>
</DataField>
<div class="flex items-center justify-between w-full gap-2"> <div class="flex items-center justify-between w-full gap-2">
<label <label
for="is_main" for="is_main"
class="text-xs font-semibold lg:text-sm text-gray-900" class="text-xs font-medium lg:text-sm text-gray-900"
> >
به عنوان آدرس پیش فرض ثبت شود؟ به عنوان آدرس پیش فرض ثبت شود؟
</label> </label>
@@ -260,7 +294,7 @@ watch(
<div class="py-6 border-t border-slate-200 flex gap-3"> <div class="py-6 border-t border-slate-200 flex gap-3">
<Button <Button
:disabled="createAddressIsPending" :disabled="createAddressIsPending"
@click="addNew" @click="handleSubmit"
class="rounded-full px-10" class="rounded-full px-10"
size="md" size="md"
> >