Project Introduction
The Traffic Management System is a web application designed to monitor and manage traffic flow, incidents, and vehicle classifications in urban areas. Built using Node.js, this platform allows traffic officers to analyze traffic data, manage traffic signals, and optimize routes for better traffic flow. The system supports multiple user roles, including admin, traffic officer, and public user, ensuring a tailored experience for each user type. The underlying MySQL database schema is structured to manage users, traffic monitoring data, traffic signals, incidents, route optimization, parking management, vehicle classification, and emergency vehicle management, providing a robust foundation for effective traffic management.
Project Objectives
- To develop a user-friendly interface for traffic officers to monitor traffic conditions and manage incidents.
- To allow public users to access real-time traffic information and updates.
- To implement a secure user authentication system for managing user roles and permissions.
- To collect and analyze traffic monitoring data, including vehicle counts and average speeds.
- To manage traffic signals and their statuses to optimize traffic flow.
- To report and track incidents, including their status and descriptions.
- To provide route optimization features for efficient navigation and reduced congestion.
- To manage parking spaces and their availability in real-time.
- To classify vehicles for better traffic analysis and reporting.
- To manage emergency vehicles and their statuses to ensure quick response times.
- 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.
- Traffic Monitoring Module:
This module collects and displays traffic data, including vehicle counts, average speeds, and congestion levels.
- Traffic Signal Management Module:
This module allows traffic officers to manage and monitor the status of traffic signals at various locations.
- Incident Management Module:
This module facilitates the reporting and tracking of traffic incidents, including their status and descriptions.
- Route Optimization Module:
This module provides optimized routes for vehicles to reduce congestion and improve travel times.
- Parking Management Module:
This module manages parking spaces, including total and available spaces at various locations.
- Vehicle Classification Module:
This module classifies vehicles based on type and tracks their counts over time.
- Emergency Vehicle Management Module:
This module tracks the status of emergency vehicles to ensure they are available and can respond quickly to incidents.
Steps Overview
Set Up the Project: Initialize a new Node.js project and install the required 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 for the application.
Create EJS Views: Design EJS views using Bootstrap 5 for the frontend.
Run the Application: Start the server and test the CRUD operations.
Step 1: Set Up the Project
Initialize the Project:
mkdir traffic-management
cd traffic-management
npm init -y
Install Required Packages:
npm install express sequelize mysql2 ejs body-parser express-session
Create the Project Structure:
mkdir models repositories controllers routes views public
touch app.js
Step 2: Define Sequelize Models
Create a file for each model in the models directory. Here’s an example for the User model:
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(50),
allowNull: false,
unique: true
},
PasswordHash: {
type: DataTypes.STRING(256),
allowNull: false
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
RoleId: {
type: DataTypes.INTEGER,
references: {
model: 'Roles',
key: 'RoleId'
}
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'User ',
tableName: 'Users',
timestamps: false
});
module.exports = User;
Repeat this process for the other models (Role, TrafficData, Incident, Signal, PerformanceMetrics, Route, Alert, Report).
Step 3: Create Repositories
Create a repository for each model in the repositories directory. Here’s an example for the User repository:
repositories/userRepository.js:
const User = require('../models/User');
class UserRepository {
async create(userData) {
return await User.create(userData);
}
async findAll() {
return await User.findAll();
}
async findById(userId) {
return await User.findByPk(userId);
}
async update(userId, userData) {
return await User.update(userData, { where: { UserId: userId } });
}
async delete(userId) {
return await User.destroy({ where: { UserId: userId } });
}
}
module.exports = new UserRepository();
Repeat this process for the other repositories.
Step 4: Set Up Controllers
Create a controller for each model in the controllers directory. Here’s an example for the User controller:
controllers/userController.js:
const userRepository = require('../repositories/userRepository');
class UserController {
async create(req, res) {
const user = await userRepository.create(req.body);
res.redirect('/users');
}
async findAll(req, res) {
const users = await userRepository.findAll();
res.render('users/index', { users });
}
async findById(req, res) {
const user = await userRepository.findById(req.params.id);
res.render('users/edit', { user });
}
async update(req, res) {
await userRepository.update(req.params.id, req.body);
res.redirect('/users');
}
async delete(req, res) {
await userRepository.delete(req.params.id);
res.redirect('/users');
}
}
module.exports = new UserController();
Repeat this process for the other controllers.
Step 5: Define Routes
Create a route for each model in the routes directory. Here’s an example for the User routes:
routes/userRoutes.js:
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.get('/', userController.findAll);
router.get('/ create', (req, res) => res.render('users/create'));
router.post('/', userController.create);
router.get('/:id', userController.findById);
router.post('/:id', userController.update);
router.get('/delete/:id', userController.delete);
module.exports = router;
Repeat this process for the other models' routes.
Step 6: Create EJS Views
Create EJS views in the views directory. Here’s an example for the User views:
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 rel="stylesheet" href="/public/bootstrap.min.css">
<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">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>" class="btn btn-warning">Edit</a>
<a href="/users/delete/<%= user.UserId %>" class="btn btn-danger">Delete</a>
</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 rel="stylesheet" href="/public/bootstrap.min.css">
<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>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
Repeat this process for the other views.
Step 7: Run the Application
In the app.js file, set up the Express server and middleware:
app.js:
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const userRoutes = require('./routes/userRoutes');
const sequelize = require('./config/database');
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(session({ secret: 'your_secret_key', resave: false, saveUninitialized: true }));
app.use('/users', userRoutes);
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => console.error(err));
This completes the setup for a complete CRUD application using Node.js, Sequelize, and EJS with Bootstrap 5 templates. You can now run the application and test the CRUD operations for the Users model, and similarly implement for other models.
Complete Setup for Remaining Models
Following are the complete setup for the remaining models (Roles, TrafficData, Incidents, Signals, PerformanceMetrics, Routes, Alerts, and Reports) in a similar manner to the Users model. This will include models, repositories, controllers, routes, and EJS views for each of these entities.
Step 2: Define Sequelize Models
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(50),
allowNull: false,
unique: true
}
}, {
sequelize,
modelName: 'Role',
tableName: 'Roles',
timestamps: false
});
module.exports = Role;
models/TrafficData.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class TrafficData extends Model {}
TrafficData.init({
TrafficDataId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
Location: {
type: DataTypes.STRING(100),
allowNull: false
},
Timestamp: {
type: DataTypes.DATE,
allowNull: false
},
VehicleCount: {
type: DataTypes.INTEGER,
allowNull: false
},
AverageSpeed: {
type: DataTypes.DECIMAL(5, 2),
allowNull: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'TrafficData',
tableName: 'TrafficData',
timestamps: false
});
module.exports = TrafficData;
models/Incident.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Incident extends Model {}
Incident.init({
IncidentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
Description: {
type: DataTypes.TEXT,
allowNull: false
},
Location: {
type: DataTypes.STRING(100),
allowNull: false
},
Severity: {
type: DataTypes.STRING(50),
allowNull: false
},
Timestamp: {
type: DataTypes.DATE,
allowNull: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'Incident',
tableName: 'Incidents',
timestamps: false
});
module.exports = Incident;
models/Signal.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Signal extends Model {}
Signal.init({
SignalId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
Location: {
type: DataTypes.STRING(100),
allowNull: false
},
SignalType: {
type: DataTypes.STRING(50),
allowNull: false
},
Status: {
type: DataTypes.STRING(50),
allowNull: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'Signal',
tableName: 'Signals',
timestamps: false
});
module.exports = Signal;
models/PerformanceMetric.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class PerformanceMetric extends Model {}
PerformanceMetric.init({
MetricId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
MetricName: {
type: DataTypes.STRING(100),
allowNull: false
},
Value: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false
},
Timestamp: {
type: DataTypes.DATE,
allowNull: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'PerformanceMetric',
tableName: 'PerformanceMetrics',
timestamps: false
});
module.exports = PerformanceMetric;
models/Route.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Route extends Model {}
Route.init({
RouteId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
StartLocation: {
type: DataTypes.STRING(100),
allowNull: false
},
EndLocation: {
type: DataTypes.STRING(100),
allowNull: false
},
Distance: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false
},
EstimatedTime: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'Route',
tableName: 'Routes',
timestamps: false
});
module.exports = Route;
models/Alert.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Alert extends Model {}
Alert.init({
AlertId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
references: {
model: 'Users',
key: 'User Id'
}
},
Message: {
type: DataTypes.STRING(256),
allowNull: false
},
IsRead: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'Alert',
tableName: 'Alerts',
timestamps: false
});
module.exports = Alert;
models/Report.js:
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/database');
class Report extends Model {}
Report.init({
ReportId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserId: {
type: DataTypes.INTEGER,
references: {
model: 'Users',
key: 'User Id'
}
},
ReportDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
Description: {
type: DataTypes.TEXT
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
}
}, {
sequelize,
modelName: 'Report',
tableName: 'Reports',
timestamps: false
});
module.exports = Report;
Step 3: Create Repositories
repositories/roleRepository.js:
const Role = require('../models/Role');
class RoleRepository {
async create(roleData) {
return await Role.create(roleData);
}
async findAll() {
return await Role.findAll();
}
async findById(roleId) {
return await Role.findByPk(roleId);
}
async update(roleId, roleData) {
return await Role.update(roleData, { where: { RoleId: roleId } });
}
async delete(roleId) {
return await Role.destroy({ where: { RoleId: roleId } });
}
}
module.exports = new RoleRepository();
repositories/trafficDataRepository.js:
const TrafficData = require('../models/TrafficData');
class TrafficDataRepository {
async create(data) {
return await TrafficData.create(data);
}
async findAll() {
return await TrafficData.findAll();
}
async findById(id) {
return await TrafficData.findByPk(id);
}
async update(id, data) {
return await TrafficData.update(data, { where: { TrafficDataId: id } });
}
async delete(id) {
return await TrafficData.destroy({ where: { TrafficDataId: id } });
}
}
module.exports = new TrafficDataRepository();
repositories/incidentRepository.js:
const Incident = require('../models/Incident');
class IncidentRepository {
async create(incidentData) {
return await Incident.create(incidentData);
}
async findAll() {
return await Incident.findAll();
}
async findById(incidentId) {
return await Incident.findByPk(incidentId);
}
async update(incidentId, incidentData) {
return await Incident.update(incidentData, { where: { IncidentId: incidentId } });
}
async delete(incidentId) {
return await Incident.destroy({ where: { IncidentId: incidentId } });
}
}
module.exports = new IncidentRepository();
repositories/signalRepository.js:
const Signal = require('../models/Signal');
class SignalRepository { async create(signalData) { return await Signal.create(signalData); }
Run
Copy code
async findAll() {
return await Signal.findAll();
}
async findById(signalId) {
return await Signal.findByPk(signalId);
}
async update(signalId, signalData) {
return await Signal.update(signalData, { where: { SignalId: signalId } });
}
async delete(signalId) {
return await Signal.destroy({ where: { SignalId: signalId } });
}
}
module.exports = new SignalRepository();
repositories/performanceMetricRepository.js:
const PerformanceMetric = require('../models/PerformanceMetric');
class PerformanceMetricRepository {
async create(metricData) {
return await PerformanceMetric.create(metricData);
}
async findAll() {
return await PerformanceMetric.findAll();
}
async findById(metricId) {
return await PerformanceMetric.findByPk(metricId);
}
async update(metricId, metricData) {
return await PerformanceMetric.update(metricData, { where: { MetricId: metricId } });
}
async delete(metricId) {
return await PerformanceMetric.destroy({ where: { MetricId: metricId } });
}
}
module.exports = new PerformanceMetricRepository();
repositories/routeRepository.js:
const Route = require('../models/Route');
class RouteRepository {
async create(routeData) {
return await Route.create(routeData);
}
async findAll() {
return await Route.findAll();
}
async findById(routeId) {
return await Route.findByPk(routeId);
}
async update(routeId, routeData) {
return await Route.update(routeData, { where: { RouteId: routeId } });
}
async delete(routeId) {
return await Route.destroy({ where: { RouteId: routeId } });
}
}
module.exports = new RouteRepository();
repositories/alertRepository.js:
const Alert = require('../models/Alert');
class AlertRepository {
async create(alertData) {
return await Alert.create(alertData);
}
async findAll() {
return await Alert.findAll();
}
async findById(alertId) {
return await Alert.findByPk(alertId);
}
async update(alertId, alertData) {
return await Alert.update(alertData, { where: { AlertId: alertId } });
}
async delete(alertId) {
return await Alert.destroy({ where: { AlertId: alertId } });
}
}
module.exports = new AlertRepository();
repositories/reportRepository.js:
const Report = require('../models/Report');
class ReportRepository {
async create(reportData) {
return await Report.create(reportData);
}
async findAll() {
return await Report.findAll();
}
async findById(reportId) {
return await Report.findByPk(reportId);
}
async update(reportId, reportData) {
return await Report.update(reportData, { where: { ReportId: reportId } });
}
async delete(reportId) {
return await Report.destroy({ where: { ReportId: reportId } });
}
}
module.exports = new ReportRepository();
Step 4: Set Up Controllers
controllers/roleController.js:
const roleRepository = require('../repositories/roleRepository');
class RoleController {
async create(req, res) {
const role = await roleRepository.create(req.body);
res.redirect('/roles');
}
async findAll(req, res) {
const roles = await roleRepository.findAll();
res.render('roles/index', { roles });
}
async findById(req, res) {
const role = await roleRepository.findById(req.params.id);
res.render('roles/edit', { role });
}
async update(req, res) {
await roleRepository.update(req.params.id, req.body);
res.redirect('/roles');
}
async delete(req, res) {
await roleRepository.delete(req.params.id);
res.redirect('/roles');
}
}
module.exports = new RoleController();
controllers/trafficDataController.js:
const trafficDataRepository = require('../repositories/trafficDataRepository');
class TrafficDataController {
async create(req, res) {
const trafficData = await trafficDataRepository.create(req.body);
res.redirect('/traffic-data');
}
async findAll(req, res) {
const trafficData = await trafficDataRepository.findAll();
res.render('traffic-data/index', { trafficData });
}
async findById(req, res) {
const trafficData = await trafficDataRepository.findBy Id(req.params.id);
res.render('traffic-data/edit', { trafficData });
}
async update(req, res) {
await trafficDataRepository.update(req.params.id, req.body);
res.redirect('/traffic-data');
}
async delete(req, res) {
await trafficDataRepository.delete(req.params.id);
res.redirect('/traffic-data');
}
}
module.exports = new TrafficDataController();
controllers/incidentController.js:
const incidentRepository = require('../repositories/incidentRepository');
class IncidentController {
async create(req, res) {
const incident = await incidentRepository.create(req.body);
res.redirect('/incidents');
}
async findAll(req, res) {
const incidents = await incidentRepository.findAll();
res.render('incidents/index', { incidents });
}
async findById(req, res) {
const incident = await incidentRepository.findById(req.params.id);
res.render('incidents/edit', { incident });
}
async update(req, res) {
await incidentRepository.update(req.params.id, req.body);
res.redirect('/incidents');
}
async delete(req, res) {
await incidentRepository.delete(req.params.id);
res.redirect('/incidents');
}
}
module.exports = new IncidentController();
controllers/signalController.js:
const signalRepository = require('../repositories/signalRepository');
class SignalController {
async create(req, res) {
const signal = await signalRepository.create(req.body);
res.redirect('/signals');
}
async findAll(req, res) {
const signals = await signalRepository.findAll();
res.render('signals/index', { signals });
}
async findById(req, res) {
const signal = await signalRepository.findById(req.params.id);
res.render('signals/edit', { signal });
}
async update(req, res) {
await signalRepository.update(req.params.id, req.body);
res.redirect('/signals');
}
async delete(req, res) {
await signalRepository.delete(req.params.id);
res.redirect('/signals');
}
}
module.exports = new SignalController();
controllers/performanceMetricController.js:
const performanceMetricRepository = require('../repositories/performanceMetricRepository');
class PerformanceMetricController {
async create(req, res) {
const metric = await performanceMetricRepository.create(req.body);
res.redirect('/performance-metrics');
}
async findAll(req, res) {
const metrics = await performanceMetricRepository.findAll();
res.render('performance-metrics/index', { metrics });
}
async findById(req, res) {
const metric = await performanceMetricRepository.findById(req.params.id);
res.render('performance-metrics/edit', { metric });
}
async update(req, res) {
await performanceMetricRepository.update(req.params.id, req.body);
res.redirect('/performance-metrics');
}
async delete(req, res) {
await performanceMetricRepository.delete(req.params.id);
res.redirect('/performance-metrics');
}
}
module.exports = new PerformanceMetricController();
controllers/routeController.js:
const routeRepository = require('../repositories/routeRepository');
class RouteController {
async create(req, res) {
const route = await routeRepository.create(req.body);
res.redirect('/routes');
}
async findAll(req, res) {
const routes = await routeRepository.findAll();
res.render('routes/index', { routes });
}
async findById(req, res) {
const route = await routeRepository.findById(req.params.id);
res.render('routes/edit', { route });
}
async update(req, res) {
await routeRepository.update(req.params.id, req.body);
res.redirect('/routes');
}
async delete(req, res) {
await routeRepository.delete(req.params.id);
res.redirect('/routes');
}
}
module.exports = new RouteController();
controllers/alertController.js:
const alertRepository = require('../repositories/alertRepository');
class AlertController {
async create(req, res) {
const alert = await alertRepository.create(req.body);
res.redirect('/alerts');
}
async findAll(req, res) {
const alerts = await alertRepository.findAll();
res.render('alerts/index', { alerts });
}
async findById(req, res) {
const alert = await alertRepository.findById(req.params.id);
res.render('alerts/edit', { alert });
}
async update(req, res) {
await alertRepository.update(req.params.id, req.body);
res.redirect('/alerts');
}
async delete(req, res) {
await alertRepository.delete(req.params.id);
res.redirect('/alerts');
}
}
module.exports = new AlertController();
controllers/reportController.js:
const reportRepository = require('../repositories/reportRepository');
class ReportController {
async create(req, res) {
const report = await reportRepository.create(req.body);
res.redirect('/reports');
}
async findAll(req, res) {
const reports = await reportRepository.findAll();
res.render('reports/index', { reports });
}
async findById(req, res) {
const report = await reportRepository.findById(req.params.id);
res.render('reports/edit', { report });
}
async update(req, res) {
await reportRepository.update(req.params.id, req.body);
res.redirect('/reports');
}
async delete(req, res) {
await reportRepository.delete(req.params.id);
res.redirect('/reports');
}
}
module.exports = new ReportController();
Step 5: Define Routes
routes/roleRoutes.js:
const express = require('express');
const router = express.Router();
const roleController = require('../controllers/roleController');
router.get('/', roleController.findAll);
router.get('/create', (req, res) => res.render('roles/create'));
router.post('/', roleController.create);
router.get('/:id', roleController.findById);
router.post('/:id', roleController.update);
router.get('/delete/:id', roleController.delete);
module.exports = router;
routes/trafficDataRoutes.js:
const express = require('express');
const router = express.Router();
const trafficDataController = require('../controllers/trafficDataController');
router.get('/', trafficDataController.findAll);
router.get('/create', (req, res) => res.render('traffic-data/create'));
router.post('/', trafficDataController.create);
router.get('/:id', trafficDataController.findById);
router.post('/:id', trafficDataController.update);
router.get('/delete/:id', trafficDataController.delete);
module.exports = router;
routes/incidentRoutes.js:
const express = require('express');
const router = express.Router();
const incidentController = require('../controllers/incidentController');
router.get('/', incidentController.findAll);
router.get('/create', (req, res) => res.render('incidents/create'));
router.post('/', incidentController.create);
router.get('/:id', incidentController.findById);
router.post('/:id', incidentController.update);
router.get('/delete/:id', incidentController.delete);
module.exports = router;
routes/signalRoutes.js:
const express = require('express');
const router = express.Router();
const signalController = require('../controllers/signalController');
router.get('/', signalController.findAll);
router.get('/create', (req, res) => res.render('signals/create'));
router.post('/', signalController.create);
router.get('/:id', signalController.findById);
router.post('/:id', signalController.update);
router.get('/delete/:id', signalController.delete);
module.exports = router;
routes/performanceMetricRoutes.js:
const express = require('express');
const router = express.Router();
const performanceMetricController = require('../controllers/performanceMetricController');
router.get('/', performanceMetricController.findAll);
router.get('/create', (req, res) => res.render('performance-metrics/create'));
router.post('/', performanceMetricController.create);
router.get('/:id', performanceMetricController.findById);
router.post('/:id', performanceMetricController.update);
router.get('/delete/:id', performanceMetricController.delete);
module.exports = router;
routes/routeRoutes.js:
const express = require('express');
const router = express.Router();
const routeController = require('../controllers/routeController');
router.get('/', routeController.findAll);
router.get('/create', (req, res) => res.render('routes/create'));
router.post('/', routeController.create);
router.get('/:id', routeController.findById);
router.post('/:id', routeController.update);
router.get('/delete/:id', routeController.delete);
module.exports = router;
routes/alertRoutes.js:
const express = require('express');
const router = express.Router();
const alertController = require('../controllers/alertController');
router.get('/', alertController.findAll);
router.get('/create', (req, res) => res.render('alerts/create'));
router.post('/', alertController.create);
router.get('/:id', alertController.findById);
router.post('/:id', alertController.update);
router.get('/delete/:id', alertController.delete);
module.exports = router;
routes/reportRoutes.js:
const express = require('express');
const router = express.Router();
const reportController = require('../controllers/reportController');
router.get('/', reportController.findAll);
router.get('/create', (req, res) => res.render('reports/create'));
router.post('/', reportController.create);
router.get('/:id', reportController.findBy Id);
router.post('/:id', reportController.update);
router.get('/delete/:id', reportController.delete);
module.exports = router;
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 rel="stylesheet" href="/public/bootstrap.min.css">
<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">
<thead>
<tr>
<th>Role Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% roles.forEach(role => { %>
<tr>
<td><%= role.RoleName %></td>
<td>
<a href="/roles/<%= role.RoleId %>" class="btn btn-warning">Edit</a>
<a href="/roles/delete/<%= role.RoleId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</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 rel="stylesheet" href="/public/bootstrap.min.css">
<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</button>
</form>
</div>
</body>
</html>
views/traffic-data/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Traffic Data</title>
</head>
<body>
<div class="container">
<h1>Traffic Data</h1>
<a href="/traffic-data/create" class="btn btn-primary">Create Traffic Data</a>
<table class="table">
<thead>
<tr>
<th>Location</th>
<th>Vehicle Count</th>
<th>Average Speed</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% trafficData.forEach(data => { %>
<tr>
<td><%= data.Location %></td>
<td><%= data.VehicleCount %></td>
<td><%= data.AverageSpeed %></td>
<td>
<a href="/traffic-data/<%= data.TrafficDataId %>" class="btn btn-warning">Edit</a>
<a href="/traffic-data/delete/<%= data.TrafficDataId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/traffic-data/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Traffic Data</title>
</head>
<body>
<div class="container">
<h1>Create Traffic Data</h1>
<form action="/traffic-data" method="POST">
<div class="mb-3">
<label for="Location" class="form-label">Location</label>
<input type="text" class="form-control" id="Location" name="Location" required>
</div>
<div class="mb-3">
<label for="VehicleCount" class="form-label">Vehicle Count</label>
<input type="number" class="form-control" id="VehicleCount" name="VehicleCount" required>
</div>
<div class="mb-3">
<label for="AverageSpeed" class="form-label">Average Speed</label>
<input type="number" step="0.01" class="form-control" id="AverageSpeed" name="AverageSpeed" required>
</div>
<div class="mb-3">
<label for="Timestamp" class="form-label">Timestamp</label>
<input type="datetime-local" class="form-control" id="Timestamp" name="Timestamp" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/incidents/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Incidents</title>
</head>
<body>
<div class="container">
<h1>Incidents</h1>
<a href="/incidents/create" class="btn btn-primary">Create Incident</a>
<table class="table">
<thead>
<tr>
<th>Description</th>
<th>Location</th>
<th>Severity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% incidents.forEach(incident => { %>
<tr>
<td><%= incident.Description %></td>
<td><%= incident.Location %></td>
<td><%= incident.Severity %></td>
<td>
<a href="/incidents/<%= incident.IncidentId %>" class="btn btn-warning">Edit</a>
<a href="/incidents/delete/<%= incident.IncidentId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/incidents/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Incident</title>
</head>
<body>
<div class="container">
<h1>Create Incident</h1>
<form action="/incidents" method="POST">
<div class="mb-3">
<label for="Description" class="form-label">Description</label>
<textarea class="form-control" id="Description" name="Description" required></textarea>
</div>
<div class="mb-3">
<label for="Location" class="form-label">Location</label>
<input type="text" class="form-control" id="Location" name="Location" required>
</div>
<div class="mb-3">
<label for="Severity" class="form-label">Severity</label>
<select class="form-control" id="Severity" name="Severity" required>
<option value="Minor">Minor</option>
<option value="Major">Major</option>
<option value="Critical">Critical</option>
</select>
</div>
<div class="mb-3">
<label for="Timestamp" class="form-label">Timestamp</label>
<input type="datetime-local" class="form-control" id="Timestamp" name="Timestamp" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/signals/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Signals</title>
</head>
<body>
<div class="container">
<h1>Signals</h1>
<a href="/signals/create" class="btn btn-primary">Create Signal</a>
<table class="table">
<thead>
<tr>
<th>Location</th>
<th>Signal Type</th>
<th>Status</th>
<th>Actions</th>
</ tr>
</thead>
<tbody>
<% signals.forEach(signal => { %>
<tr>
<td><%= signal.Location %></td>
<td><%= signal.SignalType %></td>
<td><%= signal.Status %></td>
<td>
<a href="/signals/<%= signal.SignalId %>" class="btn btn-warning">Edit</a>
<a href="/signals/delete/<%= signal.SignalId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/signals/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Signal</title>
</head>
<body>
<div class="container">
<h1>Create Signal</h1>
<form action="/signals" method="POST">
<div class="mb-3">
<label for="Location" class="form-label">Location</label>
<input type="text" class="form-control" id="Location" name="Location" required>
</div>
<div class="mb-3">
<label for="SignalType" class="form-label">Signal Type</label>
<input type="text" class="form-control" id="SignalType" name="SignalType" required>
</div>
<div class="mb-3">
<label for="Status" class="form-label">Status</label>
<select class="form-control" id="Status" name="Status" required>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/performance-metrics/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Performance Metrics</title>
</head>
<body>
<div class="container">
<h1>Performance Metrics</h1>
<a href="/performance-metrics/create" class="btn btn-primary">Create Metric</a>
<table class="table">
<thead>
<tr>
<th>Metric Name</th>
<th>Value</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% metrics.forEach(metric => { %>
<tr>
<td><%= metric.MetricName %></td>
<td><%= metric.Value %></td>
<td>
<a href="/performance-metrics/<%= metric.MetricId %>" class="btn btn-warning">Edit</a>
<a href="/performance-metrics/delete/<%= metric.MetricId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/performance-metrics/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Performance Metric</title>
</head>
<body>
<div class="container">
<h1>Create Performance Metric</h1>
<form action="/performance-metrics" method="POST">
<div class="mb-3">
<label for="MetricName" class="form-label">Metric Name</label>
<input type="text" class="form-control" id="MetricName" name="MetricName" required>
</div>
<div class="mb-3">
<label for="Value" class="form-label">Value</label>
<input type="number" step="0.01" class="form-control" id="Value" name="Value" required>
</div>
<div class="mb-3">
<label for="Timestamp" class="form-label">Timestamp</label>
<input type="datetime-local" class="form-control " id="Timestamp" name="Timestamp" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/routes/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Routes</title>
</head>
<body>
<div class="container">
<h1>Routes</h1>
<a href="/routes/create" class="btn btn-primary">Create Route</a>
<table class="table">
<thead>
<tr>
<th>Start Location</th>
<th>End Location</th>
<th>Distance</th>
<th>Estimated Time</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% routes.forEach(route => { %>
<tr>
<td><%= route.StartLocation %></td>
<td><%= route.EndLocation %></td>
<td><%= route.Distance %></td>
<td><%= route.EstimatedTime %></td>
<td>
<a href="/routes/<%= route.RouteId %>" class="btn btn-warning">Edit</a>
<a href="/routes/delete/<%= route.RouteId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/routes/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Route</title>
</head>
<body>
<div class="container">
<h1>Create Route</h1>
<form action="/routes" method="POST">
<div class="mb-3">
<label for="StartLocation" class="form-label">Start Location</label>
<input type="text" class="form-control" id="StartLocation" name="StartLocation" required>
</div>
<div class="mb-3">
<label for="EndLocation" class="form-label">End Location</label>
<input type="text" class="form-control" id="EndLocation" name="EndLocation" required>
</div>
<div class="mb-3">
<label for="Distance" class="form-label">Distance (km)</label>
<input type="number" step="0.01" class="form-control" id="Distance" name="Distance" required>
</div>
<div class="mb-3">
<label for="EstimatedTime" class="form-label">Estimated Time (minutes)</label>
<input type="number" step="0.01" class="form-control" id="EstimatedTime" name="EstimatedTime" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/alerts/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Alerts</title>
</head>
<body>
<div class="container">
<h1>Alerts</h1>
<a href="/alerts/create" class="btn btn-primary">Create Alert</a>
<table class="table">
<thead>
<tr>
<th>Message</th>
<th>Is Read</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% alerts.forEach(alert => { %>
<tr>
<td><%= alert.Message %></td>
<td><%= alert.IsRead ? 'Yes' : 'No' %></td>
<td>
<a href="/alerts/<%= alert.AlertId %>" class="btn btn-warning">Edit</a>
<a href="/alerts/delete/<%= alert.AlertId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) % </tbody>
</table>
</div>
</body>
</html>
views/alerts/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Alert</title>
</head>
<body>
<div class="container">
<h1>Create Alert</h1>
<form action="/alerts" method="POST">
<div class="mb-3">
<label for="Message" class="form-label">Message</label>
<input type="text" class="form-control" id="Message" name="Message" required>
</div>
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
views/reports/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Reports</title>
</head>
<body>
<div class="container">
<h1>Reports</h1>
<a href="/reports/create" class="btn btn-primary">Create Report</a>
<table class="table">
<thead>
<tr>
<th>Description</th>
<th>Report Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reports.forEach(report => { %>
<tr>
<td><%= report.Description %></td>
<td><%= report.ReportDate.toLocaleString() %></td>
<td>
<a href="/reports/<%= report.ReportId %>" class="btn btn-warning">Edit</a>
<a href="/reports/delete/<%= report.ReportId %>" class="btn btn-danger">Delete</a>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>
views/reports/create.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/public/bootstrap.min.css">
<title>Create Report</title>
</head>
<body>
<div class="container">
<h1>Create Report</h1>
<form action="/reports" method="POST">
<div class="mb-3">
<label for="Description" class="form-label">Description</label>
<textarea class="form-control" id="Description" name="Description" required></textarea>
</div>
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
</body>
</html>
Step 7: Update app.js to Include All Routes
In your app.js, make sure to include all the routes you created:
const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
const userRoutes = require('./routes/userRoutes');
const roleRoutes = require('./routes/roleRoutes');
const trafficDataRoutes = require('./routes/trafficDataRoutes');
const incidentRoutes = require('./routes/incidentRoutes');
const signalRoutes = require('./routes/signalRoutes');
const performanceMetricRoutes = require('./routes/performanceMetricRoutes');
const routeRoutes = require('./routes/routeRoutes');
const alertRoutes = require('./routes/alertRoutes');
const reportRoutes = require('./routes/reportRoutes');
const sequelize = require('./config/database');
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(session({ secret: 'your_secret_key', resave : false, saveUninitialized: true }));
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
app.use('/traffic-data', trafficDataRoutes);
app.use('/incidents', incidentRoutes);
app.use('/signals', signalRoutes);
app.use('/performance-metrics', performanceMetricRoutes);
app.use('/routes', routeRoutes);
app.use('/alerts', alertRoutes);
app.use('/reports', reportRoutes);
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => console.error(err));
This completes the setup for the remaining models, repositories, controllers, routes, and views for a complete CRUD application using Node.js, Sequelize, and EJS with Bootstrap 5 templates. You can now run the application and test the CRUD operations for all models.
Creating a Dashboard Page
To create a dashboard page in your Node.js project using EJS and Bootstrap 5, you'll need to set up a controller, routes, and a view to display consolidated data. Here's a high-level overview of the steps involved:
Step 1: Create the Dashboard Controller
controllers/dashboardController.js:
const roleRepository = require('../repositories/roleRepository');
const trafficDataRepository = require('../repositories/trafficDataRepository');
const incidentRepository = require('../repositories/incidentRepository');
class DashboardController {
async show(req, res) {
const roles = await roleRepository.findAll();
const trafficData = await trafficDataRepository.findAll();
const incidents = await incidentRepository.findAll();
res.render('dashboard', { roles, trafficData, incidents });
}
}
module.exports = new DashboardController();
Step 2: Define Routes
routes/dashboardRoutes.js:
const express = require('express');
const router = express.Router();
const dashboardController = require('../controllers/dashboardController');
router.get('/', dashboardController.show);
module.exports = router;
Step 3: Create the EJS View
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 rel="stylesheet" href="/public/bootstrap.min.css">
<title>Dashboard</title>
</head>
<body>
<div class="container">
<h1>Dashboard</h1>
<h2>Roles</h2>
<ul class="list-group">
<% roles.forEach(role => { %>
<li class="list-group-item"><%= role.RoleName %></li>
<% }) %>
</ul>
<h2>Traffic Data</h2>
<table class="table">
<thead>
<tr>
<th>Location</th>
<th>Vehicle Count</th>
<th>Average Speed</th>
</tr>
</thead>
<tbody>
<% trafficData.forEach(data => { %>
<tr>
<td><%= data.Location %></td>
<td><%= data.VehicleCount %></td>
<td><%= data.AverageSpeed %></td>
</tr>
<% }) %>
</tbody>
</table>
<h2>Incidents</h2>
<ul class="list-group">
<% incidents.forEach(incident => { %>
<li class="list-group-item"><%= incident.Description %> - <%= incident.Severity %></li>
<% }) %>
</ul>
</div>
</body>
</html>
Step 4: Update app.js to Include the Dashboard Route
In your app.js, make sure to include the dashboard routes:
const dashboardRoutes = require('./routes/dashboardRoutes');
app.use('/dashboard', dashboardRoutes);
With these steps, you will have a functional dashboard page that consolidates data from various models and displays it using EJS and Bootstrap 5. You can further customize the layout and data presentation as needed.