This commit is contained in:
marzban-dev
2025-03-06 23:59:18 +03:30
parent 0ac90ece3c
commit 6bc34ea407
+128 -89
View File
@@ -1,4 +1,5 @@
<script lang="ts" setup>
// import
import { helpers, required } from "@vuelidate/validators";
@@ -20,11 +21,13 @@ type LoginInfo = {
// meta
definePageMeta({
middleware: ["check-is-not-logged-in"],
middleware: ["check-is-not-logged-in"]
});
// state
const { $gsap: gsap } = useNuxtApp();
const { addToast } = useToast();
const { updateToken, updateRefreshToken } = useAuth();
@@ -41,13 +44,13 @@ const formRules = computed(() => {
phoneValidator: helpers.withMessage(
"شماره تلفن وارد شده معتبر نمی باشد",
helpers.regex(/^[1-9][0-9]{9}$/)
),
},
)
}
};
});
const loginInfo = ref<LoginInfo>({
phone: "",
phone: ""
});
const formValidator$ = useVuelidate(formRules, loginInfo);
@@ -56,16 +59,16 @@ const {
timer: otpBlockerTimePassed,
start: startOtpBlocker,
reset: resetOtpBlocker,
isPending: isResendOtpBlocked,
isPending: isResendOtpBlocked
} = useTimer({
duration: 5000,
duration: 5000
});
const { mutateAsync: sendOtp, isPending: sendOtpIsPending } = useOtp();
const {
mutateAsync: signIn,
isPending: signInIsPending,
status: signInStatus,
status: signInStatus
} = useSignIn();
// computed
@@ -74,14 +77,14 @@ const sendOtpHandler = async () => {
if (!sendOtpIsPending.value) {
try {
await sendOtp({
phone: `0${loginInfo.value.phone}`,
phone: `0${loginInfo.value.phone}`
});
addToast({
message: "کد برای شما ارسال شد",
options: {
status: "success",
},
status: "success"
}
});
showOtp.value = true;
@@ -89,8 +92,8 @@ const sendOtpHandler = async () => {
addToast({
message: "مشکلی پیش آمده",
options: {
status: "error",
},
status: "error"
}
});
}
}
@@ -107,7 +110,7 @@ const handleLogin = async () => {
try {
const response = await signIn({
otp: otpCode.value.join(""),
phone: `0${loginInfo.value.phone}`,
phone: `0${loginInfo.value.phone}`
});
updateToken(response.access);
@@ -118,8 +121,8 @@ const handleLogin = async () => {
addToast({
message: "با موفقیت وارد شدید",
options: {
status: "success",
},
status: "success"
}
});
navigateTo("/");
@@ -146,93 +149,129 @@ const resetForm = () => {
otpCode.value = [];
showOtp.value = false;
};
// const onMouseMove = (e: MouseEvent) => {
// const heylmzEyesElement = document.querySelector("#heylmz-eyes") as HTMLDivElement;
// const boundry = heylmzEyesElement.getBoundingClientRect();
//
// console.log(e.clientX, heylmzEyesElement.clientWidth, boundry.left, e.clientX - heylmzEyesElement.clientWidth);
//
// const moveX = e.clientX - heylmzEyesElement.clientWidth + 60;
// const moveY = e.clientY - heylmzEyesElement.clientHeight - 155;
//
// gsap.to("#heylmz-eyes", {
// x: moveX,
// y: moveY
// });
// };
</script>
<template>
<div
class="container min-h-[700px] flex flex-col items-center justify-center"
>
<h1 class="typo-hero-2">فرم ورود</h1>
<form @submit.prevent class="max-w-[500px] w-full mt-12">
<div v-if="!showOtp" class="flex items-center gap-2 w-full">
<Input
data-testid="phone-input"
class="w-full"
v-model="loginInfo.phone"
placeholder="9380123456"
dir="ltr"
:error="formValidator$.phone.$error"
>
<template #startItem>
<span class="text-slate-500"> +98 </span>
</template>
</Input>
<div class="flex items-center gap-1">
<Icon
class="translate-y-[-1px]"
name="twemoji:flag-iran"
size="24"
/>
</div>
</div>
<div class="flex h-svh items-center relative">
<div
class="bg-[url(/img/pattern-1.png)] -z-10 size-full absolute opacity-70"
:style="{
backgroundSize: 150,
mask: 'linear-gradient(to bottom, black 0%, rgba(0,0,0,0.3) 80%)'
}"
/>
<div class="flex items-center justify-center flex-col size-full">
<OtpInput
v-else
v-model="otpCode"
:status="
signInStatus === 'success'
? 'success'
: signInStatus === 'error'
? 'error'
: 'idle'
"
:disabled="signInIsPending || sendOtpIsPending"
:autofocus="true"
@complete="handleLogin"
<img
id="heylmz-eyes"
class="aspect-square w-[300px] translate-y-[100px]"
src="/img/heymlz-seat.gif"
alt=""
/>
<Button
data-testid="send-otp-code-button"
v-if="!showOtp"
class="rounded-full w-full mt-4"
type="submit"
@click="handleLogin"
:loading="sendOtpIsPending"
:disabled="sendOtpIsPending"
<div
class="max-w-[600px] w-full p-6 h-[400px] flex flex-col items-center bg-white border shadow-black/10 justify-center border-slate-300 rounded-xl"
>
ارسال کد
</Button>
<h1 class="typo-hero-2 mt-8">فرم ورود</h1>
<div v-else class="flex items-center w-full gap-4 mt-4">
<Button
class="rounded-full w-full mt-4"
type="button"
variant="secondary"
@click="resetForm"
:disabled="signInIsPending || sendOtpIsPending"
>
تغییر شماره
</Button>
<Button
class="rounded-full w-full mt-4"
type="submit"
@click="resendOtp"
:loading="signInIsPending || sendOtpIsPending"
:disabled="
<form @submit.prevent class="max-w-[500px] w-full mt-12">
<div v-if="!showOtp" class="flex items-center gap-2 w-full">
<Input
data-testid="phone-input"
class="w-full"
v-model="loginInfo.phone"
placeholder="9380123456"
dir="ltr"
:error="formValidator$.phone.$error"
>
<template #startItem>
<span class="text-slate-500"> +98 </span>
</template>
</Input>
<div class="flex items-center gap-1">
<Icon
class="translate-y-[-1px]"
name="twemoji:flag-iran"
size="24"
/>
</div>
</div>
<OtpInput
v-else
v-model="otpCode"
:status="
signInStatus === 'success'
? 'success'
: signInStatus === 'error'
? 'error'
: 'idle'
"
:disabled="signInIsPending || sendOtpIsPending"
:autofocus="true"
@complete="handleLogin"
/>
<Button
data-testid="send-otp-code-button"
v-if="!showOtp"
class="rounded-full w-full mt-4"
type="submit"
@click="handleLogin"
:loading="sendOtpIsPending"
:disabled="sendOtpIsPending"
>
ارسال کد
</Button>
<div v-else class="flex items-center w-full gap-4 mt-4">
<Button
class="rounded-full w-full mt-4"
type="button"
variant="secondary"
@click="resetForm"
:disabled="signInIsPending || sendOtpIsPending"
>
تغییر شماره
</Button>
<Button
class="rounded-full w-full mt-4"
type="submit"
@click="resendOtp"
:loading="signInIsPending || sendOtpIsPending"
:disabled="
signInIsPending ||
isResendOtpBlocked ||
sendOtpIsPending
"
>
ارسال مجدد کد
{{ isResendOtpBlocked ? otpBlockerTimePassed : "" }}
</Button>
</div>
>
ارسال مجدد کد
{{ isResendOtpBlocked ? otpBlockerTimePassed : "" }}
</Button>
</div>
<div class="flex items-center gap-2 justify-center mt-6">
<span> بازگشت به فروشگاه </span>
<Icon name="ci:left-rotation" size="24" />
<NuxtLink to="/" class="flex items-center gap-2 justify-center mt-6">
<span> بازگشت به فروشگاه </span>
<Icon name="ci:left-rotation" size="24" />
</NuxtLink>
</form>
</div>
</form>
</div>
</div>
</template>