UNPKG

@defikitdotnet/education-module-ai

Version:
596 lines (595 loc) 29.4 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CourseController = void 0; var CourseService_1 = require("../services/CourseService"); var controller_1 = require("../decorators/controller"); var AiContentService_1 = require("../services/AiContentService"); var SectionService_1 = require("../services/SectionService"); var LectureService_1 = require("../services/LectureService"); var QuizService_1 = require("../services/QuizService"); var QuizQuestionService_1 = require("../services/QuizQuestionService"); var LectureRepository_1 = require("../repositories/LectureRepository"); var SectionRepository_1 = require("../repositories/SectionRepository"); var CourseRepository_1 = require("../repositories/CourseRepository"); var QuizRepository_1 = require("../repositories/QuizRepository"); var QuizQuestionRepository_1 = require("../repositories/QuizQuestionRepository"); var TeacherService_1 = require("../services/TeacherService"); var CourseController = /** @class */ (function () { function CourseController(courseRepository, sectionRepository, lectureRepository, quizRepository, quizQuestionRepository, courseService, sectionService, lectureService, quizService, quizQuestionService, teacherService) { this.courseRepository = courseRepository; this.sectionRepository = sectionRepository; this.lectureRepository = lectureRepository; this.quizRepository = quizRepository; this.quizQuestionRepository = quizQuestionRepository; this.courseService = courseService; this.sectionService = sectionService; this.lectureService = lectureService; this.quizService = quizService; this.quizQuestionService = quizQuestionService; this.teacherService = teacherService; } /** * Get public courses */ CourseController.prototype.getPublicCourses = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courses, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); return [4 /*yield*/, this.courseService.getPublicCourses()]; case 1: courses = _a.sent(); res.json(courses); return [3 /*break*/, 3]; case 2: error_1 = _a.sent(); res.status(500).json({ error: error_1.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Create a new course */ CourseController.prototype.createCourse = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courseData, teacherExists, course, error_2; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); courseData = req.body; // Validate required fields if (!courseData.teacherId) { res.status(400).json({ error: "Teacher ID is required" }); return [2 /*return*/]; } if (!courseData.title) { res.status(400).json({ error: "Title is required" }); return [2 /*return*/]; } if (!courseData.level) { res.status(400).json({ error: "Level is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.teacherService.getTeacherById(courseData.teacherId)]; case 1: teacherExists = _a.sent(); if (!teacherExists) { res.status(404).json({ error: "Teacher not found" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.createCourse(courseData)]; case 2: course = _a.sent(); res.status(201).json(course); return [3 /*break*/, 4]; case 3: error_2 = _a.sent(); res.status(400).json({ error: error_2.message }); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; /** * Get all courses for a teacher */ CourseController.prototype.getCoursesByTeacherId = function (req, res) { return __awaiter(this, void 0, void 0, function () { var teacherId, courses, error_3; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); teacherId = req.params.teacherId; if (!teacherId) { res.status(400).json({ error: "Teacher ID is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.getCoursesByTeacher(teacherId)]; case 1: courses = _a.sent(); // Ensure response format matches frontend expectation { courses: [...] } res.json({ courses: courses || [] }); return [3 /*break*/, 3]; case 2: error_3 = _a.sent(); res.status(500).json({ error: error_3.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Get a course by ID with all sections, lectures, and quizzes */ CourseController.prototype.getCourseDetail = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courseId, course, error_4; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); courseId = req.params.courseId; if (!courseId) { res.status(400).json({ error: "Course ID is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.getCourseDetail(courseId)]; case 1: course = _a.sent(); if (!course) { res.status(404).json({ error: "Course not found" }); return [2 /*return*/]; } res.json(course); return [3 /*break*/, 3]; case 2: error_4 = _a.sent(); res.status(500).json({ error: error_4.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; CourseController.prototype.createCourseContent = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courseId, content, error_5; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); courseId = req.params.courseId; if (!courseId) { res.status(400).json({ error: "Course ID is required" }); return [2 /*return*/]; } // Validate required fields if (!req.body.title) { res.status(400).json({ error: "Title is required" }); return [2 /*return*/]; } if (!req.body.type) { res.status(400).json({ error: "Content type is required" }); return [2 /*return*/]; } if (!req.body.content) { res.status(400).json({ error: "Content is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.createContent(courseId, req.body)]; case 1: content = _a.sent(); res.status(201).json(content); return [3 /*break*/, 3]; case 2: error_5 = _a.sent(); res.status(500).json({ error: error_5.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Update a course */ CourseController.prototype.updateCourse = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courseId, payload, updatedCourse, error_6; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); courseId = req.params.courseId; payload = req.body; if (!courseId) { res.status(400).json({ error: "Course ID is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.updateCourse(courseId, payload)]; case 1: updatedCourse = _a.sent(); if (!updatedCourse) { res.status(404).json({ error: "Course not found" }); return [2 /*return*/]; } res.json(updatedCourse); return [3 /*break*/, 3]; case 2: error_6 = _a.sent(); console.error("Error updating course ".concat(req.params.courseId, ":"), error_6); res .status(500) .json({ error: error_6.message || "Failed to update course" }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Delete a course */ CourseController.prototype.deleteCourse = function (req, res) { return __awaiter(this, void 0, void 0, function () { var courseId, deleted, error_7; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); courseId = req.params.courseId; if (!courseId) { res.status(400).json({ error: "Course ID is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.deleteCourse(courseId)]; case 1: deleted = _a.sent(); if (!deleted) { res.status(404).json({ error: "Course not found" }); return [2 /*return*/]; } res.status(204).end(); return [3 /*break*/, 3]; case 2: error_7 = _a.sent(); res.status(500).json({ error: error_7.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Get courses by category */ CourseController.prototype.getCoursesByCategory = function (req, res) { return __awaiter(this, void 0, void 0, function () { var categoryId, courses, error_8; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); categoryId = req.params.categoryId; if (!categoryId) { res.status(400).json({ error: "Category ID is required" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.getCoursesByCategory(categoryId)]; case 1: courses = _a.sent(); res.json(courses); return [3 /*break*/, 3]; case 2: error_8 = _a.sent(); res.status(500).json({ error: error_8.message }); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); }; /** * Generate course using AI */ CourseController.prototype.generateCourse = function (req, res) { return __awaiter(this, void 0, void 0, function () { var _a, description, level, topics, teacherId, teacherExists, aiContentService, generatedCourse, error_9; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 3, , 4]); _a = req.body, description = _a.description, level = _a.level, topics = _a.topics, teacherId = _a.teacherId; // Updated validation: Check only for level, teacherId, and description (prompt) if (!level || !teacherId || !description) { res .status(400) .json({ error: "Level, teacher ID, and description (prompt) are required", }); return [2 /*return*/]; } return [4 /*yield*/, this.teacherService.getTeacherById(teacherId)]; case 1: teacherExists = _b.sent(); if (!teacherExists) { res.status(404).json({ error: "Teacher not found" }); return [2 /*return*/]; } aiContentService = new AiContentService_1.AiContentService(); return [4 /*yield*/, aiContentService.generateCourse({ teacherId: teacherId, // title is omitted description: description || "", // User's prompt becomes the description basis level: level, // subject is omitted (or set to a default/optional if needed by interface) topics: topics || [], // topics might still be useful if derived or optional numSections: req.body.numSections || 3, numLecturesPerSection: req.body.numLecturesPerSection || 3, includeQuizzes: req.body.includeQuizzes !== undefined ? req.body.includeQuizzes : true, numQuestionsPerQuiz: req.body.numQuestionsPerQuiz || 5, })]; case 2: generatedCourse = _b.sent(); res.status(200).json({ success: true, data: generatedCourse }); return [3 /*break*/, 4]; case 3: error_9 = _b.sent(); res.status(500).json({ error: error_9.message }); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; /** * Create course from AI-generated structure */ CourseController.prototype.createFromAI = function (req, res) { return __awaiter(this, void 0, void 0, function () { var _a, generatedCourse, teacherId, categoryIds, teacherExists, course, _i, _b, section, createdSection, _c, _d, lecture, quiz, _e, _f, question, courseWithDetails, error_10; return __generator(this, function (_g) { switch (_g.label) { case 0: _g.trys.push([0, 16, , 17]); _a = req.body, generatedCourse = _a.generatedCourse, teacherId = _a.teacherId, categoryIds = _a.categoryIds; if (!generatedCourse || !teacherId) { res .status(400) .json({ error: "Generated course data and teacher ID are required" }); return [2 /*return*/]; } return [4 /*yield*/, this.teacherService.getTeacherById(teacherId)]; case 1: teacherExists = _g.sent(); if (!teacherExists) { res.status(404).json({ error: "Teacher not found" }); return [2 /*return*/]; } return [4 /*yield*/, this.courseService.createCourse({ teacherId: teacherId, title: generatedCourse.title, description: generatedCourse.description, level: generatedCourse.level, categories: categoryIds || [], })]; case 2: course = _g.sent(); _i = 0, _b = generatedCourse.sections; _g.label = 3; case 3: if (!(_i < _b.length)) return [3 /*break*/, 14]; section = _b[_i]; return [4 /*yield*/, this.sectionService.createSection({ courseId: course.id, title: section.title, description: section.description, orderIndex: section.orderIndex, })]; case 4: createdSection = _g.sent(); _c = 0, _d = section.lectures; _g.label = 5; case 5: if (!(_c < _d.length)) return [3 /*break*/, 8]; lecture = _d[_c]; return [4 /*yield*/, this.lectureService.createLecture({ sectionId: createdSection.id, title: lecture.title, content: lecture.content, type: lecture.type, orderIndex: lecture.orderIndex, })]; case 6: _g.sent(); _g.label = 7; case 7: _c++; return [3 /*break*/, 5]; case 8: if (!section.quiz) return [3 /*break*/, 13]; return [4 /*yield*/, this.quizService.createQuiz({ sectionId: createdSection.id, title: section.quiz.title, description: section.quiz.description, })]; case 9: quiz = _g.sent(); _e = 0, _f = section.quiz.questions; _g.label = 10; case 10: if (!(_e < _f.length)) return [3 /*break*/, 13]; question = _f[_e]; return [4 /*yield*/, this.quizQuestionService.createQuestion({ quizId: quiz.id, question: question.question, options: question.options, answer: question.answer, explanation: question.explanation, })]; case 11: _g.sent(); _g.label = 12; case 12: _e++; return [3 /*break*/, 10]; case 13: _i++; return [3 /*break*/, 3]; case 14: return [4 /*yield*/, this.courseService.getCourseDetail(course.id)]; case 15: courseWithDetails = _g.sent(); res.status(201).json(courseWithDetails); return [3 /*break*/, 17]; case 16: error_10 = _g.sent(); res.status(500).json({ error: error_10.message }); return [3 /*break*/, 17]; case 17: return [2 /*return*/]; } }); }); }; __decorate([ (0, controller_1.Get)("/public"), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "getPublicCourses", null); __decorate([ (0, controller_1.Post)("/"), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "createCourse", null); __decorate([ (0, controller_1.Get)("/teacher/:teacherId") // @Use(authenticateTeacher) , __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "getCoursesByTeacherId", null); __decorate([ (0, controller_1.Get)("/:courseId") // @Use(authenticateTeacher) , __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "getCourseDetail", null); __decorate([ (0, controller_1.Post)("/:courseId/contents") // @Use(authenticateTeacher) , __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "createCourseContent", null); __decorate([ (0, controller_1.Put)("/:courseId") // @Use(authenticateTeacher) , __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "updateCourse", null); __decorate([ (0, controller_1.Delete)("/:courseId") // @Use(authenticateTeacher) , __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "deleteCourse", null); __decorate([ (0, controller_1.Get)("/category/:categoryId"), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "getCoursesByCategory", null); __decorate([ (0, controller_1.Post)("/generate"), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "generateCourse", null); __decorate([ (0, controller_1.Post)("/create-from-ai"), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], CourseController.prototype, "createFromAI", null); CourseController = __decorate([ (0, controller_1.Controller)("/api/courses"), __metadata("design:paramtypes", [CourseRepository_1.CourseRepository, SectionRepository_1.SectionRepository, LectureRepository_1.LectureRepository, QuizRepository_1.QuizRepository, QuizQuestionRepository_1.QuizQuestionRepository, CourseService_1.CourseService, SectionService_1.SectionService, LectureService_1.LectureService, QuizService_1.QuizService, QuizQuestionService_1.QuizQuestionService, TeacherService_1.TeacherService]) ], CourseController); return CourseController; }()); exports.CourseController = CourseController;