238 lines
8.7 KiB
Vue
238 lines
8.7 KiB
Vue
<template>
|
|
<div class="flex min-h-full w-full items-center justify-center p-20">
|
|
<!-- Show verification message on success -->
|
|
<div
|
|
v-if="registrationSuccess"
|
|
class="card justify-items-center"
|
|
>
|
|
<img
|
|
:alt="t('alt')"
|
|
src="/images/hutopymedia/loginpage/hutopylogin.svg"
|
|
/>
|
|
<div class="flex flex-col gap-10 text-center">
|
|
<h1 class="login-text text-2xl font-bold text-green-600">
|
|
{{ t('success.title') }}
|
|
</h1>
|
|
<div class="text-hOnSurface">
|
|
<p>{{ t('success.message') }}</p>
|
|
<p class="mt-2 font-medium">{{ userEmail }}</p>
|
|
</div>
|
|
<div class="mt-4 flex flex-col gap-2">
|
|
<router-link
|
|
class="text-blue-500 hover:underline"
|
|
to="/login"
|
|
>
|
|
{{ t('success.backToLogin') }}
|
|
</router-link>
|
|
<router-link
|
|
:to="{ path: '/verify-email', query: { email: userEmail } }"
|
|
class="text-blue-500 hover:underline"
|
|
>
|
|
{{ t('success.resendVerification') }}
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Show registration form -->
|
|
<div
|
|
v-else
|
|
class="card justify-items-center"
|
|
>
|
|
<img
|
|
:alt="t('alt')"
|
|
src="/images/hutopymedia/loginpage/hutopylogin.svg"
|
|
/>
|
|
<div class="flex flex-col gap-10">
|
|
<h1 class="login-text text-center text-2xl font-bold">
|
|
{{ t('title') }}
|
|
</h1>
|
|
|
|
<v-form @submit.prevent="handleRegister">
|
|
<div class="flex flex-col gap-4">
|
|
<v-text-field
|
|
v-model="name"
|
|
:label="t('name')"
|
|
required
|
|
></v-text-field>
|
|
|
|
<v-text-field
|
|
v-model="email"
|
|
:label="t('email')"
|
|
required
|
|
type="email"
|
|
></v-text-field>
|
|
|
|
<v-text-field
|
|
v-model="password"
|
|
:hint="t('passwordRequirements')"
|
|
:label="t('password')"
|
|
:type="showPassword ? 'text' : 'password'"
|
|
required
|
|
>
|
|
<template v-slot:append-inner>
|
|
<v-icon
|
|
:icon="showPassword ? mdiEyeOff : mdiEye"
|
|
class="visibility-toggle"
|
|
size="small"
|
|
@click="showPassword = !showPassword"
|
|
/>
|
|
</template>
|
|
</v-text-field>
|
|
|
|
<v-text-field
|
|
v-model="confirmPassword"
|
|
:label="t('confirmPassword')"
|
|
:type="showConfirmPassword ? 'text' : 'password'"
|
|
required
|
|
>
|
|
<template v-slot:append-inner>
|
|
<v-icon
|
|
:icon="showConfirmPassword ? mdiEyeOff : mdiEye"
|
|
class="visibility-toggle"
|
|
size="small"
|
|
@click="showConfirmPassword = !showConfirmPassword"
|
|
/>
|
|
</template>
|
|
</v-text-field>
|
|
|
|
<v-btn
|
|
:loading="isLoading"
|
|
block
|
|
color="primary"
|
|
type="submit"
|
|
>
|
|
{{ t('register') }}
|
|
</v-btn>
|
|
|
|
<!-- Error message displayed as block text below submit button -->
|
|
<div
|
|
v-if="errorMessage"
|
|
class="mt-2 p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm"
|
|
>
|
|
{{ errorMessage }}
|
|
</div>
|
|
|
|
<div class="mt-4 text-center">
|
|
{{ t('alreadyHaveAccount') }}
|
|
<router-link
|
|
class="text-blue-500"
|
|
to="/login"
|
|
>
|
|
{{ t('signIn') }}
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</v-form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
import { useClient } from '@/plugins/api.js';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { mdiEye, mdiEyeOff } from '@mdi/js';
|
|
|
|
const { t } = useI18n();
|
|
const clientApi = useClient();
|
|
|
|
const name = ref('');
|
|
const email = ref('');
|
|
const password = ref('');
|
|
const confirmPassword = ref('');
|
|
const isLoading = ref(false);
|
|
const errorMessage = ref('');
|
|
const showPassword = ref(false);
|
|
const showConfirmPassword = ref(false);
|
|
const registrationSuccess = ref(false);
|
|
const userEmail = ref('');
|
|
|
|
async function handleRegister() {
|
|
if (password.value !== confirmPassword.value) {
|
|
errorMessage.value = t('passwordsDoNotMatch');
|
|
return;
|
|
}
|
|
|
|
isLoading.value = true;
|
|
errorMessage.value = '';
|
|
|
|
try {
|
|
await clientApi.post('api/users/register', {
|
|
name: name.value,
|
|
email: email.value.trim(),
|
|
password: password.value,
|
|
});
|
|
|
|
// On success, show verification message
|
|
userEmail.value = email.value.trim();
|
|
registrationSuccess.value = true;
|
|
} catch (error) {
|
|
console.error('Registration failed:', error);
|
|
errorMessage.value = error.response?.data?.message || t('registrationFailed');
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.visibility-toggle {
|
|
@apply cursor-pointer;
|
|
@apply transition-opacity duration-300;
|
|
@apply opacity-60 hover:opacity-100;
|
|
@apply z-10;
|
|
}
|
|
|
|
/* Override Vuetify's default padding to accommodate our icon */
|
|
:deep(.v-field__append-inner) {
|
|
padding-inline-start: 0;
|
|
}
|
|
</style>
|
|
|
|
<i18n>
|
|
{
|
|
"en": {
|
|
"title": "Create your account",
|
|
"alt": "Hutopy Registration",
|
|
"name": "Full Name",
|
|
"email": "Email",
|
|
"password": "Password",
|
|
"confirmPassword": "Confirm Password",
|
|
"passwordRequirements": "Password must be at least 8 characters",
|
|
"register": "Register",
|
|
"alreadyHaveAccount": "Already have an account?",
|
|
"signIn": "Sign in",
|
|
"passwordsDoNotMatch": "Passwords do not match",
|
|
"registrationFailed": "Registration failed. Please try again.",
|
|
"success": {
|
|
"title": "Registration Successful!",
|
|
"message": "Please check your email to verify your account. We've sent a verification link to:",
|
|
"backToLogin": "Back to Login",
|
|
"resendVerification": "Didn't receive the email? Resend verification"
|
|
}
|
|
},
|
|
"fr": {
|
|
"title": "Créer votre compte",
|
|
"alt": "Inscription Hutopy",
|
|
"name": "Nom complet",
|
|
"email": "Email",
|
|
"password": "Mot de passe",
|
|
"confirmPassword": "Confirmer le mot de passe",
|
|
"passwordRequirements": "Le mot de passe doit comporter au moins 8 caractères",
|
|
"register": "S'inscrire",
|
|
"alreadyHaveAccount": "Vous avez déjà un compte?",
|
|
"signIn": "Se connecter",
|
|
"passwordsDoNotMatch": "Les mots de passe ne correspondent pas",
|
|
"registrationFailed": "L'inscription a échoué. Veuillez réessayer.",
|
|
"success": {
|
|
"title": "Inscription réussie!",
|
|
"message": "Veuillez vérifier votre email pour activer votre compte. Nous avons envoyé un lien de vérification à:",
|
|
"backToLogin": "Retour à la connexion",
|
|
"resendVerification": "Vous n'avez pas reçu l'email? Renvoyer la vérification"
|
|
}
|
|
}
|
|
}
|
|
</i18n>
|