feat: add learning classroom interface with video playback and a new dashboard index page.

This commit is contained in:
supalerk-ar66 2026-02-02 16:42:30 +07:00
parent 0ec99b140a
commit 2cd1d481aa
3 changed files with 34 additions and 37 deletions

View file

@ -141,7 +141,7 @@ onMounted(() => {
<div class="flex flex-col lg:flex-row gap-8 items-start">
<!-- LEFT SIDEBAR: Category Filter -->
<div class="w-full lg:w-64 flex-shrink-0 sticky top-24">
<div class="w-full lg:w-64 flex-shrink-0 lg:sticky lg:top-24">
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
<q-expansion-item
expand-separator

View file

@ -536,7 +536,7 @@ onBeforeUnmount(() => {
<!-- Header -->
<q-header bordered class="bg-[var(--bg-surface)] border-b border-gray-200 dark:border-white/5 text-[var(--text-main)] h-14">
<q-toolbar>
<q-btn flat round dense icon="menu" class="lg:hidden mr-2" @click="toggleSidebar" />
<q-btn flat round dense icon="menu" class="lg:hidden mr-2 text-slate-900 dark:text-white" @click="toggleSidebar" />
<NuxtLink
to="/dashboard/my-courses"

View file

@ -78,41 +78,38 @@ onMounted(async () => {
<!-- Main Content Area -->
<div class="lg:col-span-12">
<!-- Recommended Courses Container -->
<div class="bg-white dark:bg-[#1e293b] rounded-[2rem] p-8 md:p-10 border border-slate-200 dark:border-white/5 shadow-sm">
<!-- Section Header -->
<div class="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-emerald-500 rounded-full shadow-[0_0_15px_rgba(16,185,129,0.5)]"/>
{{ $t('menu.recommendedCourses') }}
</h2>
</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">
<span class="w-1.5 h-8 bg-emerald-500 rounded-full shadow-[0_0_15px_rgba(16,185,129,0.5)]"/>
{{ $t('menu.recommendedCourses') }}
</h2>
</div>
<!-- Recommended Grid -->
<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="`/course/${course.id}`" 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 bg-slate-50 dark:bg-[#0f172a]">
<div class="h-48 overflow-hidden relative rounded-t-3xl">
<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 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">
<div class="text-[10px] font-black text-slate-700 dark:text-slate-500 uppercase tracking-[0.2em] mb-2">{{ course.category }}</div>
<h4 class="font-black text-xl mb-6 text-slate-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-400 transition-colors line-clamp-2">{{ course.title }}</h4>
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-slate-700 dark:text-slate-400 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-slate-600 dark:text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
{{ course.duration }}
</span>
<span class="px-4 py-2 bg-blue-600 text-white text-xs font-bold rounded-lg hover:bg-blue-700 transition-colors shadow-md">{{ $t('menu.viewDetails') }}</span>
</div>
</div>
</NuxtLink>
</div>
<!-- Recommended Grid -->
<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="`/course/${course.id}`" 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 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 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);">
<div class="text-[10px] font-black text-slate-700 dark:text-slate-500 uppercase tracking-[0.2em] mb-2">{{ course.category }}</div>
<h4 class="font-black text-xl mb-6 text-slate-900 dark:text-white group-hover:text-blue-700 dark:group-hover:text-blue-400 transition-colors line-clamp-2">{{ course.title }}</h4>
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-slate-700 dark:text-slate-400 flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-slate-600 dark:text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
{{ course.duration }}
</span>
<span class="px-4 py-2 bg-blue-600 text-white text-xs font-bold rounded-lg hover:bg-blue-700 transition-colors shadow-md">{{ $t('menu.viewDetails') }}</span>
</div>
</div>
</NuxtLink>
</div>
<!-- Loading State for Recommended -->
<div v-if="recommendedCourses.length === 0" class="flex justify-center py-10 opacity-50">
<div class="animate-pulse">Loading recommendations...</div>
</div>
<!-- Loading State for Recommended -->
<div v-if="recommendedCourses.length === 0" class="flex justify-center py-10 opacity-50">
<div class="animate-pulse">Loading recommendations...</div>
</div>
</div>
</div>