import { Body, Delete, Get, Path, Post, Put, Query, Request, Response, Route, Security, SuccessResponse, Tags, UploadedFile, UploadedFiles, FormField } from 'tsoa'; import { ValidationError } from '../middleware/errorHandler'; import { AnnouncementsService } from '../services/announcements.service'; import { ListAnnouncementResponse, CreateAnnouncementResponse, UpdateAnnouncementResponse, DeleteAnnouncementResponse, UploadAnnouncementAttachmentResponse, DeleteAnnouncementAttachmentResponse, CreateAnnouncementBody, UpdateAnnouncementBody, } from '../types/announcements.types'; const announcementsService = new AnnouncementsService(); @Route('api/instructors/courses/{courseId}/announcements') @Tags('Announcements - Instructor') export class AnnouncementsController { /** * ดึงรายการประกาศของคอร์ส * List announcements for a course * @param courseId - รหัสคอร์ส / Course ID * @param page - หน้าที่ต้องการ / Page number * @param limit - จำนวนต่อหน้า / Items per page */ @Get() @SuccessResponse('200', 'Announcements retrieved successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') @Security('jwt') public async listAnnouncements( @Request() request: any, @Path() courseId: number, @Query() page?: number, @Query() limit?: number ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); return await announcementsService.listAnnouncement({ token, course_id: courseId, page, limit, }); } /** * สร้างประกาศใหม่ (พร้อมไฟล์แนบ) * Create a new announcement with optional file attachments * @param courseId - รหัสคอร์ส / Course ID */ @Post() @Security('jwt', ['instructor']) @SuccessResponse('201', 'Announcement created successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') public async createAnnouncement( @Request() request: any, @Path() courseId: number, @FormField() data: string, @UploadedFiles() files?: Express.Multer.File[] ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); // Parse JSON data field const parsed = JSON.parse(data) as CreateAnnouncementBody; return await announcementsService.createAnnouncement({ token, course_id: courseId, title: parsed.title, content: parsed.content, status: parsed.status, is_pinned: parsed.is_pinned, files, }); } /** * อัปเดตประกาศ * Update an announcement * @param courseId - รหัสคอร์ส / Course ID * @param announcementId - รหัสประกาศ / Announcement ID */ @Put('{announcementId}') @Security('jwt', ['instructor']) @SuccessResponse('200', 'Announcement updated successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') @Response('404', 'Announcement not found') public async updateAnnouncement( @Request() request: any, @Path() courseId: number, @Path() announcementId: number, @Body() body: UpdateAnnouncementBody ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); return await announcementsService.updateAnnouncement({ token, course_id: courseId, announcement_id: announcementId, title: body.title, content: body.content, status: body.status, is_pinned: body.is_pinned, }); } /** * ลบประกาศ * Delete an announcement * @param courseId - รหัสคอร์ส / Course ID * @param announcementId - รหัสประกาศ / Announcement ID */ @Delete('{announcementId}') @Security('jwt', ['instructor']) @SuccessResponse('200', 'Announcement deleted successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') @Response('404', 'Announcement not found') public async deleteAnnouncement( @Request() request: any, @Path() courseId: number, @Path() announcementId: number ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); return await announcementsService.deleteAnnouncement({ token, course_id: courseId, announcement_id: announcementId, }); } /** * อัปโหลดไฟล์แนบ * Upload attachment to announcement * @param courseId - รหัสคอร์ส / Course ID * @param announcementId - รหัสประกาศ / Announcement ID */ @Post('{announcementId}/attachments') @Security('jwt', ['instructor']) @SuccessResponse('201', 'Attachment uploaded successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') @Response('404', 'Announcement not found') public async uploadAttachment( @Request() request: any, @Path() courseId: number, @Path() announcementId: number, @UploadedFile() file: Express.Multer.File ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); return await announcementsService.uploadAttachment({ token, course_id: courseId, announcement_id: announcementId, file: file as any, }); } /** * ลบไฟล์แนบ * Delete attachment from announcement * @param courseId - รหัสคอร์ส / Course ID * @param announcementId - รหัสประกาศ / Announcement ID * @param attachmentId - รหัสไฟล์แนบ / Attachment ID */ @Delete('{announcementId}/attachments/{attachmentId}') @Security('jwt', ['instructor']) @SuccessResponse('200', 'Attachment deleted successfully') @Response('401', 'Unauthorized') @Response('403', 'Forbidden') @Response('404', 'Attachment not found') public async deleteAttachment( @Request() request: any, @Path() courseId: number, @Path() announcementId: number, @Path() attachmentId: number ): Promise { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) throw new ValidationError('No token provided'); return await announcementsService.deleteAttachment({ token, course_id: courseId, announcement_id: announcementId, attachment_id: attachmentId, }); } }