admin_panel/frontend/src/components/Layouts/AdminSidebar.vue

180 lines
5.2 KiB
Vue

<template>
<div
class="relative flex h-full flex-col justify-between transition-all duration-300 ease-in-out"
:class="isSidebarCollapsed ? 'w-12' : 'w-[220px]'"
>
<!-- Logo -->
<div class="p-2">
<div
class="flex items-center gap-2 px-2 py-1.5 transition-all duration-300 ease-in-out"
:class="isSidebarCollapsed ? 'justify-center' : ''"
>
<AdminLogo class="h-6 w-6 flex-shrink-0" />
<span
v-if="!isSidebarCollapsed"
class="text-lg font-semibold text-ink-gray-9"
>
Admin Panel
</span>
</div>
</div>
<!-- Navigation -->
<div class="flex-1 overflow-y-auto">
<!-- Overview -->
<div class="mb-1 px-2">
<div
v-if="!isSidebarCollapsed"
class="px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-ink-gray-4"
>
{{ $t('nav.overview') }}
</div>
<nav class="flex flex-col gap-0.5">
<SidebarLink
icon="bar-chart-2"
:label="$t('nav.dashboard')"
to="Dashboard"
:isCollapsed="isSidebarCollapsed"
/>
</nav>
</div>
<!-- Infrastructure -->
<div class="mb-1 px-2">
<div
v-if="!isSidebarCollapsed"
class="px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-ink-gray-4"
>
{{ $t('nav.infrastructure') }}
</div>
<nav class="flex flex-col gap-0.5">
<SidebarLink
icon="server"
:label="$t('nav.sites')"
to="Sites"
:isCollapsed="isSidebarCollapsed"
/>
<SidebarLink
icon="package"
:label="$t('nav.apps')"
to="Apps"
:isCollapsed="isSidebarCollapsed"
/>
<SidebarLink
icon="cloud"
:label="$t('nav.servers')"
to="Servers"
:isCollapsed="isSidebarCollapsed"
/>
</nav>
</div>
<!-- Business -->
<div class="mb-1 px-2">
<div
v-if="!isSidebarCollapsed"
class="px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-ink-gray-4"
>
{{ $t('nav.business') }}
</div>
<nav class="flex flex-col gap-0.5">
<SidebarLink
icon="credit-card"
:label="$t('nav.payments')"
to="Payments"
:isCollapsed="isSidebarCollapsed"
/>
</nav>
</div>
<!-- System -->
<div class="mb-1 px-2">
<div
v-if="!isSidebarCollapsed"
class="px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-ink-gray-4"
>
{{ $t('nav.system') }}
</div>
<nav class="flex flex-col gap-0.5">
<SidebarLink
icon="file-text"
:label="$t('nav.logs')"
to="Logs"
:isCollapsed="isSidebarCollapsed"
/>
<SidebarLink
icon="settings"
:label="$t('nav.settings')"
to="Settings"
:isCollapsed="isSidebarCollapsed"
/>
</nav>
</div>
</div>
<!-- Footer -->
<div class="m-2 flex flex-col gap-1">
<!-- User info -->
<div
v-if="!isSidebarCollapsed && session.user"
class="flex items-center gap-2 px-2 py-1.5 mb-2 text-sm text-ink-gray-7 truncate"
>
<FeatherIcon name="user" class="h-4 w-4 flex-shrink-0" />
<span class="truncate">{{ session.user }}</span>
</div>
<!-- Theme Toggle -->
<ThemeToggle :isCollapsed="isSidebarCollapsed" />
<!-- Language Toggle -->
<LanguageToggle :isCollapsed="isSidebarCollapsed" />
<!-- Logout button -->
<SidebarLink
:label="$t('auth.logout')"
:isCollapsed="isSidebarCollapsed"
@click="handleLogout"
>
<template #icon>
<span class="grid h-4 w-4 flex-shrink-0 place-items-center">
<FeatherIcon name="log-out" class="h-4 w-4 text-ink-gray-7" />
</span>
</template>
</SidebarLink>
<!-- Collapse button -->
<SidebarLink
:label="isSidebarCollapsed ? $t('nav.expand') : $t('nav.collapse')"
:isCollapsed="isSidebarCollapsed"
@click="isSidebarCollapsed = !isSidebarCollapsed"
>
<template #icon>
<span class="grid h-4 w-4 flex-shrink-0 place-items-center">
<FeatherIcon
name="chevrons-left"
class="h-4 w-4 text-ink-gray-7 duration-300 ease-in-out"
:class="{ '[transform:rotateY(180deg)]': isSidebarCollapsed }"
/>
</span>
</template>
</SidebarLink>
</div>
</div>
</template>
<script setup>
import { useStorage } from '@vueuse/core'
import { FeatherIcon } from 'frappe-ui'
import SidebarLink from '@/components/Common/SidebarLink.vue'
import ThemeToggle from '@/components/Common/ThemeToggle.vue'
import LanguageToggle from '@/components/Common/LanguageToggle.vue'
import AdminLogo from '@/components/Icons/AdminLogo.vue'
import { session } from '@/session'
function handleLogout() {
session.logout()
}
const isSidebarCollapsed = useStorage('admin-sidebar-collapsed', false)
</script>