107 lines
3.1 KiB
Vue
107 lines
3.1 KiB
Vue
<template>
|
|
<div>
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-semibold text-gray-900">โครงสร้างบทเรียน</h2>
|
|
<q-btn
|
|
color="primary"
|
|
label="จัดการโครงสร้าง"
|
|
@click="navigateTo(`/instructor/courses/${courseId}/structure`)"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Chapters -->
|
|
<div v-if="chapters.length === 0" class="text-center py-10 text-gray-500">
|
|
ยังไม่มีบทเรียน
|
|
</div>
|
|
|
|
<div v-else class="space-y-4">
|
|
<q-card
|
|
v-for="chapter in sortedChapters"
|
|
:key="chapter.id"
|
|
flat
|
|
bordered
|
|
class="rounded-lg"
|
|
>
|
|
<q-card-section>
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<div class="font-semibold text-gray-900">
|
|
Chapter {{ chapter.sort_order }}: {{ chapter.title.th }}
|
|
</div>
|
|
<div class="text-sm text-gray-500 mt-1">
|
|
{{ chapter.lessons.length }} บทเรียน · {{ getChapterDuration(chapter) }} นาที
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</q-card-section>
|
|
|
|
<!-- Lessons -->
|
|
<q-list separator class="border-t">
|
|
<q-item
|
|
v-for="lesson in getSortedLessons(chapter)"
|
|
:key="lesson.id"
|
|
class="py-3"
|
|
>
|
|
<q-item-section avatar>
|
|
<q-icon
|
|
:name="getLessonIcon(lesson.type)"
|
|
:color="getLessonIconColor(lesson.type)"
|
|
/>
|
|
</q-item-section>
|
|
<q-item-section>
|
|
<q-item-label>
|
|
Lesson {{ chapter.sort_order }}.{{ lesson.sort_order }}: {{ lesson.title.th }}
|
|
</q-item-label>
|
|
</q-item-section>
|
|
<q-item-section side>
|
|
<span class="text-sm text-gray-500">{{ lesson.duration_minutes }} นาที</span>
|
|
</q-item-section>
|
|
</q-item>
|
|
</q-list>
|
|
</q-card>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { ChapterResponse } from '~/services/instructor.service';
|
|
|
|
interface Props {
|
|
courseId: number;
|
|
chapters: ChapterResponse[];
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
// Computed
|
|
const sortedChapters = computed(() => {
|
|
return props.chapters.slice().sort((a, b) => a.sort_order - b.sort_order);
|
|
});
|
|
|
|
// Methods
|
|
const getChapterDuration = (chapter: ChapterResponse) => {
|
|
return chapter.lessons.reduce((sum, l) => sum + l.duration_minutes, 0);
|
|
};
|
|
|
|
const getSortedLessons = (chapter: ChapterResponse) => {
|
|
return chapter.lessons.slice().sort((a, b) => a.sort_order - b.sort_order);
|
|
};
|
|
|
|
const getLessonIcon = (type: string) => {
|
|
const icons: Record<string, string> = {
|
|
VIDEO: 'play_circle',
|
|
DOCUMENT: 'description',
|
|
QUIZ: 'quiz'
|
|
};
|
|
return icons[type] || 'article';
|
|
};
|
|
|
|
const getLessonIconColor = (type: string) => {
|
|
const colors: Record<string, string> = {
|
|
VIDEO: 'blue',
|
|
DOCUMENT: 'orange',
|
|
QUIZ: 'orange'
|
|
};
|
|
return colors[type] || 'grey';
|
|
};
|
|
</script>
|