Skip to content
Snippets Groups Projects
Commit 0afa0454 authored by Sofiane Lasri's avatar Sofiane Lasri
Browse files

feat: add authentication flows and basic page structure

- Implement login and registration pages with validation
- Add middleware to verify user existence for route protection
- Establish admin dashboard with middleware authentication
- Update app.vue for layout and loading improvements
- Create auth layout with navigation button
- Add initial index page with welcome component
parent f7d327c0
No related branches found
No related tags found
No related merge requests found
<template>
<div>
<NuxtRouteAnnouncer />
<NuxtWelcome />
<NuxtLoadingIndicator />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
</script>
<template>
<div class="h-screen flex items-center justify-center overlay">
<UButton
icon="i-heroicons-home"
label="Accueil"
to="/"
color="black"
class="absolute top-4"
/>
<slot/>
</div>
</template>
<style scoped>
</style>
\ No newline at end of file
export default defineNuxtRouteMiddleware(async (to) => {
let userExists = false;
try {
await useFetch('/api/auth/userExists', {
onResponse: ({response}) => {
userExists = response._data.userExists;
},
});
} catch (error) {
console.error('Error checking if user exists', error);
return abortNavigation();
}
if (userExists) {
return navigateTo('/login');
}
});
\ No newline at end of file
export default defineNuxtRouteMiddleware(async (to) => {
let userExists = false;
try {
await useFetch('/api/auth/userExists', {
onResponse: ({response}) => {
userExists = response._data.userExists;
},
});
} catch (error) {
console.error('Error checking if user exists', error);
return abortNavigation();
}
if (!userExists) {
return navigateTo('/register');
}
});
\ No newline at end of file
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
<template>
<div>
<h1>Admin Dashboard</h1>
</div>
</template>
<style scoped>
</style>
\ No newline at end of file
<script setup lang="ts">
</script>
<template>
<NuxtWelcome />
</template>
<style scoped>
</style>
\ No newline at end of file
<script setup lang="ts">
import type {FormError} from "#ui/types";
definePageMeta({
layout: 'auth',
middleware: 'verify-user-exists'
});
useSeoMeta({
title: 'Connexion',
})
const uiOptions = {
default: {
submitButton: {
label: 'Se connecter'
}
}
};
const formFields = [{
type: 'email',
label: 'Adresse email',
name: 'email',
placeholder: 'Entrez votre adresse email',
color: 'gray',
required: true
}, {
type: 'password',
label: 'Mot de passe',
name: 'password',
placeholder: 'Entrez votre mot de passe',
color: 'gray',
required: true
}];
const validate = (values: any) => {
const errors: FormError[] = [];
if(!values.email) {
errors.push({ path: 'email', message: 'Veuillez entrer votre adresse email' });
}
if(!values.password) {
errors.push({ path: 'password', message: 'Veuillez entrer votre mot de passe' });
}
return errors;
};
const authStore = useAuthStore();
const loginErrorMessage = ref<string | null>(null);
const isLoggingIn = ref(false);
async function onSubmit(data: any) {
isLoggingIn.value = true;
try {
await authStore.login(data.email, data.password);
} catch (error) {
console.error('Login failed', error);
loginErrorMessage.value = 'Identifiants incorrects';
} finally {
isLoggingIn.value = false;
}
}
</script>
<template>
<UCard class="max-w-sm w-full">
<UAuthForm
title="Connexion"
description="Connectez-vous pour accéder à l'administration."
align="top"
icon="i-heroicons-user-circle"
:validate="validate"
:fields="formFields"
:loading="isLoggingIn"
:ui="uiOptions"
@submit="onSubmit"
>
<template #password-hint>
<NuxtLink to="/" class="text-primary font-medium">Mot de passe oublié ?</NuxtLink>
</template>
<template #validation v-if="loginErrorMessage !== null">
<UAlert color="red" icon="i-heroicons-information-circle-20-solid"
:title="loginErrorMessage" />
</template>
</UAuthForm>
</UCard>
</template>
\ No newline at end of file
<script setup lang="ts">
import type {FormError} from "#ui/types";
definePageMeta({
layout: 'auth',
middleware: 'verify-user-doesnt-exists'
})
useSeoMeta({
title: 'Inscription',
})
const uiOptions = {
default: {
submitButton: {
label: 'Créer un compte'
}
}
};
const formFields = [{
name: 'name',
type: 'text',
label: 'Nom d\'utilisateur',
placeholder: 'Entrez votre nom d\'utilisateur',
required: true,
description: "Il ne s'agit là que d'un nom d'affichage, vous pourrez le modifier plus tard.",
}, {
type: 'email',
label: 'Adresse email',
name: 'email',
placeholder: 'Entrez votre adresse email',
color: 'gray',
required: true,
description: "Soyez sûr d'entrer une adresse valide, vous serez le seul maître à bord. 👀"
}, {
type: 'password',
label: 'Mot de passe',
name: 'password',
placeholder: 'Entrez votre mot de passe',
color: 'gray',
required: true
}];
const validate = (values: any) => {
const errors: FormError[] = [];
if (!values.email) {
errors.push({path: 'email', message: 'Veuillez entrer votre adresse email'});
}
if (!values.password) {
errors.push({path: 'password', message: 'Veuillez entrer votre mot de passe'});
} else {
if (values.password.length < 6 || values.password.length > 32) {
errors.push({path: 'password', message: 'Votre mot de passe doit contenir entre 6 et 32 caractères'});
}
if (!/[A-Z]/.test(values.password) || !/[a-z]/.test(values.password) || !/[0-9]/.test(values.password) || !/[^A-Za-z0-9]/.test(values.password)) {
errors.push({path: 'password', message: 'Votre mot de passe doit contenir au moins une majuscule, une minuscule, un chiffre et un caractère spécial'});
}
}
if (!values.name) {
errors.push({path: 'name', message: 'Veuillez entrer votre nom d\'utilisateur'});
} else {
if (values.name.length < 3 || values.name.length > 32) {
errors.push({path: 'name', message: 'Votre nom d\'utilisateur doit contenir entre 3 et 32 caractères'});
}
}
return errors;
};
const isRegisteringIn = ref(false);
async function onSubmit(data: any) {
console.log('Registering in with data', data);
}
</script>
<template>
<UCard class="max-w-sm w-full">
<UAuthForm
title="Inscription"
description="Bienvenue chez vous ! Créez un compte pour finaliser l'installation de votre site internet."
align="top"
icon="i-heroicons-user-circle"
:validate="validate"
:fields="formFields"
:loading="isRegisteringIn"
:ui="uiOptions"
@submit="onSubmit"
>
</UAuthForm>
</UCard>
</template>
<style scoped>
</style>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment