205 lines
8.6 KiB
TypeScript
205 lines
8.6 KiB
TypeScript
import { Get, Body, Post, Route, Tags, SuccessResponse, Response, Security, Path, Request, Query } from 'tsoa';
|
|
import { ValidationError } from '../middleware/errorHandler';
|
|
import { CoursesStudentService } from '../services/CoursesStudent.service';
|
|
import {
|
|
EnrollCourseResponse,
|
|
ListEnrolledCoursesResponse,
|
|
GetCourseLearningResponse,
|
|
GetLessonContentResponse,
|
|
CheckLessonAccessResponse,
|
|
SaveVideoProgressResponse,
|
|
SaveVideoProgressBody,
|
|
GetVideoProgressResponse,
|
|
CompleteLessonResponse,
|
|
} from '../types/CoursesStudent.types';
|
|
import { EnrollmentStatus } from '@prisma/client';
|
|
|
|
@Route('api/students')
|
|
@Tags('CoursesStudent')
|
|
export class CoursesStudentController {
|
|
|
|
private service = new CoursesStudentService();
|
|
|
|
/**
|
|
* ลงทะเบียนเรียนในคอร์ส
|
|
* Enroll in a course
|
|
* @param courseId - รหัสคอร์ส / Course ID
|
|
*/
|
|
@Post('courses/{courseId}/enroll')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Enrolled successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('404', 'Course not found')
|
|
@Response('409', 'Already enrolled in this course')
|
|
public async enrollCourse(@Request() request: any, @Path() courseId: number): Promise<EnrollCourseResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.enrollCourse({ token, course_id: courseId });
|
|
}
|
|
|
|
/**
|
|
* ดึงรายการคอร์สที่ลงทะเบียนเรียน
|
|
* Get list of enrolled courses
|
|
* @param page - หน้าที่ต้องการดึง / Page number
|
|
* @param limit - จำนวนรายการต่อหน้า / Items per page
|
|
* @param status - สถานะการลงทะเบียน / Enrollment status
|
|
*/
|
|
@Get('courses')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Enrolled courses retrieved successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
public async getEnrolledCourses(
|
|
@Request() request: any,
|
|
@Query() page?: number,
|
|
@Query() limit?: number,
|
|
@Query() status?: EnrollmentStatus
|
|
): Promise<ListEnrolledCoursesResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.GetEnrolledCourses({ token, page, limit, status });
|
|
}
|
|
|
|
/**
|
|
* ดึงข้อมูลหน้าเรียนคอร์ส (พร้อมสถานะการล็อคบทเรียน)
|
|
* Get course learning page with lesson lock status
|
|
* @param courseId - รหัสคอร์ส / Course ID
|
|
*/
|
|
@Get('courses/{courseId}/learn')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Course learning data retrieved successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('403', 'Not enrolled in this course')
|
|
@Response('404', 'Course not found')
|
|
public async getCourseLearning(@Request() request: any, @Path() courseId: number): Promise<GetCourseLearningResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.getCourseLearning({ token, course_id: courseId });
|
|
}
|
|
|
|
/**
|
|
* ดึงเนื้อหาบทเรียน (ตรวจสอบเงื่อนไขก่อนหน้า)
|
|
* Get lesson content (checks prerequisites)
|
|
* @param courseId - รหัสคอร์ส / Course ID
|
|
* @param lessonId - รหัสบทเรียน / Lesson ID
|
|
*/
|
|
@Get('courses/{courseId}/lessons/{lessonId}')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Lesson content retrieved successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('403', 'Not enrolled in this course or lesson is locked')
|
|
@Response('404', 'Lesson not found')
|
|
public async getLessonContent(
|
|
@Request() request: any,
|
|
@Path() courseId: number,
|
|
@Path() lessonId: number
|
|
): Promise<GetLessonContentResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.getlessonContent({ token, course_id: courseId, lesson_id: lessonId });
|
|
}
|
|
|
|
/**
|
|
* ตรวจสอบสิทธิ์เข้าถึงบทเรียน (ไม่โหลดเนื้อหา)
|
|
* Check lesson access without loading content
|
|
* @param courseId - รหัสคอร์ส / Course ID
|
|
* @param lessonId - รหัสบทเรียน / Lesson ID
|
|
*/
|
|
@Get('courses/{courseId}/lessons/{lessonId}/access-check')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Access check completed')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('404', 'Lesson not found')
|
|
public async checkLessonAccess(
|
|
@Request() request: any,
|
|
@Path() courseId: number,
|
|
@Path() lessonId: number
|
|
): Promise<CheckLessonAccessResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.checkAccessLesson({ token, course_id: courseId, lesson_id: lessonId });
|
|
}
|
|
|
|
/**
|
|
* บันทึกความคืบหน้าการดูวิดีโอ
|
|
* Save video progress
|
|
* @param lessonId - รหัสบทเรียน / Lesson ID
|
|
*/
|
|
@Post('lessons/{lessonId}/progress')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Video progress saved successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('403', 'Not enrolled in this course')
|
|
@Response('404', 'Lesson not found')
|
|
public async saveVideoProgress(
|
|
@Request() request: any,
|
|
@Path() lessonId: number,
|
|
@Body() body: SaveVideoProgressBody
|
|
): Promise<SaveVideoProgressResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.saveVideoProgress({
|
|
token,
|
|
lesson_id: lessonId,
|
|
video_progress_seconds: body.video_progress_seconds,
|
|
video_duration_seconds: body.video_duration_seconds,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* ดึงความคืบหน้าการดูวิดีโอ
|
|
* Get video progress
|
|
* @param lessonId - รหัสบทเรียน / Lesson ID
|
|
*/
|
|
@Get('lessons/{lessonId}/progress')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Video progress retrieved successfully')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('403', 'Not enrolled in this course')
|
|
@Response('404', 'Lesson not found')
|
|
public async getVideoProgress(
|
|
@Request() request: any,
|
|
@Path() lessonId: number
|
|
): Promise<GetVideoProgressResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.getVideoProgress({ token, lesson_id: lessonId });
|
|
}
|
|
|
|
/**
|
|
* ทำเครื่องหมายบทเรียนว่าเรียนจบ
|
|
* Mark lesson as complete
|
|
* @param courseId - รหัสคอร์ส / Course ID
|
|
* @param lessonId - รหัสบทเรียน / Lesson ID
|
|
*/
|
|
@Post('courses/{courseId}/lessons/{lessonId}/complete')
|
|
@Security('jwt', ['student'])
|
|
@SuccessResponse('200', 'Lesson marked as complete')
|
|
@Response('401', 'Invalid or expired token')
|
|
@Response('403', 'Not enrolled in this course')
|
|
@Response('404', 'Lesson not found')
|
|
public async completeLesson(
|
|
@Request() request: any,
|
|
@Path() courseId: number,
|
|
@Path() lessonId: number
|
|
): Promise<CompleteLessonResponse> {
|
|
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
if (!token) {
|
|
throw new ValidationError('No token provided');
|
|
}
|
|
return await this.service.completeLesson({ token, lesson_id: lessonId });
|
|
}
|
|
}
|