Project Introduction

The Online Quiz Platform is a web application designed to facilitate the creation, management, and participation in quizzes. Built using Node.js, this platform allows quiz creators to design quizzes and participants to take them, providing a seamless experience for both roles. The system supports multiple user roles, including admin, quiz creator, and participant, ensuring tailored access and functionality for each user type. The underlying MySQL database schema is structured to manage users, quizzes, questions, answer options, quiz attempts, feedback, and notifications, providing a robust foundation for effective quiz management.

Project Objectives

  • To develop a user-friendly interface for quiz creators to design and manage quizzes.
  • To allow participants to browse, take quizzes, and view their scores.
  • To implement a secure user authentication system for managing user roles and permissions.
  • To facilitate the creation of various question types, including multiple choice, true/false, and short answer.
  • To manage quiz attempts and track participant scores.
  • To provide feedback mechanisms for participants to comment on quizzes.
  • To send notifications to users regarding quiz updates and results.
  • To ensure the application is scalable and maintainable for future enhancements.

Project Modules

  1. User Management Module:

    This module handles user registration, authentication, and role management, allowing users to manage their accounts securely.

  2. Quiz Management Module:

    This module allows quiz creators to create, update, and manage quizzes, including titles, descriptions, and time limits.

  3. Question Management Module:

    This module facilitates the creation and management of questions for quizzes, including different question types.

  4. Answer Options Management Module:

    This module allows quiz creators to define answer options for multiple choice questions, including marking correct answers.

  5. Quiz Attempt Management Module:

    This module tracks quiz attempts by participants, including scores and completion times.

  6. Feedback Management Module:

    This module enables participants to provide feedback on quizzes, including comments and suggestions.

  7. Notification Module:

    This module sends notifications to users regarding important updates, such as quiz availability and results.

Steps Overview

Set Up the Project: Initialize a new Node.js project and install the necessary packages.

Configure Sequelize: Set up Sequelize to connect to your MySQL database.

Define Models: Create Sequelize models based on the provided SQL tables.

Create Repositories: Implement repository functions for CRUD operations.

Set Up Controllers: Create controllers to handle requests and responses.

Define Routes: Set up routes to connect the controllers.

Create Views: Use EJS to create views for displaying data.

Implement Bootstrap 5: Style the views using Bootstrap 5.

Create a Dashboard: Create a dashboard to display consolidated data.

Step 1: Set Up the Project


mkdir quiz-management-system
cd quiz-management-system
npm init -y
npm install express sequelize mysql2 ejs body-parser

Step 2: Configure Sequelize

Create a file named config.js for database configuration.


// config.js
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('database_name', 'username', 'password', {
host: 'localhost',
dialect: 'mysql',
});
module.exports = sequelize;

Step 3: Define Models

Create a folder named models and create model files for each table.

models/User.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class User extends Model {}
User .init({
UserId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Username: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
PasswordHash: {
type: DataTypes.STRING(256),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
FirstName: {
type: DataTypes.STRING(50),
allowNull: false,
},
LastName: {
type: DataTypes.STRING(50),
allowNull: false,
},
RoleId: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'User ',
timestamps: true,
});
module.exports = User;

models/Role.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Role extends Model {}
Role.init({
RoleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoleName: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
}, {
sequelize,
modelName: 'Role',
timestamps: true,
});
module.exports = Role;

models/Quiz.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Quiz extends Model {}
Quiz.init({
QuizId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Title: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Quiz',
timestamps: true,
});
module.exports = Quiz;

models/Question.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Question extends Model {}
Question.init({
QuestionId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false,
},
QuestionText: {
type: DataTypes.TEXT,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Question',
timestamps: true,
});
module.exports = Question;

models/Answer.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Answer extends Model {}
Answer.init({
AnswerId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
QuestionId: {
type: DataTypes.INTEGER,
allowNull: false,
},
AnswerText: {
type: DataTypes.TEXT,
allowNull: false,
},
IsCorrect: {
type: DataTypes.BOOLEAN,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Answer',
timestamps: true,
});
module.exports = Answer;

models/Score.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Score extends Model {}
Score.init({
ScoreId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Score: {
type: DataTypes.INTEGER,
allowNull: false,
},
AttemptedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Score',
timestamps: true,
});
module.exports = Score;

models/Performance.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Performance extends Model {}
Performance.init({
PerformanceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalQuizzes: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalScore: {
type: DataTypes.INTEGER,
allowNull: false,
},
AverageScore: {
type: DataTypes.DECIMAL(5, 2),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Performance',
timestamps: true,
});
module.exports = Performance;

models/Notification.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Notification extends Model {}
Notification.init({
NotificationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Message: {
type: DataTypes.STRING(256),
allowNull: false,
},
IsRead: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Notification',
timestamps: true,
});
module.exports = Notification;

models/Achievement.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Achievement extends Model {}
Achievement.init({
AchievementId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Title: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Achievement',
timestamps: true,
});
module.exports = Achievement;

Step 4: Create Repositories

Create a folder named repositories and implement repository functions for each model.

repositories/userRepository.js


const User = require('../models/User');
class UserRepository {
async createUser (userData) {
return await User.create(userData);
}
async getAllUsers() {
return await User.findAll();
}
async getUser ById(userId) {
return await User.findByPk(userId);
}
async updateUser (userId, userData) {
const user = await this.getUser ById(userId);
if (user) {
return await user.update(userData);
}
return null;
}
async deleteUser (userId) {
const user = await this.getUser ById(userId);
if (user) {
await user.destroy();
return true;
}
return false;
}
}
module.exports = new UserRepository();

Step 5: Set Up Controllers

Create a folder named controllers and create controller files for each model.

controllers/userController.js


const userRepository = require('../repositories/userRepository');
class UserController {
async createUser (req, res) {
try {
const user = await userRepository.createUser (req.body);
res.redirect('/users');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllUsers(req, res) {
try {
const users = await userRepository.getAllUsers();
res.render('users/index', { users });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getUser ById(req, res) {
try {
const user = await userRepository.getUser ById(req.params.id);
res.render(' users/edit', { user });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateUser (req, res) {
try {
await userRepository.updateUser (req.params.id, req.body);
res.redirect('/users');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteUser (req, res) {
try {
await userRepository.deleteUser (req.params.id);
res.redirect('/users');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new UserController();

Step 6: Define Routes

Create a folder named routes and set up routes for each model.

routes/userRoutes.js


const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.get('/', userController.getAllUsers);
router.get('/create', (req, res) => res.render('users/create'));
router.post('/', userController.createUser );
router.get('/:id', userController.getUser ById);
router.post('/:id', userController.updateUser );
router.post('/:id/delete', userController.deleteUser );
module.exports = router;

Step 7: Create Views

Create a folder named views and subfolders for each model. Use EJS to create views for displaying data.

views/users/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Users</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Users</h1>
<a href="/users/create" class="btn btn-primary mb-3">Create User</a>
<table class="table">
<thead>
<tr>
<th>UserId</th>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.UserId %></td>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/users/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create User</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create User</h1>
<form action="/users" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="Username" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="Email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="PasswordHash" required>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js "></script>
</body>
</html>

views/users/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit User</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit User</h1>
<form action="/users/<%= user.UserId %>" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="Username" value="<%= user.Username %>" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="Email" value="<%= user.Email %>" required>
</div>
<button type="submit" class="btn btn-primary">Update User</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Step 8: Implement Bootstrap 5

Bootstrap 5 has already been included in the views above. You can customize the styles further as needed.

Step 9: Create a Dashboard

You can create a dashboard similar to the one previously described, aggregating data from the various models.

Final Steps

Run the Application: Start your application by running node index.js in your terminal.

Access the Users Page: Open your browser and navigate to http://localhost:3000/users to view the user management interface.

This completes the implementation of a complete CRUD application for managing users in a quiz management system using Node.js, Sequelize, Express, EJS, and Bootstrap 5. You can replicate similar steps for other models like Roles, Quizzes, Questions, Answers, Scores, Performance, Notifications, and Achievements by following the same structure.

CRUD Implementation for Remaining Models

Following are the complete CRUD implementation for the remaining models: Roles, Quizzes, Questions, Answers, Scores, Performance, Notifications, and Achievements. This will include models, repositories, controllers, routes, and views for each entity.

Step 1: Define Remaining Models

Create model files for each remaining table in the models directory.

models/Role.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Role extends Model {}
Role.init({
RoleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoleName: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
}, {
sequelize,
modelName: 'Role',
timestamps: true,
});
module.exports = Role;

models/Quiz.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Quiz extends Model {}
Quiz.init({
QuizId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Title: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Quiz',
timestamps: true,
});
module.exports = Quiz;

models/Question.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Question extends Model {}
Question.init({
QuestionId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false,
},
QuestionText: {
type: DataTypes.TEXT,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Question',
timestamps: true,
});
module.exports = Question;

models/Answer.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Answer extends Model {}
Answer.init({
AnswerId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
QuestionId: {
type: DataTypes.INTEGER,
allowNull: false,
},
AnswerText: {
type: DataTypes.TEXT,
allowNull: false,
},
IsCorrect: {
type: DataTypes.BOOLEAN,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Answer',
timestamps: true,
});
module.exports = Answer;

models/Score.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Score extends Model {}
Score.init({
ScoreId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Score: {
type: DataTypes.INTEGER,
allowNull: false,
},
AttemptedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Score',
timestamps: true,
});
module.exports = Score;

models/Performance.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Performance extends Model {}
Performance.init({
PerformanceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalQuizzes: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalScore: {
type: DataTypes.INTEGER,
allowNull: false,
},
AverageScore: {
type: DataTypes.DECIMAL(5, 2),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Performance',
timestamps: true,
});
module.exports = Performance;

models/Notification.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Notification extends Model {}
Notification.init({
NotificationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Message: {
type: DataTypes.STRING(256),
allowNull: false,
},
IsRead: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Notification',
timestamps: true,
});
module.exports = Notification;

models/Achievement.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Achievement extends Model {}
Achievement.init({
AchievementId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Title: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Achievement',
timestamps: true,
});
module.exports = Achievement;

Step 2: Create Repositories for Remaining Models

Create repository files for each model in the repositories directory.

repositories/roleRepository.js


const Role = require('../models/Role');
class RoleRepository {
async createRole(roleData) {
return await Role.create(roleData);
}
async getAllRoles() {
return await Role.findAll();
}
async getRoleById(roleId) {
return await Role.findByPk(roleId);
}
async updateRole(roleId, roleData) {
const role = await this.getRoleById(roleId);
if (role) {
return await role.update(roleData);
}
return null;
}
async deleteRole(roleId) {
const role = await this.getRoleById(roleId);
if (role) {
await role.destroy();
return true;
}
return false;
}
}
module.exports = new RoleRepository();

repositories/quizRepository.js


const Quiz = require('../models/Quiz');
class QuizRepository {
async createQuiz(quizData) {
return await Quiz.create(quizData);
}
async getAllQuizzes() {
return await Quiz.findAll();
}
async getQuizById(quizId) {
return await Quiz.findByPk(quizId);
}
async updateQuiz(quizId, quizData) {
const quiz = await this.getQuizById(quizId);
if (quiz) {
return await quiz.update(quizData);
}
return null;
}
async deleteQuiz(quizId) {
const quiz = await this.getQuizById(quizId);
if (quiz) {
await quiz.destroy();
return true;
}
return false;
}
}
module.exports = new QuizRepository();

repositories/questionRepository.js


const Question = require('../models/Question');
class QuestionRepository {
async createQuestion(questionData) {
return await Question.create(questionData);
}
async getAllQuestions() {
return await Question.findAll();
}
async getQuestionById(questionId) {
return await Question.findByPk(questionId);
}
async updateQuestion(questionId, questionData) {
const question = await this.getQuestionById(questionId);
if (question) {
return await question.update(questionData);
}
return null;
}
async deleteQuestion(questionId) {
const question = await this.getQuestionById(questionId);
if (question) {
await question.destroy();
return true;
}
return false;
}
}
module.exports = new QuestionRepository();

repositories/answerRepository.js


const Answer = require('../models/Answer');
class AnswerRepository {
async createAnswer(answerData) {
return await Answer.create(answerData);
}
async getAllAnswers() {
return await Answer.findAll();
}
async getAnswerById(answerId) {
return await Answer.findByPk(answerId);
}
async updateAnswer(answerId, answerData) {
const answer = await this.getAnswerById(answerId);
if (answer) {
return await answer.update(answerData);
}
return null;
}
async deleteAnswer(answerId) {
const answer = await this.getAnswerById(answerId);
if (answer) {
await answer.destroy();
return true;
}
return false;
}
}
module.exports = new AnswerRepository();

repositories/scoreRepository.js


const Score = require('../models/Score');
class ScoreRepository {
async createScore(scoreData) {
return await Score.create(scoreData);
}
async getAllScores() {
return await Score.findAll();
}
async getScoreById(scoreId) {
return await Score.findByPk(scoreId);
}
async updateScore(scoreId, scoreData) {
const score = await this.getScoreById(scoreId);
if (score) {
return await score.update(scoreData );
}
return null;
}
async deleteScore(scoreId) {
const score = await this.getScoreById(scoreId);
if (score) {
await score.destroy();
return true;
}
return false;
}
}
module.exports = new ScoreRepository();

repositories/performanceRepository.js


const Performance = require('../models/Performance');
class PerformanceRepository {
async createPerformance(performanceData) {
return await Performance.create(performanceData);
}
async getAllPerformances() {
return await Performance.findAll();
}
async getPerformanceById(performanceId) {
return await Performance.findByPk(performanceId);
}
async updatePerformance(performanceId, performanceData) {
const performance = await this.getPerformanceById(performanceId);
if (performance) {
return await performance.update(performanceData);
}
return null;
}
async deletePerformance(performanceId) {
const performance = await this.getPerformanceById(performanceId);
if (performance) {
await performance.destroy();
return true;
}
return false;
}
}
module.exports = new PerformanceRepository();

repositories/notificationRepository.js


const Notification = require('../models/Notification');
class NotificationRepository {
async createNotification(notificationData) {
return await Notification.create(notificationData);
}
async getAllNotifications() {
return await Notification.findAll();
}
async getNotificationById(notificationId) {
return await Notification.findByPk(notificationId);
}
async updateNotification(notificationId, notificationData) {
const notification = await this.getNotificationById(notificationId);
if (notification) {
return await notification.update(notificationData);
}
return null;
}
async deleteNotification(notificationId) {
const notification = await this.getNotificationById(notificationId);
if (notification) {
await notification.destroy();
return true;
}
return false;
}
}
module.exports = new NotificationRepository();

repositories/achievementRepository.js


const Achievement = require('../models/Achievement');
class AchievementRepository {
async createAchievement(achievementData) {
return await Achievement.create(achievementData);
}
async getAllAchievements() {
return await Achievement.findAll();
}
async getAchievementById(achievementId) {
return await Achievement.findByPk(achievementId);
}
async updateAchievement(achievementId, achievementData) {
const achievement = await this.getAchievementById(achievementId);
if (achievement) {
return await achievement.update(achievementData);
}
return null;
}
async deleteAchievement(achievementId) {
const achievement = await this.getAchievementById(achievementId);
if (achievement) {
await achievement.destroy();
return true;
}
return false;
}
}
module.exports = new AchievementRepository();

Step 3: Set Up Controllers for Remaining Models

Create controller files for each model in the controllers directory.

controllers/roleController.js


const roleRepository = require('../repositories/roleRepository');
class RoleController {
async createRole(req, res) {
try {
await roleRepository.createRole(req.body);
res.redirect('/roles');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllRoles(req, res) {
try {
const roles = await roleRepository.getAllRoles();
res.render('roles/index', { roles });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getRoleById(req, res) {
try {
const role = await roleRepository.getRoleById(req.params.id);
res.render('roles/edit', { role });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateRole(req, res) {
try {
await roleRepository.updateRole(req.params.id, req.body);
res.redirect('/roles');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteRole(req, res) {
try {
await roleRepository.deleteRole(req.params.id);
res.redirect('/roles');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new RoleController();

controllers/quizController.js


const quizRepository = require('../repositories/quizRepository');
class QuizController {
async createQuiz(req, res) {
try {
await quizRepository.createQuiz(req .body);
res.redirect('/quizzes');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllQuizzes(req, res) {
try {
const quizzes = await quizRepository.getAllQuizzes();
res.render('quizzes/index', { quizzes });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getQuizById(req, res) {
try {
const quiz = await quizRepository.getQuizById(req.params.id);
res.render('quizzes/edit', { quiz });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateQuiz(req, res) {
try {
await quizRepository.updateQuiz(req.params.id, req.body);
res.redirect('/quizzes');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteQuiz(req, res) {
try {
await quizRepository.deleteQuiz(req.params.id);
res.redirect('/quizzes');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new QuizController();

controllers/questionController.js


const questionRepository = require('../repositories/questionRepository');
class QuestionController {
async createQuestion(req, res) {
try {
await questionRepository.createQuestion(req.body);
res.redirect('/questions');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllQuestions(req, res) {
try {
const questions = await questionRepository.getAllQuestions();
res.render('questions/index', { questions });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getQuestionById(req, res) {
try {
const question = await questionRepository.getQuestionById(req.params.id);
res.render('questions/edit', { question });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateQuestion(req, res) {
try {
await questionRepository.updateQuestion(req.params.id, req.body);
res.redirect('/questions');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteQuestion(req, res) {
try {
await questionRepository.deleteQuestion(req.params.id);
res.redirect('/questions');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new QuestionController();

controllers/answerController.js


const answerRepository = require('../repositories/answerRepository');
class AnswerController {
async createAnswer(req, res) {
try {
await answerRepository.createAnswer(req.body);
res.redirect('/answers');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllAnswers(req, res) {
try {
const answers = await answerRepository.getAllAnswers();
res.render('answers/index', { answers });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAnswerById(req, res) {
try {
const answer = await answerRepository.getAnswerById(req.params.id);
res.render('answers/edit', { answer });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateAnswer(req, res) {
try {
await answerRepository.updateAnswer(req.params.id, req.body);
res.redirect('/answers');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteAnswer(req, res) {
try {
await answerRepository.deleteAnswer(req.params.id);
res.redirect('/answers');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new AnswerController();

controllers/scoreController.js


const scoreRepository = require('../repositories/scoreRepository');
class ScoreController {
async createScore(req, res) {
try {
await scoreRepository.createScore(req.body);
res.redirect('/scores');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllScores(req, res) {
try {
const scores = await scoreRepository.getAllScores();
res.render('scores/index', { scores });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getScoreById(req, res) {
try {
const score = await scoreRepository.getScoreById(req.params.id);
res.render('scores/edit', { score });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateScore(req, res) {
try {
await scoreRepository.updateScore(req.params.id, req.body);
res.redirect('/scores');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteScore(req, res) {
try {
await scoreRepository.deleteScore(req.params.id);
res.redirect('/scores');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new ScoreController();

controllers/performanceController.js


const performanceRepository = require('../repositories/performanceRepository');
class PerformanceController {
async createPerformance(req, res) {
try {
await performanceRepository.createPerformance(req.body);
res.redirect('/performances');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllPerformances(req, res) {
try {
const performances = await performanceRepository.getAllPerformances();
res.render('performances/index', { performances });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getPerformanceById(req, res) {
try {
const performance = await performanceRepository.getPerformanceById(req.params.id);
res.render('performances/edit', { performance });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updatePerformance(req, res) {
try {
await performanceRepository.updatePerformance(req.params.id, req.body);
res.redirect('/performances');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deletePerformance(req, res) {
try {
await performanceRepository.deletePerformance(req.params.id);
res.redirect('/performances');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new PerformanceController();

controllers/notificationController.js


const notificationRepository = require('../repositories/notificationRepository');
class NotificationController {
async createNotification(req, res) {
try {
await notificationRepository.createNotification(req.body);
res.redirect('/notifications');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAllNotifications(req, res) {
try {
const notifications = await notificationRepository.getAllNotifications();
res.render('notifications/index', { notifications });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getNotificationById(req, res) {
try {
const notification = await notificationRepository.getNotificationById(req.params.id);
res.render('notifications/edit', { notification });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateNotification(req, res) {
try {
await notificationRepository.updateNotification(req.params.id, req.body);
res.redirect('/notifications');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteNotification(req, res) {
try {
await notificationRepository.deleteNotification(req.params.id);
res.redirect('/notifications');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new NotificationController();

controllers/achievementController.js


const achievementRepository = require('../repositories/achievementRepository');
class AchievementController {
async createAchievement(req, res) {
try {
await achievementRepository.createAchievement(req.body);
res.redirect('/achievements');
} catch (error) {
console.error(error);
res.status(500). send('Internal Server Error');
}
}
async getAllAchievements(req, res) {
try {
const achievements = await achievementRepository.getAllAchievements();
res.render('achievements/index', { achievements });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async getAchievementById(req, res) {
try {
const achievement = await achievementRepository.getAchievementById(req.params.id);
res.render('achievements/edit', { achievement });
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async updateAchievement(req, res) {
try {
await achievementRepository.updateAchievement(req.params.id, req.body);
res.redirect('/achievements');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
async deleteAchievement(req, res) {
try {
await achievementRepository.deleteAchievement(req.params.id);
res.redirect('/achievements');
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new AchievementController();

Step 4: Define Routes for Remaining Models

Create route files for each model in the routes directory.

routes/roleRoutes.js


const express = require('express');
const router = express.Router();
const roleController = require('../controllers/roleController');
router.get('/', roleController.getAllRoles);
router.get('/create', (req, res) => res.render('roles/create'));
router.post('/', roleController.createRole);
router.get('/:id', roleController.getRoleById);
router.post('/:id', roleController.updateRole);
router.post('/:id/delete', roleController.deleteRole);
module.exports = router;

routes/quizRoutes.js


const express = require('express');
const router = express.Router();
const quizController = require('../controllers/quizController');
router.get('/', quizController.getAllQuizzes);
router.get('/create', (req, res) => res.render('quizzes/create'));
router.post('/', quizController.createQuiz);
router.get('/:id', quizController.getQuizById);
router.post('/:id', quizController.updateQuiz);
router.post('/:id/delete', quizController.deleteQuiz);
module.exports = router;

routes/questionRoutes.js


const express = require('express');
const router = express.Router();
const questionController = require('../controllers/questionController');
router.get('/', questionController.getAllQuestions);
router.get('/create', (req, res) => res.render('questions/create'));
router.post('/', questionController.createQuestion);
router.get('/:id', questionController.getQuestionById);
router.post('/:id', questionController.updateQuestion);
router.post('/:id/delete', questionController.deleteQuestion);
module.exports = router;

routes/answerRoutes.js


const express = require('express');
const router = express.Router();
const answerController = require('../controllers/answerController');
router.get('/', answerController.getAllAnswers);
router.get('/create', (req, res) => res.render('answers/create'));
router.post('/', answerController.createAnswer);
router.get('/:id', answerController.getAnswerById);
router.post('/:id', answerController.updateAnswer);
router.post('/:id/delete', answerController.deleteAnswer);
module.exports = router;

routes/scoreRoutes.js


const express = require('express');
const router = express.Router();
const scoreController = require('../controllers/scoreController');
router.get('/', scoreController.getAllScores);
router.get('/create', (req, res) => res.render('scores/create'));
router.post('/', scoreController.createScore);
router.get('/:id', scoreController.getScoreById);
router.post('/:id', scoreController.updateScore);
router.post('/:id/delete', scoreController.deleteScore);
module.exports = router;

routes/performanceRoutes.js


const express = require('express');
const router = express.Router();
const performanceController = require('../controllers/performanceController');
router.get('/', performanceController.getAllPerformances);
router.get('/create', (req, res) => res.render('performances/create'));
router.post('/', performanceController.createPerformance);
router.get('/:id', performanceController.getPerformanceById);
router.post('/:id', performanceController.updatePerformance);
router.post('/:id/delete', performanceController.deletePerformance);
module.exports = router;

routes/notificationRoutes.js


const express = require('express');
const router = express.Router();
const notificationController = require('../controllers/notificationController');
router.get('/', notificationController.getAllNotifications);
router.get('/create', (req, res) => res.render('notifications/create'));
router.post('/', notificationController.createNotification);
router.get('/:id', notificationController.getNotificationById);
router.post ('/:id', notificationController.updateNotification);
router.post('/:id/delete', notificationController.deleteNotification);
module.exports = router;

routes/achievementRoutes.js


const express = require('express');
const router = express.Router();
const achievementController = require('../controllers/achievementController');
router.get('/', achievementController.getAllAchievements);
router.get('/create', (req, res) => res.render('achievements/create'));
router.post('/', achievementController.createAchievement);
router.get('/:id', achievementController.getAchievementById);
router.post('/:id', achievementController.updateAchievement);
router.post('/:id/delete', achievementController.deleteAchievement);
module.exports = router;

Step 5: Create Views for Remaining Models

Create view files for each model in the views directory.

views/roles/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Roles</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Roles</h1>
<a href="/roles/create" class="btn btn-primary mb-3">Create Role</a>
<table class="table">
<thead>
<tr>
<th>RoleId</th>
<th>RoleName</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% roles.forEach(role => { %>
<tr>
<td><%= role.RoleId %></td>
<td><%= role.RoleName %></td>
<td>
<a href="/roles/<%= role.RoleId %>" class="btn btn-warning">Edit</a>
<form action="/roles/<%= role.RoleId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/roles/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Role</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Role</h1>
<form action="/roles" method="POST">
<div class="mb-3">
<label for="roleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="roleName" name="RoleName" required>
</div>
<button type="submit" class="btn btn-primary">Create Role</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/roles/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Role</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Role</h1>
<form action="/roles/<%= role.RoleId %>" method="POST">
<div class="mb-3">
<label for="roleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="roleName" name="RoleName" value="<%= role.RoleName %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Role</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/quizzes/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Quizzes</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Quizzes</h1>
<a href="/quizzes/create" class="btn btn-primary mb-3">Create Quiz</a>
<table class="table">
<thead>
<tr>
<th>QuizId</th>
<th>Title</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% quizzes.forEach(quiz => { %>
<tr>
<td><%= quiz.QuizId %></td>
<td><%= quiz.Title %></td>
<td><%= quiz.Description %></td>
<td>
<a href="/quizzes/<%= quiz.QuizId %>" class="btn btn-warning">Edit</a>
<form action="/quizzes/<%= quiz.QuizId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/quizzes/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Quiz</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Quiz</h1>
<form action="/quizzes" method="POST">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="Title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description"></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Quiz</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/quizzes/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Quiz</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Quiz</h1>
<form action="/quizzes/<%= quiz.QuizId %>" method="POST">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="Title" value="<%= quiz.Title %>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description"><%= quiz.Description %></textarea>
</div>
<button type="submit" class="btn btn-primary">Update Quiz</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/questions/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https:// cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Questions</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Questions</h1>
<a href="/questions/create" class="btn btn-primary mb-3">Create Question</a>
<table class="table">
<thead>
<tr>
<th>QuestionId</th>
<th>QuizId</th>
<th>QuestionText</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% questions.forEach(question => { %>
<tr>
<td><%= question.QuestionId %></td>
<td><%= question.QuizId %></td>
<td><%= question.QuestionText %></td>
<td>
<a href="/questions/<%= question.QuestionId %>" class="btn btn-warning">Edit</a>
<form action="/questions/<%= question.QuestionId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/questions/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Question</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Question</h1>
<form action="/questions" method="POST">
<div class="mb-3">
<label for="quizId" class="form-label">Quiz ID</label>
<input type="number" class="form-control" id="quizId" name="QuizId" required>
</div>
<div class="mb-3">
<label for="questionText" class="form-label">Question Text</label>
<textarea class="form-control" id="questionText" name="QuestionText" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Question</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/questions/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Question</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Question</h1>
<form action="/questions/<%= question.QuestionId %>" method="POST">
<div class="mb-3">
<label for="quizId" class="form-label">Quiz ID</label>
<input type="number" class="form-control" id="quizId" name="QuizId" value="<%= question.QuizId %>" required>
</div>
<div class="mb-3">
<label for="questionText" class="form-label">Question Text</label>
<textarea class="form-control" id="questionText" name="QuestionText" required><%= question.QuestionText %></textarea>
</div>
<button type="submit" class="btn btn-primary">Update Question</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/answers/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Answers</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Answers</h1>
<a href="/answers/create" class="btn btn-primary mb-3">Create Answer</a>
<table class="table">
<thead>
<tr>
<th>AnswerId</th>
<th>QuestionId</th>
<th>AnswerText</th>
<th>IsCorrect</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% answers.forEach(answer => { %>
<tr>
<td><%= answer.AnswerId %></td>
<td><%= answer.QuestionId %></td>
<td><%= answer.AnswerText %></td>
<td><%= answer.IsCorrect ? 'Yes' : 'No' %></td>
<td>
<a href="/answers/<%= answer.AnswerId %>" class="btn btn-warning">Edit</a>
<form action="/answers/<%= answer.AnswerId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/answers/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Answer</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Answer</h1>
<form action="/answers" method="POST">
<div class="mb-3">
<label for="questionId" class="form-label">Question ID</label>
<input type="number" class="form-control" id="questionId" name="QuestionId" required>
</div>
<div class="mb-3">
<label for="answerText" class="form-label">Answer Text</label>
<textarea class="form-control" id="answerText" name="AnswerText" required></textarea>
</div>
<div class="mb-3">
<label for="isCorrect" class="form-label">Is Correct</label>
<select class="form-select" id="isCorrect" name="IsCorrect" required>
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Create Answer</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/answers/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Answer</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Answer</h1>
<form action="/answers/<%= answer.AnswerId %>" method="POST">
<div class="mb-3">
<label for="questionId" class="form-label">Question ID</label>
<input type="number" class="form-control" id="questionId" name="QuestionId" value="<%= answer.QuestionId %>" required>
</div>
<div class="mb-3">
<label for="answerText" class="form-label">Answer Text</label>
<textarea class="form-control" id="answerText" name="AnswerText" required><%= answer.AnswerText %></textarea>
</div>
<div class="mb-3">
<label for="isCorrect" class="form-label">Is Correct</label>
<select class="form-select" id="isCorrect" name="IsCorrect" required>
<option value="true" <%= answer.IsCorrect ? 'selected' : '' %>>Yes</option>
<option value="false" <%= !answer.IsCorrect ? 'selected' : '' %>>No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Update Answer</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/scores/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Scores</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Scores</h1>
<a href="/scores/create" class="btn btn-primary mb-3">Create Score</a>
<table class="table">
<thead>
<tr>
<th>ScoreId</th>
<th>UserId</th>
<th>QuizId</th>
<th>Score</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% scores.forEach(score => { %>
<tr>
<td><%= score.ScoreId %></td>
<td><%= score.UserId %></td>
<td><%= score.QuizId %></td>
<td><%= score.Score %></td>
<td>
<a href="/scores/<%= score.ScoreId %>" class="btn btn-warning">Edit</a>
<form action="/scores/<%= score.ScoreId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/scores/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Score</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Score</h1>
<form action="/scores" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="quizId" class="form-label">Quiz ID</label>
<input type="number" class="form-control" id="quizId" name="QuizId" required>
</div>
<div class="mb-3">
<label for="score" class="form-label">Score</label>
<input type="number" class="form-control" id="score" name="Score" required>
</div>
<button type="submit" class="btn btn-primary">Create Score</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/scores/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Score</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Score</h1>
<form action="/scores/<%= score.ScoreId %>" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" value="< %= score.UserId %>" required>
</div>
<div class="mb-3">
<label for="quizId" class="form-label">Quiz ID</label>
<input type="number" class="form-control" id="quizId" name="QuizId" value="<%= score.QuizId %>" required>
</div>
<div class="mb-3">
<label for="score" class="form-label">Score</label>
<input type="number" class="form-control" id="score" name="Score" value="<%= score.Score %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Score</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/performances/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Performances</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Performances</h1>
<a href="/performances/create" class="btn btn-primary mb-3">Create Performance</a>
<table class="table">
<thead>
<tr>
<th>PerformanceId</th>
<th>UserId</th>
<th>TotalQuizzes</th>
<th>TotalScore</th>
<th>AverageScore</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% performances.forEach(performance => { %>
<tr>
<td><%= performance.PerformanceId %></td>
<td><%= performance.UserId %></td>
<td><%= performance.TotalQuizzes %></td>
<td><%= performance.TotalScore %></td>
<td><%= performance.AverageScore %></td>
<td>
<a href="/performances/<%= performance.PerformanceId %>" class="btn btn-warning">Edit</a>
<form action="/performances/<%= performance.PerformanceId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/performances/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Performance</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Performance</h1>
<form action="/performances" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="totalQuizzes" class="form-label">Total Quizzes</label>
<input type="number" class="form-control" id="totalQuizzes" name="TotalQuizzes" required>
</div>
<div class="mb-3">
<label for="totalScore" class="form-label">Total Score</label>
<input type="number" class="form-control" id="totalScore" name="TotalScore" required>
</div>
<div class="mb-3">
<label for="averageScore" class="form-label">Average Score</label>
<input type="number" step="0.01" class="form-control" id="averageScore" name="AverageScore" required>
</div>
<button type="submit" class="btn btn-primary">Create Performance</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@ 5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/performances/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Performance</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Performance</h1>
<form action="/performances/<%= performance.PerformanceId %>" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" value="<%= performance.UserId %>" required>
</div>
<div class="mb-3">
<label for="totalQuizzes" class="form-label">Total Quizzes</label>
<input type="number" class="form-control" id="totalQuizzes" name="TotalQuizzes" value="<%= performance.TotalQuizzes %>" required>
</div>
<div class="mb-3">
<label for="totalScore" class="form-label">Total Score</label>
<input type="number" class="form-control" id="totalScore" name="TotalScore" value="<%= performance.TotalScore %>" required>
</div>
<div class="mb-3">
<label for="averageScore" class="form-label">Average Score</label>
<input type="number" step="0.01" class="form-control" id="averageScore" name="AverageScore" value="<%= performance.AverageScore %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Performance</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/notifications/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Notifications</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Notifications</h1>
<a href="/notifications/create" class="btn btn-primary mb-3">Create Notification</a>
<table class="table">
<thead>
<tr>
<th>NotificationId</th>
<th>UserId</th>
<th>Message</th>
<th>IsRead</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% notifications.forEach(notification => { %>
<tr>
<td><%= notification.NotificationId %></td>
<td><%= notification.UserId %></td>
<td><%= notification.Message %></td>
<td><%= notification.IsRead ? 'Yes' : 'No' %></td>
<td>
<a href="/notifications/<%= notification.NotificationId %>" class="btn btn-warning">Edit</a>
<form action="/notifications/<%= notification.NotificationId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/notifications/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Notification</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Notification</h1>
<form action="/notifications" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" name="Message" required></textarea>
</div>
<div class="mb-3">
<label for="isRead" class="form-label">Is Read</label>
<select class="form-select" id="isRead" name="IsRead" required>
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Create Notification</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/notifications/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Notification</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Notification</h1>
<form action="/notifications/<%= notification.NotificationId %>" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" value="<%= notification.UserId %>" required>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" name="Message" required><%= notification.Message %></textarea>
</div>
<div class="mb-3">
<label for="isRead" class="form-label">Is Read</label>
<select class="form-select" id="isRead" name="IsRead" required>
<option value="true" <%= notification.IsRead ? 'selected' : '' %>>Yes</option>
<option value="false" <%= !notification.IsRead ? 'selected' : '' %>>No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Update Notification</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/achievements/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Achievements</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Achievements</h1>
<a href="/achievements/create" class="btn btn-primary mb-3">Create Achievement</a>
<table class="table">
<thead>
<tr>
<th>AchievementId</th>
<th>UserId</th>
<th>Title</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% achievements.forEach(achievement => { %>
<tr>
<td><%= achievement.AchievementId %></td>
<td><%= achievement.UserId %></td>
<td><%= achievement.Title %></td>
<td><%= achievement.Description %></td>
<td>
<a href="/achievements/<%= achievement.AchievementId %>" class="btn btn-warning">Edit</a>
<form action="/achievements/<%= achievement.AchievementId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/achievements/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Achievement</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Achievement</h1>
<form action="/achievements" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="Title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Achievement</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/achievements/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Achievement</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Achievement</h1>
<form action="/achievements/<%= achievement.AchievementId %>" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User ID</label>
<input type="number" class="form-control" id="userId" name="User Id" value="<%= achievement.UserId %>" required>
</div>
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="Title" value="<%= achievement.Title %>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description" required><%= achievement.Description %></textarea>
</div>
<button type="submit" class="btn btn-primary">Update Achievement</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Integrate Routes

In your main application file (e.g., index.js), integrate all the routes created for each model.


const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const sequelize = require('./config');
// Import routes
const userRoutes = require('./routes/userRoutes');
const roleRoutes = require('./routes/roleRoutes');
const quizRoutes = require('./routes/quizRoutes');
const questionRoutes = require('./routes/questionRoutes');
const answerRoutes = require('./routes/answerRoutes');
const scoreRoutes = require('./routes/scoreRoutes');
const performanceRoutes = require('./routes/performanceRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const achievementRoutes = require('./routes/achievementRoutes');
// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Use routes
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
app.use('/quizzes', quizRoutes);
app.use('/questions', questionRoutes);
app.use('/answers', answerRoutes);
app.use('/scores', scoreRoutes);
app.use('/performances', performanceRoutes);
app.use('/notifications', notificationRoutes);
app.use('/achievements', achievementRoutes);
// Sync database and start server
sequelize.sync().then (() => {
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
})();

Run the Application

Start your application by running node index.js in your terminal.

Access the Application: Open your browser and navigate to the respective routes (e.g., http://localhost:3000/users, http://localhost:3000/roles, etc.) to manage users, roles, quizzes, questions, answers, scores, performances, notifications, and achievements.

Creating a Dashboard Page

To create a dashboard page that consolidates data related to the quiz management system, we will follow these steps:

Step 1: Create a Dashboard Route

Create a new file named dashboardRoutes.js in the routes directory.

routes/dashboardRoutes.js


const express = require('express');
const router = express.Router();
const dashboardController = require('../controllers/dashboardController');
router.get('/', dashboardController.getDashboard);
module.exports = router;

Step 2: Create a Dashboard Controller

Create a new file named dashboardController.js in the controllers directory.

controllers/dashboardController.js


const User = require('../models/User');
const Role = require('../models/Role');
const Quiz = require('../models/Quiz');
const Question = require('../models/Question');
const Answer = require('../models/Answer');
const Score = require('../models/Score');
const Performance = require('../models/Performance');
const Notification = require('../models/Notification');
const Achievement = require('../models/Achievement');
class DashboardController {
async getDashboard(req, res) {
try {
const userCount = await User.count();
const roleCount = await Role.count();
const quizCount = await Quiz.count();
const questionCount = await Question.count();
const answerCount = await Answer.count();
const scoreCount = await Score.count();
const performanceCount = await Performance.count();
const notificationCount = await Notification.count();
const achievementCount = await Achievement.count();
res.render('dashboard', {
userCount,
roleCount,
quizCount,
questionCount,
answerCount,
scoreCount,
performanceCount,
notificationCount,
achievementCount,
});
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new DashboardController();

Step 3: Create a Dashboard View

Create a new file named dashboard.ejs in the views directory.

views/dashboard.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Dashboard</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Dashboard</h1>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
<div class="card-header">Total Users</div>
<div class="card-body">
<h5 class="card-title"><%= userCount %></h5>
<p class="card-text">Total number of registered users.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Roles</div>
<div class="card-body">
<h5 class="card-title"><%= roleCount %></h5>
<p class="card-text">Total roles defined in the system.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-header">Total Quizzes</div>
<div class="card-body">
<h5 class="card-title"><%= quizCount %></h5>
<p class="card-text">Total quizzes created.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Total Questions</div>
<div class="card-body">
<h5 class="card-title"><%= questionCount %></h5>
<p class="card-text">Total questions available.</p>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-danger mb-3">
<div class="card-header">Total Answers</div>
<div class="card-body">
<h5 class="card-title"><%= answerCount %></h5>
<p class="card-text">Total answers provided.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-secondary mb-3">
<div class="card-header">Total Scores</div>
<div class="card-body">
<h5 class="card-title"><%= scoreCount %></h5>
<p class="card-text">Total scores recorded.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-light mb-3">
<div class="card-header">Total Performances</div>
<div class="card-body">
<h5 class="card-title"><%= performanceCount %></h5>
<p class="card -text">Total performance records.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-dark mb-3">
<div class="card-header">Total Notifications</div>
<div class="card-body">
<h5 class="card-title"><%= notificationCount %></h5>
<p class="card-text">Total notifications sent.</p>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Achievements</div>
<div class="card-body">
<h5 class="card-title"><%= achievementCount %></h5>
<p class="card-text">Total achievements earned.</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Step 4: Update the Main Application

Integrate the dashboard route into your main application file (e.g., index.js).


const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const sequelize = require('./config');
// Import routes
const userRoutes = require('./routes/userRoutes');
const roleRoutes = require('./routes/roleRoutes');
const quizRoutes = require('./routes/quizRoutes');
const questionRoutes = require('./routes/questionRoutes');
const answerRoutes = require('./routes/answerRoutes');
const scoreRoutes = require('./routes/scoreRoutes');
const performanceRoutes = require('./routes/performanceRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const achievementRoutes = require('./routes/achievementRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes'); // Import dashboard routes
// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Use routes
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
app.use('/quizzes', quizRoutes);
app.use('/questions', questionRoutes);
app.use('/answers', answerRoutes);
app.use('/scores', scoreRoutes);
app.use('/performances', performanceRoutes);
app.use('/notifications', notificationRoutes);
app.use('/achievements', achievementRoutes);
app.use('/dashboard', dashboardRoutes); // Use dashboard routes
// Sync database and start server
sequelize.sync().then(() => {
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
});

Final Steps

Run the Application: Start your application by running node index.js in your terminal.

Access the Dashboard: Open your browser and navigate to http://localhost:3000/dashboard to view the consolidated data related to the project.

This completes the implementation of a dashboard page that aggregates and displays key metrics from the quiz management system. You can further enhance the dashboard by adding charts, graphs, or additional statistics as needed.