import response from "../../response.js"; import models from "../../models/index.js"; import fs from "fs"; import path from "path"; import { clearFileBuffers, saveFileToDisk, } from "../../middlewares/uploadSection.js"; export const getSections = async (req, res) => { try { const sections = await models.Section.findAll({ where: { IS_DELETED: 0, }, }); response(200, sections, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving sections data!", res); } }; export const getSectionById = async (req, res) => { try { const { id } = req.params; const section = await models.Section.findByPk(id); if (!section) { return response(404, null, "Section not found", res); } response(200, section, "Success", res); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } }; export const getSectionForAdmin = async (req, res) => { const { page = 1, limit = 10, search = "", sort = "time" } = req.query; try { const { count, rows: sections } = await models.Section.findAndCountAll({ where: { IS_DELETED: 0, ...(search && { [models.Op.or]: [ { NAME_SECTION: { [models.Op.like]: `%${search}%`, }, }, { DESCRIPTION_SECTION: { [models.Op.like]: `%${search}%`, }, }, ], }), }, attributes: ["ID_SECTION", "NAME_SECTION", "DESCRIPTION_SECTION", "TIME_SECTION"], distinct: true, }); const formattedSections = sections.map((section) => ({ ID_SECTION: section.ID_SECTION, NAME_SECTION: section.NAME_SECTION, DESCRIPTION_SECTION: section.DESCRIPTION_SECTION, TIME_SECTION: section.TIME_SECTION, })); if (sort === "section") { formattedSections.sort((a, b) => a.NAME_SECTION.localeCompare(b.NAME_SECTION)); } else if (sort === "description") { formattedSections.sort((a, b) => a.DESCRIPTION_SECTION.localeCompare(b.DESCRIPTION_SECTION)); } else { formattedSections.sort( (a, b) => new Date(b.TIME_SECTION) - new Date(a.TIME_SECTION) ); } const paginatedSections = formattedSections.slice( (page - 1) * limit, page * limit ); const totalPages = Math.ceil(count / limit); const currentPage = parseInt(page); response( 200, { sections: paginatedSections, currentPage, totalPages, totalItems: count, }, "Sections retrieved successfully", res ); } catch (error) { console.log(error); response(500, null, "Error retrieving sections data!", res); } }; export const createSection = async (req, res) => { const { NAME_SECTION, DESCRIPTION_SECTION } = req.body; const { THUMBNAIL } = req.filesToSave || {}; if (!NAME_SECTION) { clearFileBuffers({ THUMBNAIL }); return response(400, null, "Section name is required", res); } if (!DESCRIPTION_SECTION) { clearFileBuffers({ THUMBNAIL }); return response(400, null, "Description is required", res); } const transaction = await models.db.transaction(); try { const existingSection = await models.Section.findOne({ where: { NAME_SECTION, IS_DELETED: 0 }, transaction, }); if (existingSection) { clearFileBuffers({ THUMBNAIL }); await transaction.rollback(); return response(409, null, "Section name already exists", res); } const newSection = await models.Section.create( { NAME_SECTION, DESCRIPTION_SECTION, THUMBNAIL: null, }, { transaction } ); const thumbnailFilename = THUMBNAIL ? saveFileToDisk(THUMBNAIL, "THUMBNAIL", newSection.ID_SECTION) : null; newSection.THUMBNAIL = thumbnailFilename; await newSection.save({ transaction }); await transaction.commit(); response(201, newSection, "Section created successfully", res); } catch (error) { console.log(error); await transaction.rollback(); clearFileBuffers({ THUMBNAIL }); response(500, null, "Internal Server Error", res); } }; export const updateSectionById = async (req, res) => { const { id } = req.params; const { NAME_SECTION, DESCRIPTION_SECTION } = req.body; const { THUMBNAIL } = req.filesToSave || {}; const transaction = await models.db.transaction(); try { const section = await models.Section.findByPk(id, { transaction }); if (!section) { clearFileBuffers({ THUMBNAIL }); await transaction.rollback(); return response(404, null, "Section not found", res); } if (NAME_SECTION && NAME_SECTION !== section.NAME_SECTION) { const existingSection = await models.Section.findOne({ where: { NAME_SECTION }, transaction, }); if (existingSection) { clearFileBuffers({ THUMBNAIL }); await transaction.rollback(); return response(400, null, "Section name already exists", res); } section.NAME_SECTION = NAME_SECTION; } if (DESCRIPTION_SECTION) section.DESCRIPTION_SECTION = DESCRIPTION_SECTION; if (THUMBNAIL) { if (section.THUMBNAIL) { const oldThumbnailPath = path.join( "public/uploads/section", section.THUMBNAIL ); if (fs.existsSync(oldThumbnailPath)) { fs.unlinkSync(oldThumbnailPath); } } section.THUMBNAIL = saveFileToDisk( THUMBNAIL, "THUMBNAIL", section.ID_SECTION ); } await section.save({ transaction }); await transaction.commit(); response(200, section, "Section updated successfully", res); } catch (error) { console.log(error); await transaction.rollback(); clearFileBuffers({ THUMBNAIL }); response(500, null, "Internal Server Error", res); } }; export const deleteSectionById = async (req, res) => { const { id } = req.params; try { const section = await models.Section.findByPk(id); if (!section) { return response(404, null, "Section not found", res); } section.IS_DELETED = 1; await section.save(); await models.Topic.update({ IS_DELETED: 1 }, { where: { ID_SECTION: id } }); await models.Level.update( { IS_DELETED: 1 }, { where: { ID_TOPIC: { [models.Op.in]: models.Sequelize.literal( `(SELECT ID_TOPIC FROM topic WHERE ID_SECTION = '${id}')` ), }, }, } ); await models.Exercise.update( { IS_DELETED: 1 }, { where: { ID_LEVEL: { [models.Op.in]: models.Sequelize.literal( `(SELECT ID_LEVEL FROM level WHERE ID_TOPIC IN (SELECT ID_TOPIC FROM topic WHERE ID_SECTION = '${id}') )` ), }, }, } ); response( 200, null, "Section, topics, levels, and related exercises soft deleted successfully", res ); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } };