Files
Ferme/frontend/layouts/default.vue
2026-02-12 17:09:22 +01:00

138 lines
5.3 KiB
Vue

<template>
<div class="min-h-screen text-neutral-900 grid grid-rows-[85px,1fr]">
<header class="w-full border-b border-neutral-200 bg-primary-500">
<div class="flex w-full items-center justify-center px-6 py-4">
<button
type="button"
class="inline-flex items-center justify-center text-3xl text-white md:hidden"
aria-label="Ouvrir le menu"
@click="toggleMenu"
>
<span aria-hidden="true" class="flex items-center"><Icon name="mdi:menu" size="44"/></span>
</button>
<nav class="ml-4 hidden items-center gap-8 text-2xl font-bold uppercase text-white md:flex">
<NuxtLink to="/" custom v-slot="{ href, navigate, isExactActive }">
<a
:href="href"
@click="navigate"
:class="isExactActive ? 'opacity-100' : 'opacity-50'"
>
Accueil
</a>
</NuxtLink>
<NuxtLink
to="/admin/dashboard" custom v-slot="{ href, navigate, isExactActive }"
v-if="auth.isAdmin"
>
<a
:href="href"
@click="navigate"
:class="isExactActive ? 'opacity-100' : 'opacity-50'"
>
Admin
</a>
</NuxtLink>
</nav>
<NuxtLink to="/" class="flex flex-1 items-center justify-center gap-3">
<span
class="flex items-center justify-center bg-white text-xl font-bold uppercase text-primary-500 p-4"
>
LOGO
</span>
</NuxtLink>
<div class="w-[44px] md:hidden"></div>
<button
type="button"
class="ml-auto hidden text-xl font-bold uppercase text-white transition hover:opacity-80 md:inline-flex"
@click="handleLogout"
>
Déconnexion
</button>
</div>
<transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition duration-150 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div
v-if="isMenuOpen"
class="fixed inset-0 z-40 bg-black/40 md:hidden"
@click="closeMenu"
/>
</transition>
<transition
enter-active-class="transition duration-200 ease-out"
enter-from-class="-translate-x-full"
enter-to-class="translate-x-0"
leave-active-class="transition duration-150 ease-in"
leave-from-class="translate-x-0"
leave-to-class="-translate-x-full"
>
<aside
v-if="isMenuOpen"
class="fixed left-0 top-0 z-50 h-full w-full bg-primary-600 px-6 pb-8 pt-6 text-white shadow-xl md:hidden"
role="dialog"
aria-modal="true"
>
<div class="flex items-center justify-between">
<span class="text-2xl font-bold uppercase">Menu</span>
<button
type="button"
class="text-2xl"
aria-label="Fermer le menu"
@click="closeMenu"
>
<Icon name="mdi:close" size="44"/>
</button>
</div>
<nav class="mt-8 flex flex-col gap-6 text-xl font-bold uppercase">
<NuxtLink to="/" class="opacity-100" @click="closeMenu">Accueil</NuxtLink>
</nav>
<button
type="button"
class="mt-5 text-xl font-bold uppercase"
@click="handleLogout"
>
Déconnexion
</button>
</aside>
</transition>
</header>
<main class="mx-auto w-full max-w-[1280px]">
<slot/>
</main>
<footer class="w-full mt-8 bg-primary-500 p-6">
<p class="font-bold text-white text-right">v{{ version }}</p>
</footer>
</div>
</template>
<script setup lang="ts">
import {useAuthStore} from '~/stores/auth'
const route = useRoute()
const auth = useAuthStore()
const isMenuOpen = ref(false)
const {version} = useAppVersion()
const closeMenu = () => {
isMenuOpen.value = false
}
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value
}
const handleLogout = async () => {
try {
await auth.logout()
} finally {
closeMenu()
await navigateTo('/login')
}
}
</script>