elearning/Frontend-Learner/components/layout/AppSidebar.vue

141 lines
4 KiB
Vue

<script setup lang="ts">
/**
* @file AppSidebar.vue
* @description Sidebar navigation for the authenticated dashboard.
* Uses Quasar QList for structure.
*/
const { t } = useI18n()
const navItems = computed(() => [
{
to: "/dashboard",
label: t('sidebar.overview'),
icon: "dashboard", // Using Material Icons names where possible or SVG paths
isSvg: false
},
{
to: "/dashboard/my-courses",
label: t('sidebar.myCourses'),
icon: "school",
isSvg: false
},
{
to: "/browse/discovery",
label: t('sidebar.browseCourses'),
icon: "explore",
isSvg: false
},
{
to: "/dashboard/announcements",
label: t('sidebar.announcements'),
icon: "campaign",
isSvg: false
},
{
to: "/dashboard/profile",
label: t('sidebar.profile'),
icon: "person",
isSvg: false
},
]);
const handleNavigate = (path: string) => {
if (import.meta.client) {
window.location.href = path
}
}
</script>
<template>
<div class="flex flex-col h-full bg-white dark:bg-[#1e293b] border-r border-slate-200 dark:border-slate-700">
<!-- Branding / Logo Area -->
<div class="px-6 py-8 flex items-center gap-3 cursor-pointer group" @click="handleNavigate('/dashboard')">
<div class="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center text-white font-black shadow-lg shadow-blue-600/30 group-hover:scale-110 transition-transform">
E
</div>
<div class="flex flex-col">
<span class="font-black text-lg leading-none tracking-tight text-slate-900 dark:text-white">E-Learning</span>
<span class="text-[10px] font-bold uppercase tracking-[0.2em] leading-none mt-1 text-slate-500">Platform</span>
</div>
</div>
<!-- Navigation Items -->
<q-list padding class="text-slate-600 dark:text-slate-300 flex-grow px-3">
<q-item
v-for="item in navItems"
:key="item.to"
clickable
v-ripple
@click="handleNavigate(item.to)"
class="rounded-xl mb-1 text-slate-700 dark:text-slate-200 hover:bg-slate-100 dark:hover:bg-white/5"
:class="{ 'sidebar-item--active': $route.path === item.to || ($route.path === '/dashboard' && item.to === '/dashboard') }"
>
<q-item-section avatar>
<q-icon :name="item.icon" size="22px" />
</q-item-section>
<q-item-section>
<q-item-label class="font-bold text-sm">{{ item.label }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
<!-- Sidebar Bottom: Logout & Version -->
<div class="p-4 border-t border-slate-100 dark:border-slate-700/50">
<q-btn
flat
rounded
class="w-full text-slate-500 hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/10 transition-all font-bold"
no-caps
@click="() => useAuth().logout()"
>
<q-icon name="logout" size="20px" class="mr-3" />
{{ t('auth.logout') }}
</q-btn>
<div class="mt-4 px-4 text-center">
<p class="text-[10px] font-black uppercase tracking-[0.2em] text-slate-400">Version 0.1.0 (Alpha)</p>
</div>
</div>
</div>
</template>
<style>
/* Active State styling for Sidebar items */
.sidebar-item--active {
background: rgb(239 246 255) !important; /* blue-50 */
color: rgb(29 78 216) !important; /* blue-700 */
}
.sidebar-item--active .q-icon {
color: rgb(37 99 235) !important; /* blue-600 */
}
/* Vertical indicator for active item */
.sidebar-item--active::after {
content: "";
position: absolute;
left: -12px;
top: 15%;
height: 70%;
width: 4px;
background: #2563eb;
border-radius: 0 4px 4px 0;
}
/* Dark Mode Active State */
.dark .sidebar-item--active {
background: rgba(37, 99, 235, 0.15) !important;
color: rgb(147 197 253) !important; /* blue-300 */
}
.dark .sidebar-item--active .q-icon {
color: rgb(96 165 250) !important; /* blue-400 */
}
.dark .sidebar-item--active::after {
background: #60a5fa;
}
</style>