145 lines
5.5 KiB
Vue
145 lines
5.5 KiB
Vue
<script setup lang="ts">
|
|
/**
|
|
* @file AppSidebar.vue
|
|
* @description เมนูด้านข้างสำหรับการนำทาง (Sidebar Navigation)
|
|
*/
|
|
|
|
// 1. นำเข้า Composables และไลบรารี
|
|
import { useQuasar } from 'quasar'
|
|
const { t } = useI18n()
|
|
const route = useRoute()
|
|
const $q = useQuasar()
|
|
const { logout } = useAuth()
|
|
const { isDark } = useThemeMode()
|
|
|
|
// 2. กำหนดข้อมูลเมนูหลัก (Main Navigation)
|
|
const menuItems = computed(() => [
|
|
{ to: '/dashboard', icon: 'grid_view', label: t('sidebar.overview') },
|
|
{ to: '/dashboard/my-courses', icon: 'book', label: t('sidebar.myCourses') }
|
|
])
|
|
|
|
// 3. กำหนดข้อมูลเมนูบัญชี (Account Navigation)
|
|
const accountItems = computed(() => [
|
|
{ to: '/dashboard/profile', icon: 'settings', label: t('userMenu.settings') }
|
|
])
|
|
|
|
// 4. ฟังก์ชันการออกจากระบบ (Logout Function)
|
|
const handleLogout = () => {
|
|
$q.dialog({
|
|
title: t('auth.logoutConfirmTitle'),
|
|
message: t('auth.logoutConfirmMessage'),
|
|
cancel: {
|
|
flat: true,
|
|
color: isDark.value ? 'grey-4' : 'grey-7',
|
|
label: t('common.cancel')
|
|
},
|
|
ok: {
|
|
flat: false,
|
|
color: 'red-500',
|
|
label: t('auth.logout'),
|
|
unelevated: true
|
|
},
|
|
dark: isDark.value,
|
|
class: 'p-4 rounded-2xl text-slate-900 dark:text-white',
|
|
persistent: true
|
|
}).onOk(async () => {
|
|
await logout()
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col h-full bg-white dark:!bg-[#04091a] px-4 py-6 border-r border-slate-100 dark:border-slate-800">
|
|
|
|
<!-- โลโก้แบรนด์ (Logo Section) -->
|
|
<div class="flex items-center gap-3 px-2 mb-10 transition-transform active:scale-95 cursor-pointer" @click="navigateTo('/dashboard')">
|
|
<div class="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center shadow-lg shadow-blue-500/20">
|
|
<q-icon name="school" color="white" size="24px" />
|
|
</div>
|
|
<span class="text-[22px] font-black tracking-tight text-slate-800 dark:text-white">EduLearn</span>
|
|
</div>
|
|
|
|
<!-- การนำทางหลัก (Main Navigation) -->
|
|
<div class="space-y-1 mb-8">
|
|
<NuxtLink
|
|
v-for="item in menuItems"
|
|
:key="item.to"
|
|
:to="item.to"
|
|
class="flex items-center gap-4 px-4 py-3 rounded-2xl transition-all group relative nav-item"
|
|
:class="route.path === item.to ? 'active' : 'text-slate-500 hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-200'"
|
|
>
|
|
<q-icon :name="item.icon" size="24px" class="transition-colors" />
|
|
<span class="font-bold text-[15px]">{{ item.label }}</span>
|
|
|
|
<!-- ตัวบ่งชี้หน้าปัจจุบัน (Active Indicator) -->
|
|
<div v-if="route.path === item.to" class="absolute left-0 top-1/2 -translate-y-1/2 w-1.5 h-6 bg-blue-600 rounded-r-full shadow-[2px_0_8px_rgba(37,99,235,0.4)]"></div>
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<!-- หมวดหมู่บัญชี (Account Section) -->
|
|
<div class="px-4 mb-4">
|
|
<span class="text-[12px] font-bold text-slate-400 uppercase tracking-widest">{{ $t('sidebar.accountGroup') }}</span>
|
|
</div>
|
|
<div class="space-y-1">
|
|
<NuxtLink
|
|
v-for="item in accountItems"
|
|
:key="item.to"
|
|
:to="item.to"
|
|
class="flex items-center gap-4 px-4 py-3 rounded-2xl transition-all group nav-item"
|
|
:class="route.path === item.to ? 'active' : 'text-slate-500 hover:bg-slate-50 dark:hover:bg-slate-800 hover:text-slate-900 dark:hover:text-slate-200'"
|
|
>
|
|
<q-icon :name="item.icon" size="24px" />
|
|
<span class="font-bold text-[15px]">{{ item.label }}</span>
|
|
</NuxtLink>
|
|
|
|
<!-- ปุ่มออกจากระบบ (Logout Button) -->
|
|
<button
|
|
@click="handleLogout"
|
|
class="w-full flex items-center gap-4 px-4 py-3 rounded-2xl transition-all text-red-500 hover:bg-red-50 dark:hover:bg-red-900/10 font-bold text-[15px] group"
|
|
>
|
|
<q-icon name="logout" size="24px" class="group-hover:translate-x-1 transition-transform" />
|
|
<span>{{ $t('userMenu.logout') }}</span>
|
|
</button>
|
|
</div>
|
|
|
|
<q-space />
|
|
|
|
<!-- การ์ดโปรโมชั่น (Promo Card) -->
|
|
<div class="mt-auto p-5 rounded-[2rem] bg-slate-50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-800 relative overflow-hidden group">
|
|
<div class="relative z-10">
|
|
<h4 class="font-black text-slate-800 dark:text-white text-sm mb-1">{{ $t('sidebar.promoTitle') }}</h4>
|
|
<p class="text-[11px] text-slate-500 dark:text-slate-400 mb-4">{{ $t('sidebar.promoSubtitle') }}</p>
|
|
<q-btn
|
|
unelevated
|
|
class="full-width rounded-xl bg-blue-600 hover:bg-blue-700 text-white font-bold py-2.5 no-caps transition-all active:scale-95 text-xs shadow-md shadow-blue-500/20"
|
|
@click="navigateTo('/browse/discovery')"
|
|
>
|
|
{{ $t('sidebar.learnMore') }}
|
|
</q-btn>
|
|
</div>
|
|
|
|
<!-- การตกแต่งพื้นหลังแบบจางๆ (Subtle background decoration) -->
|
|
<div class="absolute -right-2 -bottom-2 w-16 h-16 bg-blue-500/5 rounded-full blur-xl"></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.nav-item.active {
|
|
background: #EFF6FF;
|
|
color: #2563EB;
|
|
}
|
|
|
|
.dark .nav-item.active {
|
|
background: rgba(37,99,235,0.1);
|
|
color: #60A5FA;
|
|
}
|
|
|
|
.nav-item.active .q-icon {
|
|
color: #2563EB;
|
|
}
|
|
|
|
.dark .nav-item.active .q-icon {
|
|
color: #60A5FA;
|
|
}
|
|
</style>
|