feat: Introduce admin pages for pending course review and course details, and instructor pages for course management and lesson quizzes.
All checks were successful
Build and Deploy Frontend Management to Dev Server / Build Frontend Management Docker Image (push) Successful in 33s
Build and Deploy Frontend Management to Dev Server / Deploy E-learning Frontend Management to Dev Server (push) Successful in 2s
Build and Deploy Frontend Management to Dev Server / Notify Deployment Status (push) Successful in 1s

This commit is contained in:
Missez 2026-02-10 15:24:19 +07:00
parent ff91df2bd6
commit 941b195813
6 changed files with 388 additions and 27 deletions

View file

@ -3,14 +3,15 @@
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-semibold text-gray-900">โครงสรางบทเรยน</h2>
<q-btn
v-if="course.status === 'DRAFT'"
color="primary"
label="จัดการโครงสร้าง"
@click="navigateTo(`/instructor/courses/${courseId}/structure`)"
@click="navigateTo(`/instructor/courses/${course.id}/structure`)"
/>
</div>
<!-- Chapters -->
<div v-if="chapters.length === 0" class="text-center py-10 text-gray-500">
<div v-if="course.chapters.length === 0" class="text-center py-10 text-gray-500">
งไมบทเรยน
</div>
@ -41,6 +42,10 @@
v-for="lesson in getSortedLessons(chapter)"
:key="lesson.id"
class="py-3"
:class="{ 'cursor-pointer hover:bg-gray-50': course.status === 'APPROVED' }"
:clickable="course.status === 'APPROVED'"
:v-ripple="course.status === 'APPROVED'"
@click="handleLessonClick(lesson)"
>
<q-item-section avatar>
<q-icon
@ -53,26 +58,38 @@
Lesson {{ chapter.sort_order }}.{{ lesson.sort_order }}: {{ lesson.title.th }}
</q-item-label>
</q-item-section>
<q-item-section side v-if="course.status === 'APPROVED'">
<q-icon name="visibility" size="xs" color="grey-5" />
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
<!-- Lesson Preview Dialog -->
<LessonPreviewDialog
v-if="previewLesson"
v-model="showPreview"
:lesson="previewLesson"
:course-id="course.id"
/>
</div>
</template>
<script setup lang="ts">
import type { ChapterResponse } from '~/services/instructor.service';
import type { CourseDetailResponse, ChapterResponse, LessonResponse } from '~/services/instructor.service';
import LessonPreviewDialog from './LessonPreviewDialog.vue';
interface Props {
courseId: number;
chapters: ChapterResponse[];
course: CourseDetailResponse;
}
const props = defineProps<Props>();
// Computed
const sortedChapters = computed(() => {
return props.chapters.slice().sort((a, b) => a.sort_order - b.sort_order);
return props.course.chapters.slice().sort((a, b) => a.sort_order - b.sort_order);
});
// Methods
@ -101,4 +118,15 @@ const getLessonIconColor = (type: string) => {
};
return colors[type] || 'grey';
};
// Preview
const showPreview = ref(false);
const previewLesson = ref<LessonResponse | null>(null);
const handleLessonClick = (lesson: LessonResponse) => {
if (props.course.status === 'APPROVED') {
previewLesson.value = lesson;
showPreview.value = true;
}
};
</script>