feat: Add student and instructor chapter/lesson controllers and refactor instructor lesson file upload endpoints with TSOA.

This commit is contained in:
JakkrapartXD 2026-01-21 16:52:38 +07:00
parent 0c369d1197
commit 9a7eb50d17
3 changed files with 949 additions and 249 deletions

View file

@ -190,27 +190,10 @@ export interface ReorderChapterResponse {
}
// ============================================
// Chapter with Full Lessons (for detailed view)
// ============================================
export interface ChapterWithLessonsResponse {
code: number;
message: string;
data: ChapterData & {
lessons: LessonData[];
};
}
// ============================================
// Lesson Request Types
// ============================================
export interface ListLessonsRequest {
token: string;
course_id: number;
chapter_id: number;
}
export interface GetLessonRequest {
token: string;
course_id: number;
@ -315,7 +298,6 @@ export interface CreateLessonRequest {
export interface UpdateLessonInput {
title?: MultiLanguageText;
content?: MultiLanguageText;
type?: 'VIDEO' | 'QUIZ';
duration_minutes?: number;
sort_order?: number;
is_sequential?: boolean;
@ -350,13 +332,6 @@ export interface ReorderLessonsRequest {
// Lesson Response Types
// ============================================
export interface ListLessonsResponse {
code: number;
message: string;
data: LessonData[];
total: number;
}
export interface GetLessonResponse {
code: number;
message: string;
@ -375,6 +350,14 @@ export interface UpdateLessonResponse {
data: LessonData;
}
export interface UpdateVideoLessonInput {
token: string;
course_id: number;
lesson_id: number;
video?: UploadedFileInfo;
attachments?: UploadedFileInfo[];
}
export interface DeleteLessonResponse {
code: number;
message: string;
@ -398,4 +381,163 @@ export interface LessonWithDetailsResponse {
quiz: QuizData | null;
progress: LessonProgressData[];
};
}
// ============================================
// Add Video/Quiz to Lesson Input Types
// ============================================
/**
* Input for adding video and attachments to an existing VIDEO lesson
*/
export interface AddVideoToLessonInput {
token: string;
course_id: number;
lesson_id: number;
video: UploadedFileInfo;
attachments?: UploadedFileInfo[];
}
/**
* Input for adding quiz to an existing QUIZ lesson
*/
export interface AddQuizToLessonInput {
token: string;
course_id: number;
lesson_id: number;
quiz_data: {
title: MultiLanguageText;
description?: MultiLanguageText;
passing_score?: number;
time_limit?: number;
shuffle_questions?: boolean;
shuffle_choices?: boolean;
show_answers_after_completion?: boolean;
questions: CreateQuizQuestionInput[];
};
}
/**
* Input for adding a single question to a quiz lesson
*/
export interface AddQuestionInput {
token: string;
course_id: number;
lesson_id: number;
question: MultiLanguageText;
explanation?: MultiLanguageText;
question_type: 'MULTIPLE_CHOICE' | 'TRUE_FALSE' | 'SHORT_ANSWER';
score?: number;
sort_order?: number;
choices?: CreateQuizChoiceInput[];
}
/**
* Response for adding a question
*/
export interface AddQuestionResponse {
code: number;
message: string;
data: QuizQuestionData;
}
/**
* Input for updating a question
*/
export interface UpdateQuestionInput {
token: string;
course_id: number;
lesson_id: number;
question_id: number;
question?: MultiLanguageText;
explanation?: MultiLanguageText;
question_type?: 'MULTIPLE_CHOICE' | 'TRUE_FALSE' | 'SHORT_ANSWER';
score?: number;
sort_order?: number;
choices?: CreateQuizChoiceInput[]; // Replace all choices if provided
}
/**
* Response for updating a question
*/
export interface UpdateQuestionResponse {
code: number;
message: string;
data: QuizQuestionData;
}
/**
* Input for deleting a question
*/
export interface DeleteQuestionInput {
token: string;
course_id: number;
lesson_id: number;
question_id: number;
}
/**
* Response for deleting a question
*/
export interface DeleteQuestionResponse {
code: number;
message: string;
}
// ============================================
// Controller Body Request Types
// ============================================
export interface CreateChapterBody {
title: MultiLanguageText;
description?: MultiLanguageText;
sort_order?: number;
}
export interface UpdateChapterBody {
title?: MultiLanguageText;
description?: MultiLanguageText;
sort_order?: number;
is_published?: boolean;
}
export interface ReorderChapterBody {
sort_order: number;
}
export interface CreateLessonBody {
title: MultiLanguageText;
content?: MultiLanguageText;
type: 'VIDEO' | 'QUIZ';
sort_order?: number;
}
export interface UpdateLessonBody {
title?: MultiLanguageText;
content?: MultiLanguageText;
duration_minutes?: number;
sort_order?: number;
is_published?: boolean;
}
export interface ReorderLessonsBody {
lesson_ids: number[];
}
export interface AddQuestionBody {
question: MultiLanguageText;
explanation?: MultiLanguageText;
question_type: 'MULTIPLE_CHOICE' | 'TRUE_FALSE' | 'SHORT_ANSWER';
score?: number;
sort_order?: number;
choices?: CreateQuizChoiceInput[];
}
export interface UpdateQuestionBody {
question?: MultiLanguageText;
explanation?: MultiLanguageText;
question_type?: 'MULTIPLE_CHOICE' | 'TRUE_FALSE' | 'SHORT_ANSWER';
score?: number;
sort_order?: number;
choices?: CreateQuizChoiceInput[];
}