<template>
<GnNavigationShell
brand="SHSERV WEB CLIENT"
logo-src=""
title="Navigation"
subtitle="Smart Home"
:items="navItems"
active-match="prefix"
:current="pageTitle"
>
<template #content>
<slot />
</template>
<template #footer>
<GnUserCard
v-if="authStore.isAuthenticated"
:name="authStore.user?.display_name || 'User'"
:email="authStore.user?.email || ''"
:role="formatRole(authStore.user?.system_role)"
:avatar="{
src: authStore.user?.avatar_url || '',
initials: getInitials(authStore.user?.display_name),
size: 'sm',
}"
:href="authStore.user?.gauth_profile_url || ''"
compact
:actions="[
{
label: 'Logout',
icon: 'ph-sign-out',
variant: 'ghost',
onClick: handleLogout,
},
]"
/>
<GnButton
v-else
variant="primary"
size="sm"
@click="handleLogin"
>
<template #icon>
<i class="ph ph-sign-in" />
</template>
Sign in
</GnButton>
</template>
</GnNavigationShell>
</template>
<script setup>
import { computed } from "vue";
import { useRoute } from "vue-router";
import { GnNavigationShell, GnButton, GnUserCard } from "gnexus-ui-kit/vue";
import { useAuthStore } from "../../stores/auth.js";
const route = useRoute();
const authStore = useAuthStore();
const PAGE_TITLES = {
login: "Login",
"areas-favorites": "Favorites",
"areas-tree": "Areas",
"area-detail": "Area",
devices: "Devices",
"device-detail": "Device",
"devices-scanning": "Scanning",
"scripts-actions": "Actions",
"scripts-regular": "Regular",
"scripts-scopes": "Scopes",
"script-detail": "Script",
firmwares: "Firmwares",
};
const pageTitle = computed(() => {
const name = route?.name;
if (name && PAGE_TITLES[name]) {
return PAGE_TITLES[name];
}
return "";
});
const ALL_NAV_ITEMS = [
{ label: "Favorites", to: "/areas/favorites", icon: "ph-bookmarks", permission: "areas.view" },
{ label: "Areas", to: "/areas/tree", icon: "ph-map-trifold", permission: "areas.view" },
{ label: "Devices", to: "/devices", icon: "ph-cpu", permission: "devices.view" },
{ label: "Scanning", to: "/devices/scanning", icon: "ph-magnifying-glass", permission: "devices.scan" },
{ label: "Actions", to: "/scripts/actions", icon: "ph-play", permission: "scripts.run" },
{ label: "Regular", to: "/scripts/regular", icon: "ph-clock", permission: "scripts.view" },
{ label: "Scopes", to: "/scripts/scopes", icon: "ph-brackets-curly", permission: "scripts.view" },
{ label: "Firmwares", to: "/firmwares", icon: "ph-cloud-arrow-down", permission: "firmware.view" },
];
const navItems = computed(() => {
return ALL_NAV_ITEMS.filter((item) => {
if (!item.permission) {
return true;
}
return authStore.hasPermission(item.permission);
});
});
function getInitials(name) {
if (!name) return "";
return name
.split(/\s+/)
.slice(0, 2)
.map((w) => w[0]?.toUpperCase())
.join("");
}
function formatRole(role) {
if (!role) return "";
return role.charAt(0).toUpperCase() + role.slice(1);
}
function handleLogin() {
const returnTo = window.location.hash || "#/";
window.location.href = `/auth/login?return_to=${encodeURIComponent(returnTo)}`;
}
function closeDrawer() {
const backdrop = document.querySelector(".nav-drawer-backdrop");
if (backdrop) {
backdrop.click();
}
}
function handleLogout() {
closeDrawer();
authStore.logout();
}
</script>