elearning/Frontend-Learner/components/layout/AppHeader.vue
supalerk-ar66 e3873f616e
All checks were successful
Build and Deploy Frontend Learner / Build Frontend Learner Docker Image (push) Successful in 47s
Build and Deploy Frontend Learner / Deploy E-learning Frontend Learner to Dev Server (push) Successful in 4s
Build and Deploy Frontend Learner / Notify Deployment Status (push) Successful in 1s
feat: Add initial pages and components for user dashboard, profile, course discovery, and classroom learning with i18n support.
2026-02-20 14:58:18 +07:00

183 lines
5.9 KiB
Vue

<script setup lang="ts">
/**
* @file AppHeader.vue
* @description The main header for the authenticated application dashboard.
* Uses Quasar QToolbar.
*/
import { ref, computed } from "vue";
const props = defineProps<{
/** Controls visibility of the search bar */
showSearch?: boolean;
/** Controls visibility of the sidebar toggle button */
showSidebarToggle?: boolean;
/** Type of navigation links to display */
navType?: "public" | "learner";
}>();
const emit = defineEmits<{
/** Emitted when the hamburger menu is clicked */
toggleSidebar: [];
}>();
const { t } = useI18n();
const route = useRoute();
// Automatically determine navType based on route if not explicitly passed
const navTypeComputed = computed(() => {
if (props.navType) return props.navType;
// Show learner nav for dashboard, browse, classroom, and course details
const learnerRoutes = ["/dashboard", "/browse", "/classroom", "/course"];
return learnerRoutes.some((r) => route.path.startsWith(r))
? "learner"
: "public";
});
const searchText = ref("");
</script>
<template>
<q-toolbar class="bg-white text-slate-900 h-16 shadow-sm border-none p-0">
<div
class="container mx-auto w-full px-6 md:px-12 flex items-center h-full"
>
<!-- Mobile Menu Toggle -->
<q-btn
v-if="showSidebarToggle !== false && navTypeComputed !== 'learner'"
flat
round
dense
icon="menu"
class="lg:hidden mr-2 text-gray-500"
@click="$emit('toggleSidebar')"
/>
<!-- Branding -->
<div
class="flex items-center gap-3 cursor-pointer group"
@click="navigateTo('/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 group-hover:text-blue-600 transition-colors"
>E-Learning</span
>
<span
class="text-[10px] font-bold uppercase tracking-[0.2em] leading-none mt-1 text-slate-500"
>Platform</span
>
</div>
</div>
<div
class="flex items-center min-w-[200px] md:min-w-[320px] max-w-sm ml-8 mr-8 h-10"
>
<q-input
v-model="searchText"
dense
borderless
:placeholder="$t('menu.searchCourses')"
class="search-input w-full bg-slate-100/60 px-4 rounded-full transition-all duration-300 focus-within:bg-white focus-within:ring-1 focus-within:ring-blue-100 h-full flex items-center"
@keyup.enter="navigateTo(`/browse/discovery?search=${searchText}`)"
>
<template #prepend>
<q-icon name="search" size="xs" class="text-blue-600" />
</template>
</q-input>
</div>
<!-- Desktop Navigation -->
<nav class="flex items-center gap-8 text-[14px] font-bold text-slate-600">
<!-- Learner Navigation (Dashboard Mode) -->
<template v-if="navTypeComputed === 'learner'">
<NuxtLink
to="/dashboard"
class="hover:text-blue-600 transition-colors uppercase tracking-wider"
active-class="text-blue-600"
>
{{ $t("sidebar.overview") }}
</NuxtLink>
<NuxtLink
to="/browse/discovery"
class="hover:text-blue-600 transition-colors uppercase tracking-wider"
active-class="text-blue-600"
>
{{ $t("landing.allCourses") }}
</NuxtLink>
<NuxtLink
to="/dashboard/my-courses"
class="hover:text-blue-600 transition-colors uppercase tracking-wider"
active-class="text-blue-600"
>
{{ $t("sidebar.myCourses") || "คอร์สเรียนของฉัน" }}
</NuxtLink>
</template>
<!-- Public Navigation (Default) -->
<template v-else>
<div
class="cursor-pointer hover:text-purple-600 flex items-center gap-1 transition-colors"
>
คอรสเรยนทงหมด <q-icon name="keyboard_arrow_down" />
<q-menu>
<q-list dense style="min-width: 150px">
<q-item clickable v-close-popup to="/browse">
<q-item-section>งหมด</q-item-section>
</q-item>
</q-list>
</q-menu>
</div>
<div
class="cursor-pointer hover:text-purple-600 flex items-center gap-1 transition-colors"
>
หลกสตร Onsite <q-icon name="keyboard_arrow_down" />
</div>
<NuxtLink
to="/browse/recommended"
class="hover:text-purple-600 transition-colors"
>
คอรสแนะนำ
</NuxtLink>
<div class="cursor-pointer hover:text-purple-600 transition-colors">
บทความ
</div>
<div class="cursor-pointer hover:text-purple-600 transition-colors">
สมาชกรายป
</div>
<div class="cursor-pointer hover:text-purple-600 transition-colors">
สำหรบองคกร
</div>
</template>
</nav>
<q-space />
<!-- Right Actions -->
<div class="flex items-center gap-2 sm:gap-4 text-gray-500">
<!-- Search Icon -->
<!-- Language -->
<LanguageSwitcher />
<!-- User Profile -->
<UserMenu />
</div>
</div>
</q-toolbar>
</template>
<style scoped>
.search-input :deep(.q-field__control) {
border-radius: 9999px; /* Full rounded */
}
.search-input :deep(.q-field__control:before) {
border-color: #e2e8f0; /* slate-200 */
}
</style>