Files
webMontime/src/views/auth/VerifyOtpView.vue
T

117 lines
3.4 KiB
Vue
Raw Normal View History

2026-05-18 20:18:28 +03:30
<template>
<AuthLayout title="کد تأیید" :subtitle="`کد ارسال‌شده به ${mobile}`">
<p
v-if="devCode"
class="mb-4 rounded-xl border border-brand-500/40 bg-brand-500/10 px-4 py-3 text-sm text-brand-700 dark:text-brand-500"
>
حالت توسعه — کد: {{ devCode }}
</p>
<p
v-if="error"
class="mb-4 rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-600 dark:text-red-400"
>
{{ error }}
</p>
<form class="space-y-4" @submit.prevent="onSubmit">
<AppInput
id="code"
v-model="code"
label="کد ۶ رقمی"
type="text"
inputmode="numeric"
maxlength="8"
placeholder="123456"
autocomplete="one-time-code"
ltr
required
/>
<AppButton type="submit" :loading="loading">ورود</AppButton>
</form>
<p v-if="secondsLeft > 0" class="mt-4 text-center text-sm text-muted">
ارسال مجدد تا {{ secondsLeft }} ثانیه
</p>
2026-05-18 21:30:37 +03:30
<AppButton v-else variant="ghost" class="mt-2" :loading="resendLoading" @click="resend">
2026-05-18 20:18:28 +03:30
ارسال مجدد کد
</AppButton>
2026-05-18 21:30:37 +03:30
<AppButton variant="ghost" class="mt-2" @click="router.push({ name: 'login' })">
2026-05-18 20:18:28 +03:30
تغییر شماره موبایل
</AppButton>
</AuthLayout>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { requestOtp, verifyOtp } from '@/api/auth';
import { ApiError } from '@/api/client';
import AppButton from '@/components/ui/AppButton.vue';
import AppInput from '@/components/ui/AppInput.vue';
import AuthLayout from '@/layouts/AuthLayout.vue';
import { useAuthStore } from '@/stores/auth';
const route = useRoute();
const router = useRouter();
const auth = useAuthStore();
const mobile = computed(() => String(route.query.mobile ?? ''));
const devCode = computed(() => route.query.devCode as string | undefined);
const code = ref(devCode.value ?? '');
const loading = ref(false);
const resendLoading = ref(false);
const error = ref('');
const secondsLeft = ref(Number(route.query.expires) || 120);
let timer: ReturnType<typeof setInterval> | null = null;
onMounted(() => {
if (!mobile.value) {
2026-05-18 21:30:37 +03:30
router.replace({ name: 'login' });
2026-05-18 20:18:28 +03:30
return;
}
timer = setInterval(() => {
if (secondsLeft.value > 0) secondsLeft.value -= 1;
}, 1000);
});
onUnmounted(() => {
if (timer) clearInterval(timer);
});
async function onSubmit() {
error.value = '';
loading.value = true;
try {
const res = await verifyOtp(mobile.value, code.value.trim());
auth.setSession(res.accessToken, res.user);
await router.replace({ name: 'app-home' });
} catch (e) {
error.value =
e instanceof ApiError ? e.message : 'کد نامعتبر است. دوباره تلاش کنید.';
} finally {
loading.value = false;
}
}
async function resend() {
error.value = '';
resendLoading.value = true;
try {
const res = await requestOtp(mobile.value);
secondsLeft.value = res.expiresInSeconds;
if (res.otpCode) {
await router.replace({
query: { ...route.query, devCode: res.otpCode, expires: String(res.expiresInSeconds) },
});
}
} catch (e) {
error.value =
e instanceof ApiError ? e.message : 'ارسال مجدد ناموفق بود.';
} finally {
resendLoading.value = false;
}
}
</script>