feat: Implement initial e-learning platform frontend structure including dashboard, course management, authentication, and common UI components.

This commit is contained in:
supalerk-ar66 2026-02-27 10:05:33 +07:00
parent aceeb80d9a
commit ad11c6b7c5
44 changed files with 720 additions and 578 deletions

View file

@ -19,7 +19,7 @@ onMounted(() => {
</script>
<template>
<!-- Auth Shell: Wrapper for authentication pages (Login, Register, etc.) -->
<!-- Auth Shell: ครอบคลุมการแสดงผลหน้าสำหรับเข้าสู่ระบบหรือสมัครสมาชิก -->
<div class="auth-shell bg-white w-full min-h-screen">
<slot />
</div>

View file

@ -1,11 +1,11 @@
<script setup lang="ts">
/**
* @file dashboard-index.vue
* @description Layout for the Dashboard Index page, without the sidebar.
* Uses Quasar QLayout for responsive structure.
* @description เลย์เอาต์สำหรับหน้าแรกของ Dashboard (ไม่มีแผงเมนูด้านข้างเพื่อเน้นพื้นที่เนื้อหา)
* ใช้โครงสร้างจาก Quasar QLayout เพื่อให้รองรับ Responsive
*/
// Initialize global theme management
// เปิดใช้คอมโพสซิเบิลจัดการธีมแบบ Global
useThemeMode()
const { currentUser, logout } = useAuth()
@ -18,7 +18,7 @@ const toggleRightDrawer = () => {
<template>
<q-layout view="hHh lpR fFf" class="bg-slate-50 dark:!bg-[#020617] text-slate-900 dark:!text-slate-50">
<!-- Header -->
<!-- แถบด้านบนของโครงสร้าง (Header) -->
<q-header
class="bg-white/80 dark:!bg-[#0f172a]/80 backdrop-blur-md text-slate-900 dark:!text-white"
>
@ -29,7 +29,7 @@ const toggleRightDrawer = () => {
/>
</q-header>
<!-- Master Mobile Drawer (The Everything Hub) -->
<!-- แถบลิ้นชักมือถือหลัก (เมนูรวมทุกอย่างเมื่อปัดหน้าจอ/กดไอคอนบนสัดส่วนเล็ก) -->
<q-drawer
v-model="rightDrawerOpen"
side="right"
@ -39,7 +39,7 @@ const toggleRightDrawer = () => {
:width="300"
>
<div class="flex flex-col h-full bg-white dark:bg-[#0f172a]">
<!-- 1. Account Section (Premium Look) -->
<!-- 1. ส่วนบัญชีผู้ใช้ (Account Section) ดีไซน์พรีเมียม -->
<div class="p-6 bg-slate-50/50 dark:bg-slate-800/30 border-b border-slate-100 dark:border-slate-800">
<div class="flex items-center justify-between mb-8">
<div class="flex items-center gap-3">
@ -62,10 +62,10 @@ const toggleRightDrawer = () => {
</div>
</div>
<!-- 2. Integrated Content Hub -->
<!-- 2. ศูนย์รวมเมนูและเนื้อหา (Integrated Content Hub) -->
<div class="flex-grow overflow-y-auto pt-4">
<q-list padding class="text-slate-600 dark:text-slate-300">
<!-- Navigation -->
<!-- การนำทาง (Navigation) -->
<q-item-label header class="text-[11px] font-black tracking-[0.2em] text-slate-400 uppercase px-6 pb-2">เมนูหลัก</q-item-label>
<q-item to="/dashboard" clickable v-ripple class="px-6 py-4" active-class="bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400 font-bold" @click="rightDrawerOpen = false">
@ -85,10 +85,10 @@ const toggleRightDrawer = () => {
<q-separator class="my-4 mx-6 opacity-50" />
<!-- Tools & Settings -->
<!-- เครื่องมือทั่วไปและการตั้งค่าระบบ -->
<q-item-label header class="text-[11px] font-black tracking-[0.2em] text-slate-400 uppercase px-6 pb-2">เครื่องมือและการตั้งค่า</q-item-label>
<!-- Language Selection -->
<!-- ปุ่มสลับภาษา -->
<q-item class="px-6 py-2">
<q-item-section avatar><q-icon name="language" size="22px" /></q-item-section>
<q-item-section>
@ -99,7 +99,7 @@ const toggleRightDrawer = () => {
</q-item-section>
</q-item>
<!-- Dark Mode Toggle -->
<!-- เปิดปิดโหมดมืด (Dark Mode Toggle) -->
<q-item class="px-6 py-2">
<q-item-section avatar><q-icon :name="isDark ? 'dark_mode' : 'light_mode'" size="22px" /></q-item-section>
<q-item-section>
@ -121,7 +121,7 @@ const toggleRightDrawer = () => {
</q-list>
</div>
<!-- 3. Bottom Actions -->
<!-- 3. ส่วนล่างสุด เช่น ล็อกเอาต์ หรือระบุเวอร์ชันระบบ -->
<div class="p-6 mt-auto border-t border-slate-100 dark:border-slate-800">
<q-btn
unelevated
@ -138,18 +138,16 @@ const toggleRightDrawer = () => {
</div>
</q-drawer>
<!-- Sidebar Removed for this layout -->
<!-- หมายเหตุ: สำหรับหน้านี้ จะไม่ได้มีการโชว์ Sidebar ที่เป็นลิ้นชักซ้าย -->
<!-- Main Content -->
<!-- พื้นที่แสดงเนื้อหาหลัก -->
<q-page-container>
<q-page class="relative">
<slot />
</q-page>
</q-page-container>
<!-- Mobile Bottom Nav - Optional, keeping it consistent with default but maybe not needed if full width?
If we remove sidebar, we might still want mobile nav if it's main navigation.
Let's keep it for now as it doesn't hurt. -->
<!-- เมนูปุ่มกดล่างหน้าจอบนมือถือ (สำหรับช่วยให้เข้าถึงหน้าหลักได้ไวขึ้น) -->
<q-footer
v-if="$q.screen.lt.md"
class="!bg-white dark:!bg-[#1e293b] text-primary"

View file

@ -1,7 +1,8 @@
<script setup lang="ts">
/**
* @file default.vue
* @description Master layout for the EduLearn platform.
* @description เลย์เอาต์หลัก (Master Layout) สำหรับผู้ใช้งานที่เข้าสู่ระบบแล้ว
* ประกอบด้วยแถบเมนูด้านบน (Header), แถบเมนูด้านข้าง (Sidebar) และพื้นที่เนื้อหา
*/
useThemeMode()
@ -13,7 +14,7 @@ const toggleLeftDrawer = () => {
}
const route = useRoute()
// Show sidebar for these routes
// ระบุว่า path ไหนบ้างที่ให้แสดงแถบเมนูด้านข้าง (Sidebar)
const isDashboardRoute = computed(() => {
const routes = ['/dashboard', '/browse', '/classroom', '/course']
return routes.some(r => route.path.startsWith(r))
@ -23,14 +24,14 @@ const isDashboardRoute = computed(() => {
<template>
<q-layout view="lHh Lpr lFf" class="bg-[#F8FAFC] dark:!bg-[#020617] text-slate-900 dark:!text-slate-50">
<!-- Header -->
<!-- ส่วนหัว (Header) -->
<q-header
class="bg-transparent text-slate-900 dark:!text-white border-none shadow-none"
>
<AppHeader @toggleSidebar="toggleLeftDrawer" />
</q-header>
<!-- Navigation Sidebar -->
<!-- แถบเมนูด้านข้าง (Navigation Sidebar) -->
<q-drawer
v-model="leftDrawerOpen"
show-if-above
@ -42,7 +43,7 @@ const isDashboardRoute = computed(() => {
<AppSidebar />
</q-drawer>
<!-- Main Content Area -->
<!-- พื้นที่แสดงเนื้อหาหลัก (Main Content Area) -->
<q-page-container>
<q-page class="px-3 py-6 md:p-8">
<div class="max-w-[1600px] mx-auto">

View file

@ -23,20 +23,20 @@ onMounted(() => {
<q-layout view="lHh LpR lFf" class="bg-white text-slate-900">
<!-- Header (Transparent & Overlay) -->
<!-- ส่วนหัวของเพจ (แบบโปร่งใส และซ้อนทับให้โชว์เนื้อหาพื้นหลังได้) -->
<q-header class="bg-transparent" style="height: auto;">
<LandingHeader />
</q-header>
<!-- Main Content -->
<!-- padding-top: 0 forces content to go under the header (Hero effect) -->
<!-- ส่วนเนื้อหาหลัก -->
<!-- แทรก style padding-top: 0 บังคับให้เนื้อหาใต้ Header ชนชิดด้านบนสุด (ทำเป็น Hero section สวยๆ) -->
<q-page-container style="padding-top: 0 !important;">
<q-page>
<slot />
</q-page>
</q-page-container>
<!-- Footer -->
<!-- ส่วนท้ายของเพจ -->
<LandingFooter />