Project Introduction
The Virtual Classroom System is a web application designed to facilitate online learning and teaching. Built using Node.js, this platform allows teachers to create and manage courses, while students can access course materials, attend live sessions, and submit assessments. The system supports multiple user roles, including admin, teacher, and student, ensuring a tailored experience for each user type. The underlying MySQL database schema is structured to manage users, courses, course materials, classrooms, attendance, assessments, assessment submissions, feedback, notifications, and payments, providing a robust foundation for effective online education.
Project Objectives
- To develop a user-friendly interface for teachers to create and manage courses and materials.
- To allow students to enroll in courses, access materials, and participate in live sessions.
- To implement a secure user authentication system for managing user roles and permissions.
- To facilitate the creation and management of assessments for each course.
- To track attendance for live sessions and manage student participation.
- To collect feedback from students regarding courses and teaching effectiveness.
- To send notifications to users regarding important updates, such as new materials or upcoming assessments.
- To manage payments for courses, if applicable, including tracking payment statuses.
- To ensure the application is scalable and maintainable for future enhancements.
Project Modules
- User Management Module:
This module handles user registration, authentication, and role management, allowing users to manage their accounts securely.
- Course Management Module:
This module allows teachers to create, update, and manage courses, including details such as title, description, and objectives.
- Course Materials Management Module:
This module facilitates the upload and management of course materials, including videos, documents, and quizzes.
- Classroom Management Module:
This module schedules and manages live classroom sessions, including session dates, durations, and links.
- Attendance Management Module:
This module tracks student attendance for live sessions, recording their participation status.
- Assessment Management Module:
This module allows teachers to create and manage assessments, including due dates and descriptions.
- Assessment Submission Module:
This module manages student submissions for assessments, including tracking grades and feedback.
- Feedback Management Module:
This module collects feedback from students regarding courses, including ratings and comments.
- Notification Module:
This module sends notifications to users regarding important updates, such as new materials or assessment deadlines.
- Payment Management Module:
This module manages payments for courses, tracking payment methods and statuses if applicable.
Steps Overview
Set Up the Project: Initialize a new Node.js project and install the necessary packages.
Define Sequelize Models: Create Sequelize models for each table.
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 EJS Views: Design EJS views using Bootstrap 5 for the frontend.
Implement CRUD Operations: Wire everything together to perform CRUD operations.
Step 1: Set Up the Project
Initialize the Project:
mkdir virtual-class-app
cd virtual-class-app
npm init -y
npm install express sequelize mysql2 ejs body-parser
Step 2: Define Sequelize Models
Create a folder named models and create the following files for each table.
models/User.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class User extends Model {}
User .init({
UserId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
Username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
PasswordHash: {
type: DataTypes.STRING,
allowNull: false
},
Email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
FirstName: {
type: DataTypes.STRING,
allowNull: false
},
LastName: {
type: DataTypes.STRING,
allowNull: false
},
RoleId: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'User ',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = User;
models/Role.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Role extends Model {}
Role.init({
RoleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
RoleName: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
}, {
sequelize,
modelName: 'Role',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Role;
Repeat the above for Courses, Syllabus, LiveClasses, Resources, Quizzes, Grades, Notifications, Payments, and Feedback.
Step 3: Create Repositories
Create a folder named repositories and create a file for each model.
repositories/userRepository.js
const User = require('../models/User');
class UserRepository {
async createUser (data) {
return await User.create(data);
}
async getAllUsers() {
return await User.findAll();
}
async getUser ById(id) {
return await User.findByPk(id);
}
async updateUser (id, data) {
return await User.update(data, { where: { UserId: id } });
}
async deleteUser (id) {
return await User.destroy({ where: { UserId: id } });
}
}
module.exports = new UserRepository();
Repeat the above for Role, Course, Syllabus, LiveClasses, Resources, Quizzes, Grades, Notifications, Payments, and Feedback.
Step 4: Set Up Controllers
Create a folder named controllers and create a file for each model.
controllers/userController.js
const userRepository = require('../repositories/userRepository');
class UserController {
async createUser (req, res) {
const user = await userRepository.createUser (req.body);
res.redirect('/users');
}
async getAllUsers(req, res) {
const users = await userRepository.getAllUsers();
res.render('users/index', { users });
}
async getUser (req, res) {
const user = await userRepository.getUser ById(req.params.id);
res.render('users/edit', { user });
}
async updateUser (req, res) {
await userRepository.updateUser (req.params.id, req.body);
res.redirect('/users');
}
async deleteUser (req, res) {
await userRepository.deleteUser (req.params.id);
res.redirect('/users');
}
}
module.exports = new UserController();
Repeat the above for Role, Course, Syllabus, LiveClasses, Resources, Quizzes, Grades, Notifications, Payments, and Feedback.
Step 5: Define Routes
Create a folder named routes and create a file 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/edit', userController.getUser );
router.post('/:id', userController.updateUser );
router.post('/:id/delete', userController.deleteUser );
module.exports = router;
Repeat the above for Role, Course, Syllabus, LiveClasses, Resources, Quizzes, Grades, Notifications, Payments, and Feedback.
Step 6: Create EJS Views
Create a folder named views and create subfolders for each model.
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>Users</h1>
<a href="/users/create" class="btn btn-primary">Create User</a>
<table class=" table table-striped">
<thead>
<tr>
<th>UserId</th>
<th>Username</th>
<th>Email</th>
<th>First Name</th>
<th>Last Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.UserId %></td>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td><%= user.FirstName %></td>
<td><%= user.LastName %></td>
<td>
<a href="/users/<%= user.UserId %>/edit" 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>
</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>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="PasswordHash" class="form-label">Password</label>
<input type="password" class="form-control" id="PasswordHash" name="PasswordHash" required>
</div>
<div class="mb-3">
<label for="FirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="FirstName" name="FirstName" required>
</div>
<div class="mb-3">
<label for="LastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="LastName" name="LastName" required>
</div>
<div class="mb-3">
<label for="RoleId" class="form-label">Role ID</label>
<input type="number" class="form-control" id="RoleId" name="RoleId" required>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
</div>
</body>
</html>
Repeat the above for other models like Role, Course, Syllabus, LiveClasses, Resources, Quizzes, Grades, Notifications, Payments, and Feedback.
Step 7: Implement CRUD Operations
In your main application file (e.g., app.js), set up the Express server, middleware, and routes:
const express = require('express');
const bodyParser = require('body-parser');
const userRoutes = require('./routes/userRoutes');
// Import other routes
const app = express();
const PORT = process.env.PORT || 3000;
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/users', userRoutes);
// Use other routes
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
This setup provides a complete CRUD application structure using Node.js, Sequelize, and EJS with Bootstrap 5 templates, allowing for user management and other functionalities as defined in the SQL schema.
Complete Implementation for Remaining Models
Following are the complete implementation for the remaining models, repositories, controllers, routes, and views based on the SQL schema you provided.
Step 2: Define Sequelize Models
models/Role.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Course extends Model {}
Course.init({
CourseId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseName: {
type: DataTypes.STRING,
allowNull: false
},
Description: {
type: DataTypes.TEXT
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Course',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Course;
models/Course.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Syllabus extends Model {}
Syllabus.init({
SyllabusId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
Topic: {
type: DataTypes.STRING,
allowNull: false
},
Description: {
type: DataTypes.TEXT
}
}, {
sequelize,
modelName: 'Syllabus',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Syllabus;
models/Syllabus.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class LiveClass extends Model {}
LiveClass.init({
LiveClassId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
ClassDate: {
type: DataTypes.DATE,
allowNull: false
},
Duration: {
type: DataTypes.INTEGER,
allowNull: false
},
Link: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'LiveClass',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = LiveClass;
models/LiveClass.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Resource extends Model {}
Resource.init({
ResourceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
ResourceName: {
type: DataTypes.STRING,
allowNull: false
},
ResourceType: {
type: DataTypes.STRING,
allowNull: false
},
ResourceLink: {
type: DataTypes.STRING
}
}, {
sequelize,
modelName: 'Resource',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Resource;
models/Resource.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Quiz extends Model {}
Quiz.init({
QuizId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
QuizName: {
type: DataTypes.STRING,
allowNull: false
},
TotalMarks: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Quiz',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Quiz;
models/Quiz.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Grade extends Model {}
Grade.init({
GradeId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false
},
MarksObtained: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Grade',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Grade;
models/Grade.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Notification extends Model {}
Notification.init({
NotificationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
Message: {
type: DataTypes.STRING,
allowNull: false
},
IsRead: {
type: DataTypes.BOOLEAN,
defaultValue: false
}
}, {
sequelize,
modelName: 'Notification',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Notification;
models/Notification.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Payment extends Model {}
Payment.init({
PaymentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
Amount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
PaymentStatus: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'Payment',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Payment;
models/Payment.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Feedback extends Model {}
Feedback.init({
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
FeedbackContent: {
type: DataTypes.TEXT,
allowNull: false
}
}, {
sequelize,
modelName: 'Feedback',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Feedback;
models/Feedback.js
const Role = require('../models/Role');
class RoleRepository {
async createRole(data) {
return await Role.create(data);
}
async getAllRoles() {
return await Role.findAll();
}
async getRoleById(id) {
return await Role.findByPk(id);
}
async updateRole(id, data) {
return await Role.update(data, { where: { RoleId: id } });
}
async deleteRole(id) {
return await Role.destroy({ where: { RoleId: id } });
}
}
module.exports = new RoleRepository();
Step 3: Create Repositories
repositories/roleRepository.js
const roleRepository = require('../repositories/roleRepository');
class RoleController {
async createRole(req, res) {
await roleRepository.createRole(req.body);
res.redirect('/roles');
}
async getAllRoles(req, res) {
const roles = await roleRepository.getAllRoles();
res.render('roles/index', { roles });
}
async getRole(req, res) {
const role = await roleRepository.getRoleById(req.params.id);
res.render('roles/edit', { role });
}
async updateRole(req, res) {
await roleRepository.updateRole(req.params.id, req.body);
res.redirect('/roles');
}
async deleteRole(req, res) {
await roleRepository.deleteRole(req.params.id);
res.redirect('/roles');
}
}
module.exports = new RoleController();
Repeat the above for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 4: Set Up Controllers
controllers/roleController.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/edit', roleController.getRole);
router.post('/:id', roleController.updateRole);
router.post('/:id/delete', roleController.deleteRole);
module.exports = router;
Repeat the above for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 5: Define Routes
routes/roleRoutes.js
<!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>Roles </h1>
<a href="/roles/create" class="btn btn-primary">Create Role</a>
<table class="table table-striped">
<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 %>/edit" 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>
</body>
</html>
Repeat the above for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 6: Create EJS Views
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>Create Role</title>
</head>
<body>
<div class="container">
<h1>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>
</body>
</html>
views/roles/create.ejs
const express = require('express');const bodyParser = require('body-parser');const userRoutes = require('./routes/userRoutes');const roleRoutes = require('./routes/roleRoutes');// Import other routesconst app = express();const PORT = process.env.PORT || 3000;app.set('view engine', 'ejs');app.use(bodyParser.urlencoded({ extended: true }));app.use(express.static('public'));app.use('/users', userRoutes);app.use('/roles', roleRoutes);// Use other routesapp.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`);});
This completes the implementation for all remaining models, repositories, controllers, routes, and views based on the SQL schema you provided. You can now manage users, roles, courses, and other entities through the CRUD application.Sure! Below is the complete implementation for the remaining models, repositories, controllers, routes, and views for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 2: Define Sequelize Modelsmodels/Course.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Course extends Model {}
Course.init({
CourseId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseName: {
type: DataTypes.STRING,
allowNull: false
},
Description: {
type: DataTypes.TEXT
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Course',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Course;
Repeat the above for other models like Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 7: Implement CRUD Operations
In your main application file (e.g., app.js), set up the Express server, middleware, and routes:
const express = require('express');
const bodyParser = require('body-parser');
const userRoutes = require('./routes/userRoutes');
const roleRoutes = require('./routes/roleRoutes');
// Import other routes
const app = express();
const PORT = process.env.PORT || 3000;
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
// Use other routes
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
This completes the implementation for all remaining models, repositories, controllers, routes, and views based on the SQL schema you provided. You can now manage users, roles, courses, and other entities through the CRUD application.
Complete Implementation for Remaining Models
Following are the complete implementation for the remaining models, repositories, controllers, routes, and views for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 2: Define Sequelize Models
models/Course.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Course extends Model {}
Course.init({
CourseId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseName: {
type: DataTypes.STRING,
allowNull: false
},
Description: {
type: DataTypes.TEXT
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Course',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Course;
models/Syllabus.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Syllabus extends Model {}
Syllabus.init({
SyllabusId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
Topic: {
type: DataTypes.STRING,
allowNull: false
},
Description: {
type: DataTypes.TEXT
}
}, {
sequelize,
modelName: 'Syllabus',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Syllabus;
models/LiveClass.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class LiveClass extends Model {}
LiveClass.init({
LiveClassId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
ClassDate: {
type: DataTypes.DATE,
allowNull: false
},
Duration: {
type: DataTypes.INTEGER,
allowNull: false
},
Link: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'LiveClass',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = LiveClass;
models/Resource.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Resource extends Model {}
Resource.init({
ResourceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
ResourceName: {
type: DataTypes.STRING,
allowNull: false
},
ResourceType: {
type: DataTypes.STRING,
allowNull: false
},
ResourceLink: {
type: DataTypes.STRING
}
}, {
sequelize,
modelName: 'Resource',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Resource;
models/Quiz.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Quiz extends Model {}
Quiz.init({
QuizId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
QuizName: {
type: DataTypes.STRING,
allowNull: false
},
TotalMarks: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Quiz',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Quiz;
models/Grade.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Grade extends Model {}
Grade.init({
GradeId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
QuizId: {
type: DataTypes.INTEGER,
allowNull: false
},
MarksObtained: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {
sequelize,
modelName: 'Grade',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Grade;
models/Notification.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Notification extends Model {}
Notification.init({
NotificationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
Message: {
type: DataTypes.STRING,
allowNull: false
},
IsRead: {
type: DataTypes.BOOLEAN,
defaultValue: false
}
}, {
sequelize,
modelName: 'Notification',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Notification;
models/Payment.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Payment extends Model {}
Payment.init({
PaymentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
Amount: {
type: DataTypes.DECIMAL( 18, 2),
allowNull: false
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
PaymentStatus: {
type: DataTypes.STRING,
allowNull: false
}
}, {
sequelize,
modelName: 'Payment',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Payment;
models/Feedback.js
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Feedback extends Model {}
Feedback.init({
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
CourseId: {
type: DataTypes.INTEGER,
allowNull: false
},
FeedbackContent: {
type: DataTypes.TEXT,
allowNull: false
}
}, {
sequelize,
modelName: 'Feedback',
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt'
});
module.exports = Feedback;
Step 3: Create Repositories
repositories/courseRepository.js
const Course = require('../models/Course');
class CourseRepository {
async createCourse(data) {
return await Course.create(data);
}
async getAllCourses() {
return await Course.findAll();
}
async getCourseById(id) {
return await Course.findByPk(id);
}
async updateCourse(id, data) {
return await Course.update(data, { where: { CourseId: id } });
}
async deleteCourse(id) {
return await Course.destroy({ where: { CourseId: id } });
}
}
module.exports = new CourseRepository();
Repeat the above for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 4: Set Up Controllers
controllers/courseController.js
const courseRepository = require('../repositories/courseRepository');
class CourseController {
async createCourse(req, res) {
await courseRepository.createCourse(req.body);
res.redirect('/courses');
}
async getAllCourses(req, res) {
const courses = await courseRepository.getAllCourses();
res.render('courses/index', { courses });
}
async getCourse(req, res) {
const course = await courseRepository.getCourseById(req.params.id);
res.render('courses/edit', { course });
}
async updateCourse(req, res) {
await courseRepository.updateCourse(req.params.id, req.body);
res.redirect('/courses');
}
async deleteCourse(req, res) {
await courseRepository.deleteCourse(req.params.id);
res.redirect('/courses');
}
}
module.exports = new CourseController();
Repeat the above for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 5: Define Routes
routes/courseRoutes.js
const express = require('express');
const router = express.Router();
const courseController = require('../controllers/courseController');
router.get('/', courseController.getAllCourses);
router.get('/create', (req, res) => res.render('courses/create'));
router.post('/', courseController.createCourse);
router.get('/:id/edit', courseController.getCourse);
router.post('/:id', courseController.updateCourse);
router.post('/:id/delete', courseController.deleteCourse);
module.exports = router;
Repeat the above for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 6: Create EJS Views
views/courses/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>Courses</title>
</head>
<body>
<div class="container">
<h1>Courses</h1>
<a href="/courses/create" class="btn btn-primary">Create Course</a>
<table class="table table-striped">
<thead>
<tr>
<th>CourseId</th>
<th>CourseName</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% courses.forEach(course => { %>
<tr>
<td><%= course.CourseId %></td>
<td><%= course.CourseName %></td>
<td>
<a href="/courses/<%= course.CourseId %>/edit" class="btn btn-warning">Edit</a>
<form action="/courses/<%= course.CourseId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/courses/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 Course</title>
</head>
<body>
<div class="container">
<h1>Create Course</h1>
<form action="/courses" method="POST">
<div class="mb-3">
<label for="CourseName" class="form-label">Course Name</label>
<input type="text" class="form-control" id="CourseName" name="CourseName" 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 Course</button>
</form>
</div>
</body>
</html>
Repeat the above for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 7: Implement CRUD Operations
In your main application file (e.g., app.js), set up the Express server, middleware, and routes:
const express = require('express');
const bodyParser = require('body-parser');
const courseRoutes = require('./routes/courseRoutes');
const syllabusRoutes = require('./routes/syllabusRoutes');
// Import other routes
const app = express();
const PORT = process.env.PORT || 3000;
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/courses', courseRoutes);
app.use('/syllabus', syllabusRoutes);
// Use other routes
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
This completes the implementation for all remaining models, repositories, controllers, routes, and views for Course, Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback. You can now manage these entities through the CRUD application.
Complete Implementation for Remaining Models
Certainly! Below is the complete implementation for the remaining models, repositories, controllers, routes, and views for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback.
Step 3: Create Repositories
repositories/syllabusRepository.js
const Syllabus = require('../models/Syllabus');
class SyllabusRepository {
async createSyllabus(data) {
return await Syllabus.create(data);
}
async getAllSyllabuses() {
return await Syllabus.findAll();
}
async getSyllabusById(id) {
return await Syllabus.findByPk(id);
}
async updateSyllabus(id, data) {
return await Syllabus.update(data, { where: { SyllabusId: id } });
}
async deleteSyllabus(id) {
return await Syllabus.destroy({ where: { SyllabusId: id } });
}
}
module.exports = new SyllabusRepository();
repositories/liveClassRepository.js
const LiveClass = require('../models/LiveClass');
class LiveClassRepository {
async createLiveClass(data) {
return await LiveClass.create(data);
}
async getAllLiveClasses() {
return await LiveClass.findAll();
}
async getLiveClassById(id) {
return await LiveClass.findByPk(id);
}
async updateLiveClass(id, data) {
return await LiveClass.update(data, { where: { LiveClassId: id } });
}
async deleteLiveClass(id) {
return await LiveClass.destroy({ where: { LiveClassId: id } });
}
}
module.exports = new LiveClassRepository();
repositories/resourceRepository.js
const Resource = require('../models/Resource');
class ResourceRepository {
async createResource(data) {
return await Resource.create(data);
}
async getAllResources() {
return await Resource.findAll();
}
async getResourceById(id) {
return await Resource.findByPk(id);
}
async updateResource(id, data) {
return await Resource.update(data, { where: { ResourceId: id } });
}
async deleteResource(id) {
return await Resource.destroy({ where: { ResourceId: id } });
}
}
module.exports = new ResourceRepository();
repositories/quizRepository.js
const Quiz = require('../models/Quiz');
class QuizRepository {
async createQuiz(data) {
return await Quiz.create(data);
}
async getAllQuizzes() {
return await Quiz.findAll();
}
async getQuizById(id) {
return await Quiz.findByPk(id);
}
async updateQuiz(id, data) {
return await Quiz.update(data, { where: { QuizId: id } });
}
async deleteQuiz(id) {
return await Quiz.destroy({ where: { QuizId: id } });
}
}
module.exports = new QuizRepository();
repositories/gradeRepository.js
const Grade = require('../models/Grade');
class GradeRepository {
async createGrade(data) {
return await Grade.create(data);
}
async getAllGrades() {
return await Grade.findAll();
}
async getGradeById(id) {
return await Grade.findByPk(id);
}
async updateGrade(id, data) {
return await Grade.update(data, { where: { GradeId: id } });
}
async deleteGrade(id) {
return await Grade.destroy({ where: { GradeId: id } });
}
}
module.exports = new GradeRepository();
repositories/notificationRepository.js
const Notification = require('../models/Notification');
class NotificationRepository {
async createNotification(data) {
return await Notification.create(data);
}
async getAllNotifications() {
return await Notification.findAll();
}
async getNotificationById(id) {
return await Notification.findByPk(id);
}
async updateNotification(id, data) {
return await Notification.update(data, { where: { NotificationId: id } });
}
async deleteNotification(id) {
return await Notification.destroy({ where: { NotificationId: id } });
}
}
module.exports = new NotificationRepository();
repositories/paymentRepository.js
const Payment = require('../models/Payment');
class PaymentRepository {
async createPayment(data) {
return await Payment.create(data);
}
async getAllPayments() {
return await Payment.findAll();
}
async getPaymentById(id) {
return await Payment.findByPk(id);
}
async updatePayment(id, data) {
return await Payment.update(data, { where: { PaymentId: id } });
}
async deletePayment(id) {
return await Payment.destroy({ where: { PaymentId: id } });
}
}
module.exports = new PaymentRepository();
repositories/feedbackRepository.js
const Feedback = require('../models/Feedback');
class FeedbackRepository {
async createFeedback(data) {
return await Feedback.create(data);
}
async getAllFeedbacks() {
return await Feedback.findAll();
}
async getFeedbackById(id) {
return await Feedback.findByPk(id);
}
async updateFeedback(id, data) {
return await Feedback.update(data, { where: { FeedbackId: id } });
}
async deleteFeedback(id) {
return await Feedback.destroy({ where: { FeedbackId: id } });
}
}
module.exports = new FeedbackRepository();
Step 4: Set Up Controllers
controllers/syllabusController.js
const syllabusRepository = require('../repositories/syllabusRepository');
class SyllabusController {
async createSyllabus(req, res) {
await syllabusRepository.createSyllabus(req.body);
res.redirect('/syllabus');
}
async getAllSyllabuses(req, res) {
const syllabuses = await syllabusRepository.getAllSyllabuses();
res.render('syllabus/index', { syllabuses });
}
async getSyllabus(req, res) {
const syllabus = await syllabusRepository.getSyllabusById(req.params.id);
res.render('syllabus/edit', { syllabus });
}
async updateSyllabus(req, res) {
await syllabusRepository.updateSyllabus(req.params.id, req.body);
res.redirect('/syllabus');
}
async deleteSyllabus(req, res) {
await syllabusRepository.deleteSyllabus(req.params.id);
res.redirect('/syllabus');
}
}
module.exports = new SyllabusController();
controllers/liveClassController.js
const liveClassRepository = require('../repositories/liveClassRepository');
class LiveClassController {
async createLiveClass(req, res) {
await liveClassRepository.createLiveClass(req.body);
res.redirect('/liveclass');
}
async getAllLiveClasses(req, res) {
const liveClasses = await liveClassRepository.getAllLiveClasses();
res.render('liveclass/index', { liveClasses });
}
async getLiveClass(req, res) {
const liveClass = await liveClassRepository.getLiveClassById(req.params.id);
res.render('liveclass/edit', { liveClass });
}
async updateLiveClass(req, res) {
await liveClassRepository.updateLiveClass(req.params.id, req.body);
res.redirect('/liveclass');
}
async deleteLiveClass(req, res) {
await liveClassRepository.deleteLiveClass(req.params.id);
res.redirect('/liveclass');
}
}
module.exports = new LiveClassController();
controllers/resourceController.js
const resourceRepository = require('../repositories/resourceRepository');
class ResourceController {
async createResource(req, res) {
await resourceRepository.createResource(req.body);
res.redirect('/resource');
}
async getAllResources(req, res) {
const resources = await resourceRepository.getAllResources();
res.render('resource/index', { resources });
}
async getResource(req, res) {
const resource = await resourceRepository.getResourceById(req.params.id);
res.render('resource/edit', { resource });
}
async updateResource(req, res) {
await resourceRepository.updateResource(req.params.id, req.body);
res.redirect('/resource');
}
async deleteResource(req, res) {
await resourceRepository.deleteResource(req.params.id);
res.redirect('/resource');
}
}
module.exports = new ResourceController();
controllers/quizController.js
const quizRepository = require('../repositories/quizRepository');
class QuizController {
async createQuiz(req, res) {
await quizRepository.createQuiz(req.body);
res.redirect('/quiz');
}
async getAllQuizzes(req, res) {
const quizzes = await quizRepository.getAllQuizzes();
res.render('quiz/index', { quizzes });
}
async getQuiz(req, res) {
const quiz = await quizRepository.getQuizById(req.params.id);
res.render('quiz/edit', { quiz });
}
async updateQuiz(req, res) {
await quizRepository.updateQuiz(req.params.id, req.body);
res.redirect('/quiz');
}
async deleteQuiz(req, res) {
await quizRepository.deleteQuiz(req.params.id);
res.redirect('/quiz');
}
}
module.exports = new QuizController();
controllers/gradeController.js
const gradeRepository = require('../repositories/gradeRepository');
class GradeController {
async createGrade(req, res) {
await gradeRepository.createGrade(req.body);
res.redirect('/grade');
}
async getAllGrades(req, res) {
const grades = await gradeRepository.getAllGrades();
res.render('grade/index', { grades });
}
async getGrade(req, res) {
const grade = await gradeRepository.getGradeById(req.params.id);
res.render('grade/edit', { grade });
}
async updateGrade(req, res) {
await gradeRepository.updateGrade(req.params.id, req.body);
res.redirect('/grade');
}
async deleteGrade(req, res) {
await gradeRepository.deleteGrade(req.params.id);
res.redirect('/grade');
}
}
module.exports = new GradeController();
controllers/notificationController.js
const notificationRepository = require('../repositories/notificationRepository');
class NotificationController {
async createNotification(req, res) {
await notificationRepository.createNotification(req.body);
res.redirect('/notification');
}
async getAllNotifications(req, res) {
const notifications = await notificationRepository.getAllNotifications();
res.render('notification/index', { notifications });
}
async getNotification(req, res) {
const notification = await notificationRepository.getNotificationById(req.params.id);
res.render('notification/edit', { notification });
}
async updateNotification(req, res) {
await notificationRepository.updateNotification(req.params.id, req.body);
res.redirect('/notification');
}
async deleteNotification(req, res) {
await notificationRepository.deleteNotification(req.params.id);
res.redirect('/notification');
}
}
module.exports = new NotificationController();
controllers/paymentController.js
const paymentRepository = require('../repositories/paymentRepository');
class PaymentController {
async createPayment(req, res) {
await paymentRepository.createPayment(req.body);
res.redirect('/payment');
}
async getAllPayments(req, res) {
const payments = await paymentRepository.getAllPayments();
res.render('payment/index', { payments });
}
async getPayment(req, res) {
const payment = await paymentRepository.getPaymentById(req.params.id);
res.render('payment/edit', { payment });
}
async updatePayment(req, res) {
await paymentRepository.updatePayment(req.params.id, req.body);
res.redirect('/payment');
}
async deletePayment(req, res) {
await paymentRepository.deletePayment(req.params.id);
res.redirect('/payment');
}
}
module.exports = new PaymentController();
controllers/feedbackController.js
const feedbackRepository = require('../repositories/feedbackRepository');
class FeedbackController {
async createFeedback(req, res) {
await feedbackRepository.createFeedback(req.body);
res.redirect('/feedback');
}
async getAllFeedbacks(req, res) {
const feedbacks = await feedbackRepository.getAllFeedbacks();
res.render('feedback/index', { feedbacks });
}
async getFeedback(req, res) {
const feedback = await feedbackRepository.getFeedbackById(req.params.id);
res.render('feedback/edit', { feedback });
}
async updateFeedback(req, res) {
await feedbackRepository.updateFeedback(req.params.id, req.body);
res.redirect('/feedback');
}
async deleteFeedback(req, res) {
await feedbackRepository.deleteFeedback(req.params.id);
res.redirect('/feedback');
}
}
module.exports = new FeedbackController();
Step 5: Define Routes
routes/syllabusRoutes.js
const express = require('express');
const router = express.Router();
const syllabusController = require('../controllers/syllabusController');
router.get('/', syllabusController.getAllSyllabuses);
router.get('/create', (req, res) => res.render('syllabus/create'));
router.post('/', syllabusController.createSyllabus);
router.get('/:id/edit', syllabusController.getSyllabus);
router.post('/:id', syllabusController.updateSyllabus);
router.post('/:id/delete', syllabusController.deleteSyllabus);
module.exports = router;
routes/liveClassRoutes.js
const express = require('express');
const router = express.Router();
const liveClassController = require('../controllers/liveClassController');
router.get('/', liveClassController.getAllLiveClasses);
router.get('/create', (req, res) => res.render('liveclass/create'));
router.post('/', liveClassController.createLiveClass);
router.get('/:id/edit', liveClassController.getLiveClass);
router.post('/:id', liveClassController.updateLiveClass);
router.post('/:id/delete', liveClassController.deleteLiveClass);
module.exports = router;
routes/resourceRoutes.js
const express = require('express');
const router = express.Router();
const resourceController = require('../controllers/resourceController');
router.get('/', resourceController.getAllResources);
router.get('/create', (req, res) => res.render('resource/create'));
router.post('/', resourceController.createResource);
router.get('/:id/edit', resourceController.getResource);
router.post('/:id', resourceController.updateResource);
router.post('/:id/delete', resourceController.deleteResource);
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('quiz/create'));
router.post('/', quizController.createQuiz);
router.get('/:id/edit', quizController.getQuiz);
router.post('/:id', quizController.updateQuiz);
router.post('/:id/delete', quizController.deleteQuiz);
module.exports = router;
routes/gradeRoutes.js
const express = require('express');
const router = express.Router();
const gradeController = require('../controllers/gradeController');
router.get('/', gradeController.getAllGrades);
router.get('/create', (req, res) => res.render('grade/create'));
router.post('/', gradeController.createGrade);
router.get('/:id/edit', gradeController.getGrade);
router.post('/:id', gradeController.updateGrade);
router.post('/:id/delete', gradeController.deleteGrade);
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('notification/create'));
router.post('/', notificationController.createNotification);
router.get('/:id/edit ', notificationController.getNotification);
router.post('/:id', notificationController.updateNotification);
router.post('/:id/delete', notificationController.deleteNotification);
module.exports = router;
routes/paymentRoutes.js
const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');
router.get('/', paymentController.getAllPayments);
router.get('/create', (req, res) => res.render('payment/create'));
router.post('/', paymentController.createPayment);
router.get('/:id/edit', paymentController.getPayment);
router.post('/:id', paymentController.updatePayment);
router.post('/:id/delete', paymentController.deletePayment);
module.exports = router;
routes/feedbackRoutes.js
const express = require('express');
const router = express.Router();
const feedbackController = require('../controllers/feedbackController');
router.get('/', feedbackController.getAllFeedbacks);
router.get('/create', (req, res) => res.render('feedback/create'));
router.post('/', feedbackController.createFeedback);
router.get('/:id/edit', feedbackController.getFeedback);
router.post('/:id', feedbackController.updateFeedback);
router.post('/:id/delete', feedbackController.deleteFeedback);
module.exports = router;
Step 6: Create EJS Views
views/syllabus/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>Syllabus</title>
</head>
<body>
<div class="container">
<h1>Syllabus</h1>
<a href="/syllabus/create" class="btn btn-primary">Create Syllabus</a>
<table class="table table-striped">
<thead>
<tr>
<th>SyllabusId</th>
<th>CourseId</th>
<th>Topic</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% syllabuses.forEach(syllabus => { %>
<tr>
<td><%= syllabus.SyllabusId %></td>
<td><%= syllabus.CourseId %></td>
<td><%= syllabus.Topic %></td>
<td>
<a href="/syllabus/<%= syllabus.SyllabusId %>/edit" class="btn btn-warning">Edit</a>
<form action="/syllabus/<%= syllabus.SyllabusId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/liveclass/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>Live Classes</title>
</head>
<body>
<div class="container">
<h1>Live Classes</h1>
<a href="/liveclass/create" class="btn btn-primary">Create Live Class</a>
<table class="table table-striped">
<thead>
<tr>
<th>LiveClassId</th>
<th>CourseId</th>
<th>ClassDate</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% liveClasses.forEach(liveClass => { %>
<tr>
<td><%= liveClass.LiveClassId %></td>
<td><%= liveClass.CourseId %></td>
<td><%= liveClass.ClassDate %></td>
<td>
<a href="/liveclass/<%= liveClass.LiveClassId %>/edit" class="btn btn-warning">Edit</a>
<form action="/liveclass/<%= liveClass.LiveClassId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/resource/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>Resources</title>
</head>
<body>
<div class="container">
<h1>Resources</h1>
<a href="/resource/create" class="btn btn-primary">Create Resource</a>
<table class="table table-striped">
<thead>
<tr>
<th>ResourceId</th>
<th>CourseId</th>
<th>ResourceName</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% resources.forEach(resource => { %>
<tr>
<td><%= resource.ResourceId %></td>
<td><%= resource.CourseId %></td>
<td><%= resource.ResourceName %></td>
<td>
<a href="/resource/<%= resource.ResourceId %>/edit" class="btn btn-warning">Edit</a>
<form action="/resource/<%= resource.ResourceId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/quiz/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>Quizzes</h1>
<a href="/quiz/create" class="btn btn-primary">Create Quiz</a>
<table class="table table-striped">
<thead>
<tr>
<th>QuizId</th>
<th>CourseId</th>
<th>QuizName</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% quizzes.forEach(quiz => { %>
<tr>
<td><%= quiz.QuizId %></td>
<td><%= quiz.CourseId %></td>
<td><%= quiz.QuizName %></td>
<td>
<a href="/quiz/<%= quiz.QuizId %>/edit" class="btn btn-warning">Edit</a>
<form action="/quiz/<%= quiz.QuizId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/grade/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>Grades</title>
</head>
<body>
<div class="container">
<h1>Grades</h1>
<a href="/grade/create" class="btn btn-primary">Create Grade</a>
<table class="table table-striped">
<thead>
<tr>
<th>GradeId</th>
<th>UserId</th>
<th>QuizId</th>
<th>MarksObtained</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% grades.forEach(grade => { %>
<tr>
<td><%= grade.GradeId %></td>
<td><%= grade.UserId %></td>
<td><%= grade.QuizId %></td>
<td><%= grade.MarksObtained %></td>
<td>
<a href="/grade/<%= grade.GradeId %>/edit" class="btn btn-warning">Edit</a>
<form action="/grade/<%= grade.GradeId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/notification/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>Notifications</h1>
<a href="/notification/create" class="btn btn-primary">Create Notification</a>
<table class="table table-striped">
<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="/notification/<%= notification.NotificationId %>/edit" class="btn btn-warning">Edit</a>
<form action="/notification/<%= notification.NotificationId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/payment/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>Payments</title>
</head>
<body>
<div class="container">
<h1>Payments</h1>
<a href="/payment/create" class="btn btn-primary">Create Payment</a>
<table class="table table-striped">
<thead>
<tr>
<th>PaymentId</th>
<th>UserId</th>
<th>CourseId</th>
<th>Amount</th>
<th>PaymentStatus</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% payments.forEach(payment => { %>
<tr>
<td><%= payment.PaymentId %></td>
<td><%= payment.UserId %></td>
<td><%= payment.CourseId %></td>
<td><%= payment.Amount %></td>
<td><%= payment.PaymentStatus %></td>
<td>
<a href="/payment/<%= payment.PaymentId %>/edit" class="btn btn-warning">Edit</a>
<form action="/payment/<%= payment.PaymentId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/feedback/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>Feedbacks</title>
</head>
<body>
<div class="container">
<h1>Feedbacks</h1>
<a href="/feedback/create" class="btn btn-primary">Create Feedback</a>
<table class="table table-striped">
<thead>
<tr>
<th>FeedbackId</th>
<th>UserId</th>
<th>CourseId</th>
<th>FeedbackContent</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% feedbacks.forEach(feedback => { %>
<tr>
<td><%= feedback.FeedbackId %></td>
<td><%= feedback.UserId %></td>
<td><%= feedback.CourseId %></td>
<td><%= feedback.FeedbackContent %></td>
<td>
<a href="/feedback/<%= feedback.FeedbackId %>/edit" class="btn btn-warning">Edit</a>
<form action="/feedback/<%= feedback.FeedbackId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
Step 7: Implement CRUD Operations
In your main application file (e.g., app.js), set up the Express server, middleware, and routes:
const express = require('express');
const bodyParser = require('body-parser');
const courseRoutes = require('./routes/courseRoutes');
const syllabusRoutes = require('./routes/syllabusRoutes');
const liveClassRoutes = require('./routes/liveClassRoutes');
const resourceRoutes = require('./routes/resourceRoutes');
const quizRoutes = require('./routes/quizRoutes');
const gradeRoutes = require('./routes/gradeRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const paymentRoutes = require('./routes/paymentRoutes');
const feedbackRoutes = require('./routes/feedbackRoutes');
const app = express();
const PORT = process.env.PORT || 3000;
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/courses', courseRoutes);
app.use('/syllabus', syllabusRoutes);
app.use('/liveclass', liveClassRoutes);
app.use('/resource', resourceRoutes);
app.use('/quiz', quizRoutes);
app.use('/grade', gradeRoutes);
app.use('/notification', notificationRoutes);
app.use('/payment', paymentRoutes);
app.use('/feedback', feedbackRoutes);
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
This completes the implementation for all remaining models, repositories, controllers, routes, and views for Syllabus, LiveClass, Resource, Quiz, Grade, Notification, Payment, and Feedback. You can now manage these entities through the CRUD application.
Creating a Dashboard Page
To create a dashboard page that consolidates data related to the project, we will follow these steps:
Step 1: Create a Dashboard Route
Create a new file named dashboardRoutes.js in the routes directory.
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.
const User = require('../models/User');
const Course = require('../models/Course');
const Syllabus = require('../models/Syllabus');
const LiveClass = require('../models/LiveClass');
const Resource = require('../models/Resource');
const Quiz = require('../models/Quiz');
const Grade = require('../models/Grade');
const Notification = require('../models/Notification');
const Payment = require('../models/Payment');
const Feedback = require('../models/Feedback');
class DashboardController {
async getDashboard(req, res) {
try {
const userCount = await User.count();
const courseCount = await Course.count();
const syllabusCount = await Syllabus.count();
const liveClassCount = await LiveClass.count();
const resourceCount = await Resource.count();
const quizCount = await Quiz.count();
const gradeCount = await Grade.count();
const notificationCount = await Notification.count();
const paymentCount = await Payment.count();
const feedbackCount = await Feedback.count();
res.render('dashboard', {
userCount,
courseCount,
syllabusCount,
liveClassCount,
resourceCount,
quizCount,
gradeCount,
notificationCount,
paymentCount,
feedbackCount
});
} 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.
<!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">Users</div>
<div class="card-body">
<h5 class="card-title"><%= userCount %></h5>
<p class="card-text">Total number of users.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Courses</div>
<div class="card-body">
<h5 class="card-title"><%= courseCount %></h5>
<p class="card-text">Total number of courses.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Syllabuses</div>
<div class="card-body">
<h5 class="card-title"><%= syllabusCount %></h5>
<p class="card-text">Total number of syllabuses.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-danger mb-3">
<div class="card-header">Live Classes</div>
<div class="card-body">
<h5 class="card-title"><%= liveClassCount %></h5>
<p class="card-text">Total number of live classes.</p>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-header">Resources</div>
<div class="card-body">
<h5 class="card-title"><%= resourceCount %></h5>
<p class="card-text">Total number of resources.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-secondary mb-3">
<div class="card-header">Quizzes</div>
<div class="card-body">
<h5 class="card-title"><%= quizCount %></h5>
<p class="card-text">Total number of quizzes.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-dark mb-3">
<div class="card-header">Grades</div>
<div class="card-body">
<h5 class="card-title"><%= gradeCount %></h5>
<p class="card-text">Total number of grades.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-light mb-3">
<div class="card-header">Notifications</div>
<div class="card-body">
<h5 class="card-title"><%= notificationCount %></h5>
<p class="card-text">Total number of notifications.</p>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
<div class="card-header">Payments</div>
<div class="card-body">
<h5 class="card-title"><%= paymentCount %></h5>
<p class="card-text">Total number of payments.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Feedbacks</div>
<div class="card-body">
<h5 class="card-title"><%= feedbackCount %></h5>
<p class="card-text">Total number of feedbacks.</p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Step 4: Update the Main Application File
In your main application file (e.g., app.js), import the dashboard routes and add them to the application.
const dashboardRoutes = require('./routes/dashboardRoutes');
app.use('/dashboard', dashboardRoutes);
Now you have a complete dashboard page that consolidates data related to users, courses, syllabuses, live classes, resources, quizzes, grades, notifications, payments, and feedbacks. The dashboard displays the total counts of each entity in a visually appealing manner using Bootstrap cards. You can access the dashboard by navigating to /dashboard in your application.