157 lines
4.6 KiB
Vue
157 lines
4.6 KiB
Vue
<template>
|
|
<form class="otp-code">
|
|
<h1>{{ $t("enterReceivedCode") }}</h1>
|
|
<ul ref="list">
|
|
<li v-for="(_, i) in 6" :key="i">
|
|
<InputNumber v-model="code[i]" @input="events.input($event, i)" @keyup="events.keyup($event, i)"
|
|
@focus="events.focus($event, i)" :disabled="inputs.length < 1" />
|
|
</li>
|
|
</ul>
|
|
<span :class="{ invisible: seconds < 1 }">
|
|
{{ $t("moreSecondReceiveCode", { seconds }) }}
|
|
</span>
|
|
<Button v-bind="btns.next.props" @click="events.next()" />
|
|
<div v-show="seconds < 1">
|
|
<p>{{ $t("notReceivedCode") }}</p>
|
|
<Button v-bind="btns.try.props" @click="events.try()" />
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<script setup>
|
|
import init from "../../initialize/auth/otp-code.js";
|
|
const { btns } = init();
|
|
|
|
const { t, toast } = inject('service')
|
|
|
|
let inputs = reactive([]);
|
|
const list = ref();
|
|
const code = ref([]);
|
|
const seconds = ref(0);
|
|
const form = computed(() => code.value.join(""));
|
|
|
|
const store = useOtpCodeStore();
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
|
|
const events = reactive({
|
|
next: async () => {
|
|
btns.next.props.loading = true
|
|
if (form.value.length == 6) {
|
|
const { status, error } = await store.check(form.value);
|
|
if (status.value == "success")
|
|
router.push({ query: { step: 2 } });
|
|
else {
|
|
code.value = []
|
|
let detail = t("error-500");
|
|
switch (error.value.statusCode) {
|
|
case 400:
|
|
detail = t("incorrect-code");
|
|
break;
|
|
case 429:
|
|
detail = t("error-429");
|
|
break;
|
|
}
|
|
toast.add({ severity: "error", summary: t("error"), detail, life: 3000 });
|
|
}
|
|
}
|
|
btns.next.props.loading = false
|
|
},
|
|
try: async () => {
|
|
btns.try.props.loading = true
|
|
|
|
const form = { number: store.number };
|
|
let result = {}
|
|
if (route.path.includes('register'))
|
|
result = await store.withoutToken(form)
|
|
else if (route.path.includes('restore'))
|
|
result = await store.forgotPassword(form
|
|
)
|
|
const { status, error } = result;
|
|
if (status.value == "success")
|
|
seconds.value = 60;
|
|
else
|
|
toast.add({ severity: "error", summary: t("error"), detail: error.value.message, life: 3000 });
|
|
btns.try.props.loading = false
|
|
|
|
},
|
|
input: (e, i) => {
|
|
if (e.value != null) inputs[i++].value = e.originalEvent.key;
|
|
if (i < 6) inputs[i].focus();
|
|
else {
|
|
inputs[5].blur();
|
|
events.next();
|
|
}
|
|
},
|
|
keyup: (e, i) => {
|
|
if (e.code == "Backspace" && i > 0) {
|
|
code.value[i - 1] = null;
|
|
inputs[i - 1].focus();
|
|
}
|
|
},
|
|
focus: (e, i) => {
|
|
const length = code.value.filter((c) => typeof c == "number").length;
|
|
if (length < i) inputs[length].focus();
|
|
},
|
|
});
|
|
|
|
onMounted(() => {
|
|
inputs.push(...list.value.querySelectorAll("input"));
|
|
setTimeout(() => inputs[0].focus(), 1);
|
|
seconds.value = 60;
|
|
setInterval(() => {
|
|
if (seconds.value > 0) seconds.value--;
|
|
}, 1000);
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.auth .otp-code {
|
|
@apply flex flex-col h-max gap-3 lg:gap-4 items-center mx-auto;
|
|
|
|
&>h1 {
|
|
@apply w-full text-[#CCCCCC] font-black font-vazir text-right leading-[3rem] whitespace-nowrap;
|
|
@apply text-xl lg:text-3xl lg:text-center;
|
|
}
|
|
|
|
&>ul {
|
|
@apply flex gap-2.5 mt-3 lg:mt-8 ltr;
|
|
|
|
li {
|
|
input {
|
|
@apply w-12 lg:w-10 h-10 p-0 rounded-lg border border-stone-300 text-center;
|
|
@apply focus:text-primary-600 text-stone-300 text-xl font-medium font-vazir leading-[1.9rem];
|
|
}
|
|
}
|
|
}
|
|
|
|
&>span {
|
|
@apply text-[#999999] text-xs lg:text-sm font-medium font-vazir mt-1 lg:mt-0;
|
|
}
|
|
|
|
&>button {
|
|
@apply w-full h-11 mt-3 lg:h-14 lg:mt-6 #{!important};
|
|
|
|
.p-button-label {
|
|
@apply text-sm font-medium font-iran-sans;
|
|
}
|
|
}
|
|
|
|
&>div {
|
|
@apply flex items-center lg:mt-2 whitespace-nowrap;
|
|
|
|
p {
|
|
@apply text-[#999999] text-xs lg:text-sm font-medium font-vazir;
|
|
}
|
|
|
|
button {
|
|
@apply w-full px-1 h-11 lg:h-14 #{!important};
|
|
|
|
.p-button-label {
|
|
@apply text-sm font-medium font-iran-sans;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|