feat: Initial auth components
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
const { login } = useAuthConnexion();
|
||||
|
||||
const fields = [
|
||||
{
|
||||
name: "username",
|
||||
type: "text" as const,
|
||||
label: "Courriel",
|
||||
placeholder: "Entrez votre courriel",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "password",
|
||||
label: "Mot de passe",
|
||||
type: "password" as const,
|
||||
placeholder: "Entrez votre mot de passe",
|
||||
required: true,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UAuthForm
|
||||
:schema="authLoginFormSchema"
|
||||
:fields="fields"
|
||||
title="Connexion"
|
||||
description="Veuillez vous identifier."
|
||||
loading-auto
|
||||
@submit="login"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
const { logout } = useAuthConnexion();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full space-y-6">
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-xl font-semibold text-pretty text-highlighted">Déconnexion</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">Veuillez confirmer la déconnexion.</div>
|
||||
</div>
|
||||
<UButton
|
||||
icon="i-lucide-log-out"
|
||||
block
|
||||
loading-auto
|
||||
to="#"
|
||||
label="Déconnexion"
|
||||
@click="logout()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div class="w-full space-y-6">
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-xl font-semibold text-pretty text-highlighted">Redirection en cours</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">Veuillez patienter...</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
7
wp-content/themes/headless/app/composables/useAuth.ts
Normal file
7
wp-content/themes/headless/app/composables/useAuth.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export function useAuth() {
|
||||
const { loggedIn: isLoggedIn, session } = useUserSession();
|
||||
const hasRole = (role: string) => session.value?.user?.roles?.includes(role) || false;
|
||||
const isAdmin = computed(() => hasRole("administrator"));
|
||||
|
||||
return { isLoggedIn, hasRole, isAdmin };
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { delay } from "es-toolkit/promise";
|
||||
|
||||
import type { FormSubmitEvent } from "@nuxt/ui";
|
||||
|
||||
export function useAuthConnexion() {
|
||||
const toast = useToast();
|
||||
|
||||
const defaultRedirect = (useRoute().query.redirect as string) || undefined;
|
||||
const isRedirecting = useState("auth.isRedirecting", () => false);
|
||||
const { fetch: refreshUserSession } = useUserSession();
|
||||
|
||||
// Helper: Redirect after login / logout
|
||||
async function redirectTo(to: string | undefined) {
|
||||
isRedirecting.value = true;
|
||||
await delay(1000);
|
||||
await refreshUserSession();
|
||||
await navigateTo(to || defaultRedirect || "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt login with the provided credentials.
|
||||
*
|
||||
* @param event The form submit event containing the login credentials.
|
||||
* @param redirect Optional URL to redirect to after successful login.
|
||||
* @returns A promise that resolves when the login process is complete.
|
||||
*/
|
||||
async function login({ data: body }: FormSubmitEvent<AuthLoginForm>, redirect?: string) {
|
||||
try {
|
||||
const { success, message } = await $fetch("/api/login", { method: "POST", body });
|
||||
if (!success) throw new Error(message);
|
||||
|
||||
toast.add({
|
||||
color: "success",
|
||||
title: "Connexion réussie",
|
||||
description: message,
|
||||
});
|
||||
|
||||
await redirectTo(redirect);
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
color: "error",
|
||||
title: "Erreur de connexion",
|
||||
description:
|
||||
error instanceof Error ? error.message : "Une erreur est survenue lors de la connexion.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout the current user.
|
||||
*
|
||||
* @param redirect Optional URL to redirect to after successful logout.
|
||||
* @returns A promise that resolves when the logout process is complete.
|
||||
*/
|
||||
async function logout(redirect?: string) {
|
||||
try {
|
||||
const { success, message } = await $fetch("/api/logout", { method: "POST" });
|
||||
if (!success) throw new Error(message);
|
||||
|
||||
toast.add({
|
||||
color: "success",
|
||||
title: "Déconnexion réussie",
|
||||
description: message,
|
||||
});
|
||||
|
||||
await redirectTo(redirect);
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
color: "error",
|
||||
title: "Erreur de déconnexion",
|
||||
description:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Une erreur est survenue lors de la déconnexion.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { isRedirecting, login, logout };
|
||||
}
|
||||
17
wp-content/themes/headless/app/pages/connexion.vue
Normal file
17
wp-content/themes/headless/app/pages/connexion.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
const { isLoggedIn } = useAuth();
|
||||
const { isRedirecting } = useAuthConnexion();
|
||||
onBeforeMount(() => (isRedirecting.value = false));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="page-connexion" class="container-sm py-12">
|
||||
<AuthState>
|
||||
<AuthRedirecting v-if="isRedirecting" />
|
||||
<template v-else>
|
||||
<AuthLoginForm v-if="!isLoggedIn" />
|
||||
<AuthLogoutForm v-else />
|
||||
</template>
|
||||
</AuthState>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user