feat: Implement comprehensive quiz functionality, new browse pages, and a classroom learning page with i18n support.
This commit is contained in:
parent
b96f85e650
commit
e082c77946
6 changed files with 234 additions and 107 deletions
|
|
@ -1,4 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* @file learning.vue
|
||||
* @description หน้าเรียนออนไลน์ (Classroom Interface)
|
||||
|
|
@ -17,6 +17,7 @@ useHead({
|
|||
})
|
||||
|
||||
const route = useRoute()
|
||||
const { t } = useI18n()
|
||||
const { fetchCourseLearningInfo, fetchLessonContent, saveVideoProgress, markLessonComplete, checkLessonAccess } = useCourse()
|
||||
|
||||
// State
|
||||
|
|
@ -43,8 +44,9 @@ const saveProgressInterval = ref<any>(null) // ตัวแปรเก็บ se
|
|||
|
||||
// Helper for localization
|
||||
const getLocalizedText = (text: any) => {
|
||||
if (!text) return ''
|
||||
if (typeof text === 'string') return text
|
||||
return text?.th || text?.en || ''
|
||||
return text.th || text.en || ''
|
||||
}
|
||||
|
||||
const toggleSidebar = () => {
|
||||
|
|
@ -108,7 +110,7 @@ const loadLesson = async (lessonId: number) => {
|
|||
// Optional: Check access first
|
||||
const accessRes = await checkLessonAccess(courseId.value, lessonId)
|
||||
if (accessRes.success && !accessRes.data.is_accessible) {
|
||||
alert('บทเรียนนี้ยังไม่เปิดให้เข้าชม')
|
||||
alert(t('classroom.notAvailable'))
|
||||
isLessonLoading.value = false
|
||||
return
|
||||
}
|
||||
|
|
@ -245,10 +247,10 @@ onBeforeUnmount(() => {
|
|||
<q-toolbar>
|
||||
<q-btn flat round dense icon="menu" class="lg:hidden mr-2" @click="toggleSidebar" />
|
||||
|
||||
<q-btn flat dense no-caps icon="arrow_back" label="กลับไปหน้าหลัก" to="/dashboard/my-courses" class="text-slate-600 dark:text-slate-300 mobile-hide-label" />
|
||||
<q-btn flat dense no-caps icon="arrow_back" :label="$t('classroom.backToDashboard')" to="/dashboard/my-courses" class="text-slate-600 dark:text-slate-300 mobile-hide-label" />
|
||||
|
||||
<q-toolbar-title class="text-sm font-bold text-center lg:text-left truncate">
|
||||
{{ courseData ? getLocalizedText(courseData.course.title) : 'กำลังโหลด...' }}
|
||||
{{ courseData ? getLocalizedText(courseData.course.title) : $t('classroom.loadingTitle') }}
|
||||
</q-toolbar-title>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -306,7 +308,7 @@ onBeforeUnmount(() => {
|
|||
</div>
|
||||
<div v-else-if="isLoading" class="p-6 text-center text-slate-500">
|
||||
<q-spinner color="primary" size="2em" />
|
||||
<div class="mt-2 text-xs">กำลังโหลดเนื้อหา...</div>
|
||||
<div class="mt-2 text-xs">{{ $t('classroom.loadingCurriculum') }}</div>
|
||||
</div>
|
||||
</q-drawer>
|
||||
|
||||
|
|
@ -314,9 +316,8 @@ onBeforeUnmount(() => {
|
|||
<q-page-container class="bg-white dark:bg-slate-900">
|
||||
<q-page class="flex flex-col h-full bg-slate-50 dark:bg-[#0B0F1A]">
|
||||
<!-- Video Player & Content Area -->
|
||||
<!-- Note: Using existing logic but wrapped -->
|
||||
<div class="w-full max-w-7xl mx-auto p-4 md:p-6 flex-grow">
|
||||
<!-- Video Player Component Placeholder logic -->
|
||||
<!-- Video Player -->
|
||||
<div v-if="currentLesson" class="bg-black rounded-xl overflow-hidden shadow-lg mb-6 aspect-video relative group">
|
||||
<video
|
||||
ref="videoRef"
|
||||
|
|
@ -331,7 +332,7 @@ onBeforeUnmount(() => {
|
|||
<div v-else class="flex items-center justify-center h-full text-white/50 bg-slate-900">
|
||||
<div class="text-center">
|
||||
<q-icon name="article" size="xl" />
|
||||
<p class="mt-2">บทเรียนนี้เป็นเอกสารประกอบการเรียน</p>
|
||||
<p class="mt-2">{{ $t('classroom.readingMaterial') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -351,11 +352,10 @@ onBeforeUnmount(() => {
|
|||
<div v-if="currentLesson" class="bg-white dark:bg-slate-800 p-6 rounded-2xl shadow-sm border border-slate-100 dark:border-white/5">
|
||||
<h1 class="text-2xl font-bold mb-2">{{ getLocalizedText(currentLesson.title) }}</h1>
|
||||
<p class="text-slate-500 dark:text-slate-400" v-if="currentLesson.description">{{ currentLesson.description }}</p>
|
||||
<div class="mt-6 prose dark:prose-invert max-w-none">
|
||||
<!-- Content description or attachments here -->
|
||||
<div v-if="!videoSrc" class="p-4 bg-slate-50 dark:bg-slate-900/50 rounded-xl border border-dashed border-slate-300 dark:border-slate-700 text-center">
|
||||
<p>เนื้อหาบทเรียน</p>
|
||||
</div>
|
||||
|
||||
<!-- Lesson Content Area -->
|
||||
<div v-if="!videoSrc && currentLesson.content" class="mt-6 prose dark:prose-invert max-w-none p-6 bg-slate-50 dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/5">
|
||||
<div v-html="getLocalizedText(currentLesson.content)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -376,4 +376,3 @@ onBeforeUnmount(() => {
|
|||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue