306 lines
11 KiB
Vue
306 lines
11 KiB
Vue
<template>
|
|
<div class="flex min-h-full w-full items-center justify-center p-4">
|
|
<div class="flex w-full max-w-[512px] flex-col gap-10 text-center">
|
|
<!-- Loading state while verification is in progress -->
|
|
<div
|
|
v-if="isLoading"
|
|
class="flex flex-col items-center gap-4"
|
|
>
|
|
<v-progress-circular
|
|
color="primary"
|
|
indeterminate
|
|
size="64"
|
|
></v-progress-circular>
|
|
<h2 class="text-xl font-medium">{{ t('verifying') }}</h2>
|
|
</div>
|
|
|
|
<!-- Success state -->
|
|
<div
|
|
v-else-if="verificationSuccess"
|
|
class="flex flex-col items-center gap-6"
|
|
>
|
|
<v-icon
|
|
color="green"
|
|
icon="mdi-check-circle"
|
|
size="64"
|
|
></v-icon>
|
|
<h1 class="text-2xl font-bold text-green-600">{{ t('success.title') }}</h1>
|
|
<p>{{ t('success.message') }}</p>
|
|
<v-btn
|
|
color="primary"
|
|
@click="goToLogin"
|
|
>
|
|
{{ t('success.goToLogin') }}
|
|
</v-btn>
|
|
</div>
|
|
|
|
<!-- Error state -->
|
|
<div
|
|
v-else-if="showResendOnly"
|
|
class="flex flex-col items-center gap-6"
|
|
>
|
|
<v-icon
|
|
color="primary"
|
|
icon="mdi-email-sync"
|
|
size="64"
|
|
></v-icon>
|
|
<h1 class="text-2xl font-bold">{{ t('pending.title') }}</h1>
|
|
<p>{{ t('pending.message') }}</p>
|
|
|
|
<div class="mt-4 flex flex-col gap-4 w-full">
|
|
<v-form
|
|
class="w-full"
|
|
@submit.prevent="handleResendVerification"
|
|
>
|
|
<div class="flex flex-col gap-4">
|
|
<v-text-field
|
|
v-model="resendEmail"
|
|
:error-messages="resendEmailError"
|
|
:label="t('resend.emailLabel')"
|
|
required
|
|
type="email"
|
|
></v-text-field>
|
|
|
|
<v-btn
|
|
:loading="resendLoading"
|
|
block
|
|
color="secondary"
|
|
type="submit"
|
|
>
|
|
{{ t('resend.button') }}
|
|
</v-btn>
|
|
|
|
<!-- Resend success message -->
|
|
<div
|
|
v-if="resendSuccess"
|
|
class="mt-2 p-3 bg-green-50 border border-green-200 rounded text-green-700 text-sm"
|
|
>
|
|
{{ t('resend.success') }}
|
|
</div>
|
|
|
|
<!-- Resend error message -->
|
|
<div
|
|
v-if="resendError"
|
|
class="mt-2 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm"
|
|
>
|
|
{{ resendError }}
|
|
</div>
|
|
</div>
|
|
</v-form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Error state -->
|
|
<div
|
|
v-else
|
|
class="flex flex-col items-center gap-6"
|
|
>
|
|
<v-icon
|
|
color="error"
|
|
icon="mdi-alert-circle"
|
|
size="64"
|
|
></v-icon>
|
|
<h1 class="text-2xl font-bold text-red-600">{{ t('error.title') }}</h1>
|
|
<p>{{ errorMessage || t('error.defaultMessage') }}</p>
|
|
|
|
<div class="mt-4 flex flex-col gap-4 w-full">
|
|
<v-btn
|
|
color="primary"
|
|
@click="goToLogin"
|
|
>
|
|
{{ t('error.goToLogin') }}
|
|
</v-btn>
|
|
<v-divider class="my-4"></v-divider>
|
|
|
|
<h2 class="text-xl font-medium">{{ t('resend.title') }}</h2>
|
|
<v-form
|
|
class="w-full"
|
|
@submit.prevent="handleResendVerification"
|
|
>
|
|
<div class="flex flex-col gap-4">
|
|
<v-text-field
|
|
v-model="resendEmail"
|
|
:error-messages="resendEmailError"
|
|
:label="t('resend.emailLabel')"
|
|
required
|
|
type="email"
|
|
></v-text-field>
|
|
|
|
<v-btn
|
|
:loading="resendLoading"
|
|
block
|
|
color="secondary"
|
|
type="submit"
|
|
>
|
|
{{ t('resend.button') }}
|
|
</v-btn>
|
|
|
|
<div
|
|
v-if="resendSuccess"
|
|
class="mt-2 p-3 bg-green-50 border border-green-200 rounded text-green-700 text-sm"
|
|
>
|
|
{{ t('resend.success') }}
|
|
</div>
|
|
|
|
<div
|
|
v-if="resendError"
|
|
class="mt-2 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm"
|
|
>
|
|
{{ resendError }}
|
|
</div>
|
|
</div>
|
|
</v-form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref } from 'vue';
|
|
import { useClient } from '@/plugins/api.js';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
const { t } = useI18n();
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const clientApi = useClient();
|
|
|
|
// Verification state
|
|
const isLoading = ref(true);
|
|
const verificationSuccess = ref(false);
|
|
const errorMessage = ref('');
|
|
const showResendOnly = ref(false);
|
|
|
|
// Resend verification state
|
|
const resendEmail = ref('');
|
|
const resendEmailError = ref('');
|
|
const resendLoading = ref(false);
|
|
const resendSuccess = ref(false);
|
|
const resendError = ref('');
|
|
|
|
onMounted(async () => {
|
|
const userId = route.query.userId;
|
|
const token = route.query.token;
|
|
|
|
// Populate resend email field if it was in the URL
|
|
if (route.query.email) {
|
|
resendEmail.value = route.query.email;
|
|
}
|
|
|
|
// Check if we have the required parameters
|
|
if (!userId || !token) {
|
|
isLoading.value = false;
|
|
if (route.query.email || route.query.pending) {
|
|
showResendOnly.value = true;
|
|
} else {
|
|
errorMessage.value = t('error.missingParams');
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Call the verification endpoint
|
|
await clientApi.get(`/api/users/verify-email?userId=${userId}&token=${token}`);
|
|
verificationSuccess.value = true;
|
|
} catch (error) {
|
|
console.error('Email verification failed:', error);
|
|
errorMessage.value = error.response?.data?.message || t('error.defaultMessage');
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
});
|
|
|
|
async function handleResendVerification() {
|
|
// Reset states
|
|
resendEmailError.value = '';
|
|
resendSuccess.value = false;
|
|
resendError.value = '';
|
|
|
|
// Simple email validation
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(resendEmail.value)) {
|
|
resendEmailError.value = t('resend.invalidEmail');
|
|
return;
|
|
}
|
|
|
|
resendLoading.value = true;
|
|
|
|
try {
|
|
await clientApi.post('/api/users/resend-verification', {
|
|
email: resendEmail.value.trim(),
|
|
});
|
|
resendSuccess.value = true;
|
|
} catch (error) {
|
|
console.error('Resend verification failed:', error);
|
|
resendError.value = error.response?.data?.message || t('resend.error');
|
|
} finally {
|
|
resendLoading.value = false;
|
|
}
|
|
}
|
|
|
|
function goToLogin() {
|
|
router.push('/login');
|
|
}
|
|
</script>
|
|
|
|
<i18n>
|
|
{
|
|
"en": {
|
|
"verifying": "Verifying your email...",
|
|
"success": {
|
|
"title": "Email Verified Successfully!",
|
|
"message": "Your email has been verified. You can now log in to your account.",
|
|
"goToLogin": "Go to Login"
|
|
},
|
|
"error": {
|
|
"title": "Verification Failed",
|
|
"defaultMessage": "We couldn't verify your email. The link may be invalid or expired.",
|
|
"missingParams": "Missing required verification parameters.",
|
|
"goToLogin": "Go to Login"
|
|
},
|
|
"pending": {
|
|
"title": "Check your email",
|
|
"message": "We sent a verification link to your inbox. You can request a new link if it doesn't arrive."
|
|
},
|
|
"resend": {
|
|
"title": "Resend Verification Email",
|
|
"description": "Enter your account email and we'll send a new verification link.",
|
|
"emailLabel": "Email",
|
|
"button": "Resend Verification Email",
|
|
"success": "Verification email sent successfully. Please check your inbox.",
|
|
"error": "Failed to send verification email. Please try again.",
|
|
"invalidEmail": "Please enter a valid email address."
|
|
}
|
|
},
|
|
"fr": {
|
|
"verifying": "Vérification de votre email...",
|
|
"success": {
|
|
"title": "Email vérifié avec succès !",
|
|
"message": "Votre email a été vérifié. Vous pouvez maintenant vous connecter à votre compte.",
|
|
"goToLogin": "Aller à la connexion"
|
|
},
|
|
"error": {
|
|
"title": "Échec de la vérification",
|
|
"defaultMessage": "Nous n'avons pas pu vérifier votre email. Le lien peut être invalide ou expiré.",
|
|
"missingParams": "Paramètres de vérification requis manquants.",
|
|
"goToLogin": "Aller à la connexion"
|
|
},
|
|
"pending": {
|
|
"title": "Vérifiez votre email",
|
|
"message": "Nous avons envoyé un lien de vérification dans votre boîte de réception. Vous pouvez demander un nouveau lien s'il n'arrive pas."
|
|
},
|
|
"resend": {
|
|
"title": "Renvoyer l'email de vérification",
|
|
"description": "Entrez l'email de votre compte et nous enverrons un nouveau lien de vérification.",
|
|
"emailLabel": "Email",
|
|
"button": "Renvoyer l'email de vérification",
|
|
"success": "Email de vérification envoyé avec succès. Veuillez vérifier votre boîte de réception.",
|
|
"error": "Échec de l'envoi de l'email de vérification. Veuillez réessayer.",
|
|
"invalidEmail": "Veuillez entrer une adresse email valide."
|
|
}
|
|
}
|
|
}
|
|
</i18n>
|