feat: implement My Courses page with a new CourseCard component and certificate download functionality, along with new Thai locale strings.

This commit is contained in:
supalerk-ar66 2026-02-09 14:30:05 +07:00
parent 6d31cc2e45
commit 0fc67bf9c3
3 changed files with 24 additions and 13 deletions

View file

@ -67,12 +67,7 @@ const displayDescription = computed(() => getLocalizedText(props.description))
<!-- Overlays --> <!-- Overlays -->
<div class="absolute inset-0 bg-gradient-to-t from-slate-900/40 to-transparent"></div> <div class="absolute inset-0 bg-gradient-to-t from-slate-900/40 to-transparent"></div>
<!-- Category Badge -->
<div class="absolute top-4 left-4">
<span class="px-3 py-1 bg-white/90 dark:bg-slate-900/90 backdrop-blur-sm text-[10px] font-black uppercase tracking-widest rounded-lg shadow-sm text-slate-800 dark:text-slate-200">
{{ category }}
</span>
</div>
<!-- Completed Badge --> <!-- Completed Badge -->
<div v-if="completed" class="absolute inset-0 bg-emerald-900/40 backdrop-blur-[2px] flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300"> <div v-if="completed" class="absolute inset-0 bg-emerald-900/40 backdrop-blur-[2px] flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
@ -117,30 +112,43 @@ const displayDescription = computed(() => getLocalizedText(props.description))
</div> </div>
<!-- Action Buttons --> <!-- Action Buttons -->
<!-- View Details (Secondary Action) -->
<q-btn <q-btn
v-if="showViewDetails && !completed && !progress" v-if="showViewDetails && !completed && !progress"
unelevated flat
rounded rounded
class="w-full font-bold shadow-blue-200 dark:shadow-none bg-blue-600 text-white" class="w-full font-bold text-blue-600 bg-blue-50 hover:bg-blue-100 dark:bg-blue-900/20 dark:text-blue-400 dark:hover:bg-blue-900/30"
:label="$t('menu.viewDetails')" :label="$t('menu.viewDetails')"
:to="`/course/${id}`" :to="`/course/${id}`"
/> />
<!-- Continue Learning (Primary Action) -->
<q-btn <q-btn
v-if="showContinue || (progress && !completed)" v-if="showContinue || (progress && !completed) || (progress === 0 && !completed)"
unelevated unelevated
rounded rounded
class="w-full font-bold bg-slate-900 dark:bg-white text-white dark:text-slate-900" class="w-full font-bold bg-blue-600 text-white hover:bg-blue-700 shadow-md shadow-blue-500/20 transition-all hover:scale-[1.02]"
:label="$t('course.continueLearning')" :label="(!progress || progress === 0) ? $t('course.startLearning') : $t('course.continueLearning')"
:to="`/classroom/learning?course_id=${id}`" :to="`/classroom/learning?course_id=${id}`"
/> />
<div v-if="completed" class="space-y-2"> <div v-if="completed" class="space-y-2">
<!-- Study Again -->
<q-btn
v-if="showStudyAgain"
flat
rounded
class="w-full font-bold text-slate-600 hover:text-blue-600 dark:text-slate-400 dark:hover:text-blue-400"
:label="$t('course.studyAgain')"
:to="`/classroom/learning?course_id=${id}`"
/>
<!-- Download Certificate -->
<q-btn <q-btn
v-if="showCertificate" v-if="showCertificate"
outline unelevated
rounded rounded
class="w-full font-bold text-emerald-600 border-emerald-200 dark:text-emerald-400 dark:border-emerald-900" class="w-full font-bold bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:bg-emerald-900/20 dark:text-emerald-400 dark:hover:bg-emerald-900/30 border border-emerald-100 dark:border-emerald-800/50"
:label="$t('course.downloadCertificate')" :label="$t('course.downloadCertificate')"
@click="emit('viewCertificate')" @click="emit('viewCertificate')"
/> />

View file

@ -36,6 +36,7 @@
"certificate": "ใบประกาศ", "certificate": "ใบประกาศ",
"available": "มี", "available": "มี",
"continueLearning": "เรียนต่อทันที", "continueLearning": "เรียนต่อทันที",
"startLearning": "เริ่มเรียนทันที",
"studyAgain": "ทบทวนบทเรียน", "studyAgain": "ทบทวนบทเรียน",
"downloadCertificate": "ดาวน์โหลดประกาศนียบัตร", "downloadCertificate": "ดาวน์โหลดประกาศนียบัตร",
"completed": "เรียนจบเรียบร้อย" "completed": "เรียนจบเรียบร้อย"

View file

@ -168,6 +168,7 @@ const validCourseId = computed(() => {
:progress="course.progress" :progress="course.progress"
:image="course.thumbnail_url" :image="course.thumbnail_url"
show-continue show-continue
:show-view-details="false"
/> />
<!-- Completed Course Card --> <!-- Completed Course Card -->
<CourseCard <CourseCard
@ -179,6 +180,7 @@ const validCourseId = computed(() => {
:completed="true" :completed="true"
show-certificate show-certificate
show-study-again show-study-again
:show-view-details="false"
:loading="downloadingCourseId === course.id" :loading="downloadingCourseId === course.id"
@view-certificate="downloadCertificate(course)" @view-certificate="downloadCertificate(course)"
/> />