Project Introduction

The Online Auction System is a web application designed to facilitate the buying and selling of items through an auction format. Built using Node.js, this platform allows sellers to list their items for auction and buyers to place bids. The system supports multiple user roles, including admin, buyer, and seller, ensuring a tailored experience for each user type. The underlying MySQL database schema is structured to manage users, auction items, bids, payments, notifications, feedback, and auction reports, providing a robust foundation for effective auction management.

Project Objectives

  • To develop a user-friendly interface for buyers to browse and bid on auction items.
  • To allow sellers to create and manage auction listings, including setting starting and reserve prices.
  • To implement a secure user authentication system for managing user roles and permissions.
  • To facilitate the bidding process, allowing users to place bids and track their status.
  • To manage payment processing for completed auctions, including various payment methods.
  • To provide notifications for users regarding bid status, auction updates, and payment confirmations.
  • To enable buyers to leave feedback for sellers after a transaction.
  • To generate auction reports summarizing bidding activity and outcomes.
  • To ensure the application is scalable and maintainable for future enhancements.

Project Modules

  1. User Management Module:

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

  2. Auction Item Management Module:

    This module allows sellers to create, update, and manage auction listings, including item details and auction types.

  3. Bidding Management Module:

    This module facilitates the bidding process, allowing buyers to place bids and view current bid statuses.

  4. Payment Management Module:

    This module manages payment processing for auction items, including tracking payment statuses and methods.

  5. Notification Module:

    This module sends notifications to users regarding important updates, such as bid confirmations and auction results.

  6. Feedback Management Module:

    This module allows buyers to leave feedback for sellers, including ratings and comments on their experience.

  7. Auction Reporting Module:

    This module generates reports summarizing auction activity, including total bids and highest bids for items.

Steps Overview

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

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

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

Create Repositories: Implement repository functions for CRUD operations.

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

Define Routes: Set up routes to connect the controllers.

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

Implement Bootstrap 5: Style the views using Bootstrap 5.

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

Step 1: Set Up the Project


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

Step 2: Configure Sequelize

Create a file named config.js for database configuration.


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

Step 3: Define Models

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

models/User.js


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

models/Role.js


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

models/Item.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Item extends Model {}
Item.init({
ItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ItemName: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
StartingPrice: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
AuctionId: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Item',
timestamps: true,
});
module.exports = Item;

models/Bid.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Bid extends Model {}
Bid.init({
BidId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ItemId: {
type: DataTypes.INTEGER,
allowNull: false,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
BidAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
BidTime: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Bid',
timestamps: true,
});
module.exports = Bid;

models/Payment.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Payment extends Model {}
Payment.init({
PaymentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
ItemId: {
type: DataTypes.INTEGER,
allowNull: false,
},
PaymentAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
PaymentStatus: {
type: DataTypes.STRING(20),
allowNull: false,
},
}, {
sequelize,
modelName: 'Payment',
timestamps: true,
});
module.exports = Payment;

models/Auction.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Auction extends Model {}
Auction.init({
AuctionId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
AuctionTitle: {
type: DataTypes.STRING(100),
allowNull: false,
},
AuctionTypeId: {
type: DataTypes.INTEGER,
allowNull: false,
},
StartDate: {
type: DataTypes.DATE,
allowNull: false,
},
EndDate: {
type: DataTypes.DATE,
allowNull: false,
},
}, {
sequelize,
modelName: 'Auction',
timestamps: true,
});
module.exports = Auction;

models/AuctionType.js


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

models/Report.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Report extends Model {}
Report.init({
ReportId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
ReportDate: {
type: DataTypes.DATE,
allowNull: false,
},
ReportContent: {
type: DataTypes.TEXT,
},
}, {
sequelize,
modelName: 'Report',
timestamps: true,
});
module.exports = Report;

models/Feedback.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Feedback extends Model {}
Feedback.init({
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
FeedbackContent: {
type: DataTypes.TEXT,
allowNull: false,
},
}, {
sequelize,
modelName: 'Feedback',
timestamps: true,
});
module.exports = Feedback;

models/Notification.js


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

Step 4: Create Repositories

Create a folder named repositories and implement repository functions for CRUD operations.

repositories/userRepository.js


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

Step 5: Set Up Controllers

Create a folder named controllers and create controller files for handling requests.

controllers/userController.js


const userRepository = require('../repositories/userRepository');
class UserController {
async createUser (req, res) {
try {
const user = await userRepository.createUser (req.body);
res.status(201).json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllUsers(req, res) {
try {
const users = await userRepository.getAllUsers();
res.status(200).json(users);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getUser ById(req, res) {
try {
const user = await userRepository.getUser ById(req.params.id);
if (user) {
res.status(200).json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateUser (req, res) {
try {
const updatedUser = await userRepository.updateUser (req.params.id, req.body);
if (updatedUser ) {
res.status(200).json(updatedUser );
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteUser (req, res) {
try {
const deletedUser = await userRepository.deleteUser (req.params.id);
if (deletedUser ) {
res.status(204).send();
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new UserController();

Step 6: Define Routes

Create a folder named routes and set up routes for the user entity.

routes/userRoutes.js


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

Step 7: Create Views

Create a folder named views and create EJS files for displaying user data.

views/users.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Users</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Users</h1>
<table class="table mt-4">
<thead>
<tr>
<th>User ID</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 %>" class="btn btn-info">View</a>
<a href="/users/<%= user.UserId %>/edit" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/users/new" class="btn btn-primary">Add User</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Step 8: Implement Bootstrap 5

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

Step 9: Create a Dashboard

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

Final Steps

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

Access the User Management: Open your browser and navigate to http://localhost:3000/users to view and manage.

CRUD Implementation for Remaining Models

Following are the complete CRUD implementation for the remaining models: Assets, InventoryItems, Documents, Meetings, Tasks, Attendance, Reports, and Feedback. This will include models, repositories, controllers, routes, and views for each entity.

Step 1: Define Remaining Models

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

models/Asset.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Asset extends Model {}
Asset.init({
AssetId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
AssetName: {
type: DataTypes.STRING(100),
allowNull: false,
},
AssetType: {
type: DataTypes.STRING(50),
allowNull: false,
},
PurchaseDate: {
type: DataTypes.DATE,
allowNull: false,
},
Status: {
type: DataTypes.STRING(20),
allowNull: false,
},
}, {
sequelize,
modelName: 'Asset',
timestamps: true,
});
module.exports = Asset;

models/InventoryItem.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class InventoryItem extends Model {}
InventoryItem.init({
InventoryItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ItemName: {
type: DataTypes.STRING(100),
allowNull: false,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
Location: {
type: DataTypes.STRING(100),
},
}, {
sequelize,
modelName: 'InventoryItem',
timestamps: true,
});
module.exports = InventoryItem;

models/Document.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Document extends Model {}
Document.init({
DocumentId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
DocumentName: {
type: DataTypes.STRING(100),
allowNull: false,
},
DocumentType: {
type: DataTypes.STRING(50),
allowNull: false,
},
UploadedBy: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Document',
timestamps: true,
});
module.exports = Document;

models/Meeting.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Meeting extends Model {}
Meeting.init({
MeetingId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
MeetingTitle: {
type: DataTypes.STRING(100),
allowNull: false,
},
MeetingDate: {
type: DataTypes.DATE,
allowNull: false,
},
CreatedBy: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
sequelize,
modelName: 'Meeting',
timestamps: true,
});
module.exports = Meeting;

models/Task.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Task extends Model {}
Task.init({
TaskId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
TaskTitle: {
type: DataTypes.STRING(100),
allowNull: false,
},
AssignedTo: {
type: DataTypes.INTEGER,
allowNull: false,
},
DueDate: {
type: DataTypes.DATE,
allowNull: false,
},
Status: {
type: DataTypes.STRING(20),
allowNull: false,
},
}, {
sequelize,
modelName: 'Task',
timestamps: true,
});
module.exports = Task;

models/Attendance.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Attendance extends Model {}
Attendance.init({
AttendanceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
AttendanceDate: {
type: DataTypes.DATE,
allowNull: false,
},
Status: {
type: DataTypes.STRING(20),
allowNull: false,
},
}, {
sequelize,
modelName: 'Attendance',
timestamps: true,
});
module.exports = Attendance;

models/Report.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Report extends Model {}
Report.init({
ReportId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
ReportDate: {
type: DataTypes.DATE,
allowNull: false,
},
ReportContent: {
type: DataTypes.TEXT,
},
}, {
sequelize,
modelName: 'Report',
timestamps: true,
});
module.exports = Report;

models/Feedback.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Feedback extends Model {}
Feedback.init({
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type : DataTypes.INTEGER,
allowNull: false,
},
FeedbackContent: {
type: DataTypes.TEXT,
allowNull: false,
},
}, {
sequelize,
modelName: 'Feedback',
timestamps: true,
});
module.exports = Feedback;

Step 2: Create Repositories

Create repository files for each model in the repositories directory.

repositories/assetRepository.js


const Asset = require('../models/Asset');
class AssetRepository {
async createAsset(assetData) {
return await Asset.create(assetData);
}
async getAllAssets() {
return await Asset.findAll();
}
async getAssetById(assetId) {
return await Asset.findByPk(assetId);
}
async updateAsset(assetId, assetData) {
const asset = await this.getAssetById(assetId);
if (asset) {
return await asset.update(assetData);
}
return null;
}
async deleteAsset(assetId) {
const asset = await this.getAssetById(assetId);
if (asset) {
return await asset.destroy();
}
return null;
}
}
module.exports = new AssetRepository();

repositories/inventoryItemRepository.js


const InventoryItem = require('../models/InventoryItem');
class InventoryItemRepository {
async createInventoryItem(itemData) {
return await InventoryItem.create(itemData);
}
async getAllInventoryItems() {
return await InventoryItem.findAll();
}
async getInventoryItemById(itemId) {
return await InventoryItem.findByPk(itemId);
}
async updateInventoryItem(itemId, itemData) {
const item = await this.getInventoryItemById(itemId);
if (item) {
return await item.update(itemData);
}
return null;
}
async deleteInventoryItem(itemId) {
const item = await this.getInventoryItemById(itemId);
if (item) {
return await item.destroy();
}
return null;
}
}
module.exports = new InventoryItemRepository();

repositories/documentRepository.js


const Document = require('../models/Document');
class DocumentRepository {
async createDocument(docData) {
return await Document.create(docData);
}
async getAllDocuments() {
return await Document.findAll();
}
async getDocumentById(docId) {
return await Document.findByPk(docId);
}
async updateDocument(docId, docData) {
const doc = await this.getDocumentById(docId);
if (doc) {
return await doc.update(docData);
}
return null;
}
async deleteDocument(docId) {
const doc = await this.getDocumentById(docId);
if (doc) {
return await doc.destroy();
}
return null;
}
}
module.exports = new DocumentRepository();

repositories/meetingRepository.js


const Meeting = require('../models/Meeting');
class MeetingRepository {
async createMeeting(meetingData) {
return await Meeting.create(meetingData);
}
async getAllMeetings() {
return await Meeting.findAll();
}
async getMeetingById(meetingId) {
return await Meeting.findByPk(meetingId);
}
async updateMeeting(meetingId, meetingData) {
const meeting = await this.getMeetingById(meetingId);
if (meeting) {
return await meeting.update(meetingData);
}
return null;
}
async deleteMeeting(meetingId) {
const meeting = await this.getMeetingById(meetingId);
if (meeting) {
return await meeting.destroy();
}
return null;
}
}
module.exports = new MeetingRepository();

repositories/taskRepository.js


const Task = require('../models/Task');
class TaskRepository {
async createTask(taskData) {
return await Task.create(taskData);
}
async getAllTasks() {
return await Task.findAll();
}
async getTaskById(taskId) {
return await Task.findByPk(taskId);
}
async updateTask(taskId, taskData) {
const task = await this.getTaskById(taskId);
if (task) {
return await task.update(taskData);
}
return null;
}
async deleteTask(taskId) {
const task = await this.getTaskById(taskId);
if (task) {
return await task.destroy();
}
return null;
}
}
module.exports = new TaskRepository();

repositories/attendanceRepository.js


const Attendance = require('../models/Attendance');
class AttendanceRepository {
async createAttendance(attendanceData) {
return await Attendance.create (attendanceData);
}
async getAllAttendanceRecords() {
return await Attendance.findAll();
}
async getAttendanceById(attendanceId) {
return await Attendance.findByPk(attendanceId);
}
async updateAttendance(attendanceId, attendanceData) {
const attendance = await this.getAttendanceById(attendanceId);
if (attendance) {
return await attendance.update(attendanceData);
}
return null;
}
async deleteAttendance(attendanceId) {
const attendance = await this.getAttendanceById(attendanceId);
if (attendance) {
return await attendance.destroy();
}
return null;
}
}
module.exports = new AttendanceRepository();

Step 3: Set Up Controllers

Create controller files for each model in the controllers directory.

controllers/assetController.js


const assetRepository = require('../repositories/assetRepository');
class AssetController {
async createAsset(req, res) {
try {
const asset = await assetRepository.createAsset(req.body);
res.status(201).json(asset);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllAssets(req, res) {
try {
const assets = await assetRepository.getAllAssets();
res.status(200).json(assets);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAssetById(req, res) {
try {
const asset = await assetRepository.getAssetById(req.params.id);
if (asset) {
res.status(200).json(asset);
} else {
res.status(404).json({ message: 'Asset not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateAsset(req, res) {
try {
const updatedAsset = await assetRepository.updateAsset(req.params.id, req.body);
if (updatedAsset) {
res.status(200).json(updatedAsset);
} else {
res.status(404).json({ message: 'Asset not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteAsset(req, res) {
try {
const deletedAsset = await assetRepository.deleteAsset(req.params.id);
if (deletedAsset) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Asset not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new AssetController();

controllers/inventoryItemController.js


const inventoryItemRepository = require('../repositories/inventoryItemRepository');
class InventoryItemController {
async createInventoryItem(req, res) {
try {
const item = await inventoryItemRepository.createInventoryItem(req.body);
res.status(201).json(item);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllInventoryItems(req, res) {
try {
const items = await inventoryItemRepository.getAllInventoryItems();
res.status(200).json(items);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getInventoryItemById(req, res) {
try {
const item = await inventoryItemRepository.getInventoryItemById(req.params.id);
if (item) {
res.status(200).json(item);
} else {
res.status(404).json({ message: 'Inventory item not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateInventoryItem(req, res) {
try {
const updatedItem = await inventoryItemRepository.updateInventoryItem(req.params.id, req.body);
if (updatedItem) {
res.status(200).json(updatedItem);
} else {
res.status(404).json({ message: 'Inventory item not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteInventoryItem(req, res) {
try {
const deletedItem = await inventoryItemRepository.deleteInventoryItem(req.params.id);
if (deletedItem) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Inventory item not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new InventoryItemController();

controllers/documentController.js


const documentRepository = require('../repositories/documentRepository');
class DocumentController {
async createDocument(req, res) {
try {
const document = await documentRepository.createDocument(req.body);
res.status(201).json(document);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllDocuments(req, res) {
try {
const documents = await documentRepository.getAllDocuments();
res.status(200).json(documents);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getDocumentById(req, res) {
try {
const document = await documentRepository.getDocumentById(req.params.id);
if (document) {
res.status(200).json(document);
} else {
res.status(404).json({ message: 'Document not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateDocument(req, res) {
try {
const updatedDocument = await documentRepository.updateDocument(req.params.id, req.body);
if (updatedDocument) {
res.status(200).json(updatedDocument);
} else {
res.status(404).json({ message: 'Document not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteDocument(req, res) {
try {
const deletedDocument = await documentRepository.deleteDocument(req.params.id);
if (deletedDocument) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Document not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new DocumentController();

controllers/meetingController.js


const meetingRepository = require('../repositories/meetingRepository');
class MeetingController {
async createMeeting(req, res) {
try {
const meeting = await meetingRepository.createMeeting(req.body);
res.status(201).json(meeting);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllMeetings(req, res) {
try {
const meetings = await meetingRepository.getAllMeetings();
res.status(200).json(meetings);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getMeetingById(req, res) {
try {
const meeting = await meetingRepository.getMeetingById(req.params.id);
if (meeting) {
res.status(200).json(meeting);
} else {
res.status(404).json({ message: 'Meeting not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateMeeting(req, res) {
try {
const updatedMeeting = await meetingRepository.updateMeeting(req.params.id, req.body);
if (updatedMeeting) {
res.status(200).json(updatedMeeting);
} else {
res.status(404).json({ message: 'Meeting not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteMeeting(req, res) {
try {
const deletedMeeting = await meetingRepository.deleteMeeting(req.params.id);
if (deletedMeeting) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Meeting not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new MeetingController();

controllers/taskController.js


const taskRepository = require('../repositories/taskRepository');
class TaskController {
async createTask(req, res) {
try {
const task = await taskRepository.createTask(req.body);
res.status(201).json(task);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllTasks(req, res) {
try {
const tasks = await taskRepository.getAllTasks();
res.status(200).json(tasks);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getTaskById(req, res) {
try {
const task = await taskRepository.getTaskById(req.params.id);
if (task) {
res.status( 200).json(task);
} else {
res.status(404).json({ message: 'Task not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateTask(req, res) {
try {
const updatedTask = await taskRepository.updateTask(req.params.id, req.body);
if (updatedTask) {
res.status(200).json(updatedTask);
} else {
res.status(404).json({ message: 'Task not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteTask(req, res) {
try {
const deletedTask = await taskRepository.deleteTask(req.params.id);
if (deletedTask) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Task not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new TaskController();

controllers/attendanceController.js


const attendanceRepository = require('../repositories/attendanceRepository');
class AttendanceController {
async createAttendance(req, res) {
try {
const attendance = await attendanceRepository.createAttendance(req.body);
res.status(201).json(attendance);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAllAttendanceRecords(req, res) {
try {
const records = await attendanceRepository.getAllAttendanceRecords();
res.status(200).json(records);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async getAttendanceById(req, res) {
try {
const record = await attendanceRepository.getAttendanceById(req.params.id);
if (record) {
res.status(200).json(record);
} else {
res.status(404).json({ message: 'Attendance record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async updateAttendance(req, res) {
try {
const updatedRecord = await attendanceRepository.updateAttendance(req.params.id, req.body);
if (updatedRecord) {
res.status(200).json(updatedRecord);
} else {
res.status(404).json({ message: 'Attendance record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
async deleteAttendance(req, res) {
try {
const deletedRecord = await attendanceRepository.deleteAttendance(req.params.id);
if (deletedRecord) {
res.status(204).send();
} else {
res.status(404).json({ message: 'Attendance record not found' });
}
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
module.exports = new AttendanceController();

Step 4: Define Routes

Create route files for each model in the routes directory.

routes/assetRoutes.js


const express = require('express');
const router = express.Router();
const assetController = require('../controllers/assetController');
router.post('/', assetController.createAsset);
router.get('/', assetController.getAllAssets);
router.get('/:id', assetController.getAssetById);
router.put('/:id', assetController.updateAsset);
router.delete('/:id', assetController.deleteAsset);
module.exports = router;

routes/inventoryItemRoutes.js


const express = require('express');
const router = express.Router();
const inventoryItemController = require('../controllers/inventoryItemController');
router.post('/', inventoryItemController.createInventoryItem);
router.get('/', inventoryItemController.getAllInventoryItems);
router.get('/:id', inventoryItemController.getInventoryItemById);
router.put('/:id', inventoryItemController.updateInventoryItem);
router.delete('/:id', inventoryItemController.deleteInventoryItem);
module.exports = router;

routes/documentRoutes.js


const express = require('express');
const router = express.Router();
const documentController = require('../controllers/documentController');
router.post('/', documentController.createDocument);
router.get('/', documentController.getAllDocuments);
router.get('/:id', documentController.getDocumentById);
router.put('/:id', documentController.updateDocument);
router.delete('/:id', documentController.deleteDocument);
module.exports = router;

routes/meetingRoutes.js


const express = require('express');
const router = express.Router();
const meetingController = require('../controllers/meetingController');
router.post('/', meetingController.createMeeting);
router.get('/', meetingController.getAllMeetings);
router.get('/:id', meeting Controller.getMeetingById);
router.put('/:id', meetingController.updateMeeting);
router.delete('/:id', meetingController.deleteMeeting);
module.exports = router;

routes/taskRoutes.js


const express = require('express');
const router = express.Router();
const taskController = require('../controllers/taskController');
router.post('/', taskController.createTask);
router.get('/', taskController.getAllTasks);
router.get('/:id', taskController.getTaskById);
router.put('/:id', taskController.updateTask);
router.delete('/:id', taskController.deleteTask);
module.exports = router;

routes/attendanceRoutes.js


const express = require('express');
const router = express.Router();
const attendanceController = require('../controllers/attendanceController');
router.post('/', attendanceController.createAttendance);
router.get('/', attendanceController.getAllAttendanceRecords);
router.get('/:id', attendanceController.getAttendanceById);
router.put('/:id', attendanceController.updateAttendance);
router.delete('/:id', attendanceController.deleteAttendance);
module.exports = router;

Step 5: Create Views

Create EJS files for displaying data for each model in the views directory.

views/assets.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>Assets</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Assets</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Asset ID</th>
<th>Asset Name</th>
<th>Asset Type</th>
<th>Purchase Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% assets.forEach(asset => { %>
<tr>
<td><%= asset.AssetId %></td>
<td><%= asset.AssetName %></td>
<td><%= asset.AssetType %></td>
<td><%= asset.PurchaseDate.toISOString().split('T')[0] %></td>
<td><%= asset.Status %></td>
<td>
<a href="/assets/<%= asset.AssetId %>" class="btn btn-info">View</a>
<a href="/assets/<%= asset.AssetId %>/edit" class="btn btn-warning">Edit</a>
<form action="/assets/<%= asset.AssetId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/assets/new" class="btn btn-primary">Add Asset</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/inventoryItems.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>Inventory Items</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Inventory Items</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Item ID</th>
<th>Item Name</th>
<th>Quantity</th>
<th>Location</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% items.forEach(item => { %>
<tr>
<td><%= item.InventoryItemId %></td>
<td><%= item.ItemName %></td>
<td><%= item.Quantity %></td>
<td><%= item.Location %></td>
<td>
<a href="/inventory-items/<%= item.InventoryItemId %>" class="btn btn-info">View</a>
<a href="/inventory-items/<%= item.InventoryItemId %>/edit" class="btn btn-warning">Edit</a>
<form action="/inventory-items/<%= item.InventoryItemId %>" method=" POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/inventory-items/new" class="btn btn-primary">Add Inventory Item</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/documents.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>Documents</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Documents</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Document ID</th>
<th>Document Name</th>
<th>Document Type</th>
<th>Uploaded By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% documents.forEach(document => { %>
<tr>
<td><%= document.DocumentId %></td>
<td><%= document.DocumentName %></td>
<td><%= document.DocumentType %></td>
<td><%= document.UploadedBy %></td>
<td>
<a href="/documents/<%= document.DocumentId %>" class="btn btn-info">View</a>
<a href="/documents/<%= document.DocumentId %>/edit" class="btn btn-warning">Edit</a>
<form action="/documents/<%= document.DocumentId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/documents/new" class="btn btn-primary">Add Document</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/meetings.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>Meetings</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Meetings</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Meeting ID</th>
<th>Meeting Title</th>
<th>Meeting Date</th>
<th>Created By</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% meetings.forEach(meeting => { %>
<tr>
<td><%= meeting.MeetingId %></td>
<td><%= meeting.MeetingTitle %></td>
<td><%= meeting.MeetingDate.toISOString().split('T')[0] %></td>
<td><%= meeting.CreatedBy %></td>
<td>
<a href="/meetings/<%= meeting.MeetingId %>" class="btn btn-info">View</a>
<a href="/meetings/<%= meeting.MeetingId %>/edit" class="btn btn-warning">Edit</a>
<form action="/meetings/<%= meeting.MeetingId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/meetings/new" class="btn btn-primary">Add Meeting</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/tasks.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>Tasks</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Tasks</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Task ID</th>
<th>Task Title</th>
<th>Assigned To</th>
<th>Due Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% tasks.forEach(task => { %>
<tr>
<td><%= task.TaskId %></td>
<td><%= task.TaskTitle %></td>
<td><%= task.AssignedTo %></td>
<td><%= task.DueDate.toISOString().split('T')[0] %></td>
<td><%= task.Status %></td>
<td>
<a href="/tasks/<%= task.TaskId %>" class="btn btn-info">View</a>
<a href="/tasks/<%= task.TaskId %>/edit" class="btn btn-warning">Edit</a>
<form action="/tasks/<%= task.TaskId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/tasks/new" class="btn btn-primary">Add Task</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/attendance.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>Attendance Records</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Attendance Records</h1>
<table class="table mt-4">
<thead>
<tr>
<th>Attendance ID</th>
<th>User ID</th>
<th>Attendance Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% records.forEach(record => { %>
<tr>
<td><%= record.AttendanceId %></td>
<td><%= record.UserId %></td>
<td><%= record.AttendanceDate.toISOString().split('T')[0] %></td>
<td><%= record.Status %></td>
<td>
<a href="/attendance/<%= record.AttendanceId %>" class="btn btn-info">View</a>
<a href="/attendance/<%= record.AttendanceId %>/edit" class="btn btn-warning">Edit</a>
<form action="/attendance/<%= record.AttendanceId %>" method="POST" style="display:inline;">
<input type="hidden" name="_method" value="DELETE">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<a href="/attendance/new" class="btn btn-primary">Add Attendance Record</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Integrate Routes

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


const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const sequelize = require('./config');
// Import routes
const userRoutes = require('./routes/userRoutes');
const assetRoutes = require('./routes/assetRoutes');
const inventoryItemRoutes = require('./routes/inventoryItemRoutes');
const documentRoutes = require('./routes/documentRoutes');
const meetingRoutes = require('./routes/meetingRoutes');
const taskRoutes = require('./routes/taskRoutes');
const attendanceRoutes = require('./routes/attendanceRoutes');
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Routes
app.use('/users', userRoutes);
app.use('/assets', assetRoutes);
app.use('/inventory-items', inventoryItemRoutes);
app.use('/documents', documentRoutes);
app.use('/meetings', meetingRoutes);
app.use('/tasks', taskRoutes);
app.use('/attendance', attendanceRoutes);
// Sync database and start server
sequelize.sync().then(() => {
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});

Run the Application

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

Access the Application: Open your browser and navigate to the respective routes (e.g., http://localhost:3000/users, http://localhost:3000/assets, etc.) to view and manage the data for each entity.

Creating a Dashboard Page

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

Step 1: Create a Dashboard Route

Define a route for the dashboard.

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

routes/dashboardRoutes.js


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

Step 2: Create a Dashboard Controller

Implement a controller to fetch and aggregate data from various models.

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

controllers/dashboardController.js


const User = require('../models/User');
const Role = require('../models/Role');
const Asset = require('../models/Asset');
const InventoryItem = require('../models/InventoryItem');
const Document = require('../models/Document');
const Meeting = require('../models/Meeting');
const Task = require('../models/Task');
const Attendance = require('../models/Attendance');
const Report = require('../models/Report');
const Feedback = require('../models/Feedback');
class DashboardController {
async getDashboard(req, res) {
try {
const userCount = await User.count();
const roleCount = await Role.count();
const assetCount = await Asset.count();
const inventoryItemCount = await InventoryItem.count();
const documentCount = await Document.count();
const meetingCount = await Meeting.count();
const taskCount = await Task.count();
const attendanceCount = await Attendance.count();
const reportCount = await Report.count();
const feedbackCount = await Feedback.count();
res.render('dashboard', {
userCount,
roleCount,
assetCount,
inventoryItemCount,
documentCount,
meetingCount,
taskCount,
attendanceCount,
reportCount,
feedbackCount,
});
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new DashboardController();

Step 3: Create a Dashboard View

Design a view to display the consolidated data.

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

views/dashboard.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Dashboard</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Dashboard</h1>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
<div class="card-header">Total Users</div>
<div class="card-body">
<h5 class="card-title"><%= userCount %></h5>
<p class="card-text">Total number of registered users.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Roles</div>
<div class="card-body">
<h5 class="card-title"><%= roleCount %></h5>
<p class="card-text">Total roles defined in the system.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-header">Total Assets</div>
<div class="card-body">
<h5 class="card-title"><%= assetCount %></h5>
<p class="card-text">Total assets managed.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Total Inventory Items</div>
<div class="card-body">
<h5 class="card-title"><%= inventoryItemCount %></h5>
<p class="card-text">Total inventory items available.</p>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-danger mb-3">
<div class="card-header">Total Documents</div>
<div class="card-body">
<h5 class="card-title"><%= documentCount %></h5>
<p class="card-text">Total documents uploaded.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-secondary mb-3">
<div class="card-header">Total Meetings</div>
<div class="card-body">
<h5 class="card-title"><%= meetingCount %></h5>
<p class="card-text">Total meetings scheduled.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-light mb-3">
<div class="card-header">Total Tasks</div>
<div class="card-body">
<h5 class="card-title"><%= taskCount %></h5>
<p class="card-text">Total tasks assigned.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-dark mb-3">
<div class="card-header">Total Attendance Records</div>
<div class="card-body">
<h5 class="card-title"><%= attendanceCount %></h5>
<p class="card-text">Total attendance records logged.</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">Total Reports</div>
<div class="card-body">
<h5 class="card-title"><%= reportCount %></h5>
<p class="card-text">Total reports generated.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Feedback</div>
<div class="card-body">
<h5 class="card-title"><%= feedbackCount %></h5>
<p class="card-text">Total feedback received.</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Step 4: Update the Main Application

In your main application file (e.g., index.js), integrate the dashboard route.


const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const sequelize = require('./config');
// Import routes
const userRoutes = require('./routes/userRoutes');
const assetRoutes = require('./routes/assetRoutes');
const inventoryItemRoutes = require('./routes/inventoryItemRoutes');
const documentRoutes = require('./routes/documentRoutes');
const meetingRoutes = require('./routes/meetingRoutes');
const taskRoutes = require('./routes/taskRoutes');
const attendanceRoutes = require('./routes/attendanceRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes'); // Add this line
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Routes
app.use('/users', userRoutes);
app.use('/assets', assetRoutes);
app.use('/inventory-items', inventoryItemRoutes);
app.use('/documents', documentRoutes);
app.use('/meetings', meetingRoutes);
app.use('/tasks', taskRoutes);
app.use('/attendance', attendanceRoutes);
app.use('/dashboard', dashboardRoutes); // Add this line
// Sync database and start server
sequelize.sync().then(() => {
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});

Final Steps

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

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

This completes the implementation of the dashboard page, which aggregates and displays key metrics from various models in your asset management system. You can further enhance the dashboard by adding charts or graphs for better visualization of the data.