Project Introduction

The Online Ticket Booking System is a web application designed to facilitate the booking of tickets for various events. Built using Node.js, this platform allows event organizers to create and manage events while customers can browse events, book tickets, and leave reviews. The system supports multiple user roles, including admin, customer, and event organizer, ensuring a tailored experience for each user type. The underlying MySQL database schema is structured to manage users, events, ticket types, bookings, reviews, promotions, and notifications, providing a robust foundation for effective ticket management.

Project Objectives

  • To develop a user-friendly interface for customers to browse and book tickets for events.
  • To allow event organizers to create, update, and manage their events and ticket types.
  • To implement a secure user authentication system for managing user roles and permissions.
  • To facilitate the booking process, allowing users to select ticket types and quantities.
  • To manage reviews and ratings for events, providing feedback for organizers and potential attendees.
  • To implement promotional codes and discounts for events to enhance customer engagement.
  • To send notifications to users regarding important updates, such as booking confirmations and event reminders.
  • 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. Event Management Module:

    This module allows event organizers to create, update, and manage events, including details such as title, description, and date.

  3. Ticket Type Management Module:

    This module enables organizers to define different ticket types for events, including pricing and availability.

  4. Booking Management Module:

    This module facilitates the booking process, allowing customers to select ticket types, quantities, and complete their purchases.

  5. Review Management Module:

    This module allows customers to leave reviews and ratings for events they have attended.

  6. Promotion Management Module:

    This module manages promotional codes and discounts for events, allowing for enhanced marketing strategies.

  7. Notification Module:

    This module sends notifications to users regarding important updates, such as booking confirmations and event changes.

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 event-management-system
cd event-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,
},
RoleId: {
type: DataTypes.INTEGER,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'User ',
timestamps: false,
});
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: false,
});
module.exports = Role;

models/Event.js


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

models/Ticket.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Ticket extends Model {}
Ticket.init({
TicketId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
EventId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
TotalAvailable: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Ticket',
timestamps: false,
});
module.exports = Ticket;

models/Booking.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Booking extends Model {}
Booking.init({
BookingId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
TicketId: {
type: DataTypes.INTEGER,
allowNull: false,
},
BookingDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Booking',
timestamps: false,
});
module.exports = Booking;

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,
},
BookingId: {
type: DataTypes.INTEGER,
allowNull: false,
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Amount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
PaymentMethod: {
type: DataTypes.STRING(50),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Payment',
timestamps: false,
});
module.exports = Payment;

models/Notification.js


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

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,
defaultValue: DataTypes.NOW,
},
Description: {
type: DataTypes.TEXT,
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Report',
timestamps: false,
});
module.exports = Report;

models/Achievement.js


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

Step 4: Create Repositories for Remaining Models

Create repository files for each model in the repositories directory.

repositories/roleRepository.js


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

repositories/quizRepository.js


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

repositories/questionRepository.js


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

repositories/answerRepository.js


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

repositories/bookingRepository.js


const Booking = require('../models/Booking');
class BookingRepository {
async createBooking(bookingData) {
return await Booking.create(bookingData);
}
async getAllBookings() {
return await Booking.findAll();
}
async getBookingById(bookingId) {
return await Booking.findByPk(bookingId);
}
async updateBooking(bookingId, bookingData) {
const booking = await this.getBookingById(bookingId);
if (booking) {
return await booking.update(bookingData);
}
return null;
}
async deleteBooking(bookingId) {
const booking = await this.getBookingById(bookingId);
if (booking) {
await booking.destroy();
return true;
}
return false;
}
}
module.exports = new BookingRepository();

repositories/paymentRepository.js


const Payment = require('../models/Payment');
class PaymentRepository {
async createPayment(paymentData) {
return await Payment.create(paymentData);
}
async getAllPayments() {
return await Payment.findAll();
}
async getPaymentById(paymentId) {
return await Payment.findByPk(paymentId);
}
async updatePayment(paymentId, paymentData) {
const payment = await this.getPaymentById(paymentId);
if (payment) {
return await payment.update(paymentData);
}
return null;
}
async deletePayment(paymentId) {
const payment = await this.getPaymentById(paymentId);
if (payment) {
await payment.destroy();
return true;
}
return false;
}
}
module.exports = new PaymentRepository();

repositories/notificationRepository.js


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

repositories/reportRepository.js


const Report = require('../models/Report');
class ReportRepository {
async createReport(reportData) {
return await Report.create(reportData);
}
async getAllReports() {
return await Report.findAll();
}
async getReportById(reportId) {
return await Report.findByPk(reportId);
}
async updateReport(reportId, reportData) {
const report = await this.getReportById(reportId);
if (report) {
return await report.update(reportData);
}
return null;
}
async deleteReport(reportId) {
const report = await this.getReportById(reportId);
if (report) {
await report.destroy();
return true;
}
return false;
}
}
module.exports = new ReportRepository();

repositories/supportTicketRepository.js


const SupportTicket = require('../models/SupportTicket');
class SupportTicketRepository {
async createSupportTicket(ticketData) {
return await SupportTicket.create(ticketData);
}
async getAllSupportTickets() {
return await SupportTicket.findAll();
}
async getSupportTicketById(ticketId) {
return await SupportTicket.findByPk(ticketId);
}
async updateSupportTicket(ticketId, ticketData) {
const ticket = await this.getSupportTicketById(ticketId);
if (ticket) {
return await ticket.update(ticketData);
}
return null;
}
async deleteSupportTicket(ticketId) {
const ticket = await this.getSupportTicketById(ticketId);
if (ticket) {
await ticket.destroy();
return true;
}
return false;
}
}
module.exports = new SupportTicketRepository();

repositories/feedbackRepository.js


const Feedback = require('../models/Feedback');
class FeedbackRepository {
async createFeedback(feedbackData) {
return await Feedback.create(feedbackData);
}
async getAllFeedbacks() {
return await Feedback.findAll();
}
async getFeedbackById(feedbackId) {
return await Feedback.findByPk(feedbackId);
}
async updateFeedback(feedbackId, feedbackData) {
const feedback = await this.getFeedbackById(feedbackId);
if (feedback) {
return await feedback.update(feedbackData);
}
return null;
}
async deleteFeedback(feedbackId) {
const feedback = await this.getFeedbackById(feedbackId);
if (feedback) {
await feedback.destroy();
return true;
}
return false;
}
}
module.exports = new FeedbackRepository();

Step 5: Set Up Controllers

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

controllers/userController.js


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

controllers/roleController.js


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

controllers/eventController.js


const EventRepository = require('../repositories/eventRepository');
class EventController {
async createEvent(req, res) {
try {
await EventRepository.createEvent(req.body);
res.redirect('/events');
} catch (error) {
res.status(500).send('Error creating event');
}
}
async getAllEvents(req, res) {
const events = await EventRepository.getAllEvents();
res.render('events/index', { events });
}
async getEventById(req, res) {
const event = await EventRepository.getEventById(req.params.id);
res.render('events/edit', { event });
}
async updateEvent(req, res) {
try {
await EventRepository.updateEvent(req.params.id, req.body);
res.redirect('/events');
} catch (error) {
res.status(500).send('Error updating event');
}
}
async deleteEvent(req, res) {
await EventRepository.deleteEvent(req.params.id);
res.redirect('/events');
}
}
module.exports = new EventController();

controllers/ticketController.js


const TicketRepository = require('../repositories/ticketRepository');
class TicketController {
async createTicket(req, res) {
try {
await TicketRepository.createTicket(req.body);
res.redirect('/tickets');
} catch (error) {
res.status(500).send('Error creating ticket');
}
}
async getAllTickets(req, res) {
const tickets = await TicketRepository.getAllTickets();
res.render('tickets/index', { tickets });
}
async getTicketById(req, res) {
const ticket = await TicketRepository.getTicketById(req.params.id);
res.render('tickets/edit', { ticket });
}
async updateTicket(req, res) {
try {
await TicketRepository.updateTicket(req.params.id, req.body);
res.redirect('/tickets');
} catch (error) {
res.status(500).send('Error updating ticket');
}
}
async deleteTicket(req, res) {
await TicketRepository.deleteTicket(req.params.id);
res.redirect('/tickets');
}
}
module.exports = new TicketController();

controllers/bookingController.js


const BookingRepository = require('../repositories/bookingRepository');
class BookingController {
async createBooking(req, res) {
try {
await BookingRepository.createBooking(req.body);
res.redirect('/bookings');
} catch (error) {
res.status(500).send('Error creating booking');
}
}
async getAllBookings(req, res) {
const bookings = await BookingRepository.getAllBookings();
res.render('bookings/index', { bookings });
}
async getBookingById(req, res) {
const booking = await BookingRepository.getBookingById(req.params.id);
res.render('bookings/edit', { booking });
}
async updateBooking(req, res) {
try {
await BookingRepository.updateBooking(req.params.id, req.body);
res.redirect('/bookings');
} catch (error) {
res.status(500).send('Error updating booking');
}
}
async deleteBooking(req, res) {
await BookingRepository.deleteBooking(req.params.id);
res.redirect('/bookings');
}
}
module.exports = new BookingController();

controllers/paymentController.js


const PaymentRepository = require('../repositories/paymentRepository');
class PaymentController {
async createPayment(req, res) {
try {
await PaymentRepository.createPayment(req.body);
res.redirect('/payments');
} catch (error) {
res.status(500).send('Error creating payment');
}
}
async getAllPayments(req, res) {
const payments = await PaymentRepository.getAllPayments();
res.render('payments/index', { payments });
}
async getPaymentById(req, res) {
const payment = await PaymentRepository.getPaymentById(req.params.id);
res.render('payments/edit', { payment });
}
async updatePayment(req, res) {
try {
await PaymentRepository.updatePayment(req.params.id, req.body);
res.redirect('/payments');
} catch (error) {
res.status(500).send('Error updating payment');
}
}
async deletePayment(req, res) {
await PaymentRepository.deletePayment(req.params.id);
res.redirect('/payments');
}
}
module.exports = new PaymentController();

controllers/notificationController.js


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

controllers/reportController.js


const ReportRepository = require('../repositories/reportRepository');
class ReportController {
async createReport(req, res) {
try {
await ReportRepository.createReport(req.body);
res.redirect('/reports');
} catch (error) {
res.status(500).send('Error creating report');
}
}
async getAllReports(req, res) {
const reports = await ReportRepository.getAllReports();
res.render('reports/index', { reports });
}
async getReportById(req, res) {
const report = await ReportRepository.getReportById(req.params.id);
res.render('reports/edit', { report });
}
async updateReport(req, res) {
try {
await ReportRepository.updateReport(req.params.id, req.body);
res.redirect('/reports');
} catch (error) {
res.status(500).send('Error updating report');
}
}
async deleteReport(req, res) {
await ReportRepository.deleteReport(req.params.id);
res.redirect('/reports');
}
}
module.exports = new ReportController();

controllers/supportTicketController.js


javascript javascript const SupportTicketRepository = require('../repositories/supportTicketRepository');
class SupportTicketController { async createSupportTicket(req, res) { try { await SupportTicketRepository.createSupportTicket(req.body); res.redirect('/support-tickets'); } catch (error) { res.status(500).send('Error creating support ticket'); } }
async getAllSupportTickets(req, res) {
const tickets = await SupportTicketRepository.getAllSupportTickets();
res.render('support-tickets/index', { tickets });
}
async getSupportTicketById(req, res) {
const ticket = await SupportTicketRepository.getSupportTicketById(req.params.id);
res.render('support-tickets/edit', { ticket });
}
async updateSupportTicket(req, res) {
try {
await SupportTicketRepository.updateSupportTicket(req.params.id, req.body);
res.redirect('/support-tickets');
} catch (error) {
res.status(500).send('Error updating support ticket');
}
}
async deleteSupportTicket(req, res) {
await SupportTicketRepository.deleteSupportTicket(req.params.id);
res.redirect('/support-tickets');
}
}
module.exports = new SupportTicketController();

controllers/feedbackController.js


const FeedbackRepository = require('../repositories/feedbackRepository');
class FeedbackController {
async createFeedback(req, res) {
try {
await FeedbackRepository.createFeedback(req.body);
res.redirect('/feedbacks');
} catch (error) {
res.status(500).send('Error creating feedback');
}
}
async getAllFeedbacks(req, res) {
const feedbacks = await FeedbackRepository.getAllFeedbacks();
res.render('feedbacks/index', { feedbacks });
}
async getFeedbackById(req, res) {
const feedback = await FeedbackRepository.getFeedbackById(req.params.id);
res.render('feedbacks/edit', { feedback });
}
async updateFeedback(req, res) {
try {
await FeedbackRepository.updateFeedback(req.params.id, req.body);
res.redirect('/feedbacks');
} catch (error) {
res.status(500).send('Error updating feedback');
}
}
async deleteFeedback(req, res) {
await FeedbackRepository.deleteFeedback(req.params.id);
res.redirect('/feedbacks');
}
}
module.exports = new FeedbackController();

Step 6: Define Routes

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

routes/userRoutes.js


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

routes/roleRoutes.js


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

routes/eventRoutes.js


const express = require('express');
const router = express.Router();
const eventController = require('../controllers/eventController');
router.get('/', eventController.getAllEvents);
router.get('/create', (req, res) => res.render('events/create'));
router.post('/', eventController.createEvent);
router.get('/:id/edit', eventController.getEventById);
router.post('/:id', eventController.updateEvent);
router.post('/:id/delete', eventController.deleteEvent);
module.exports = router;

routes/ticketRoutes.js


const express = require('express');
const router = express.Router();
const ticketController = require('../controllers/ticketController');
router.get('/', ticketController.getAllTickets);
router.get('/create', (req, res) => res.render('tickets/create'));
router.post('/', ticketController.createTicket);
router.get('/:id/edit', ticketController.getTicketById);
router.post('/:id', ticketController.updateTicket);
router.post('/:id/delete', ticketController.deleteTicket);
module.exports = router;

routes/bookingRoutes.js


const express = require('express');
const router = express.Router();
const bookingController = require('../controllers/bookingController');
router.get('/', bookingController.getAllBookings);
router.get('/create', (req, res) => res.render('bookings/create'));
router.post ('/', bookingController.createBooking);
router.get('/:id/edit', bookingController.getBookingById);
router.post('/:id', bookingController.updateBooking);
router.post('/:id/delete', bookingController.deleteBooking);
module.exports = router;

routes/paymentRoutes.js


const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');
router.get('/', paymentController.getAllPayments);
router.get('/create', (req, res) => res.render('payments/create'));
router.post('/', paymentController.createPayment);
router.get('/:id/edit', paymentController.getPaymentById);
router.post('/:id', paymentController.updatePayment);
router.post('/:id/delete', paymentController.deletePayment);
module.exports = router;

routes/notificationRoutes.js


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

routes/reportRoutes.js


const express = require('express');
const router = express.Router();
const reportController = require('../controllers/reportController');
router.get('/', reportController.getAllReports);
router.get('/create', (req, res) => res.render('reports/create'));
router.post('/', reportController.createReport);
router.get('/:id/edit', reportController.getReportById);
router.post('/:id', reportController.updateReport);
router.post('/:id/delete', reportController.deleteReport);
module.exports = router;

routes/supportTicketRoutes.js


const express = require('express');
const router = express.Router();
const supportTicketController = require('../controllers/supportTicketController');
router.get('/', supportTicketController.getAllSupportTickets);
router.get('/create', (req, res) => res.render('support-tickets/create'));
router.post('/', supportTicketController.createSupportTicket);
router.get('/:id/edit', supportTicketController.getSupportTicketById);
router.post('/:id', supportTicketController.updateSupportTicket);
router.post('/:id/delete', supportTicketController.deleteSupportTicket);
module.exports = router;

routes/feedbackRoutes.js


const express = require('express');
const router = express.Router();
const feedbackController = require('../controllers/feedbackController');
router.get('/', feedbackController.getAllFeedbacks);
router.get('/create', (req, res) => res.render('feedbacks/create'));
router.post('/', feedbackController.createFeedback);
router.get('/:id/edit', feedbackController.getFeedbackById);
router.post('/:id', feedbackController.updateFeedback);
router.post('/:id/delete', feedbackController.deleteFeedback);
module.exports = router;

Step 7: Create Views

Create a folder named views and create EJS files for each model's 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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Users</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Users</h1>
<a href="/users/create" class="btn btn-primary mb-3">Create User</a>
<table class="table">
<thead>
<tr>
<th>UserId</th>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.UserId %></td>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>/edit" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/users/create.ejs


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

views/users/edit.ejs


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

Repeat for Other Models: You would create similar views for roles, events, tickets, bookings, payments, notifications, reports, support tickets, and feedback. Each model would have an index view to list items, a create view for adding new items, and an edit view for modifying existing items.

Step 8: Implement Bootstrap 5

Ensure that all views utilize Bootstrap 5 for styling, as shown in the examples above. This will provide a responsive and modern look to your application.

Step 9: Create a Dashboard

You can create a dashboard view similar to the one previously described, aggregating data from all models to provide an overview of the system.

Final Steps

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

Access the Application: Open your browser and navigate to http://localhost:3000/users, http://localhost:3000/roles, etc., to manage users, roles, events, and other entities.

This completes the implementation of a complete CRUD application for an event management system using Node.js, Sequelize, Express, EJS, and Bootstrap 5. You can further enhance the application by adding features like authentication, authorization, and more advanced data validation as needed.

Step 1: Define Remaining Models

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

models/Event.js


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

models/Ticket.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Ticket extends Model {}
Ticket.init({
TicketId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
EventId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
TotalAvailable: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Ticket',
timestamps: false,
});
module.exports = Ticket;

models/Booking.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class Booking extends Model {}
Booking.init({
BookingId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
TicketId: {
type: DataTypes.INTEGER,
allowNull: false,
},
BookingDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
TotalAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Booking',
timestamps: false,
});
module.exports = Booking;

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,
},
BookingId: {
type: DataTypes.INTEGER,
allowNull: false,
},
PaymentDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Amount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
PaymentMethod: {
type: DataTypes.STRING(50),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Payment',
timestamps: false,
});
module.exports = Payment;

models/Notification.js


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

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,
defaultValue: DataTypes.NOW,
},
Description: {
type: DataTypes.TEXT,
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'Report',
timestamps: false,
});
module.exports = Report;

models/SupportTicket.js


const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config');
class SupportTicket extends Model {}
SupportTicket.init({
SupportTicketId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
Subject: {
type: DataTypes.STRING(100),
allowNull: false,
},
Message: {
type: DataTypes.TEXT,
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
sequelize,
modelName: 'SupportTicket',
timestamps: false,
});
module.exports = SupportTicket;

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,
},
Comments: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
sequelize,
modelName: 'Feedback',
timestamps: false,
});
module.exports = Feedback;

Step 5: Create Repositories for Remaining Models

Create repository files for each model in the repositories directory.

repositories/eventRepository.js


const Event = require('../models/Event');
class EventRepository {
async createEvent(eventData) {
return await Event.create(eventData);
}
async getAllEvents() {
return await Event.findAll();
}
async getEventById(eventId) {
return await Event.findByPk(eventId);
}
async updateEvent(eventId, eventData) {
const event = await this.getEventById(eventId);
if (event) {
return await event.update(eventData);
}
return null;
}
async deleteEvent(eventId) {
const event = await this.getEventById(eventId);
if (event) {
await event.destroy();
return true;
}
return false;
}
}
module.exports = new EventRepository();

repositories/ticketRepository.js


const Ticket = require('../models/Ticket');
class TicketRepository {
async createTicket(ticketData) {
return await Ticket.create(ticketData);
}
async getAllTickets() {
return await Ticket.findAll();
}
async getTicketById(ticketId) {
return await Ticket.findByPk(ticketId);
}
async updateTicket(ticketId, ticketData) {
const ticket = await this.getTicketById(ticketId);
if (ticket) {
return await ticket.update(ticketData);
}
return null;
}
async deleteTicket(ticketId) {
const ticket = await this.getTicketById(ticketId);
if (ticket) {
await ticket.destroy();
return true;
}
return false;
}
}
module.exports = new TicketRepository();

repositories/bookingRepository.js


const Booking = require('../models/Booking');
class BookingRepository {
async createBooking(bookingData) {
return await Booking.create(bookingData);
}
async getAllBookings() {
return await Booking.findAll();
}
async getBookingById(bookingId) {
return await Booking.findByPk(bookingId);
}
async updateBooking(bookingId, bookingData) {
const booking = await this.getBookingById(bookingId);
if (booking) {
return await booking.update(bookingData);
}
return null;
}
async deleteBooking(bookingId) {
const booking = await this.getBookingById(bookingId);
if (booking) {
await booking.destroy();
return true;
}
return false;
}
}
module.exports = new BookingRepository();

repositories/paymentRepository.js


const Payment = require('../models/Payment');
class PaymentRepository {
async createPayment(paymentData) {
return await Payment.create(paymentData);
}
async getAllPayments() {
return await Payment.findAll();
}
async getPaymentById(paymentId) {
return await Payment.findByPk(paymentId);
}
async updatePayment(paymentId, paymentData) {
const payment = await this.getPaymentById(paymentId);
if (payment) {
return await payment.update(paymentData);
}
return null;
}
async deletePayment(paymentId) {
const payment = await this.getPaymentById(paymentId);
if (payment) {
await payment.destroy();
return true;
}
return false;
}
}
module.exports = new PaymentRepository();

repositories/notificationRepository.js


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

repositories/reportRepository.js


const Report = require('../models/Report');
class ReportRepository {
async createReport(reportData) {
return await Report.create(reportData);
}
async getAllReports() {
return await Report.findAll();
}
async getReportById(reportId) {
return await Report.findByPk(reportId);
}
async updateReport(reportId, reportData) {
const report = await this.getReportById(reportId);
if (report) {
return await report.update(reportData);
}
return null;
}
async deleteReport(reportId) {
const report = await this.getReportById(reportId);
if (report) {
await report.destroy();
return true;
}
return false;
}
}
module.exports = new ReportRepository();

repositories/supportTicketRepository.js


const SupportTicket = require('../models/SupportTicket');
class SupportTicketRepository {
async createSupportTicket(ticketData) {
return await SupportTicket.create(ticketData);
}
async getAllSupportTickets() {
return await SupportTicket.findAll();
}
async getSupportTicketById(ticketId) {
return await SupportTicket.findByPk(ticketId);
}
async updateSupportTicket(ticketId, ticketData) {
const ticket = await this.getSupportTicketById(ticketId);
if (ticket) {
return await ticket.update(ticketData);
}
return null;
}
async deleteSupportTicket(ticketId) {
const ticket = await this.getSupportTicketById(ticketId);
if (ticket) {
await ticket.destroy();
return true;
}
return false;
}
}
module.exports = new SupportTicketRepository();

repositories/feedbackRepository.js


const Feedback = require('../models/Feedback');
class FeedbackRepository {
async createFeedback(feedbackData) {
return await Feedback.create(feedbackData);
}
async getAllFeedbacks() {
return await Feedback.findAll();
}
async getFeedbackById(feedbackId) {
return await Feedback.findByPk(feedbackId);
}
async updateFeedback(feedbackId, feedbackData) {
const feedback = await this.getFeedbackById(feedbackId);
if (feedback) {
return await feedback.update(feedbackData);
}
return null;
}
async deleteFeedback(feedbackId) {
const feedback = await this.getFeedbackById(feedbackId);
if (feedback) {
await feedback.destroy();
return true;
}
return false;
}
}
module.exports = new FeedbackRepository();

Step 6: Set Up Controllers for Remaining Models

Create controller files for each model in the controllers directory.

controllers/eventController.js


const eventRepository = require('../repositories/eventRepository');
class EventController {
async createEvent(req, res) {
try {
await eventRepository.createEvent(req.body);
res.redirect('/events');
} catch (error) {
console.error(error);
res.status(500).send('Error creating event');
}
}
async getAllEvents(req, res) {
const events = await eventRepository.getAllEvents();
res.render('events/index', { events });
}
async getEventById(req, res) {
const event = await eventRepository.getEventById(req.params.id);
res.render('events/edit', { event });
}
async updateEvent(req, res) {
try {
await eventRepository.updateEvent(req.params.id, req.body);
res.redirect('/events');
} catch (error) {
console.error(error);
res.status(500).send('Error updating event');
}
}
async deleteEvent(req, res) {
await eventRepository.deleteEvent(req.params.id);
res.redirect('/events');
}
}
module.exports = new EventController();

controllers/ticketController.js


const ticketRepository = require('../repositories/ticketRepository');
class TicketController {
async createTicket(req, res) {
try {
await ticketRepository.createTicket(req.body);
res.redirect('/tickets');
} catch (error) {
console.error(error);
res.status(500).send('Error creating ticket');
}
}
async getAllTickets(req, res) {
const tickets = await ticketRepository.getAllTickets();
res.render('tickets/index', { tickets });
}
async getTicketById(req, res) {
const ticket = await ticketRepository.getTicketById(req.params.id);
res.render('tickets/edit', { ticket });
}
async updateTicket(req, res) {
try {
await ticketRepository.updateTicket(req.params.id, req.body);
res.redirect('/tickets');
} catch (error) {
console.error(error);
res.status(500).send('Error updating ticket');
}
}
async deleteTicket(req, res) {
await ticketRepository.deleteTicket(req.params.id);
res.redirect('/tickets');
}
}
module.exports = new TicketController();

controllers/bookingController.js


const bookingRepository = require('../repositories/bookingRepository');
class BookingController {
async createBooking(req, res) {
try {
await bookingRepository.createBooking(req.body);
res.redirect('/bookings');
} catch (error) {
console.error(error);
res.status(500).send('Error creating booking');
}
}
async getAllBookings(req, res) {
const bookings = await bookingRepository.getAllBookings();
res.render('bookings/index', { bookings });
}
async getBookingById(req, res) {
const booking = await bookingRepository.getBookingById(req.params.id);
res.render('bookings/edit', { booking });
}
async updateBooking(req, res) {
try {
await bookingRepository.updateBooking(req.params.id, req.body);
res.redirect('/bookings');
} catch (error) {
console.error(error);
res.status(500).send('Error updating booking');
}
}
async deleteBooking(req, res) {
await bookingRepository.deleteBooking(req.params.id);
res.redirect('/bookings');
}
}
module.exports = new BookingController();

controllers/paymentController.js


const paymentRepository = require('../repositories/paymentRepository');
class PaymentController {
async createPayment(req, res) {
try {
await paymentRepository.createPayment(req.body);
res.redirect('/payments');
} catch (error) {
console.error(error);
res.status(500).send('Error creating payment');
}
}
async getAllPayments(req, res) {
const payments = await paymentRepository.getAllPayments();
res.render('payments/index', { payments });
}
async getPaymentById(req, res) {
const payment = await paymentRepository.getPaymentById(req.params.id);
res.render('payments/edit', { payment });
}
async updatePayment(req, res) {
try {
await paymentRepository.updatePayment(req.params.id, req.body);
res.redirect('/payments');
} catch (error) {
console.error(error);
res.status(500).send('Error updating payment');
}
}
async deletePayment(req, res) {
await paymentRepository.deletePayment(req.params.id);
res.redirect('/payments');
}
}
module.exports = new PaymentController();

controllers/notificationController.js


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

controllers/reportController.js


const reportRepository = require('../repositories/reportRepository');
class ReportController {
async createReport(req, res) {
try {
await reportRepository.createReport(req.body);
res.redirect('/reports');
} catch (error) {
console.error(error);
res.status(500).send('Error creating report');
}
}
async getAllReports(req, res) {
const reports = await reportRepository.getAllReports();
res.render('reports/index', { reports });
}
async getReportById(req, res) {
const report = await reportRepository.getReportById(req.params.id);
res.render('reports/edit', { report });
}
async updateReport(req, res) {
try {
await reportRepository.updateReport(req.params.id, req.body);
res.redirect('/reports');
} catch (error) {
console.error(error);
res.status(500).send('Error updating report');
}
}
async deleteReport(req, res) {
await reportRepository.deleteReport(req.params.id);
res.redirect('/reports');
}
}
module.exports = new ReportController();

controllers/supportTicketController.js


const supportTicketRepository = require('../repositories/supportTicketRepository');
class SupportTicketController {
async createSupportTicket(req, res) {
try {
await supportTicketRepository.createSupportTicket(req.body);
res.redirect('/support-tickets');
} catch (error) {
console.error(error);
res.status(500).send('Error creating support ticket');
}
}
async getAllSupportTickets(req, res) {
const tickets = await supportTicketRepository.getAllSupportTickets();
res.render('support-tickets/index', { tickets });
}
async getSupportTicketById(req, res) {
const ticket = await supportTicketRepository.getSupportTicketById(req.params.id);
res.render('support-tickets/edit', { ticket });
}
async updateSupportTicket(req, res) {
try {
await supportTicketRepository.updateSupportTicket(req.params.id, req.body);
res.redirect('/support-tickets');
} catch (error) {
console.error(error);
res.status(500).send('Error updating support ticket');
}
}
async deleteSupportTicket(req, res) {
await supportTicketRepository.deleteSupportTicket(req.params.id);
res.redirect('/support-tickets');
}
}
module.exports = new SupportTicketController();

controllers/feedbackController.js


const feedbackRepository = require('../repositories/feedbackRepository');
class FeedbackController {
async createFeedback(req, res) {
try {
await feedbackRepository.createFeedback(req.body);
res.redirect('/feedbacks');
} catch (error) {
console.error(error);
res.status(500).send('Error creating feedback');
}
}
async getAllFeedbacks(req, res) {
const feedbacks = await feedbackRepository.getAllFeedbacks();
res.render('feedbacks/index', { feedbacks });
}
async getFeedbackById(req, res) {
const feedback = await feedbackRepository.getFeedbackById(req.params.id);
res.render('feedbacks/edit', { feedback });
}
async updateFeedback(req, res) {
try {
await feedbackRepository.updateFeedback(req.params.id, req.body);
res.redirect('/feedbacks');
} catch (error) {
console.error(error);
res.status(500).send('Error updating feedback');
}
}
async deleteFeedback(req, res) {
await feedbackRepository.deleteFeedback(req.params.id);
res.redirect('/feedbacks');
}
}
module.exports = new FeedbackController();

Step 6: Define Routes for Remaining Models

Create route files for each model in the routes directory.

routes/eventRoutes.js


const express = require('express');
const router = express.Router();
const eventController = require('../controllers/eventController');
router.get('/', eventController.getAllEvents);
router.get('/create', (req, res) => res.render('events/create'));
router.post('/', eventController.createEvent);
router.get('/:id/edit', eventController.getEventById);
router.post('/:id', eventController.updateEvent);
router.post('/:id/delete', eventController.deleteEvent);
module.exports = router;

routes/ticketRoutes.js


const express = require('express');
const router = express.Router();
const ticketController = require('../controllers/ticketController');
router.get('/', ticketController.getAllTickets);
router.get('/create', (req, res) => res.render('tickets/create'));
router.post('/', ticketController.createTicket);
router.get('/:id/edit', ticketController.getTicketById);
router.post('/:id', ticketController.updateTicket);
router.post('/:id/delete', ticketController.deleteTicket);
module.exports = router;

routes/bookingRoutes.js


const express = require('express');
const router = express.Router();
const bookingController = require('../controllers/bookingController');
router.get('/', bookingController.getAllBookings);
router.get('/create', (req, res) => res.render('bookings/create'));
router.post('/', bookingController.createBooking);
router.get('/:id/edit', bookingController.getBookingById);
router.post('/:id', bookingController.updateBooking);
router.post('/:id/delete', bookingController.deleteBooking);
module.exports = router;

routes/paymentRoutes.js


const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');
router.get('/', paymentController.getAllPayments);
router.get('/create', (req, res) => res.render('payments/create'));
router.post('/', paymentController.createPayment);
router.get('/:id/edit', paymentController.getPaymentById);
router.post('/:id', paymentController.updatePayment);
router.post('/:id/delete', paymentController.deletePayment);
module.exports = router;

routes/notificationRoutes.js


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

routes/reportRoutes.js


const express = require('express');
const router = express.Router();
const reportController = require('../controllers/reportController');
router.get('/', reportController.getAllReports);
router.get('/create', (req, res) => res.render('reports/create'));
router.post('/', reportController.createReport);
router.get('/:id/edit', reportController.getReportById);
router.post('/:id', reportController.updateReport);
router.post('/:id/delete', reportController.deleteReport);
module.exports = router;

routes/supportTicketRoutes.js


const express = require('express');
const router = express.Router();
const supportTicketController = require('../controllers/supportTicketController');
router.get('/', supportTicketController.getAllSupportTickets);
router.get('/create', (req, res) => res.render('support-tickets/create'));
router.post('/', supportTicketController.createSupportTicket);
router.get('/:id/edit', supportTicketController.getSupportTicketById);
router.post('/:id', supportTicketController.updateSupportTicket);
router.post('/:id/delete', supportTicketController.deleteSupportTicket);
module.exports = router;

routes/feedbackRoutes.js


const express = require('express');
const router = express.Router();
const feedbackController = require('../controllers/feedbackController');
router.get('/', feedbackController.getAllFeedbacks);
router.get('/create', (req, res) => res.render('feedbacks/create'));
router.post('/', feedbackController.createFeedback);
router.get('/:id/edit', feedbackController.getFeedbackById);
router.post('/:id', feedbackController.updateFeedback);
router.post('/:id/delete', feedbackController.deleteFeedback);
module.exports = router;

Step 7: Create Views for Remaining Models

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

views/events/index.ejs


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

views/events/create.ejs


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

views/events/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Event</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Event</h1>
<form action="/events/<%= event.EventId %>" method="POST">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" class="form-control" id="title" name="Title" value="<%= event.Title %>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description"><%= event.Description %></textarea>
</div>
<div class="mb-3">
<label for="eventDate" class="form-label">Event Date</label>
<input type="datetime-local" class="form-control" id="eventDate" name="EventDate" value="<%= event.EventDate.toISOString().split('T')[0] %>T<%= event.EventDate.toTimeString().split(' ')[0] %>" required>
</div>
<div class="mb-3">
<label for="venue" class="form-label">Venue</label>
<input type="text" class="form-control" id="venue" name="Venue" value="<%= event.Venue %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Event</button>
<a href="/events" class="btn btn-secondary">Cancel</a>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Repeat for Other Models: You would create similar views for tickets, bookings, payments, notifications, reports, support tickets, and feedback. Each model would have an index view to list items, a create view for adding new items, and an edit view for modifying existing items.

Example Views for Tickets

views/tickets/index.ejs


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

views/tickets/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Ticket</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Ticket</h1>
<form action="/tickets" method="POST">
<div class="mb-3">
<label for="eventId" class="form-label">EventId</label>
<input type="number" class="form-control" id="eventId" name="EventId" required>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" step="0.01" class="form-control" id="price" name="Price" required>
</div>
<div class="mb-3">
<label for="totalAvailable" class="form-label">Total Available</label>
<input type="number" class="form-control" id="totalAvailable" name="TotalAvailable" required>
</div>
<button type="submit" class="btn btn-primary">Create Ticket</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/tickets/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Ticket</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Ticket</h1>
<form action="/tickets/<%= ticket.TicketId %>" method="POST">
<div class="mb-3">
<label for="eventId" class="form-label">EventId</label>
<input type="number" class="form-control" id="eventId" name="EventId" value="<%= ticket.EventId %>" required>
</div>
<div class="mb-3">
<label for="price" class="form-label">Price</label>
<input type="number" step="0.01" class="form-control" id="price" name="Price" value="<%= ticket.Price %>" required>
</div>
<div class="mb-3">
<label for="totalAvailable" class="form-label">Total Available</label>
<input type="number" class="form-control" id="totalAvailable" name="TotalAvailable" value="<%= ticket.TotalAvailable %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Ticket</button>
<a href="/tickets" class="btn btn-secondary">Cancel</a>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Example Views for Bookings

views/bookings/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Bookings</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Bookings</h1>
<a href="/bookings/create" class="btn btn-primary mb-3">Create Booking</a>
<table class="table">
<thead>
<tr>
<th>BookingId</th>
<th>UserId</th>
<th>TicketId</th>
<th>BookingDate</th>
<th>Quantity</th>
<th>TotalAmount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% bookings.forEach(booking => { %>
<tr>
<td><%= booking.BookingId %></td>
<td><%= booking.UserId %></td>
<td><%= booking.TicketId %></td>
<td><%= booking.BookingDate.toISOString().split('T')[0] %></td>
<td><%= booking.Quantity %></td>
<td><%= booking.TotalAmount %></td>
<td><%= booking.Status %></td>
<td>
<a href="/bookings/<%= booking.BookingId %>/edit" class="btn btn-warning">Edit</a>
<form action="/bookings/<%= booking.BookingId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/bookings/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Booking</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Booking</h1>
<form action="/bookings" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User Id</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="ticketId" class="form-label">TicketId</label>
<input type="number" class="form-control" id="ticketId" name="TicketId" required>
</div>
<div class="mb-3">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" name="Quantity" required>
</div>
<div class="mb-3">
<label for="totalAmount" class="form-label">Total Amount</label>
<input type="number" step="0.01" class="form-control" id="totalAmount" name="TotalAmount" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="Status" required>
</div>
<button type="submit" class="btn btn-primary">Create Booking</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/bookings/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Booking</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Booking</h1>
<form action="/bookings/<%= booking.BookingId %>" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User Id</label>
<input type="number" class="form-control" id="userId" name="User Id" value="<%= booking.UserId %>" required>
</div>
<div class="mb-3">
<label for="ticketId" class="form-label">TicketId</label>
<input type="number" class="form-control" id="ticketId" name="TicketId" value="<%= booking.TicketId %>" required>
</div>
<div class="mb-3">
<label for="quantity" class="form-label">Quantity</label>
<input type="number" class="form-control" id="quantity" name="Quantity" value="<%= booking.Quantity %>" required>
</div>
<div class="mb-3">
<label for="totalAmount" class="form-label">Total Amount</label>
<input type="number" step="0.01" class="form-control" id="totalAmount" name="TotalAmount" value="<%= booking.TotalAmount %>" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="Status" value="<%= booking.Status %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Booking</button>
<a href="/bookings" class="btn btn-secondary">Cancel</a>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Example Views for Payments

views/payments/index.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Payments</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Payments</h1>
<a href="/payments/create" class="btn btn-primary mb-3">Create Payment</a>
<table class="table">
<thead>
<tr>
<th>PaymentId</th>
<th>BookingId</th>
<th>PaymentDate</th>
<th>Amount</th>
<th>PaymentMethod</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% payments.forEach(payment => { %>
<tr>
<td><%= payment.PaymentId %></td>
<td><%= payment.BookingId % </td>
<td><%= payment.PaymentDate.toISOString().split('T')[0] %></td>
<td><%= payment.Amount %></td>
<td><%= payment.PaymentMethod %></td>
<td><%= payment.Status %></td>
<td>
<a href="/payments/<%= payment.PaymentId %>/edit" class="btn btn-warning">Edit</a>
<form action="/payments/<%= payment.PaymentId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/payments/create.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Payment</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Payment</h1>
<form action="/payments" method="POST">
<div class="mb-3">
<label for="bookingId" class="form-label">BookingId</label>
<input type="number" class="form-control" id="bookingId" name="BookingId" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount</label>
<input type="number" step="0.01" class="form-control" id="amount" name="Amount" required>
</div>
<div class="mb-3">
<label for="paymentMethod" class="form-label">Payment Method</label>
<input type="text" class="form-control" id="paymentMethod" name="PaymentMethod" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="Status" required>
</div>
<button type="submit" class="btn btn-primary">Create Payment</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/payments/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Payment</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Payment</h1>
<form action="/payments/<%= payment.PaymentId %>" method="POST">
<div class="mb-3">
<label for="bookingId" class="form-label">BookingId</label>
<input type="number" class="form-control" id="bookingId" name="BookingId" value="<%= payment.BookingId %>" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount</label>
<input type="number" step="0.01" class="form-control" id="amount" name="Amount" value="<%= payment.Amount %>" required>
</div>
<div class="mb-3">
<label for="paymentMethod" class="form-label">Payment Method</label>
<input type="text" class="form-control" id="paymentMethod" name="PaymentMethod" value="<%= payment.PaymentMethod %>" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="Status" value="<%= payment.Status %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Payment</button>
<a href="/payments" class="btn btn-secondary">Cancel</a>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Example Views for Notifications

views/notifications/index.ejs


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

views/notifications/create.ejs


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

views/notifications/edit.ejs


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

Example Views for Reports

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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Reports</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Reports</h1>
<a href="/reports/create" class="btn btn-primary mb-3">Create Report</a>
<table class="table">
<thead>
<tr>
<th>ReportId</th>
<th>UserId</th>
<th>ReportDate</th>
<th>Description</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reports.forEach(report => { %>
<tr>
<td><%= report.ReportId %></td>
<td><%= report.UserId %></td>
<td><%= report.ReportDate.toISOString().split('T')[0] %></td>
<td><%= report.Description %></td>
<td><%= report.Status %></td>
<td>
<a href="/reports/<%= report.ReportId %>/edit" class="btn btn-warning">Edit</a>
<form action="/reports/<%= report.ReportId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/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 href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Report</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Create Report</h1>
<form action="/reports" method="POST">
<div class="mb-3">
<label for="userId" class="form-label">User Id</label>
<input type="number" class="form-control" id="userId" name="User Id" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="Description" required></textarea>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<input type="text" class="form-control" id="status" name="Status" required>
</div>
<button type="submit" class="btn btn-primary">Create Report</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

views/reports/edit.ejs


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

Example Views for Support Tickets

views/support-tickets/index.ejs


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

views/support-tickets/create.ejs


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

views/support-tickets/edit.ejs


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Edit Support Ticket</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Edit Support Ticket</h1>
<form action="/support-tickets/<%= ticket.SupportTicketId %>" method="POST">
<div class="mb-3"> <label for="userId" class="form-label">User Id</label> <input type="number" class="form-control" id="userId" name="User Id" value="<%= ticket.UserId %>" required> </div>
<div class="mb-3"> <label for="subject" class="form-label">Subject</label> <input type="text" class="form-control" id="subject" name="Subject" value="<%= ticket.Subject %>" required> </div>
<div class="mb-3"> <label for="message" class="form-label">Message</label> <textarea class="form-control" id="message" name="Message" required><%= ticket.Message %></textarea> </div>
<div class="mb-3"> <label for="status" class="form-label">Status</label> <input type="text" class="form-control" id="status" name="Status" value="<%= ticket.Status %>" required> </div>
<button type="submit" class="btn btn-primary">Update Support Ticket</button> <a href="/support-tickets" class="btn btn-secondary">Cancel</a>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Example Views for Feedback
views/feedbacks/index.ejs

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

Example Views for Feedback

views/feedbacks/create.ejs


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

views/feedbacks/edit.ejs


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

Final Steps

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

Access the Application: Open your browser and navigate to the various routes to manage users, roles, events, tickets, bookings, payments, notifications, reports, support tickets, and feedback.

This completes the implementation of a complete CRUD application for an event management system using Node.js, Sequelize, Express, EJS, and Bootstrap 5. You can further enhance the application by adding features like authentication, authorization, and more advanced data validation as needed.

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

Create a Dashboard Route: Define a route for the dashboard.

Create a Dashboard Controller: Implement a controller to fetch and aggregate data from various models.

Create a Dashboard View: Design a view to display the consolidated data.

Update the Main Application: Integrate the dashboard into the main application.

Step 1: Create a Dashboard Route

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


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

Step 2: Create a Dashboard Controller

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


const User = require('../models/User');
const Role = require('../models/Role');
const Event = require('../models/Event');
const Ticket = require('../models/Ticket');
const Booking = require('../models/Booking');
const Payment = require('../models/Payment');
const Notification = require('../models/Notification');
const Report = require('../models/Report');
const SupportTicket = require('../models/SupportTicket');
const Feedback = require('../models/Feedback');
class DashboardController {
async getDashboard(req, res) {
try {
const userCount = await User.count();
const roleCount = await Role.count();
const eventCount = await Event.count();
const ticketCount = await Ticket.count();
const bookingCount = await Booking.count();
const paymentCount = await Payment.count();
const notificationCount = await Notification.count();
const reportCount = await Report.count();
const supportTicketCount = await SupportTicket.count();
const feedbackCount = await Feedback.count();
res.render('dashboard', {
userCount,
roleCount,
eventCount,
ticketCount,
bookingCount,
paymentCount,
notificationCount,
reportCount,
supportTicketCount,
feedbackCount,
});
} catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new DashboardController();

Step 3: Create a Dashboard View

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


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Dashboard</title>
</head>
<body>
<div class="container">
<h1 class="mt-4">Dashboard</h1>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-primary mb-3">
<div class="card-header">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 Events</div>
<div class="card-body">
<h5 class="card-title"><%= eventCount %></h5>
<p class="card-text">Total events created.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Total Tickets</div>
<div class="card-body">
<h5 class="card-title"><%= ticketCount %></h5>
<p class="card-text">Total tickets 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 Bookings</div>
<div class="card-body">
<h5 class="card-title"><%= bookingCount %></h5>
<p class="card-text">Total bookings made.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-secondary mb-3">
<div class="card-header">Total Payments</div>
<div class="card-body">
<h5 class="card-title"><%= paymentCount %></h5>
<p class="card-text">Total payments processed.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-light mb-3">
<div class="card-header">Total Notifications</div>
<div class="card-body">
<h5 class="card-title"><%= notificationCount %></h5>
<p class="card-text">Total notifications sent.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-dark 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>
<div class="row mt-4">
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Support Tickets</div>
<div class="card-body">
<h5 class="card-title"><%= supportTicketCount %></h5>
<p class="card-text">Total support tickets created.</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info 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 roleRoutes = require('./routes/roleRoutes');
const eventRoutes = require('./routes/eventRoutes');
const ticketRoutes = require('./routes/ticketRoutes');
const bookingRoutes = require('./routes/bookingRoutes');
const paymentRoutes = require('./routes/paymentRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const reportRoutes = require('./routes/reportRoutes');
const supportTicketRoutes = require('./routes/supportTicketRoutes');
const feedbackRoutes = require('./routes/feedbackRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes'); // Import dashboard routes
// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Use routes
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
app.use('/events', eventRoutes);
app.use('/tickets', ticketRoutes);
app.use('/bookings', bookingRoutes);
app.use('/payments', paymentRoutes);
app.use('/notifications', notificationRoutes);
app.use('/reports', reportRoutes);
app.use('/support-tickets', supportTicketRoutes);
app.use('/feedbacks', feedbackRoutes);
app.use('/dashboard', dashboardRoutes); // Use dashboard routes
// Sync database and start server
sequelize.sync().then(() => {
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
}).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 a dashboard page that aggregates and displays key metrics from the event management system. You can further enhance the dashboard by adding charts, graphs, or additional statistics as needed.