add: ver()

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-08 11:31:40 +08:00
parent 0e4cd86119
commit bb7e8fde08
29 changed files with 2234 additions and 780 deletions
+4
View File
@@ -29,6 +29,8 @@ const usersRoutes = require('./users.routes');
const groupsRoutes = require('./groups.routes');
const assetsRoutes = require('./assets.routes');
const coursesRoutes = require('./courses.routes');
const unitsRoutes = require('./units.routes');
const lessonsRoutes = require('./lessons.routes');
const taskRoutes = require('./task.routes');
const tiersRoutes = require('./tiers.routes');
const tierPoliciesRoutes = require('./tier_policies.routes');
@@ -54,6 +56,8 @@ router.use('/users', usersRoutes);
router.use('/groups', groupsRoutes);
router.use('/assets', assetsRoutes);
router.use('/courses', coursesRoutes);
router.use('/units', unitsRoutes); // standalone Unit library (junction revamp)
router.use('/lessons', lessonsRoutes); // standalone Lesson library (junction revamp)
router.use('/task-lists', taskRoutes);
router.use('/tiers/categories', tierCategoriesRoutes);
router.use('/tiers', tiersRoutes);
+5 -2
View File
@@ -96,9 +96,11 @@ router.get("/:courseId/assessment/:assessmentId/sessions", ctrl.getAssessment
router.get("/:courseId/field-values", ctrl.getUnitFieldValues);
router.get("/:courseId/units", ctrl.getUnits);
router.post("/:courseId/units", ctrl.createUnit);
router.post("/:courseId/units", ctrl.createUnit); // create new unit + attach, or attach existing via body { unit_id }
// static before :unitId
router.post("/:courseId/units/attach", ctrl.attachUnits); // bulk-attach existing library units { unit_ids }
router.put("/:courseId/units/order", ctrl.reorderUnits); // persist course-level unit ordering { unit_ids }
router.delete("/:courseId/units/bulk", ctrl.bulkArchiveUnits);
router.delete("/:courseId/units/bulk/permanent", ctrl.bulkPermanentlyDeleteUnits);
router.get("/:courseId/units/archives", ctrl.getArchivedUnits);
@@ -150,9 +152,10 @@ router.get("/:courseId/units/:unitId/quiz/:quizId/completions", ctrl.getQuizComp
router.get("/:courseId/units/:unitId/field-values", ctrl.getLessonFieldValues);
router.get("/:courseId/units/:unitId/lessons", ctrl.getLessons);
router.post("/:courseId/units/:unitId/lessons", ctrl.createLesson);
router.post("/:courseId/units/:unitId/lessons", ctrl.createLesson); // create new lesson + attach, or attach existing via body { lesson_id }
// static before :lessonId
router.put("/:courseId/units/:unitId/lessons/order", ctrl.reorderLessons); // persist unit-level lesson ordering { lesson_ids }
router.delete("/:courseId/units/:unitId/lessons/bulk", ctrl.bulkArchiveLessons);
router.delete("/:courseId/units/:unitId/lessons/bulk/permanent", ctrl.bulkPermanentlyDeleteLessons);
router.get("/:courseId/units/:unitId/lessons/archives", ctrl.getArchivedLessons);
+39
View File
@@ -0,0 +1,39 @@
/***********************************************************************************************************************************************************************
* File Name: lessons.routes.js (admin)
* Type of Program: Router
* Description: Standalone Lesson library — Lessons run independently of Units.
* Unit membership (attach/detach/reorder) lives under
* /admin/units/:unitId/lessons.
*
* Author: Kenneth Obsequio (@lash0000)
* Date Created: Jul. 7, 2026
***********************************************************************************************************************************************************************/
const router = require("express").Router();
const ctrl = require("../../controllers/admin/lessons.controller");
// Guards are applied by admin.routes.js (authenticate → requireAdmin → adminLimiter)
// ── static segments first ─────────────────────────────────────────────────────
router.get("/", ctrl.getLessons);
router.post("/", ctrl.createLesson);
router.get("/flat", ctrl.getLessonsFlat);
router.get("/field-values", ctrl.getLessonFieldValues);
router.delete("/bulk", ctrl.bulkArchiveLessons);
router.delete("/bulk/permanent", ctrl.bulkPermanentlyDeleteLessons);
router.get("/archives", ctrl.getArchivedLessons);
router.patch("/restore/bulk", ctrl.bulkRestoreLessons);
router.get("/archives/:lessonId", ctrl.getArchivedLesson);
// ── then :lessonId ────────────────────────────────────────────────────────────
router.patch("/:lessonId/restore", ctrl.restoreLesson);
router.get("/:lessonId/permanent-delete-impact", ctrl.getLessonPermanentDeleteImpact);
router.get("/:lessonId", ctrl.getLesson);
router.put("/:lessonId", ctrl.updateLesson);
router.delete("/:lessonId", ctrl.archiveLesson);
router.delete("/:lessonId/permanent", ctrl.permanentlyDeleteLesson);
// ── Lesson page (block content) ───────────────────────────────────────────────
router.get("/:lessonId/page", ctrl.getLessonPage);
router.put("/:lessonId/page", ctrl.upsertLessonPage);
module.exports = router;
+64
View File
@@ -0,0 +1,64 @@
/***********************************************************************************************************************************************************************
* File Name: units.routes.js (admin)
* Type of Program: Router
* Description: Standalone Unit library — Units run independently of Courses.
* Course membership (attach/detach/reorder) stays under
* /admin/courses/:courseId/units.
*
* Author: Kenneth Obsequio (@lash0000)
* Date Created: Jul. 7, 2026
***********************************************************************************************************************************************************************/
const router = require("express").Router();
const ctrl = require("../../controllers/admin/units.controller");
const questionCtrl = require("../../controllers/admin/courses.controller"); // shared quiz-question handlers (keyed by quizId)
// Guards are applied by admin.routes.js (authenticate → requireAdmin → adminLimiter)
// ── static segments first ─────────────────────────────────────────────────────
router.get("/", ctrl.getUnits);
router.post("/", ctrl.createUnit);
router.get("/flat", ctrl.getUnitsFlat);
router.get("/field-values", ctrl.getUnitFieldValues);
router.delete("/bulk", ctrl.bulkArchiveUnits);
router.delete("/bulk/permanent", ctrl.bulkPermanentlyDeleteUnits);
router.get("/archives", ctrl.getArchivedUnits);
router.patch("/restore/bulk", ctrl.bulkRestoreUnits);
router.get("/archives/:unitId", ctrl.getArchivedUnit);
// ── then :unitId ──────────────────────────────────────────────────────────────
router.patch("/:unitId/restore", ctrl.restoreUnit);
router.get("/:unitId/archive-impact", ctrl.getUnitArchiveImpact);
router.get("/:unitId/permanent-delete-impact", ctrl.getUnitPermanentDeleteImpact);
router.get("/:unitId", ctrl.getUnit);
router.put("/:unitId", ctrl.updateUnit);
router.delete("/:unitId", ctrl.archiveUnit);
router.delete("/:unitId/permanent", ctrl.permanentlyDeleteUnit);
// ── Lesson membership (attach / detach / reorder) ─────────────────────────────
router.post("/:unitId/lessons", ctrl.attachLessons);
router.put("/:unitId/lessons/order", ctrl.reorderLessons);
router.delete("/:unitId/lessons/:lessonId", ctrl.detachLesson);
// ── Unit quiz (travels with the Unit) ─────────────────────────────────────────
router.get("/:unitId/quiz", ctrl.getQuiz);
router.post("/:unitId/quiz", ctrl.createQuiz);
router.get("/:unitId/quiz/archives", ctrl.getArchivedQuiz);
router.patch("/:unitId/quiz/:quizId", ctrl.updateQuiz);
router.delete("/:unitId/quiz/:quizId", ctrl.deleteQuiz);
router.patch("/:unitId/quiz/:quizId/restore", ctrl.restoreQuiz);
// ── Quiz questions (shared handlers — keyed by quizId only) ───────────────────
router.get("/:unitId/quiz/:quizId/questions", questionCtrl.getQuestions);
router.post("/:unitId/quiz/:quizId/questions", questionCtrl.createQuestion);
router.delete("/:unitId/quiz/:quizId/questions/bulk", questionCtrl.bulkArchiveQuestions);
router.patch("/:unitId/quiz/:quizId/questions/restore/bulk", questionCtrl.bulkRestoreQuestions);
router.put("/:unitId/quiz/:quizId/questions/bulk-sync", questionCtrl.bulkSyncQuestions);
router.get("/:unitId/quiz/:quizId/questions/archives/:questionId", questionCtrl.getArchivedQuestion);
router.patch("/:unitId/quiz/:quizId/questions/:questionId", questionCtrl.updateQuestion);
router.delete("/:unitId/quiz/:quizId/questions/:questionId", questionCtrl.deleteQuestion);
router.patch("/:unitId/quiz/:quizId/questions/:questionId/restore", questionCtrl.restoreQuestion);
// ── Quiz completions ──────────────────────────────────────────────────────────
router.get("/:unitId/quiz/:quizId/completions", questionCtrl.getQuizCompletions);
module.exports = router;
+4
View File
@@ -28,6 +28,8 @@ const { handleAvatarUpload } = require('../../middleware/avatar_upload.middlewar
const tiersRoutes = require('./tiers.routes');
const coursesRoutes = require('./courses.routes');
const unitsRoutes = require('./units.routes');
const lessonsRoutes = require('./lessons.routes');
const coursePurchasesRoutes = require('./course_purchases.routes');
const mediaRoutes = require("./media.routes");
const groupsRoutes = require("./groups.routes");
@@ -58,6 +60,8 @@ router.delete('/sessions/:id', profileCtrl.revokeSession);
router.use('/tiers', tiersRoutes);
router.use('/courses', coursesRoutes);
router.use('/units', unitsRoutes); // standalone Unit consumption (junction revamp)
router.use('/lessons', lessonsRoutes); // standalone Lesson consumption (junction revamp)
router.use('/course-purchases', coursePurchasesRoutes);
router.use('/groups', groupsRoutes);
router.use('/advertisements', advertisementRoutes);
+20
View File
@@ -0,0 +1,20 @@
/***********************************************************************************************************************************************************************
* File Name: lessons.routes.js (client)
* Type of Program: Router
* Description: Standalone Lesson consumption — each Lesson runs independently.
*
* GET /client/lessons/:uuid → lesson with full block content
* POST /client/lessons/:uuid/progress → standalone reading progress
* (course NULL; body.unit_uuid optional)
*
* Author: Kenneth Obsequio (@lash0000)
* Date Created: Jul. 7, 2026
***********************************************************************************************************************************************************************/
const express = require('express');
const router = express.Router();
const ctrl = require('../../controllers/client/units.controller');
router.get('/:uuid', ctrl.getLessonByUuid);
router.post('/:uuid/progress', ctrl.upsertStandaloneLessonProgress);
module.exports = router;
+26
View File
@@ -0,0 +1,26 @@
/***********************************************************************************************************************************************************************
* File Name: units.routes.js (client)
* Type of Program: Router
* Description: Standalone Unit consumption — Units run independently of Courses.
*
* GET /client/units → learner-facing unit library
* GET /client/units/:uuid → unit metadata
* GET /client/units/:uuid/lessons → unit + ALL lesson data
* GET /client/units/:uuid/quiz → quiz (answers stripped)
* POST /client/units/:uuid/quiz/:quizId/submit → graded attempt (no course context)
*
* Author: Kenneth Obsequio (@lash0000)
* Date Created: Jul. 7, 2026
***********************************************************************************************************************************************************************/
const express = require('express');
const router = express.Router();
const ctrl = require('../../controllers/client/units.controller');
router.get('/', ctrl.getUnits);
router.get('/:uuid/lessons', ctrl.getLessonsByUnitUuid);
router.get('/:uuid/quiz', ctrl.getUnitQuiz);
router.patch('/:uuid/quiz/:quizId/draft', ctrl.saveUnitQuizDraft);
router.post('/:uuid/quiz/:quizId/submit', ctrl.submitUnitQuiz);
router.get('/:uuid', ctrl.getUnitByUuid);
module.exports = router;