refactor: class model function

This commit is contained in:
elangptra 2024-10-14 08:23:37 +07:00
parent 80de2108b8
commit 4ced73bca2
16 changed files with 1359 additions and 107 deletions

30
config/config.js Normal file
View File

@ -0,0 +1,30 @@
import dotenv from "dotenv";
dotenv.config();
export default {
development: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
dialect: "mysql",
timezone: "+07:00",
},
test: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_TEST,
host: process.env.DB_HOST,
dialect: "mysql",
timezone: "+07:00",
},
production: {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOST,
dialect: "mysql",
timezone: "+07:00",
},
};

View File

@ -272,7 +272,6 @@ export const getLevelsByTopicId = async (req, res) => {
.json({ message: "No levels found for the given topic." }); .json({ message: "No levels found for the given topic." });
} }
// Mencari pembelajaran terakhir yang selesai
const lastCompletedLearning = await models.StdLearning.findOne({ const lastCompletedLearning = await models.StdLearning.findOne({
where: { where: {
ID: ID, ID: ID,
@ -290,7 +289,6 @@ export const getLevelsByTopicId = async (req, res) => {
let currentLearningLevel = null; let currentLearningLevel = null;
// Jika ada pembelajaran yang selesai, kita dapat memeriksa level berikutnya dari NEXT_LEARNING
if (lastCompletedLearning?.NEXT_LEARNING) { if (lastCompletedLearning?.NEXT_LEARNING) {
currentLearningLevel = await models.Level.findOne({ currentLearningLevel = await models.Level.findOne({
where: { where: {
@ -303,7 +301,6 @@ export const getLevelsByTopicId = async (req, res) => {
const nextLearningLevel = currentLearningLevel; const nextLearningLevel = currentLearningLevel;
// Memasukkan level berikutnya (jika ada) ke dalam UNLOCKED_LEVELS
const unlockedLevels = lastCompletedLearning const unlockedLevels = lastCompletedLearning
? await models.Level.findAll({ ? await models.Level.findAll({
where: { where: {
@ -321,8 +318,10 @@ export const getLevelsByTopicId = async (req, res) => {
const unlockedLevelNames = unlockedLevels.map((lvl) => lvl.NAME_LEVEL); const unlockedLevelNames = unlockedLevels.map((lvl) => lvl.NAME_LEVEL);
// Menambahkan level berikutnya ke dalam UNLOCKED_LEVELS jika belum termasuk if (
if (nextLearningLevel && !unlockedLevelNames.includes(nextLearningLevel.NAME_LEVEL)) { nextLearningLevel &&
!unlockedLevelNames.includes(nextLearningLevel.NAME_LEVEL)
) {
unlockedLevelNames.push(nextLearningLevel.NAME_LEVEL); unlockedLevelNames.push(nextLearningLevel.NAME_LEVEL);
} }

View File

@ -28,6 +28,95 @@ export const getClassById = async (req, res) => {
} }
}; };
export const getClassForAdmin = async (req, res) => {
const { page = 1, limit = 10, search = "", sort = "time" } = req.query;
try {
const { count, rows: classes } = await models.Class.findAndCountAll({
where: {
...(search && {
[models.Op.or]: [
{
NAME_CLASS: {
[models.Op.like]: `%${search}%`,
},
},
models.Sequelize.where(
models.Sequelize.literal(
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
),
{
[models.Op.like]: `%${search}%`,
}
),
{
TOTAL_STUDENT: {
[models.Op.like]: `%${search}%`,
},
},
],
}),
},
attributes: [
"ID_CLASS",
"NAME_CLASS",
"TOTAL_STUDENT",
"TIME_CLASS",
[
models.Sequelize.literal(
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
),
"STUDENTS",
],
],
distinct: true,
});
const formattedClasses = classes.map((classItem) => ({
ID_CLASS: classItem.ID_CLASS,
NAME_CLASS: classItem.NAME_CLASS,
STUDENTS: classItem.get("STUDENTS"),
TOTAL_STUDENT: classItem.TOTAL_STUDENT,
TIME_CLASS: classItem.TIME_CLASS,
}));
if (sort === "class") {
formattedClasses.sort((a, b) => a.NAME_CLASS.localeCompare(b.NAME_CLASS));
} else if (sort === "total") {
formattedClasses.sort((a, b) => a.TOTAL_STUDENT - b.TOTAL_STUDENT);
} else if (sort === "students") {
formattedClasses.sort((a, b) => a.STUDENTS - b.STUDENTS);
} else {
formattedClasses.sort(
(a, b) => new Date(b.TIME_CLASS) - new Date(a.TIME_CLASS)
);
}
const paginatedClasses = formattedClasses.slice(
(page - 1) * limit,
page * limit
);
const totalPages = Math.ceil(count / limit);
const currentPage = parseInt(page);
response(
200,
{
classes: paginatedClasses,
currentPage,
totalPages,
totalItems: count,
},
"Classes retrieved successfully",
res
);
} catch (error) {
console.log(error);
response(500, null, "Error retrieving classes data!", res);
}
};
export const createClass = async (req, res) => { export const createClass = async (req, res) => {
const { NAME_CLASS, TOTAL_STUDENT } = req.body; const { NAME_CLASS, TOTAL_STUDENT } = req.body;
@ -85,9 +174,28 @@ export const deleteClassById = async (req, res) => {
return response(404, null, "Class not found", res); return response(404, null, "Class not found", res);
} }
await models.Student.update(
{ ID_CLASS: null },
{
where: { ID_CLASS: id },
}
);
await models.Monitoring.update(
{ ID_CLASS: null },
{
where: { ID_CLASS: id },
}
);
await classes.destroy(); await classes.destroy();
response(200, null, "Class deleted successfully", res); response(
200,
null,
"Class deleted successfully and related models updated",
res
);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
response(500, null, "Internal Server Error", res); response(500, null, "Internal Server Error", res);

View File

@ -111,75 +111,130 @@ export const updateMonitoringClass = async ({
}; };
export const monitoringStudentsProgress = async (req, res) => { export const monitoringStudentsProgress = async (req, res) => {
try { const { page = 1, limit = 10, search = "", sort = "time" } = req.query;
const result = await models.Monitoring.findAll({
include: [
{
model: models.StdLearning,
as: "stdLearningMonitoring",
include: [
{
model: models.User,
as: "learningUser",
attributes: ["NAME_USERS"],
include: [
{
model: models.Student,
as: "students",
attributes: ["NISN"],
include: [
{
model: models.Class,
as: "studentClass",
attributes: ["NAME_CLASS"],
},
],
},
],
},
{
model: models.Level,
as: "level",
attributes: ["NAME_LEVEL"],
include: [
{
model: models.Topic,
as: "levelTopic",
attributes: ["NAME_TOPIC"],
include: [
{
model: models.Section,
as: "topicSection",
attributes: ["NAME_SECTION"],
},
],
},
],
},
],
},
],
});
const formattedResult = result.map((monitoring) => { try {
return { const { count, rows: monitorings } =
ID_MONITORING: monitoring.ID_MONITORING, await models.Monitoring.findAndCountAll({
NISN: monitoring.stdLearningMonitoring?.learningUser?.students?.NISN, include: [
NAME_USERS: monitoring.stdLearningMonitoring?.learningUser?.NAME_USERS, {
NAME_SECTION: model: models.StdLearning,
monitoring.stdLearningMonitoring?.level?.levelTopic?.topicSection as: "stdLearningMonitoring",
?.NAME_SECTION, include: [
NAME_TOPIC: {
monitoring.stdLearningMonitoring?.level?.levelTopic?.NAME_TOPIC, model: models.User,
NAME_CLASS: as: "learningUser",
monitoring.stdLearningMonitoring?.learningUser?.students?.studentClass attributes: ["NAME_USERS"],
?.NAME_CLASS ?? null, include: [
}; {
}); model: models.Student,
as: "students",
attributes: ["NISN"],
include: [
{
model: models.Class,
as: "studentClass",
attributes: ["NAME_CLASS"],
},
],
},
],
},
{
model: models.Level,
as: "level",
attributes: ["NAME_LEVEL"],
include: [
{
model: models.Topic,
as: "levelTopic",
attributes: ["NAME_TOPIC"],
include: [
{
model: models.Section,
as: "topicSection",
attributes: ["NAME_SECTION"],
},
],
},
],
},
],
},
],
where: {
...(search && {
[models.Op.or]: [
{
"$stdLearningMonitoring.learningUser.students.NISN$": {
[models.Op.like]: `%${search}%`,
},
},
{
"$stdLearningMonitoring.learningUser.NAME_USERS$": {
[models.Op.like]: `%${search}%`,
},
},
{
"$stdLearningMonitoring.level.levelTopic.topicSection.NAME_SECTION$":
{
[models.Op.like]: `%${search}%`,
},
},
{
"$stdLearningMonitoring.level.levelTopic.NAME_TOPIC$": {
[models.Op.like]: `%${search}%`,
},
},
],
}),
},
distinct: true,
});
const formattedResult = monitorings.map((monitoring) => ({
ID_MONITORING: monitoring.ID_MONITORING,
NISN: monitoring.stdLearningMonitoring?.learningUser?.students?.NISN,
NAME_USERS: monitoring.stdLearningMonitoring?.learningUser?.NAME_USERS,
NAME_SECTION:
monitoring.stdLearningMonitoring?.level?.levelTopic?.topicSection
?.NAME_SECTION,
NAME_TOPIC:
monitoring.stdLearningMonitoring?.level?.levelTopic?.NAME_TOPIC,
NAME_CLASS:
monitoring.stdLearningMonitoring?.learningUser?.students?.studentClass
?.NAME_CLASS ?? null,
}));
if (sort === "nisn") {
formattedResult.sort((a, b) => a.NISN.localeCompare(b.NISN));
} else if (sort === "name") {
formattedResult.sort((a, b) => a.NAME_USERS.localeCompare(b.NAME_USERS));
} else if (sort === "section") {
formattedResult.sort((a, b) =>
a.NAME_SECTION.localeCompare(b.NAME_SECTION)
);
} else if (sort === "topic") {
formattedResult.sort((a, b) => a.NAME_TOPIC.localeCompare(b.NAME_TOPIC));
} else {
formattedResult.sort((a, b) => new Date(b.TIME) - new Date(a.TIME));
}
const paginatedResult = formattedResult.slice(
(page - 1) * limit,
page * limit
);
const totalPages = Math.ceil(count / limit);
const currentPage = parseInt(page);
response( response(
200, 200,
formattedResult, {
monitorings: paginatedResult,
currentPage,
totalPages,
totalItems: count,
},
"Success retrieving student monitoring progress!", "Success retrieving student monitoring progress!",
res res
); );
@ -191,6 +246,7 @@ export const monitoringStudentsProgress = async (req, res) => {
export const monitoringStudentProgressById = async (req, res) => { export const monitoringStudentProgressById = async (req, res) => {
const { id } = req.params; const { id } = req.params;
const { page = 1, limit = 10, search = "", sort = "start" } = req.query;
try { try {
const monitoring = await models.Monitoring.findOne({ const monitoring = await models.Monitoring.findOne({
@ -213,6 +269,32 @@ export const monitoringStudentProgressById = async (req, res) => {
model: models.Level, model: models.Level,
as: "level", as: "level",
attributes: ["ID_TOPIC", "NAME_LEVEL"], attributes: ["ID_TOPIC", "NAME_LEVEL"],
include: [
{
model: models.Topic,
as: "levelTopic",
attributes: ["NAME_TOPIC"],
include: [
{
model: models.Section,
as: "topicSection",
attributes: ["NAME_SECTION"],
},
],
},
],
},
{
model: models.User,
as: "learningUser",
attributes: ["NAME_USERS"],
include: [
{
model: models.Student,
as: "students",
attributes: ["NISN"],
},
],
}, },
], ],
}, },
@ -231,10 +313,38 @@ export const monitoringStudentProgressById = async (req, res) => {
const userID = stdLearning.ID; const userID = stdLearning.ID;
const topicID = stdLearning.level.ID_TOPIC; const topicID = stdLearning.level.ID_TOPIC;
const studentName = stdLearning.learningUser.NAME_USERS;
const nisn = stdLearning.learningUser.students.NISN;
const topicName = stdLearning.level.levelTopic.NAME_TOPIC;
const sectionName = stdLearning.level.levelTopic.topicSection.NAME_SECTION;
const levels = await models.StdLearning.findAll({ // Fetch levels with pagination, search, and sort
const levels = await models.StdLearning.findAndCountAll({
where: { where: {
ID: userID, ID: userID,
...(search && {
[models.Op.or]: [
{
"$level.NAME_LEVEL$": { [models.Op.like]: `%${search}%` },
},
{
SCORE: { [models.Op.like]: `%${search}%` },
},
{
FEEDBACK_STUDENT: { [models.Op.like]: `%${search}%` },
},
// {
// [models.Sequelize.fn('DATE_FORMAT', models.Sequelize.col('STUDENT_START'), '%Y-%m-%d')]: {
// [models.Op.like]: `%${search}%`,
// },
// },
// {
// [models.Sequelize.fn('DATE_FORMAT', models.Sequelize.col('STUDENT_FINISH'), '%Y-%m-%d')]: {
// [models.Op.like]: `%${search}%`,
// },
// },
],
}),
}, },
include: [ include: [
{ {
@ -252,18 +362,10 @@ export const monitoringStudentProgressById = async (req, res) => {
"STUDENT_START", "STUDENT_START",
"STUDENT_FINISH", "STUDENT_FINISH",
], ],
distinct: true,
}); });
if (levels.length === 0) { const levelArray = levels.rows
return response(
404,
null,
"No levels found for the given user and topic!",
res
);
}
const levelArray = levels
.map((learning) => ({ .map((learning) => ({
NAME_LEVEL: learning.level.NAME_LEVEL, NAME_LEVEL: learning.level.NAME_LEVEL,
SCORE: learning.SCORE, SCORE: learning.SCORE,
@ -272,18 +374,35 @@ export const monitoringStudentProgressById = async (req, res) => {
STUDENT_FINISH: learning.STUDENT_FINISH, STUDENT_FINISH: learning.STUDENT_FINISH,
})) }))
.sort((a, b) => { .sort((a, b) => {
if (a.NAME_LEVEL === "Pretest") return -1; if (sort === "level") {
if (b.NAME_LEVEL === "Pretest") return 1; return a.NAME_LEVEL.localeCompare(b.NAME_LEVEL);
} else if (sort === "score") {
const levelNumberA = parseInt(a.NAME_LEVEL.replace("Level ", ""), 10); return b.SCORE - a.SCORE;
const levelNumberB = parseInt(b.NAME_LEVEL.replace("Level ", ""), 10); } else if (sort === "feedback") {
return levelNumberA - levelNumberB; return a.FEEDBACK_STUDENT.localeCompare(b.FEEDBACK_STUDENT);
} else if (sort === "start") {
return new Date(a.STUDENT_START) - new Date(b.STUDENT_START);
} else if (sort === "finish") {
return new Date(a.STUDENT_FINISH) - new Date(b.STUDENT_FINISH);
}
return 0;
}); });
// Pagination logic
const paginatedResult = levelArray.slice((page - 1) * limit, page * limit);
const totalPages = Math.ceil(levels.count / limit);
const currentPage = parseInt(page);
const result = { const result = {
ID_MONITORING: monitoring.ID_MONITORING, ID_MONITORING: monitoring.ID_MONITORING,
levels: levelArray, NAME_SECTION: sectionName,
FEEDBACK_GURU: monitoring.FEEDBACK_GURU, NAME_TOPIC: topicName,
NAME_USERS: studentName,
NISN: nisn,
levels: paginatedResult,
currentPage,
totalPages,
totalItems: levels.count,
}; };
response(200, result, "Success retrieving student progress!", res); response(200, result, "Success retrieving student progress!", res);

View File

@ -0,0 +1,51 @@
const { Sequelize } = require("sequelize");
module.exports = {
async up(queryInterface) {
await queryInterface.createTable("users", {
ID: {
type: Sequelize.UUID,
primaryKey: true,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
},
NAME_USERS: {
type: Sequelize.STRING(100),
allowNull: false,
},
EMAIL: {
type: Sequelize.STRING(100),
allowNull: false,
},
PASSWORD: {
type: Sequelize.STRING(100),
allowNull: false,
},
ROLE: {
type: Sequelize.STRING(100),
allowNull: true,
},
PICTURE: {
type: Sequelize.STRING(1024),
allowNull: true,
},
REFRESH_TOKEN: {
type: Sequelize.STRING(256),
allowNull: true,
},
TIME_USERS: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
});
await queryInterface.addConstraint("users", {
fields: ["EMAIL"],
type: "unique",
name: "user_unique_email",
});
},
async down(queryInterface) {
await queryInterface.dropTable("users");
},
};

View File

@ -0,0 +1,21 @@
const bcrypt = require('bcrypt');
const { v4: uuidv4 } = require('uuid');
module.exports = {
up: async (queryInterface) => {
const hashedPassword = await bcrypt.hash('adminsealspolinema24', 10);
await queryInterface.bulkInsert('users', [
{
ID: uuidv4(),
NAME_USERS: 'Administrator',
EMAIL: 'adminseals@gmail.com',
PASSWORD: hashedPassword,
ROLE: 'admin',
TIME_USERS: new Date(),
},
]);
},
down: async (queryInterface) => {
await queryInterface.bulkDelete('users', { EMAIL: 'adminseals@gmail.com' });
},
};

14
generateMigration.js Normal file
View File

@ -0,0 +1,14 @@
import { execSync } from "child_process";
const name = process.argv[2];
if (!name) {
console.error("Error: Migration name is required.");
process.exit(1);
}
execSync(
`npx sequelize-cli migration:generate --migrations-path database/migrations --config config/config.js --name ${name}`,
{ stdio: "inherit" }
);
execSync("node renameFiles.js", { stdio: "inherit" });

14
generateSeed.js Normal file
View File

@ -0,0 +1,14 @@
import { execSync } from "child_process";
const name = process.argv[2];
if (!name) {
console.error("Error: Migration name is required.");
process.exit(1);
}
execSync(
`npx sequelize-cli seed:generate --seeders-path database/seeders --config config/config.js --name ${name}`,
{ stdio: "inherit" }
);
execSync("node renameFiles.js", { stdio: "inherit" });

View File

@ -21,7 +21,7 @@ const ClassModel = (DataTypes) => {
}, },
}, },
TOTAL_STUDENT: { TOTAL_STUDENT: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER(11),
allowNull: true, allowNull: true,
}, },
TIME_CLASS: { TIME_CLASS: {

View File

@ -33,7 +33,7 @@ const StudentModel = (DataTypes) => {
}, },
}, },
NISN: { NISN: {
type: DataTypes.INTEGER, type: DataTypes.BIGINT(11),
allowNull: false, allowNull: false,
unique: true, unique: true,
validate: { validate: {

View File

@ -25,7 +25,7 @@ const TeacherModel = (DataTypes) => {
}, },
}, },
NIP: { NIP: {
type: DataTypes.INTEGER, type: DataTypes.BIGINT(11),
allowNull: false, allowNull: false,
unique: true, unique: true,
validate: { validate: {

View File

@ -14,14 +14,14 @@ const UserModel = (DataTypes) => {
}, },
}, },
NAME_USERS: { NAME_USERS: {
type: DataTypes.STRING, type: DataTypes.STRING(100),
allowNull: false, allowNull: false,
validate: { validate: {
notEmpty: true, notEmpty: true,
}, },
}, },
EMAIL: { EMAIL: {
type: DataTypes.STRING, type: DataTypes.STRING(100),
allowNull: false, allowNull: false,
unique: true, unique: true,
validate: { validate: {
@ -30,19 +30,20 @@ const UserModel = (DataTypes) => {
}, },
}, },
PASSWORD: { PASSWORD: {
type: DataTypes.STRING, type: DataTypes.STRING(100),
allowNull: false, allowNull: false,
}, },
ROLE: { ROLE: {
type: DataTypes.STRING, type: DataTypes.STRING(100),
allowNull: true, allowNull: true,
}, },
PICTURE: { PICTURE: {
type: DataTypes.STRING, type: DataTypes.STRING(1024),
allowNull: true, allowNull: true,
}, },
REFRESH_TOKEN: { REFRESH_TOKEN: {
type: DataTypes.STRING, type: DataTypes.STRING(256),
allowNull: true,
}, },
TIME_USERS: { TIME_USERS: {
type: DataTypes.DATE, type: DataTypes.DATE,

863
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,13 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"api-start": "nodemon index.js" "api-start": "nodemon index.js",
"db:migrate": "npx sequelize-cli db:migrate --migrations-path database/migrations --config config/config.js",
"db:seed": "npx sequelize-cli db:seed:all --seeders-path database/seeders --config config/config.js",
"db:migrate:undo": "npx sequelize-cli db:migrate:undo --migrations-path database/migrations --config config/config.js",
"db:seed:undo": "npx sequelize-cli db:seed:undo --seeders-path database/seeders --config config/config.js",
"migrate:generate": "node generateMigration.js",
"seed:generate": "node generateSeed.js"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
@ -23,6 +29,8 @@
"mysql2": "^3.11.0", "mysql2": "^3.11.0",
"nodemailer": "^6.9.14", "nodemailer": "^6.9.14",
"nodemon": "^3.1.4", "nodemon": "^3.1.4",
"sequelize": "^6.37.3" "sequelize": "^6.37.3",
"sequelize-cli": "^6.6.2",
"uuid": "^10.0.0"
} }
} }

30
renameFiles.js Normal file
View File

@ -0,0 +1,30 @@
import fs from "fs";
import path from "path";
function renameFilesInDirectory(directory) {
fs.readdir(directory, (err, files) => {
if (err) {
console.error(`Error reading directory ${directory}:`, err);
return;
}
files.forEach((file) => {
const ext = path.extname(file);
if (ext === ".js") {
const oldPath = path.join(directory, file);
const newPath = path.join(directory, file.replace(".js", ".cjs"));
fs.rename(oldPath, newPath, (renameErr) => {
if (renameErr) {
console.error(`Error renaming file ${file}:`, renameErr);
} else {
console.log(`Renamed: ${file} -> ${path.basename(newPath)}`);
}
});
}
});
});
}
renameFilesInDirectory("./database/migrations");
renameFilesInDirectory("./database/seeders");

View File

@ -1,11 +1,13 @@
import express from "express"; import express from "express";
import { getClasses, getClassById, getStudentsByClassId, getStudentsWithNoClass, createClass, updateClassById, deleteClassById, updateStudentClassByName } from "../../controllers/monitoringControllers/class.js"; import { getClasses, getClassById, getStudentsByClassId, getClassForAdmin, getStudentsWithNoClass, createClass, updateClassById, deleteClassById, updateStudentClassByName } from "../../controllers/monitoringControllers/class.js";
import { verifyLoginUser, adminOrTeacherOnly } from "../../middlewares/User/authUser.js"; import { verifyLoginUser, adminOrTeacherOnly } from "../../middlewares/User/authUser.js";
const router = express.Router(); const router = express.Router();
router.get("/classes", verifyLoginUser, getClasses); router.get("/classes", verifyLoginUser, getClasses);
router.get("/class/admin", verifyLoginUser, getClassForAdmin);
router.get("/class/:id", verifyLoginUser, getClassById); router.get("/class/:id", verifyLoginUser, getClassById);
router.get("/class/student/unassigned", verifyLoginUser, adminOrTeacherOnly, getStudentsWithNoClass); router.get("/class/student/unassigned", verifyLoginUser, adminOrTeacherOnly, getStudentsWithNoClass);
@ -14,7 +16,7 @@ router.get("/class/student/:classId", verifyLoginUser, adminOrTeacherOnly, getSt
router.post("/class", verifyLoginUser, createClass); router.post("/class", verifyLoginUser, createClass);
router.put("/class/update/:classId", verifyLoginUser, updateClassById); router.put("/class/update/:id", verifyLoginUser, updateClassById);
router.delete("/class/delete/:id", verifyLoginUser, deleteClassById); router.delete("/class/delete/:id", verifyLoginUser, deleteClassById);