feat: Implement instructor course management pages and service for listing, creating, viewing, and editing courses.
This commit is contained in:
parent
cad3f276f5
commit
1e06041769
5 changed files with 838 additions and 9 deletions
|
|
@ -147,16 +147,119 @@ export const instructorService = {
|
|||
}
|
||||
|
||||
const token = getAuthToken();
|
||||
|
||||
// Clean data - remove empty thumbnail_url
|
||||
const cleanedData = { ...data };
|
||||
if (!cleanedData.thumbnail_url) {
|
||||
delete cleanedData.thumbnail_url;
|
||||
}
|
||||
|
||||
console.log('=== CREATE COURSE DEBUG ===');
|
||||
console.log('Body:', JSON.stringify({ data: cleanedData }, null, 2));
|
||||
console.log('===========================');
|
||||
|
||||
const response = await $fetch<{ code: number; data: CourseResponse }>('/api/instructors/courses', {
|
||||
method: 'POST',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
body: { data: cleanedData }
|
||||
});
|
||||
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getCourseById(courseId: number): Promise<CourseDetailResponse> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
return MOCK_COURSE_DETAIL;
|
||||
}
|
||||
|
||||
const token = getAuthToken();
|
||||
const response = await $fetch<{ code: number; data: CourseDetailResponse }>(`/api/instructors/courses/${courseId}`, {
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async updateCourse(courseId: number, data: CreateCourseRequest): Promise<CourseResponse> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
return {
|
||||
...MOCK_COURSES[0],
|
||||
id: courseId,
|
||||
...data,
|
||||
price: String(data.price)
|
||||
} as CourseResponse;
|
||||
}
|
||||
|
||||
const token = getAuthToken();
|
||||
|
||||
// Debug log
|
||||
console.log('=== UPDATE COURSE DEBUG ===');
|
||||
console.log('URL:', `${config.public.apiBaseUrl}/api/instructors/courses/${courseId}`);
|
||||
console.log('Body:', JSON.stringify({ data }, null, 2));
|
||||
console.log('===========================');
|
||||
|
||||
const response = await $fetch<{ code: number; data: CourseResponse }>(`/api/instructors/courses/${courseId}`, {
|
||||
method: 'PUT',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
body: { data }
|
||||
});
|
||||
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async deleteCourse(courseId: number): Promise<void> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = getAuthToken();
|
||||
await $fetch(`/api/instructors/courses/${courseId}`, {
|
||||
method: 'DELETE',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async sendForReview(courseId: number): Promise<void> {
|
||||
const config = useRuntimeConfig();
|
||||
const useMockData = config.public.useMockData as boolean;
|
||||
|
||||
if (useMockData) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
return;
|
||||
}
|
||||
|
||||
const token = getAuthToken();
|
||||
await $fetch(`/api/instructors/courses/send-review/${courseId}`, {
|
||||
method: 'POST',
|
||||
baseURL: config.public.apiBaseUrl as string,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -177,3 +280,154 @@ export interface CreateCourseRequest {
|
|||
is_free: boolean;
|
||||
have_certificate: boolean;
|
||||
}
|
||||
|
||||
// Course detail with chapters and lessons
|
||||
export interface CourseDetailResponse extends CourseResponse {
|
||||
chapters: ChapterResponse[];
|
||||
}
|
||||
|
||||
export interface ChapterResponse {
|
||||
id: number;
|
||||
course_id: number;
|
||||
title: { en: string; th: string };
|
||||
description: { en: string; th: string };
|
||||
sort_order: number;
|
||||
is_published: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
lessons: LessonResponse[];
|
||||
}
|
||||
|
||||
export interface LessonResponse {
|
||||
id: number;
|
||||
chapter_id: number;
|
||||
title: { en: string; th: string };
|
||||
content: { en: string; th: string } | null;
|
||||
type: 'VIDEO' | 'QUIZ' | 'DOCUMENT';
|
||||
duration_minutes: number;
|
||||
sort_order: number;
|
||||
is_sequential: boolean;
|
||||
prerequisite_lesson_ids: number[] | null;
|
||||
require_pass_quiz: boolean;
|
||||
is_published: boolean;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
quiz: QuizResponse | null;
|
||||
}
|
||||
|
||||
export interface QuizResponse {
|
||||
id: number;
|
||||
lesson_id: number;
|
||||
title: { en: string; th: string };
|
||||
description: { en: string; th: string };
|
||||
passing_score: number;
|
||||
time_limit: number;
|
||||
shuffle_questions: boolean;
|
||||
shuffle_choices: boolean;
|
||||
show_answers_after_completion: boolean;
|
||||
}
|
||||
|
||||
// Mock course detail
|
||||
const MOCK_COURSE_DETAIL: CourseDetailResponse = {
|
||||
...MOCK_COURSES[0],
|
||||
chapters: [
|
||||
{
|
||||
id: 1,
|
||||
course_id: 1,
|
||||
title: { en: 'Chapter 1: Getting Started', th: 'บทที่ 1: เริ่มต้น' },
|
||||
description: { en: 'Introduction to JavaScript', th: 'แนะนำ JavaScript' },
|
||||
sort_order: 1,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
lessons: [
|
||||
{
|
||||
id: 1,
|
||||
chapter_id: 1,
|
||||
title: { en: 'What is JavaScript', th: 'JavaScript คืออะไร' },
|
||||
content: { en: 'Introduction', th: 'แนะนำ' },
|
||||
type: 'VIDEO',
|
||||
duration_minutes: 15,
|
||||
sort_order: 1,
|
||||
is_sequential: true,
|
||||
prerequisite_lesson_ids: null,
|
||||
require_pass_quiz: false,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
quiz: null
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
chapter_id: 1,
|
||||
title: { en: 'Variables', th: 'ตัวแปร' },
|
||||
content: { en: 'Learn variables', th: 'เรียนรู้ตัวแปร' },
|
||||
type: 'VIDEO',
|
||||
duration_minutes: 20,
|
||||
sort_order: 2,
|
||||
is_sequential: true,
|
||||
prerequisite_lesson_ids: null,
|
||||
require_pass_quiz: false,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
quiz: null
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
chapter_id: 1,
|
||||
title: { en: 'Chapter 1 Quiz', th: 'แบบทดสอบบทที่ 1' },
|
||||
content: null,
|
||||
type: 'QUIZ',
|
||||
duration_minutes: 10,
|
||||
sort_order: 3,
|
||||
is_sequential: true,
|
||||
prerequisite_lesson_ids: null,
|
||||
require_pass_quiz: true,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
quiz: {
|
||||
id: 1,
|
||||
lesson_id: 3,
|
||||
title: { en: 'Chapter 1 Quiz', th: 'แบบทดสอบบทที่ 1' },
|
||||
description: { en: 'Test your knowledge', th: 'ทดสอบความรู้' },
|
||||
passing_score: 70,
|
||||
time_limit: 10,
|
||||
shuffle_questions: true,
|
||||
shuffle_choices: true,
|
||||
show_answers_after_completion: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
course_id: 1,
|
||||
title: { en: 'Chapter 2: Functions', th: 'บทที่ 2: ฟังก์ชัน' },
|
||||
description: { en: 'Learn about functions', th: 'เรียนรู้เกี่ยวกับฟังก์ชัน' },
|
||||
sort_order: 2,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
lessons: [
|
||||
{
|
||||
id: 4,
|
||||
chapter_id: 2,
|
||||
title: { en: 'Creating Functions', th: 'การสร้างฟังก์ชัน' },
|
||||
content: { en: 'How to create functions', th: 'วิธีสร้างฟังก์ชัน' },
|
||||
type: 'VIDEO',
|
||||
duration_minutes: 25,
|
||||
sort_order: 1,
|
||||
is_sequential: true,
|
||||
prerequisite_lesson_ids: null,
|
||||
require_pass_quiz: false,
|
||||
is_published: true,
|
||||
created_at: '2024-01-15T00:00:00Z',
|
||||
updated_at: '2024-01-15T00:00:00Z',
|
||||
quiz: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue