elearning/Frontend-Learner/components/classroom/CurriculumSidebar.vue

90 lines
3.2 KiB
Vue

<script setup lang="ts">
/**
* @file CurriculumSidebar.vue
* @description Sidebar Component for displaying course curriculum (Chapters & Lessons)
* Handles lesson navigation, locked status display, and unread announcement badge.
*/
const props = defineProps<{
modelValue: boolean; // Sidebar open state (v-model)
courseData: any;
currentLessonId?: number;
isLoading: boolean;
hasUnreadAnnouncements: boolean;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
(e: 'select-lesson', lessonId: number): void;
(e: 'open-announcements'): void;
}>();
const { locale } = useI18n()
// Helper for localization
const getLocalizedText = (text: any) => {
if (!text) return ''
if (typeof text === 'string') return text
const currentLocale = locale.value as 'th' | 'en'
return text[currentLocale] || text.th || text.en || ''
}
</script>
<template>
<q-drawer
:model-value="modelValue"
@update:model-value="(val) => emit('update:modelValue', val)"
show-if-above
bordered
side="left"
:width="320"
:breakpoint="1024"
class="bg-[var(--bg-surface)]"
content-class="bg-[var(--bg-surface)]"
>
<div v-if="courseData" class="h-full scroll">
<q-list class="pb-10">
<template v-for="chapter in courseData.chapters" :key="chapter.id">
<q-item-label header class="bg-slate-100 dark:bg-slate-800 text-[var(--text-main)] font-bold sticky top-0 z-10 border-b dark:border-white/5 text-sm py-4">
{{ getLocalizedText(chapter.title) }}
</q-item-label>
<q-item
v-for="lesson in chapter.lessons"
:key="lesson.id"
clickable
v-ripple
:active="currentLessonId === lesson.id"
active-class="bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:text-blue-200 font-medium"
class="border-b border-gray-50 dark:border-white/5"
@click="!lesson.is_locked && emit('select-lesson', lesson.id)"
:disable="lesson.is_locked"
>
<q-item-section avatar v-if="lesson.is_locked">
<q-icon name="lock" size="xs" color="grey" />
</q-item-section>
<q-item-section>
<q-item-label class="text-sm md:text-base line-clamp-2 text-[var(--text-main)]">
{{ getLocalizedText(lesson.title) }}
</q-item-label>
</q-item-section>
<q-item-section side>
<q-icon v-if="lesson.is_completed || lesson.progress?.is_completed" name="check_circle" color="positive" size="xs" />
<q-icon v-else-if="currentLessonId === lesson.id" name="play_circle" color="primary" size="xs" />
<q-icon v-else name="radio_button_unchecked" color="grey-4" size="xs" />
</q-item-section>
</q-item>
</template>
</q-list>
</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">{{ $t('classroom.loadingCurriculum') }}</div>
</div>
</q-drawer>
</template>