feat: del mock , crud add instructor , VerifyEmail

This commit is contained in:
Missez 2026-02-03 11:55:26 +07:00
parent b2365a4c6a
commit 278bc17fa0
8 changed files with 345 additions and 1566 deletions

View file

@ -63,6 +63,23 @@ export interface InstructorsListResponse {
data: CourseInstructorResponse[];
}
export interface SearchInstructorResult {
id: number;
username: string;
email: string;
profile: {
first_name: string;
last_name: string;
avatar_url: string | null;
};
}
export interface SearchInstructorsResponse {
code: number;
message: string;
data: SearchInstructorResult[];
}
// Helper function to get auth token from cookie
const getAuthToken = (): string => {
const tokenCookie = useCookie('token');
@ -108,113 +125,14 @@ const authRequest = async <T>(
}
};
// Mock courses data
const MOCK_COURSES: CourseResponse[] = [
{
id: 1,
category_id: 1,
title: { en: 'JavaScript Fundamentals', th: 'พื้นฐาน JavaScript' },
slug: 'javascript-fundamentals',
description: {
en: 'Learn JavaScript fundamentals from scratch',
th: 'เรียนรู้พื้นฐาน JavaScript ตั้งแต่เริ่มต้น'
},
thumbnail_url: null,
price: '0',
is_free: true,
have_certificate: true,
status: 'APPROVED',
approved_by: 1,
approved_at: '2024-01-15T00:00:00Z',
rejection_reason: null,
created_at: '2024-01-15T00:00:00Z',
created_by: 2,
updated_at: '2024-01-15T00:00:00Z',
updated_by: null
},
{
id: 2,
category_id: 2,
title: { en: 'React for Beginners', th: 'React สำหรับผู้เริ่มต้น' },
slug: 'react-for-beginners',
description: {
en: 'Build modern web apps with React',
th: 'สร้างเว็บแอปพลิเคชันด้วย React'
},
thumbnail_url: null,
price: '990',
is_free: false,
have_certificate: true,
status: 'PENDING',
approved_by: null,
approved_at: null,
rejection_reason: null,
created_at: '2024-02-01T00:00:00Z',
created_by: 2,
updated_at: '2024-02-01T00:00:00Z',
updated_by: null
},
{
id: 3,
category_id: 1,
title: { en: 'TypeScript Masterclass', th: 'TypeScript ขั้นสูง' },
slug: 'typescript-masterclass',
description: {
en: 'Master TypeScript for better JavaScript development',
th: 'เรียนรู้ TypeScript เพื่อพัฒนา JavaScript ได้ดียิ่งขึ้น'
},
thumbnail_url: null,
price: '1290',
is_free: false,
have_certificate: true,
status: 'DRAFT',
approved_by: null,
approved_at: null,
rejection_reason: null,
created_at: '2024-02-15T00:00:00Z',
created_by: 2,
updated_at: '2024-02-15T00:00:00Z',
updated_by: null
}
];
export const instructorService = {
async getCourses(): Promise<CourseResponse[]> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return MOCK_COURSES;
}
const response = await authRequest<CoursesListResponse>('/api/instructors/courses');
return response.data;
},
async createCourse(data: CreateCourseRequest): Promise<ApiResponse<CourseResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 201,
message: 'Course created successfully (Mock)',
data: {
...MOCK_COURSES[0],
id: Date.now(),
...data,
price: String(data.price), // Convert number to string to match CourseResponse type
status: 'DRAFT',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
} as CourseResponse
};
}
// Clean data - remove empty thumbnail_url
const cleanedData = { ...data };
if (!cleanedData.thumbnail_url) {
delete cleanedData.thumbnail_url;
@ -230,36 +148,11 @@ export const instructorService = {
},
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 response = await authRequest<{ code: number; data: CourseDetailResponse }>(`/api/instructors/courses/${courseId}`);
return response.data;
},
async updateCourse(courseId: number, data: CreateCourseRequest): Promise<ApiResponse<CourseResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Course updated successfully (Mock)',
data: {
...MOCK_COURSES[0],
id: courseId,
...data,
price: String(data.price)
} as CourseResponse
};
}
return await authRequest<ApiResponse<CourseResponse>>(`/api/instructors/courses/${courseId}`, {
method: 'PUT',
body: { data }
@ -267,18 +160,6 @@ export const instructorService = {
},
async uploadCourseThumbnail(courseId: number, file: File): Promise<ApiResponse<{ thumbnail_url: string }>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Thumbnail uploaded successfully (Mock)',
data: { thumbnail_url: URL.createObjectURL(file) }
};
}
const formData = new FormData();
formData.append('file', file);
@ -289,70 +170,20 @@ export const instructorService = {
},
async getCourseInstructors(courseId: number): Promise<CourseInstructorResponse[]> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return [
{
id: 1,
course_id: courseId,
user_id: 1,
is_primary: true,
joined_at: new Date().toISOString(),
user: {
id: 1,
username: 'instructor',
email: 'instructor@elearning.local',
role_id: 2,
email_verified_at: new Date().toISOString(),
is_deactivated: false,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
}
}
];
}
const response = await authRequest<InstructorsListResponse>(
`/api/instructors/courses/listinstructor/${courseId}`
);
return response.data;
},
async addInstructor(courseId: number, userId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Instructor added successfully (Mock)',
data: undefined
};
}
async addInstructor(courseId: number, emailOrUsername: string): Promise<ApiResponse<void>> {
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/add-instructor/${courseId}/${userId}`,
`/api/instructors/courses/add-instructor/${courseId}/${encodeURIComponent(emailOrUsername)}`,
{ method: 'POST' }
);
},
async removeInstructor(courseId: number, userId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Instructor removed successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/remove-instructor/${courseId}/${userId}`,
{ method: 'DELETE' }
@ -360,65 +191,28 @@ export const instructorService = {
},
async setPrimaryInstructor(courseId: number, userId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Primary instructor updated successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/set-primary-instructor/${courseId}/${userId}`,
{ method: 'PUT' }
);
},
async searchInstructors(query: string): Promise<SearchInstructorResult[]> {
const response = await authRequest<SearchInstructorsResponse>(
`/api/instructors/courses/search-instructors?query=${encodeURIComponent(query)}`
);
return response.data;
},
async deleteCourse(courseId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Course deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(`/api/instructors/courses/${courseId}`, { method: 'DELETE' });
},
async sendForReview(courseId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Sent for review successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(`/api/instructors/courses/send-review/${courseId}`, { method: 'POST' });
},
async getChapters(courseId: number): Promise<ChapterResponse[]> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return MOCK_COURSE_DETAIL.chapters;
}
// Get chapters from course detail endpoint
const response = await authRequest<{ code: number; data: { chapters: ChapterResponse[] } }>(
`/api/instructors/courses/${courseId}`
@ -427,23 +221,6 @@ export const instructorService = {
},
async createChapter(courseId: number, data: CreateChapterRequest): Promise<ApiResponse<ChapterResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 201,
message: 'Chapter created successfully (Mock)',
data: {
...MOCK_COURSE_DETAIL.chapters[0],
id: Date.now(),
...data,
lessons: []
}
};
}
return await authRequest<ApiResponse<ChapterResponse>>(
`/api/instructors/courses/${courseId}/chapters`,
{ method: 'POST', body: data }
@ -451,22 +228,6 @@ export const instructorService = {
},
async updateChapter(courseId: number, chapterId: number, data: CreateChapterRequest): Promise<ApiResponse<ChapterResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Chapter updated successfully (Mock)',
data: {
...MOCK_COURSE_DETAIL.chapters[0],
id: chapterId,
...data
}
};
}
return await authRequest<ApiResponse<ChapterResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}`,
{ method: 'PUT', body: data }
@ -474,18 +235,6 @@ export const instructorService = {
},
async deleteChapter(courseId: number, chapterId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Chapter deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}`,
{ method: 'DELETE' }
@ -493,18 +242,6 @@ export const instructorService = {
},
async reorderChapter(courseId: number, chapterId: number, sortOrder: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 300));
return {
code: 200,
message: 'Chapter reordered successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/reorder`,
{ method: 'PUT', body: { sort_order: sortOrder } }
@ -513,14 +250,6 @@ export const instructorService = {
// Lesson CRUD
async getLesson(courseId: number, chapterId: number, lessonId: number): Promise<LessonDetailResponse> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return MOCK_COURSE_DETAIL.chapters[0].lessons[0] as LessonDetailResponse;
}
const response = await authRequest<{ code: number; data: LessonDetailResponse }>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}`
);
@ -528,22 +257,6 @@ export const instructorService = {
},
async createLesson(courseId: number, chapterId: number, data: CreateLessonRequest): Promise<ApiResponse<LessonResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 201,
message: 'Lesson created successfully (Mock)',
data: {
...MOCK_COURSE_DETAIL.chapters[0].lessons[0],
id: Date.now(),
...data
}
};
}
return await authRequest<ApiResponse<LessonResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons`,
{ method: 'POST', body: data }
@ -551,22 +264,6 @@ export const instructorService = {
},
async updateLesson(courseId: number, chapterId: number, lessonId: number, data: UpdateLessonRequest): Promise<ApiResponse<LessonResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Lesson updated successfully (Mock)',
data: {
...MOCK_COURSE_DETAIL.chapters[0].lessons[0],
id: lessonId,
...data
}
};
}
return await authRequest<ApiResponse<LessonResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}`,
{ method: 'PUT', body: data }
@ -574,18 +271,6 @@ export const instructorService = {
},
async deleteLesson(courseId: number, chapterId: number, lessonId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Lesson deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}`,
{ method: 'DELETE' }
@ -593,18 +278,6 @@ export const instructorService = {
},
async reorderLesson(courseId: number, chapterId: number, lessonId: number, sortOrder: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 300));
return {
code: 200,
message: 'Lesson reordered successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/reorder-lessons`,
{ method: 'PUT', body: { lesson_id: lessonId, sort_order: sortOrder } }
@ -613,35 +286,6 @@ export const instructorService = {
// Question CRUD
async createQuestion(courseId: number, chapterId: number, lessonId: number, data: CreateQuestionRequest): Promise<ApiResponse<QuizQuestionResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 201,
message: 'Question created successfully (Mock)',
data: {
id: Date.now(),
quiz_id: 1,
question: data.question,
explanation: data.explanation || null,
question_type: data.question_type,
score: data.score || 1,
sort_order: data.sort_order || 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
choices: data.choices.map((c, i) => ({
id: Date.now() + i,
question_id: Date.now(),
text: c.text,
is_correct: c.is_correct,
sort_order: c.sort_order || i + 1
}))
}
};
}
return await authRequest<ApiResponse<QuizQuestionResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/questions`,
{ method: 'POST', body: data }
@ -649,35 +293,6 @@ export const instructorService = {
},
async updateQuestion(courseId: number, chapterId: number, lessonId: number, questionId: number, data: CreateQuestionRequest): Promise<ApiResponse<QuizQuestionResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Question updated successfully (Mock)',
data: {
id: questionId,
quiz_id: 1,
question: data.question,
explanation: data.explanation || null,
question_type: data.question_type,
score: data.score || 1,
sort_order: data.sort_order || 1,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
choices: data.choices.map((c, i) => ({
id: Date.now() + i,
question_id: questionId,
text: c.text,
is_correct: c.is_correct,
sort_order: c.sort_order || i + 1
}))
}
};
}
return await authRequest<ApiResponse<QuizQuestionResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/questions/${questionId}`,
{ method: 'PUT', body: data }
@ -685,18 +300,6 @@ export const instructorService = {
},
async deleteQuestion(courseId: number, chapterId: number, lessonId: number, questionId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Question deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/questions/${questionId}`,
{ method: 'DELETE' }
@ -704,18 +307,6 @@ export const instructorService = {
},
async reorderQuestion(courseId: number, chapterId: number, lessonId: number, questionId: number, sortOrder: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 300));
return {
code: 200,
message: 'Question reordered successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/questions/${questionId}/reorder`,
{ method: 'PUT', body: { sort_order: sortOrder } }
@ -724,28 +315,6 @@ export const instructorService = {
// Quiz Settings
async updateQuizSettings(courseId: number, chapterId: number, lessonId: number, data: UpdateQuizSettingsRequest): Promise<ApiResponse<QuizResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Quiz settings updated successfully (Mock)',
data: {
id: 1,
lesson_id: lessonId,
title: data.title,
description: data.description,
passing_score: data.passing_score,
time_limit: data.time_limit,
shuffle_questions: data.shuffle_questions,
shuffle_choices: data.shuffle_choices,
show_answers_after_completion: data.show_answers_after_completion
}
};
}
return await authRequest<ApiResponse<QuizResponse>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/quiz`,
{ method: 'PUT', body: data }
@ -754,18 +323,6 @@ export const instructorService = {
// Video Upload
async uploadLessonVideo(courseId: number, chapterId: number, lessonId: number, video: File, attachments?: File[]): Promise<ApiResponse<LessonResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 1000));
return {
code: 200,
message: 'Video uploaded successfully (Mock)',
data: MOCK_COURSE_DETAIL.chapters[0].lessons[0] as LessonResponse
};
}
const formData = new FormData();
formData.append('video', video);
if (attachments) {
@ -781,18 +338,6 @@ export const instructorService = {
},
async updateLessonVideo(courseId: number, chapterId: number, lessonId: number, video?: File, attachments?: File[]): Promise<ApiResponse<LessonResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 1000));
return {
code: 200,
message: 'Video updated successfully (Mock)',
data: MOCK_COURSE_DETAIL.chapters[0].lessons[0] as LessonResponse
};
}
const formData = new FormData();
if (video) {
formData.append('video', video);
@ -811,18 +356,6 @@ export const instructorService = {
// Attachments
async addAttachments(courseId: number, chapterId: number, lessonId: number, files: File[]): Promise<ApiResponse<LessonResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Attachments added successfully (Mock)',
data: MOCK_COURSE_DETAIL.chapters[0].lessons[0] as LessonResponse
};
}
const formData = new FormData();
files.forEach(file => {
formData.append('attachment', file);
@ -835,18 +368,6 @@ export const instructorService = {
},
async deleteAttachment(courseId: number, chapterId: number, lessonId: number, attachmentId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Attachment deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/chapters/${chapterId}/lessons/${lessonId}/attachments/${attachmentId}`,
{ method: 'DELETE' }
@ -855,14 +376,6 @@ export const instructorService = {
// Announcements
async getAnnouncements(courseId: number): Promise<AnnouncementResponse[]> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return MOCK_ANNOUNCEMENTS;
}
const response = await authRequest<AnnouncementsListResponse>(
`/api/instructors/courses/${courseId}/announcements`
);
@ -870,27 +383,6 @@ export const instructorService = {
},
async createAnnouncement(courseId: number, data: CreateAnnouncementRequest, files?: File[]): Promise<ApiResponse<AnnouncementResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 201,
message: 'Announcement created successfully (Mock)',
data: {
id: Date.now(),
title: data.title,
content: data.content,
status: data.status || 'DRAFT',
is_pinned: data.is_pinned || false,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
attachments: []
}
};
}
const formData = new FormData();
formData.append('data', JSON.stringify(data));
@ -907,27 +399,6 @@ export const instructorService = {
},
async updateAnnouncement(courseId: number, announcementId: number, data: CreateAnnouncementRequest): Promise<ApiResponse<AnnouncementResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Announcement updated successfully (Mock)',
data: {
id: announcementId,
title: data.title,
content: data.content,
status: data.status || 'DRAFT',
is_pinned: data.is_pinned || false,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
attachments: []
}
};
}
return await authRequest<ApiResponse<AnnouncementResponse>>(
`/api/instructors/courses/${courseId}/announcements/${announcementId}`,
{ method: 'PUT', body: data }
@ -935,18 +406,6 @@ export const instructorService = {
},
async deleteAnnouncement(courseId: number, announcementId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Announcement deleted successfully (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/announcements/${announcementId}`,
{ method: 'DELETE' }
@ -954,18 +413,6 @@ export const instructorService = {
},
async uploadAnnouncementAttachment(courseId: number, announcementId: number, file: File): Promise<ApiResponse<AnnouncementResponse>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Upload attachment success (Mock)',
data: MOCK_ANNOUNCEMENTS[0]
};
}
const formData = new FormData();
formData.append('file', file);
@ -976,18 +423,6 @@ export const instructorService = {
},
async deleteAnnouncementAttachment(courseId: number, announcementId: number, attachmentId: number): Promise<ApiResponse<void>> {
const config = useRuntimeConfig();
const useMockData = config.public.useMockData as boolean;
if (useMockData) {
await new Promise(resolve => setTimeout(resolve, 500));
return {
code: 200,
message: 'Delete attachment success (Mock)',
data: undefined
};
}
return await authRequest<ApiResponse<void>>(
`/api/instructors/courses/${courseId}/announcements/${announcementId}/attachments/${attachmentId}`,
{ method: 'DELETE' }
@ -1192,146 +627,3 @@ export interface CreateAnnouncementRequest {
status?: 'DRAFT' | 'PUBLISHED';
is_pinned?: boolean;
}
// Mock announcements
const MOCK_ANNOUNCEMENTS: AnnouncementResponse[] = [
{
id: 1,
title: { th: 'ยินดีต้อนรับสู่คอร์ส', en: 'Welcome to the Course' },
content: {
th: 'ยินดีต้อนรับทุกคนสู่คอร์ส JavaScript Fundamentals! เราจะเริ่มเรียนในสัปดาห์หน้า',
en: 'Welcome everyone to JavaScript Fundamentals! We will start next week'
},
status: 'PUBLISHED',
is_pinned: true,
created_at: '2024-01-15T10:00:00Z',
updated_at: '2024-01-15T10:00:00Z',
attachments: []
},
{
id: 2,
title: { th: 'อัพเดทตารางเรียน', en: 'Schedule Update' },
content: {
th: 'มีการเปลี่ยนแปลงตารางเรียนสำหรับบทที่ 3',
en: 'There is a schedule change for Chapter 3'
},
status: 'PUBLISHED',
is_pinned: false,
created_at: '2024-01-20T14:00:00Z',
updated_at: '2024-01-20T14:00:00Z',
attachments: []
}
];
// 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',
video_url: null,
attachments: [],
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',
video_url: null,
attachments: [],
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',
video_url: null,
attachments: [],
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',
video_url: null,
attachments: [],
quiz: null
}
]
}
]
};