import response from "../../response.js"; import models from "../../models/index.js"; import fs from "fs"; import path from "path"; export const getExercises = async (req, res) => { try { const exercises = await models.Exercise.findAll({ include: [ { model: models.MultipleChoices, as: "multipleChoices", }, { model: models.MatchingPairs, as: "matchingPairs", }, { model: models.TrueFalse, as: "trueFalse", }, ], }); if (exercises.length === 0) { return response(404, null, "No exercises found", res); } const result = exercises.map((exercise) => { const exerciseData = { ...exercise.dataValues }; const questionType = exercise.QUESTION_TYPE; if (questionType === "MCQ") { delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } else if (questionType === "MPQ") { delete exerciseData.multipleChoices; delete exerciseData.trueFalse; } else if (questionType === "TFQ") { delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; } else { delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } return exerciseData; }); response(200, result, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getExercisesForAdmin = async (req, res) => { try { const exercises = await models.Exercise.findAll({ include: [ { model: models.MultipleChoices, as: "multipleChoices", attributes: ["ANSWER_KEY"], }, { model: models.MatchingPairs, as: "matchingPairs", attributes: ["LEFT_PAIR", "RIGHT_PAIR"], }, { model: models.TrueFalse, as: "trueFalse", attributes: ["IS_TRUE"], }, ], }); const formattedExercises = exercises.map((exercise) => { const questionType = exercise.QUESTION_TYPE; let answerKey = null; if (questionType === "MCQ" && exercise.multipleChoices.length > 0) { answerKey = exercise.multipleChoices[0].ANSWER_KEY; } else if (questionType === "MPQ" && exercise.matchingPairs.length > 0) { answerKey = exercise.matchingPairs .map((pair) => `${pair.LEFT_PAIR}-${pair.RIGHT_PAIR}`) .join(", "); } else if (questionType === "TFQ" && exercise.trueFalse.length > 0) { answerKey = exercise.trueFalse[0].IS_TRUE === 1 ? "true" : "false"; } return { ID_ADMIN_EXERCISE: exercise.ID_ADMIN_EXERCISE, ID_LEVEL: exercise.ID_LEVEL, TITLE: exercise.TITLE, QUESTION: exercise.QUESTION, SCORE_WEIGHT: exercise.SCORE_WEIGHT, QUESTION_TYPE: questionType, AUDIO: exercise.AUDIO, VIDEO: exercise.VIDEO, IMAGE: exercise.IMAGE, ANSWER_KEY: answerKey, }; }); response(200, formattedExercises, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving exercises data!", res); } }; export const getExerciseById = async (req, res) => { try { const { id } = req.params; const exercise = await models.Exercise.findByPk(id, { include: [ { model: models.MultipleChoices, as: "multipleChoices", }, { model: models.MatchingPairs, as: "matchingPairs", }, { model: models.TrueFalse, as: "trueFalse", }, ], }); if (!exercise) { return response(404, null, "Exercise not found", res); } const exerciseData = { ...exercise.dataValues }; const questionType = exercise.QUESTION_TYPE; if (questionType === "MCQ") { if (exerciseData.multipleChoices) { exerciseData.multipleChoices = exerciseData.multipleChoices.map( (choice) => { const { ANSWER_KEY, ...rest } = choice.dataValues; return rest; } ); } delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } else if (questionType === "MPQ") { if (exerciseData.matchingPairs) { exerciseData.matchingPairs = exerciseData.matchingPairs.map((pair) => { const { LEFT_PAIR, RIGHT_PAIR, ...rest } = pair.dataValues; return rest; }); } delete exerciseData.multipleChoices; delete exerciseData.trueFalse; } else if (questionType === "TFQ") { if (exerciseData.trueFalse) { exerciseData.trueFalse = exerciseData.trueFalse.map((tf) => { const { IS_TRUE, ...rest } = tf.dataValues; return rest; }); } delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; } else { delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } response(200, exerciseData, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getExerciseByLevelId = async (req, res) => { try { const { idLevel } = req.params; const levelExists = await models.Level.findByPk(idLevel); if (!levelExists) { return response(404, null, "Level not found", res); } const exercises = await models.Exercise.findAll({ where: { ID_LEVEL: idLevel }, include: [ { model: models.MultipleChoices, as: "multipleChoices", }, { model: models.MatchingPairs, as: "matchingPairs", }, { model: models.TrueFalse, as: "trueFalse", }, ], }); if (!exercises || exercises.length === 0) { return response(404, null, "No exercises found for this level", res); } const formattedExercises = exercises.map((exercise) => { const exerciseData = { ...exercise.dataValues }; const questionType = exercise.QUESTION_TYPE; if (questionType === "MCQ") { if (exerciseData.multipleChoices) { exerciseData.multipleChoices = exerciseData.multipleChoices.map( (choice) => { const { ANSWER_KEY, ...rest } = choice.dataValues; return rest; } ); } delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } else if (questionType === "MPQ") { if (exerciseData.matchingPairs) { exerciseData.matchingPairs = exerciseData.matchingPairs.map( (pair) => pair.dataValues ); } delete exerciseData.multipleChoices; delete exerciseData.trueFalse; } else if (questionType === "TFQ") { if (exerciseData.trueFalse) { exerciseData.trueFalse = exerciseData.trueFalse.map((tf) => { const { IS_TRUE, ...rest } = tf.dataValues; return rest; }); } delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; } else { delete exerciseData.multipleChoices; delete exerciseData.matchingPairs; delete exerciseData.trueFalse; } return exerciseData; }); response(200, formattedExercises, "Success", res); } catch (error) { console.log(error); res.status(500).json({ message: "Internal Server Error" }); } }; // export const deleteExerciseById = async (req, res) => { // const { id } = req.params; // const transaction = await models.db.transaction(); // try { // const exercise = await models.Exercise.findByPk(id, { // include: [ // { // model: models.MultipleChoices, // as: "multipleChoices", // }, // { // model: models.MatchingPairs, // as: "matchingPairs", // }, // { // model: models.TrueFalse, // as: "trueFalse", // }, // ], // }); // if (!exercise) { // await transaction.rollback(); // return response(404, null, "Exercise not found", res); // } // if (exercise.AUDIO) { // const audioPath = path.join( // "public/uploads/exercise/audio", // exercise.AUDIO // ); // if (fs.existsSync(audioPath)) fs.unlinkSync(audioPath); // } // if (exercise.IMAGE) { // const imagePath = path.join( // "public/uploads/exercise/image", // exercise.IMAGE // ); // if (fs.existsSync(imagePath)) fs.unlinkSync(imagePath); // } // const questionType = exercise.QUESTION_TYPE; // if (questionType === "MCQ") { // await models.MultipleChoices.destroy({ // where: { ID_ADMIN_EXERCISE: id }, // transaction, // }); // } else if (questionType === "MPQ") { // await models.MatchingPairs.destroy({ // where: { ID_ADMIN_EXERCISE: id }, // transaction, // }); // } else if (questionType === "TFQ") { // await models.TrueFalse.destroy({ // where: { ID_ADMIN_EXERCISE: id }, // transaction, // }); // } // await exercise.destroy({ transaction }); // await transaction.commit(); // response(200, null, "Exercise and related data deleted successfully", res); // } catch (error) { // console.log(error); // await transaction.rollback(); // response(500, null, "Internal Server Error", res); // } // }; export const deleteExerciseById = async (req, res) => { const { id } = req.params; const transaction = await models.db.transaction(); try { const exercise = await models.Exercise.findByPk(id, { include: [ { model: models.MultipleChoices, as: "multipleChoices", }, { model: models.MatchingPairs, as: "matchingPairs", }, { model: models.TrueFalse, as: "trueFalse", }, ], }); if (!exercise) { await transaction.rollback(); return response(404, null, "Exercise not found", res); } await models.StdExercise.destroy({ where: { ID_ADMIN_EXERCISE: id }, transaction, }); if (exercise.AUDIO) { const audioPath = path.join( "public/uploads/exercise/audio", exercise.AUDIO ); if (fs.existsSync(audioPath)) fs.unlinkSync(audioPath); } if (exercise.IMAGE) { const imagePath = path.join( "public/uploads/exercise/image", exercise.IMAGE ); if (fs.existsSync(imagePath)) fs.unlinkSync(imagePath); } const questionType = exercise.QUESTION_TYPE; if (questionType === "MCQ") { await models.MultipleChoices.destroy({ where: { ID_ADMIN_EXERCISE: id }, transaction, }); } else if (questionType === "MPQ") { await models.MatchingPairs.destroy({ where: { ID_ADMIN_EXERCISE: id }, transaction, }); } else if (questionType === "TFQ") { await models.TrueFalse.destroy({ where: { ID_ADMIN_EXERCISE: id }, transaction, }); } await exercise.destroy({ transaction }); await transaction.commit(); response(200, null, "Exercise and related data deleted successfully", res); } catch (error) { console.log(error); await transaction.rollback(); response(500, null, "Internal Server Error", res); } }; export const deleteExerciseFileById = async (req, res) => { const { id } = req.params; const { fileType } = req.body; if (!["audio", "image", "video"].includes(fileType)) { return response(400, null, "Invalid file type specified", res); } try { const exercise = await models.Exercise.findByPk(id); if (!exercise) { return response(404, null, "Exercise not found", res); } let filePath; let fileName; if (fileType === "audio" && exercise.AUDIO) { fileName = exercise.AUDIO; filePath = path.join("public/uploads/exercise/audio", fileName); exercise.AUDIO = null; } else if (fileType === "image" && exercise.IMAGE) { fileName = exercise.IMAGE; filePath = path.join("public/uploads/exercise/image", fileName); exercise.IMAGE = null; } else if (fileType === "video" && exercise.VIDEO) { exercise.VIDEO = null; } else { return response( 404, null, `${ fileType.charAt(0).toUpperCase() + fileType.slice(1) } file not found`, res ); } if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } await exercise.save(); response( 200, exercise, `${ fileType.charAt(0).toUpperCase() + fileType.slice(1) } file deleted successfully`, res ); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } };