111 lines
3.4 KiB
Vue
111 lines
3.4 KiB
Vue
<template>
|
|
<aside
|
|
class="sticky top-0 z-50 w-full min-w-0 border-b border-[#e7e5e4] bg-white/90 backdrop-blur lg:fixed lg:inset-y-0 lg:left-0 lg:h-screen lg:w-[248px] lg:border-b-0 lg:border-r xl:w-[280px]">
|
|
<div class="flex h-full min-h-0 w-full min-w-0 flex-col gap-4 px-3 py-3 sm:px-4 lg:px-5 lg:py-6">
|
|
<NuxtLink to="/home"
|
|
class="flex min-w-0 items-center gap-3 rounded-2xl px-1 text-base font-semibold tracking-[0.16px] text-[#0c0a09] lg:px-0">
|
|
<span class="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-[#292524] text-white">
|
|
<Icon name="mdi:gamepad-variant" class="text-xl" />
|
|
</span>
|
|
<span class="min-w-0 truncate">GameVerse</span>
|
|
</NuxtLink>
|
|
|
|
<nav
|
|
class="flex w-full min-w-0 gap-2 overflow-x-auto pb-1 lg:min-h-0 lg:flex-1 lg:flex-col lg:overflow-y-auto lg:overflow-x-visible lg:pb-0"
|
|
aria-label="Rotas internas">
|
|
<NuxtLink v-for="item in navigationItems" :key="item.to" :to="item.to"
|
|
:aria-current="isActive(item.to) ? 'page' : undefined" :class="[
|
|
'inline-flex h-10 shrink-0 items-center gap-2 rounded-full border px-4 text-[14px] font-medium leading-none transition lg:w-full lg:min-w-0 lg:justify-start',
|
|
isActive(item.to)
|
|
? 'border-[#292524] bg-[#292524] text-white'
|
|
: 'border-[#d6d3d1] bg-transparent text-[#0c0a09] hover:border-[#0c0a09]'
|
|
]">
|
|
<Icon :name="item.icon" class="shrink-0 text-base" />
|
|
<span class="min-w-0 truncate">{{ item.label }}</span>
|
|
</NuxtLink>
|
|
</nav>
|
|
|
|
<button type="button" :disabled="isLeaving" @click="sair"
|
|
class="inline-flex h-10 shrink-0 items-center justify-center gap-2 rounded-full bg-[#292524] px-4 text-[14px] font-medium leading-none text-white transition hover:bg-[#0c0a09] disabled:cursor-not-allowed disabled:opacity-70 lg:w-full">
|
|
<Icon v-if="isLeaving" name="mdi:loading" class="animate-spin text-base" />
|
|
<Icon v-else name="mdi:logout" class="text-base" />
|
|
<span>{{ isLeaving ? 'Saindo...' : 'Sair' }}</span>
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
</template>
|
|
|
|
<script setup>
|
|
const route = useRoute()
|
|
const { $toast } = useNuxtApp()
|
|
|
|
const token = useCookie('token', {
|
|
secure: true,
|
|
sameSite: 'lax',
|
|
maxAge: 900
|
|
})
|
|
|
|
const isLeaving = ref(false)
|
|
|
|
const navigationItems = [
|
|
{
|
|
label: 'Home',
|
|
to: '/home',
|
|
icon: 'mdi:view-dashboard-outline'
|
|
},
|
|
{
|
|
label: 'Dados da conta',
|
|
to: '/dados-conta',
|
|
icon: 'mdi:account-circle-outline'
|
|
},
|
|
{
|
|
label: 'Rankings',
|
|
to: '/ranking-jogos',
|
|
icon: 'mdi:trophy-outline'
|
|
},
|
|
{
|
|
label: 'Perfil gamer',
|
|
to: '/perfil-gamer',
|
|
icon: 'mdi:account-star-outline'
|
|
},
|
|
{
|
|
label: 'Gift card',
|
|
to: '/gift-card',
|
|
icon: 'mdi:gift-outline'
|
|
},
|
|
{
|
|
label: 'Favoritos',
|
|
to: '/favoritos',
|
|
icon: 'mdi:heart-outline'
|
|
},
|
|
{
|
|
label: 'Catálogo',
|
|
to: '/catalogo',
|
|
icon: 'mdi:controller-classic-outline'
|
|
},
|
|
{
|
|
label: 'Novo jogo',
|
|
to: '/catalogo/criar',
|
|
icon: 'mdi:plus'
|
|
}
|
|
]
|
|
|
|
const isActive = (path) => {
|
|
if (path === '/catalogo') {
|
|
return (
|
|
route.path === '/catalogo' ||
|
|
(route.path.startsWith('/catalogo/') && route.path !== '/catalogo/criar')
|
|
)
|
|
}
|
|
|
|
return route.path === path
|
|
}
|
|
|
|
async function sair() {
|
|
isLeaving.value = true
|
|
token.value = null
|
|
$toast.success('Sessão encerrada com sucesso.', { duration: 8000 })
|
|
await navigateTo('/login')
|
|
}
|
|
</script>
|