feat: Add dashboard, course discovery, and quiz pages to introduce core e-learning functionalities.

This commit is contained in:
supalerk-ar66 2026-01-21 17:14:58 +07:00
parent f6bbd60f2b
commit db9ff684ae
3 changed files with 38 additions and 269 deletions

View file

@ -25,14 +25,6 @@ const getLocalizedText = (text: string | { th: string; en: string } | undefined)
return text.th || text.en || ''
}
// Mock data: Recent Course Progress
const recentCourse = {
title: 'เบื้องต้นการออกแบบ UX/UI',
lesson: 'บทที่ 3: พื้นฐานการวาดโครงร่าง (Wireframing Basics)',
progress: 65,
image: 'https://images.unsplash.com/photo-1586717791821-3f44a563de4c?w=400&auto=format&fit=crop&q=60'
}
// Recommended Courses State
const recommendedCourses = ref<any[]>([])
@ -56,9 +48,9 @@ onMounted(async () => {
title: getLocalizedText(c.title),
category: getLocalizedText(catMap.get(c.category_id)) || 'General', // Map Category ID to Name
duration: c.lessons ? `${c.lessons} บทเรียน` : 'พร้อมเรียน', // Use lesson count or default
image: c.thumbnail_url || 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?w=400&q=80',
badge: 'Recommended',
badgeType: 'warning'
image: c.thumbnail_url || '',
badge: '', // No mock badge
badgeType: ''
}))
}
})
@ -83,43 +75,6 @@ onMounted(async () => {
<!-- Main Content Area -->
<div class="lg:col-span-12">
<!-- Section: Continue Learning -->
<div class="flex items-center justify-between mb-8">
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
<span class="w-1.5 h-8 bg-blue-500 rounded-full shadow-[0_0_15px_rgba(59,130,246,0.5)]"/>
{{ $t('menu.continueLearning') }}
</h2>
<NuxtLink to="/classroom/learning" class="text-sm font-black text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 transition-colors uppercase tracking-widest">{{ $t('menu.goToLesson') }} </NuxtLink>
</div>
<!-- Featured Current Course Card -->
<div class="p-0 overflow-hidden group mb-12 border border-slate-200 dark:border-white/5 rounded-3xl shadow-sm dark:shadow-2xl transition-all hover:-translate-y-1 dark:hover:-translate-y-1" style="background-color: var(--bg-surface);">
<div class="flex flex-col md:flex-row">
<!-- Course Image -->
<div class="md:w-2/5 aspect-video md:aspect-auto overflow-hidden relative rounded-t-3xl md:rounded-l-3xl md:rounded-tr-none">
<img :src="recentCourse.image" :alt="recentCourse.title" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" >
<div class="absolute inset-0 bg-gradient-to-t from-slate-900/30 via-transparent to-transparent opacity-40 dark:opacity-60 dark:from-[#0f172a]"/>
</div>
<!-- Course Details & Progress -->
<div class="p-8 md:p-10 flex-1 flex flex-col justify-center" style="background-color: var(--bg-surface);">
<span class="text-[10px] font-black uppercase tracking-[0.2em] text-blue-700 dark:text-blue-400 mb-3">{{ $t('course.currentlyLearning') }}</span>
<h3 class="text-3xl font-black mb-2 leading-tight text-slate-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-400 transition-colors">{{ recentCourse.title }}</h3>
<p class="text-slate-700 dark:text-slate-400 text-base mb-8 font-medium">{{ recentCourse.lesson }}</p>
<!-- Progress Bar -->
<div class="mt-auto bg-slate-100 dark:bg-slate-900/50 p-6 rounded-3xl border border-slate-200 dark:border-white/5">
<div class="flex justify-between items-center mb-3">
<span class="text-xs font-black text-slate-800 dark:text-slate-500 uppercase tracking-widest">{{ $t('course.progress') }}</span>
<span class="text-sm font-black text-blue-700 dark:text-blue-400">{{ recentCourse.progress }}%</span>
</div>
<div class="h-2.5 w-full bg-slate-300 dark:bg-slate-700 rounded-full overflow-hidden shadow-inner">
<div class="h-full bg-gradient-to-r from-blue-600 to-blue-500 rounded-full shadow-[0_0_10px_rgba(59,130,246,0.3)] transition-all duration-1000" :style="{ width: `${recentCourse.progress}%` }"/>
</div>
</div>
</div>
</div>
</div>
<!-- Section: Recommended Courses -->
<div class="mb-8">
<h2 class="text-2xl font-black flex items-center gap-3 tracking-tight text-slate-900 dark:text-white">
@ -132,8 +87,10 @@ onMounted(async () => {
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<NuxtLink v-for="(course, idx) in recommendedCourses" :key="course.id" to="/browse/discovery" class="p-0 overflow-hidden group border border-slate-200 dark:border-white/5 rounded-3xl shadow-sm dark:shadow-xl transition-all hover:-translate-y-1 dark:hover:-translate-y-1 block" style="background-color: var(--bg-surface);">
<div class="h-48 overflow-hidden relative rounded-t-3xl">
<img :src="course.image" :alt="course.title" class="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" >
<span v-if="course.badge" :class="`absolute top-5 left-5 status-pill status-${course.badgeType} shadow-lg font-black text-[9px]`">{{ course.badge }}</span>
<img v-if="course.image" :src="course.image" :alt="course.title" class="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" >
<div v-else class="w-full h-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center">
<span class="text-4xl">📚</span>
</div>
<div class="absolute inset-x-0 bottom-0 h-1/2 bg-gradient-to-t from-slate-900/20 dark:from-[#1e293b] to-transparent"/>
</div>
<div class="p-7" style="background-color: var(--bg-surface);">