Project Introduction
The Hotel Management System is a comprehensive web application designed to streamline the management of hotel operations, including room bookings, customer management, and payment processing. Built using Node.js, this platform allows hotel staff to efficiently manage room availability, customer reservations, and billing. The system supports multiple user roles, ensuring a tailored experience for hotel administrators and customers. The underlying MySQL database schema is structured to manage hotels, rooms, customers, bookings, and payments, providing a robust foundation for effective hotel management.
Project Objectives
- To develop a user-friendly interface for hotel staff to manage room bookings and customer information.
- To implement a secure user authentication system for customers to manage their bookings.
- To facilitate the management of room availability and status updates.
- To enable customers to make reservations and view their booking history.
- To manage payment processing for bookings, including tracking payment statuses.
- To ensure the application is scalable and maintainable for future enhancements.
Project Modules
- Hotel Management Module:
This module allows hotel administrators to add, update, and manage hotel information, including name, address, and contact details.
- Room Management Module:
This module enables hotel staff to manage room details, including room types, pricing, and availability status.
- Customer Management Module:
This module handles customer registration, authentication, and profile management, allowing customers to manage their accounts securely.
- Booking Management Module:
This module facilitates the booking process, allowing customers to reserve rooms and manage their bookings.
- Payment Management Module:
This module manages payment processing for bookings, including tracking payment amounts and dates.
Steps Overview
Set Up the Project
Create Sequelize Models
Create Repositories
Create Controllers
Create Routes
Create EJS Views
Set Up the Main Application File
Run the Application
Create a Dashboard Page
Step 1: Set Up the Project
Initialize a new Node.js project:
mkdir hotel-management
cd hotel-management
npm init -y
Install required packages:
npm install express sequelize mysql2 ejs body-parser
Create the project structure:
mkdir models repositories controllers routes views public
Step 2: Create Sequelize Models
Create a file for each model in the models directory. Below are the models based on your SQL schema.
User Model (models/User.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const User = sequelize.define('User ', {
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,
},
});
module.exports = User;
Role Model (models/Role.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Role = sequelize.define('Role', {
RoleId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoleName: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
});
module.exports = Role;
Reservation Model (models/Reservation.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Reservation = sequelize.define('Reservation', {
ReservationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
GuestId: {
type: DataTypes.INTEGER,
},
RoomId: {
type: DataTypes.INTEGER,
},
CheckInDate: {
type: DataTypes.DATE,
allowNull: false,
},
CheckOutDate: {
type: DataTypes.DATE,
allowNull: false,
},
NumberOfGuests: {
type: DataTypes.INTEGER,
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Reservation;
Room Model (models/Room.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Room = sequelize.define('Room', {
RoomId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoomNumber: {
type: DataTypes.STRING(10),
allowNull: false,
unique: true,
},
RoomType: {
type: DataTypes.STRING(50),
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Room;
Invoice Model (models/Invoice.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Invoice = sequelize.define('Invoice', {
InvoiceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ReservationId: {
type: DataTypes.INTEGER,
},
Amount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
PaymentStatus: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Invoice;
HousekeepingTask Model (models/HousekeepingTask.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const HousekeepingTask = sequelize.define('HousekeepingTask', {
TaskId: {
type: DataTypes.INTEGER,
primaryKey: true autoIncrement: true,
},
RoomId: {
type: DataTypes.INTEGER,
},
TaskDescription: {
type: DataTypes.STRING(256),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = HousekeepingTask;
Guest Model (models/Guest.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Guest = sequelize.define('Guest', {
GuestId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
FirstName: {
type: DataTypes.STRING(50),
allowNull: false,
},
LastName: {
type: DataTypes.STRING(50),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
Phone: {
type: DataTypes.STRING(15),
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Guest;
Feedback Model (models/Feedback.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Feedback = sequelize.define('Feedback', {
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
GuestId: {
type: DataTypes.INTEGER,
},
Rating: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 1,
max: 5,
},
},
Comments: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Feedback;
MenuItem Model (models/MenuItem.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const MenuItem = sequelize.define('MenuItem', {
MenuItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = MenuItem;
EventBooking Model (models/EventBooking.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const EventBooking = sequelize.define('EventBooking', {
EventBookingId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
EventName: {
type: DataTypes.STRING(100),
allowNull: false,
},
BookingDate: {
type: DataTypes.DATE,
allowNull: false,
},
NumberOfGuests: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = EventBooking;
Promotion Model (models/Promotion.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Promotion = sequelize.define('Promotion', {
PromotionId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Code: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
DiscountAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
ExpirationDate: {
type: DataTypes.DATE,
allowNull: false,
},
IsActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
});
module.exports = Promotion;
Step 3: Create Repositories
Create a repository for each model in the repositories directory. Below is an example for the User repository.
User Repository (repositories/User Repository.js):
const User = require('../models/User');
class UserRepository {
async createUser (userData) {
return await User.create(userData);
}
async getAllUsers() {
return await User.findAll();
}
async getUser ById(userId) {
return await User.findByPk(userId);
}
async updateUser (userId, userData) {
const user = await this.getUser ById(userId);
if (user) {
return await user.update(userData);
}
throw new Error('User not found');
}
async deleteUser (userId) {
const user = await this.getUser ById(userId);
if (user) {
return await user.destroy();
}
throw new Error('User not found');
}
}
module.exports = new UserRepository();
Step 4: Create Controllers
Create a controller for each model in the controllers directory. Below is an example for the User controller.
User Controller (controllers/UserController.js):
const UserRepository = require('../repositories/UserRepository');
class UserController {
async createUser (req, res) {
try {
const user = await UserRepository.createUser (req.body);
res.redirect('/users');
} catch (error) {
console.error('Error creating user:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllUsers(req, res) {
try {
const users = await UserRepository.getAllUsers();
res.render('users/index', { users });
} catch (error) {
console.error('Error fetching users:', error);
res.status(500).send('Internal Server Error');
}
}
async getUser (req, res) {
try {
const user = await UserRepository.getUser ById(req.params.id);
if (user) {
res.render('users/edit', { user });
} else {
res.status(404).send('User not found');
}
} catch (error) {
console.error('Error fetching user:', error);
res.status(500).send('Internal Server Error');
}
}
async updateUser (req, res) {
try {
await UserRepository.updateUser (req.params.id, req.body);
res.redirect('/users');
} catch (error) {
console.error('Error updating user:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteUser (req, res) {
try {
await UserRepository.deleteUser (req.params.id);
res.redirect('/users');
} catch (error) {
console.error('Error deleting user:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new UserController();
Step 5: Create Routes
Create a route for each model in the routes directory. Below is an example for the User routes.
User Routes (routes/userRoutes.js):
const express = require('express');
const router = express.Router();
const UserController = require('../controllers/UserController');
router.get('/', UserController.getAllUsers);
router.get('/create', (req, res) => res.render('users/create'));
router.post('/', UserController.createUser );
router.get('/:id', UserController.getUser );
router.post('/:id', UserController.updateUser );
router.delete('/:id', UserController.deleteUser );
module.exports = router;
Step 6: Create EJS Views
Create EJS views for each model in the views directory. Below is an example for the User views.
User Index View (views/users/index.ejs):
<%- include('partials/header') %>
<h1>Users</h1>
<a href="/users/create" class="btn btn-primary">Create User</a>
<table class="table">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% users.forEach(user => { %>
<tr>
<td><%= user.Username %></td>
<td><%= user.Email %></td>
<td>
<a href="/users/<%= user.UserId %>" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
User Create View (views/users/create.ejs):
<%- include('partials/header') %>
<h1>Create User</h1>
<form action="/users" method="POST">
<div class="mb-3">
<label for="Username" class="form-label">Username</label>
<input type="text" class="form-control" id="Username" name="Username" required>
</div>
<div class="mb-3">
<label for="Email" class="form-label">Email</label>
<input type="email" class="form-control" id="Email" name="Email" required>
</div>
<div class="mb-3">
<label for="PasswordHash" class="form-label">Password</label>
<input type="password" class="form-control" id="PasswordHash" name="PasswordHash" required>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
<%- include('partials/footer') %>
User Edit View (views/users/edit.ejs):
<%- include('partials/header') %>
<h1>Edit User</h1>
<form action="/users/<%= user.UserId %>" method="POST">
<div class="mb-3">
<label for="Username" class="form-label">Username</label>
<input type="text" class="form-control" id="Username" name="Username" value="<%= user.Username %>" required>
</div>
<div class="mb-3">
<label for="Email" class="form-label">Email</label>
<input type="email" class="form-control" id="Email" name="Email" value="<%= user.Email %>" required>
</div>
<button type="submit" class="btn btn-primary">Update User</button>
</form>
<%- include('partials/footer') %>
Step 7: Set Up the Main Application File
Set up the main application file to include all routes and middleware.
Main Application File (app.js):
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const path = require('path');
const userRoutes = require('./routes/userRoutes');
const sequelize = require('./config');
const app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/users', userRoutes);
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
Step 8: Run the Application
Start the application:
node app.js
Access the application: Open your browser and navigate to http://localhost:3000/users to see the user management interface.
Step 9: Create a Dashboard Page
To create a dashboard page that summarizes the data, follow a similar approach as outlined in the previous dashboard example. Create a new route, controller, and view for the dashboard, and aggregate data from the various models.
Dashboard Route (routes/dashboardRoutes.js):
const express = require('express');
const router = express.Router();
const DashboardController = require('../controllers/DashboardController');
router.get('/', DashboardController.showDashboard);
module.exports = router;
Dashboard Controller (controllers/DashboardController.js):
const UserRepository = require('../repositories/UserRepository');
const ReservationRepository = require('../repositories/ReservationRepository');
const RoomRepository = require('../repositories/RoomRepository');
const InvoiceRepository = require('../repositories/InvoiceRepository');
class DashboardController {
async showDashboard(req, res) {
try {
const totalUsers = await UserRepository.getAllUsers();
const totalReservations = await ReservationRepository.getAllReservations();
const totalRooms = await RoomRepository.getAllRooms();
const totalInvoices = await InvoiceRepository.getAllInvoices();
res.render('dashboard', {
totalUsers: totalUsers.length,
totalReservations: totalReservations.length,
totalRooms: totalRooms.length,
totalInvoices: totalInvoices.length,
});
} catch (error) {
console.error('Error fetching dashboard data:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new DashboardController();
Dashboard View:
<%- include('partials/header') %>
<h1>Dashboard</h1> <div class="row"> <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"><%= totalUsers %></h5> </div> </div> </div> <div class="col-md-3"> <div class="card text-white bg-success mb-3"> <div class="card-header">Total Reservations</div> <div class="card-body"> <h5 class="card-title"><%= totalReservations %></h5> </div> </div> </div> <div class="col-md-3"> <div class="card text-white bg-warning mb-3"> <div class="card-header">Total Rooms</div> <div class="card-body"> <h5 class="card-title"><%= totalRooms %></h5> </div> </div> </div> <div class="col-md-3"> <div class="card text-white bg-danger mb-3"> <div class="card-header">Total Invoices</div> <div class="card-body"> <h5 class="card-title"><%= totalInvoices %></h5> </div> </div> </div> </div> <%- include('partials/footer') %>
You have now created a complete CRUD application for managing users, reservations, rooms, invoices, and more using Node.js, Sequelize, Express, and EJS with Bootstrap 5 templates. The application includes a dashboard that summarizes key data points, and you can expand this structure to include additional models and features as needed.
Further Implementation for Remaining Models
Following are the complete setup for the remaining models (Reservations, Rooms, Invoices, HousekeepingTasks, Guests, Feedback, MenuItems, EventBookings, Promotions) including their Sequelize models, repositories, controllers, routes, and EJS views.
Step 1: Create Remaining Models
Reservation Model (models/Reservation.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Reservation = sequelize.define('Reservation', {
ReservationId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
GuestId: {
type: DataTypes.INTEGER,
allowNull: false,
},
RoomId: {
type: DataTypes.INTEGER,
allowNull: false,
},
CheckInDate: {
type: DataTypes.DATE,
allowNull: false,
},
CheckOutDate: {
type: DataTypes.DATE,
allowNull: false,
},
NumberOfGuests: {
type: DataTypes.INTEGER,
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Reservation;
Room Model (models/Room.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Room = sequelize.define('Room', {
RoomId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoomNumber: {
type: DataTypes.STRING(10),
allowNull: false,
unique: true,
},
RoomType: {
type: DataTypes.STRING(50),
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Room;
Invoice Model (models/Invoice.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Invoice = sequelize.define('Invoice', {
InvoiceId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ReservationId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Amount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
PaymentStatus: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Invoice;
HousekeepingTask Model (models/HousekeepingTask.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const HousekeepingTask = sequelize.define('HousekeepingTask', {
TaskId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
RoomId: {
type: DataTypes.INTEGER,
allowNull: false,
},
TaskDescription: {
type: DataTypes.STRING(256),
allowNull: false,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = HousekeepingTask;
Guest Model (models/Guest.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Guest = sequelize.define('Guest', {
GuestId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
FirstName: {
type: DataTypes.STRING(50),
allowNull: false,
},
LastName: {
type: DataTypes.STRING(50),
allowNull: false,
},
Email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
Phone: {
type: DataTypes.STRING(15),
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = Guest;
Feedback Model (models/Feedback.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Feedback = sequelize.define('Feedback', {
FeedbackId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
GuestId: {
type: DataTypes.INTEGER,
allowNull: false,
},
Rating: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 1,
max: 5,
},
},
Comments: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE defaultValue: DataTypes.NOW,
},
});
module.exports = Feedback;
MenuItem Model (models/MenuItem.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const MenuItem = sequelize.define('MenuItem', {
MenuItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = MenuItem;
EventBooking Model (models/EventBooking.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const EventBooking = sequelize.define('EventBooking', {
EventBookingId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
EventName: {
type: DataTypes.STRING(100),
allowNull: false,
},
BookingDate: {
type: DataTypes.DATE,
allowNull: false,
},
NumberOfGuests: {
type: DataTypes.INTEGER,
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
});
module.exports = EventBooking;
Promotion Model (models/Promotion.js):
const { DataTypes } = require('sequelize');
const sequelize = require('../config');
const Promotion = sequelize.define('Promotion', {
PromotionId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Code: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
},
DiscountAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
ExpirationDate: {
type: DataTypes.DATE,
allowNull: false,
},
IsActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
});
module.exports = Promotion;
Step 2: Create Repositories for Remaining Models
Reservation Repository (repositories/ReservationRepository.js):
const Reservation = require('../models/Reservation');
class ReservationRepository {
async createReservation(reservationData) {
return await Reservation.create(reservationData);
}
async getAllReservations() {
return await Reservation.findAll();
}
async getReservationById(reservationId) {
return await Reservation.findByPk(reservationId);
}
async updateReservation(reservationId, reservationData) {
const reservation = await this.getReservationById(reservationId);
if (reservation) {
return await reservation.update(reservationData);
}
throw new Error('Reservation not found');
}
async deleteReservation(reservationId) {
const reservation = await this.getReservationById(reservationId);
if (reservation) {
return await reservation.destroy();
}
throw new Error('Reservation not found');
}
}
module.exports = new ReservationRepository();
Room Repository (repositories/RoomRepository.js):
const Room = require('../models/Room');
class RoomRepository {
async createRoom(roomData) {
return await Room.create(roomData);
}
async getAllRooms() {
return await Room.findAll();
}
async getRoomById(roomId) {
return await Room.findByPk(roomId);
}
async updateRoom(roomId, roomData) {
const room = await this.getRoomById(roomId);
if (room) {
return await room.update(roomData);
}
throw new Error('Room not found');
}
async deleteRoom(roomId) {
const room = await this.getRoomById(roomId);
if (room) {
return await room.destroy();
}
throw new Error('Room not found');
}
}
module.exports = new RoomRepository();
Invoice Repository (repositories/InvoiceRepository.js):
const Invoice = require('../models/Invoice');
class InvoiceRepository {
async createInvoice(invoiceData) {
return await Invoice.create(invoiceData);
}
async getAllInvoices() {
return await Invoice.findAll();
}
async getInvoiceById(invoiceId) {
return await Invoice.findByPk(invoiceId);
}
async updateInvoice(invoiceId, invoiceData) {
const invoice = await this.getInvoiceById(invoiceId);
if (invoice) {
return await invoice.update(invoiceData);
}
throw new Error('Invoice not found');
}
async deleteInvoice(invoiceId) {
const invoice = await this.getInvoiceById(invoiceId);
if (invoice) {
return await invoice.destroy();
}
throw new Error('Invoice not found');
}
}
module.exports = new InvoiceRepository();
HousekeepingTask Repository (repositories/HousekeepingTaskRepository.js):
const HousekeepingTask = require('../models/HousekeepingTask');
class HousekeepingTaskRepository {
async createTask(taskData) {
return await HousekeepingTask.create(taskData);
}
async getAllTasks() {
return await HousekeepingTask.findAll();
}
async getTaskById(taskId) {
return await HousekeepingTask.findByPk(taskId);
}
async updateTask(taskId, taskData) {
const task = await this.getTaskById(taskId);
if (task) {
return await task.update(taskData);
}
throw new Error('Task not found');
}
async deleteTask(taskId) {
const task = await this.getTaskById(taskId);
if (task) {
return await task.destroy();
}
throw new Error('Task not found');
}
}
module.exports = new HousekeepingTaskRepository();
Guest Repository (repositories/GuestRepository.js):
const Guest = require('../models/Guest');
class GuestRepository {
async createGuest(guestData) {
return await Guest.create(guestData);
}
async getAllGuests() {
return await Guest.findAll();
}
async getGuestById(guestId) {
return await Guest.findByPk(guestId);
}
async updateGuest(guestId, guestData) {
const guest = await this.getGuestById(guestId);
if (guest) {
return await guest.update(guestData);
}
throw new Error('Guest not found');
}
async deleteGuest(guestId) {
const guest = await this.getGuestById(guestId);
if (guest) {
return await guest.destroy();
}
throw new Error('Guest not found');
}
}
module.exports = new GuestRepository();
Feedback Repository (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);
}
throw new Error('Feedback not found');
}
async deleteFeedback(feedbackId) {
const feedback = await this.getFeedbackById(feedbackId);
if (feedback) {
return await feedback.destroy();
}
throw new Error('Feedback not found');
}
}
module.exports = new FeedbackRepository();
MenuItem Repository (repositories/MenuItemRepository.js):
const MenuItem = require('../models/MenuItem');
class MenuItemRepository {
async createMenuItem(menuItemData) {
return await MenuItem.create(menuItemData);
}
async getAllMenuItems() {
return await MenuItem.findAll();
}
async getMenuItemById(menuItemId) {
return await MenuItem.findByPk(menuItemId);
}
async updateMenuItem(menuItemId, menuItemData) {
const menuItem = await this.getMenuItemById(menuItemId);
if (menuItem) {
return await menuItem.update(menuItemData);
}
throw new Error('Menu Item not found');
}
async deleteMenuItem(menuItemId) {
const menuItem = await this.getMenuItemById(menuItemId);
if (menuItem) {
return await menuItem.destroy();
}
throw new Error('Menu Item not found');
}
}
module.exports = new MenuItemRepository();
EventBooking Repository (repositories/EventBookingRepository.js):
const EventBooking = require('../models/EventBooking');
class EventBookingRepository {
async createEventBooking(eventBookingData) {
return await EventBooking.create(eventBookingData);
}
async getAllEventBookings() {
return await EventBooking.findAll();
}
async getEventBookingById(eventBookingId) {
return await EventBooking.findByPk(eventBookingId);
}
async updateEventBooking(eventBookingId, eventBookingData) {
const eventBooking = await this.getEventBookingById(eventBookingId);
if (eventBooking) {
return await eventBooking.update(eventBookingData);
}
throw new Error('Event Booking not found');
}
async deleteEventBooking(eventBookingId) {
const eventBooking = await this.getEventBookingById(eventBookingId);
if (eventBooking) {
return await eventBooking.destroy();
}
throw new Error('Event Booking not found');
}
}
module.exports = new EventBookingRepository();
Promotion Repository (repositories/PromotionRepository.js):
const Promotion = require('../models/Promotion');
class PromotionRepository {
async createPromotion(promotionData) {
return await Promotion.create(promotionData);
}
async getAllPromotions() {
return await Promotion.findAll();
}
async getPromotionById(promotionId) {
return await Promotion.findByPk(promotionId);
}
async updatePromotion(promotionId, promotionData) {
const promotion = await this.getPromotionById(promotionId);
if (promotion) {
return await promotion.update(promotionData);
}
throw new Error('Promotion not found');
}
async deletePromotion(promotionId) {
const promotion = await this.getPromotionById(promotionId);
if (promotion) {
return await promotion.destroy();
}
throw new Error('Promotion not found');
}
}
module.exports = new PromotionRepository();
Step 3: Create Controllers for Remaining Models
Reservation Controller (controllers/ReservationController.js):
const ReservationRepository = require('../repositories/ReservationRepository');
class ReservationController {
async createReservation(req, res) {
try {
const reservation = await ReservationRepository.createReservation(req.body);
res.redirect('/reservations');
} catch (error) {
console.error('Error creating reservation:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllReservations(req, res) {
try {
const reservations = await ReservationRepository.getAllReservations();
res.render('reservations/index', { reservations });
} catch (error) {
console.error('Error fetching reservations:', error);
res.status(500).send('Internal Server Error');
}
}
async getReservation(req, res) {
try {
const reservation = await ReservationRepository.getReservationById(req.params.id);
if (reservation) {
res.render('reservations/edit', { reservation });
} else {
res.status(404).send('Reservation not found');
}
} catch (error) {
console.error('Error fetching reservation:', error);
res.status(500).send('Internal Server Error');
}
}
async updateReservation(req, res) {
try {
await ReservationRepository.updateReservation(req.params.id, req.body);
res.redirect('/reservations');
} catch (error) {
console.error('Error updating reservation:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteReservation(req, res) {
try {
await ReservationRepository.deleteReservation(req.params.id);
res.redirect('/reservations');
} catch (error) {
console.error('Error deleting reservation:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new ReservationController();
Room Controller (controllers/RoomController.js):
const RoomRepository = require('../repositories/RoomRepository');
class RoomController {
async createRoom(req, res) {
try {
const room = await RoomRepository.createRoom(req.body);
res.redirect('/rooms');
} catch (error) {
console.error('Error creating room:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllRooms(req, res) {
try {
const rooms = await RoomRepository.getAllRooms();
res.render('rooms/index', { rooms });
} catch (error) {
console.error('Error fetching rooms:', error);
res.status(500).send('Internal Server Error');
}
}
async getRoom(req, res) {
try {
const room = await RoomRepository.getRoomBy Id(req.params.id);
if (room) {
res.render('rooms/edit', { room });
} else {
res.status(404).send('Room not found');
}
} catch (error) {
console.error('Error fetching room:', error);
res.status(500).send('Internal Server Error');
}
}
async updateRoom(req, res) {
try {
await RoomRepository.updateRoom(req.params.id, req.body);
res.redirect('/rooms');
} catch (error) {
console.error('Error updating room:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteRoom(req, res) {
try {
await RoomRepository.deleteRoom(req.params.id);
res.redirect('/rooms');
} catch (error) {
console.error('Error deleting room:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new RoomController();
Invoice Controller (controllers/InvoiceController.js):
const InvoiceRepository = require('../repositories/InvoiceRepository');
class InvoiceController {
async createInvoice(req, res) {
try {
const invoice = await InvoiceRepository.createInvoice(req.body);
res.redirect('/invoices');
} catch (error) {
console.error('Error creating invoice:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllInvoices(req, res) {
try {
const invoices = await InvoiceRepository.getAllInvoices();
res.render('invoices/index', { invoices });
} catch (error) {
console.error('Error fetching invoices:', error);
res.status(500).send('Internal Server Error');
}
}
async getInvoice(req, res) {
try {
const invoice = await InvoiceRepository.getInvoiceById(req.params.id);
if (invoice) {
res.render('invoices/edit', { invoice });
} else {
res.status(404).send('Invoice not found');
}
} catch (error) {
console.error('Error fetching invoice:', error);
res.status(500).send('Internal Server Error');
}
}
async updateInvoice(req, res) {
try {
await InvoiceRepository.updateInvoice(req.params.id, req.body);
res.redirect('/invoices');
} catch (error) {
console.error('Error updating invoice:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteInvoice(req, res) {
try {
await InvoiceRepository.deleteInvoice(req.params.id);
res.redirect('/invoices');
} catch (error) {
console.error('Error deleting invoice:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new InvoiceController();
HousekeepingTask Controller (controllers/HousekeepingTaskController.js):
const HousekeepingTaskRepository = require('../repositories/HousekeepingTaskRepository');
class HousekeepingTaskController {
async createTask(req, res) {
try {
const task = await HousekeepingTaskRepository.createTask(req.body);
res.redirect('/housekeeping-tasks');
} catch (error) {
console.error('Error creating task:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllTasks(req, res) {
try {
const tasks = await HousekeepingTaskRepository.getAllTasks();
res.render('housekeeping-tasks/index', { tasks });
} catch (error) {
console.error('Error fetching tasks:', error);
res.status(500).send('Internal Server Error');
}
}
async getTask(req, res) {
try {
const task = await HousekeepingTaskRepository.getTaskById(req.params.id);
if (task) {
res.render('housekeeping-tasks/edit', { task });
} else {
res.status(404).send('Task not found');
}
} catch (error) {
console.error('Error fetching task:', error);
res.status(500).send('Internal Server Error');
}
}
async updateTask(req, res) {
try {
await HousekeepingTaskRepository.updateTask(req.params.id, req.body);
res.redirect('/housekeeping-tasks');
} catch (error) {
console.error('Error updating task:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteTask(req, res) {
try {
await HousekeepingTaskRepository.deleteTask(req.params.id);
res.redirect('/housekeeping-tasks');
} catch (error) {
console.error('Error deleting task:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new HousekeepingTaskController();
Guest Controller (controllers/GuestController.js):
const GuestRepository = require('../repositories/GuestRepository');
class GuestController {
async createGuest(req, res) {
try {
const guest = await GuestRepository.createGuest(req.body);
res.redirect('/guests');
} catch (error) {
console.error('Error creating guest:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllGuests(req, res) {
try {
const guests = await GuestRepository.getAllGuests();
res.render('guests/index', { guests });
} catch (error) {
console.error('Error fetching guests:', error);
res.status(500).send('Internal Server Error');
}
}
async getGuest(req, res) {
try {
const guest = await GuestRepository.getGuestById(req.params.id);
if (guest) {
res.render('guests/edit', { guest });
} else {
res.status(404).send('Guest not found');
}
} catch (error) {
console.error('Error fetching guest:', error);
res.status(500).send('Internal Server Error');
}
}
async updateGuest(req, res) {
try {
await GuestRepository.updateGuest(req.params.id, req.body);
res.redirect('/guests');
} catch (error) {
console.error('Error updating guest:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteGuest(req, res) {
try {
await GuestRepository.deleteGuest(req.params.id);
res.redirect('/guests');
} catch (error) {
console.error('Error deleting guest:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new GuestController();
Feedback Controller (controllers/FeedbackController.js):
const FeedbackRepository = require('../repositories/FeedbackRepository');
class FeedbackController {
async createFeedback(req, res) {
try {
const feedback = await FeedbackRepository.createFeedback(req.body);
res.redirect('/feedbacks');
} catch (error) {
console.error('Error creating feedback:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllFeedbacks(req, res) {
try {
const feedbacks = await FeedbackRepository.getAllFeedbacks();
res.render('feedbacks/index', { feedbacks });
} catch (error) {
console.error('Error fetching feedbacks:', error);
res.status(500).send('Internal Server Error');
}
}
async getFeedback(req, res) {
try {
const feedback = await FeedbackRepository.getFeedbackById(req.params.id);
if (feedback) {
res.render('feedbacks/edit', { feedback });
} else {
res.status(404).send('Feedback not found');
}
} catch (error) {
console.error('Error fetching feedback:', error);
res.status(500).send('Internal Server Error');
}
}
async updateFeedback(req, res) {
try {
await FeedbackRepository.updateFeedback(req.params.id, req.body);
res.redirect('/feedbacks');
} catch (error) {
console.error('Error updating feedback:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteFeedback(req, res) {
try {
await FeedbackRepository.deleteFeedback(req.params.id);
res.redirect('/feedbacks');
} catch (error) {
console.error('Error deleting feedback:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new FeedbackController();
MenuItem Controller (controllers/MenuItemController.js):
const MenuItemRepository = require('../repositories/MenuItemRepository');
class MenuItemController {
async createMenuItem(req, res) {
try {
const menuItem = await MenuItemRepository.createMenuItem(req.body);
res.redirect('/menu-items');
} catch (error) {
console.error('Error creating menu item:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllMenuItems(req, res) {
try {
const menuItems = await MenuItemRepository.getAllMenuItems();
res.render('menu-items/index', { menuItems });
} catch (error) {
console.error('Error fetching menu items:', error);
res.status(500).send('Internal Server Error');
}
}
async getMenuItem(req, res) {
try
{
const menuItem = await MenuItemRepository.getMenuItemById(req.params.id);
if (menuItem) {
res.render('menu-items/edit', { menuItem });
} else {
res.status(404).send('Menu Item not found');
}
} catch (error) {
console.error('Error fetching menu item:', error);
res.status(500).send('Internal Server Error');
}
}
async updateMenuItem(req, res) {
try {
await MenuItemRepository.updateMenuItem(req.params.id, req.body);
res.redirect('/menu-items');
} catch (error) {
console.error('Error updating menu item:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteMenuItem(req, res) {
try {
await MenuItemRepository.deleteMenuItem(req.params.id);
res.redirect('/menu-items');
} catch (error) {
console.error('Error deleting menu item:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new MenuItemController();
EventBooking Controller (controllers/EventBookingController.js):
const EventBookingRepository = require('../repositories/EventBookingRepository');
class EventBookingController {
async createEventBooking(req, res) {
try {
const eventBooking = await EventBookingRepository.createEventBooking(req.body);
res.redirect('/event-bookings');
} catch (error) {
console.error('Error creating event booking:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllEventBookings(req, res) {
try {
const eventBookings = await EventBookingRepository.getAllEventBookings();
res.render('event-bookings/index', { eventBookings });
} catch (error) {
console.error('Error fetching event bookings:', error);
res.status(500).send('Internal Server Error');
}
}
async getEventBooking(req, res) {
try {
const eventBooking = await EventBookingRepository.getEventBookingById(req.params.id);
if (eventBooking) {
res.render('event-bookings/edit', { eventBooking });
} else {
res.status(404).send('Event Booking not found');
}
} catch (error) {
console.error('Error fetching event booking:', error);
res.status(500).send('Internal Server Error');
}
}
async updateEventBooking(req, res) {
try {
await EventBookingRepository.updateEventBooking(req.params.id, req.body);
res.redirect('/event-bookings');
} catch (error) {
console.error('Error updating event booking:', error);
res.status(500).send('Internal Server Error');
}
}
async deleteEventBooking(req, res) {
try {
await EventBookingRepository.deleteEventBooking(req.params.id);
res.redirect('/event-bookings');
} catch (error) {
console.error('Error deleting event booking:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new EventBookingController();
Promotion Controller (controllers/PromotionController.js):
const PromotionRepository = require('../repositories/PromotionRepository');
class PromotionController {
async createPromotion(req, res) {
try {
const promotion = await PromotionRepository.createPromotion(req.body);
res.redirect('/promotions');
} catch (error) {
console.error('Error creating promotion:', error);
res.status(500).send('Internal Server Error');
}
}
async getAllPromotions(req, res) {
try {
const promotions = await PromotionRepository.getAllPromotions();
res.render('promotions/index', { promotions });
} catch (error) {
console.error('Error fetching promotions:', error);
res.status(500).send('Internal Server Error');
}
}
async getPromotion(req, res) {
try {
const promotion = await PromotionRepository.getPromotionById(req.params.id);
if (promotion) {
res.render('promotions/edit', { promotion });
} else {
res.status(404).send('Promotion not found');
}
} catch (error) {
console.error('Error fetching promotion:', error);
res.status(500).send('Internal Server Error');
}
}
async updatePromotion(req, res) {
try {
await PromotionRepository.updatePromotion(req.params.id, req.body);
res.redirect('/promotions');
} catch (error) {
console.error('Error updating promotion:', error);
res.status(500).send('Internal Server Error');
}
}
async deletePromotion(req, res) {
try {
await Promotion Repository.deletePromotion(req.params.id);
res.redirect('/promotions');
} catch (error) {
console.error('Error deleting promotion:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new PromotionController();
Step 4: Create Routes for Remaining Models
Reservation Routes (routes/reservationRoutes.js):
const express = require('express');
const router = express.Router();
const ReservationController = require('../controllers/ReservationController');
router.get('/', ReservationController.getAllReservations);
router.get('/create', (req, res) => res.render('reservations/create'));
router.post('/', ReservationController.createReservation);
router.get('/:id', ReservationController.getReservation);
router.post('/:id', ReservationController.updateReservation);
router.delete('/:id', ReservationController.deleteReservation);
module.exports = router;
Room Routes (routes/roomRoutes.js):
const express = require('express');
const router = express.Router();
const RoomController = require('../controllers/RoomController');
router.get('/', RoomController.getAllRooms);
router.get('/create', (req, res) => res.render('rooms/create'));
router.post('/', RoomController.createRoom);
router.get('/:id', RoomController.getRoom);
router.post('/:id', RoomController.updateRoom);
router.delete('/:id', RoomController.deleteRoom);
module.exports = router;
Invoice Routes (routes/invoiceRoutes.js):
const express = require('express');
const router = express.Router();
const InvoiceController = require('../controllers/InvoiceController');
router.get('/', InvoiceController.getAllInvoices);
router.get('/create', (req, res) => res.render('invoices/create'));
router.post('/', InvoiceController.createInvoice);
router.get('/:id', InvoiceController.getInvoice);
router.post('/:id', InvoiceController.updateInvoice);
router.delete('/:id', InvoiceController.deleteInvoice);
module.exports = router;
HousekeepingTask Routes (routes/housekeepingTaskRoutes.js):
const express = require('express');
const router = express.Router();
const HousekeepingTaskController = require('../controllers/HousekeepingTaskController');
router.get('/', HousekeepingTaskController.getAllTasks);
router.get('/create', (req, res) => res.render('housekeeping-tasks/create'));
router.post('/', HousekeepingTaskController.createTask);
router.get('/:id', HousekeepingTaskController.getTask);
router.post('/:id', HousekeepingTaskController.updateTask);
router.delete('/:id', HousekeepingTaskController.deleteTask);
module.exports = router;
Guest Routes (routes/guestRoutes.js):
const express = require('express');
const router = express.Router();
const GuestController = require('../controllers/GuestController');
router.get('/', GuestController.getAllGuests);
router.get('/create', (req, res) => res.render('guests/create'));
router.post('/', GuestController.createGuest);
router.get('/:id', GuestController.getGuest);
router.post('/:id', GuestController.updateGuest);
router.delete('/:id', GuestController.deleteGuest);
module.exports = router;
Feedback Routes (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', FeedbackController.getFeedback);
router.post('/:id', FeedbackController.updateFeedback);
router.delete('/:id', FeedbackController.deleteFeedback);
module.exports = router;
MenuItem Routes (routes/menuItemRoutes.js):
const express = require('express');
const router = express.Router();
const MenuItemController = require('../controllers/MenuItemController');
router.get('/', MenuItemController.getAllMenuItems);
router.get('/create', (req, res) => res.render('menu-items/create'));
router.post('/', MenuItemController.createMenuItem);
router.get('/:id', MenuItemController.getMenuItem);
router.post('/:id', MenuItemController.updateMenuItem);
router.delete('/:id', MenuItemController.deleteMenuItem);
module.exports = router;
EventBooking Routes (routes/eventBookingRoutes.js):
const express = require('express');
const router = express.Router();
const EventBookingController = require('../controllers/EventBookingController');
router.get('/', EventBookingController.getAllEventBookings);
router.get('/create', (req, res) => res.render('event-bookings/create'));
router.post('/', EventBookingController.createEventBooking);
router.get('/:id', EventBookingController.getEventBooking);
router.post('/:id', EventBookingController.updateEventBooking);
router.delete('/:id', EventBookingController.deleteEventBooking);
module.exports = router;
Promotion Routes (routes/promotionRoutes.js):
const express = require('express');
const router = express.Router();
const PromotionController = require('../controllers/PromotionController');
router.get('/', PromotionController.getAllPromotions);
router.get('/create', (req, res) => res.render('promotions/create'));
router.post('/', PromotionController.createPromotion);
router.get('/:id', PromotionController.getPromotion);
router.post('/:id', PromotionController.updatePromotion);
router.delete('/:id', PromotionController.deletePromotion);
module.exports = router;
Step 5: Create EJS Views for Remaining Models
Reservation Views:
Index View (views/reservations/index.ejs):
<%- include('partials/header') %>
<h1>Reservations</h1>
<a href="/reservations/create" class="btn btn-primary">Create Reservation</a>
<table class="table">
<thead>
<tr>
<th>Guest ID</th>
<th>Room ID</th>
<th>Check-In Date</th>
<th>Check-Out Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reservations.forEach(reservation => { %>
<tr>
<td><%= reservation.GuestId %></td>
<td><%= reservation.RoomId %></td>
<td><%= reservation.CheckInDate %></td>
<td><%= reservation.CheckOutDate %></td>
<td><%= reservation.Status %></td>
<td>
<a href="/reservations/<%= reservation.ReservationId %>" class="btn btn-warning">Edit</a>
<form action="/reservations/<%= reservation.ReservationId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/reservations/create.ejs):
<%- include('partials/header') %>
<h1>Create Reservation</h1>
<form action="/reservations" method="POST">
<div class="mb-3">
<label for="GuestId" class="form-label">Guest ID</label>
<input type="number" class="form-control" id="GuestId" name="GuestId" required>
</div>
<div class="mb-3">
<label for="RoomId" class="form-label">Room ID</label>
<input type="number" class="form-control" id="RoomId" name="RoomId" required>
</div>
<div class="mb-3">
<label for="CheckInDate" class="form-label">Check-In Date</label>
<input type="datetime-local" class="form-control" id="CheckInDate" name="CheckInDate" required>
</div>
<div class="mb-3">
<label for="CheckOutDate" class="form-label">Check-Out Date</label>
<input type="datetime-local" class="form-control" id="CheckOutDate" name="CheckOutDate" required>
</div>
<div class="mb-3">
<label for="NumberOfGuests" class="form-label">Number of Guests</label>
<input type="number" class="form-control" id="NumberOfGuests" name="NumberOfGuests" required>
</div>
<button type="submit" class="btn btn-primary">Create Reservation</button>
</form>
<%- include('partials/footer') %>
Edit View (views/reservations/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Reservation</h1>
<form action="/reservations/<%= reservation.ReservationId %>" method="POST">
<div class=" mb-3">
<label for="GuestId" class="form-label">Guest ID</label>
<input type="number" class="form-control" id="GuestId" name="GuestId" value="<%= reservation.GuestId %>" required>
</div>
<div class="mb-3">
<label for="RoomId" class="form-label">Room ID</label>
<input type="number" class="form-control" id="RoomId" name="RoomId" value="<%= reservation.RoomId %>" required>
</div>
<div class="mb-3">
<label for="CheckInDate" class="form-label">Check-In Date</label>
<input type="datetime-local" class="form-control" id="CheckInDate" name="CheckInDate" value="<%= reservation.CheckInDate.toISOString().slice(0, 16) %>" required>
</div>
<div class="mb-3">
<label for="CheckOutDate" class="form-label">Check-Out Date</label>
<input type="datetime-local" class="form-control" id="CheckOutDate" name="CheckOutDate" value="<%= reservation.CheckOutDate.toISOString().slice(0, 16) %>" required>
</div>
<div class="mb-3">
<label for="NumberOfGuests" class="form-label">Number of Guests</label>
<input type="number" class="form-control" id="NumberOfGuests" name="NumberOfGuests" value="<%= reservation.NumberOfGuests %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Reservation</button>
</form>
<%- include('partials/footer') %>
Room Views:
Index View (views/rooms/index.ejs):
<%- include('partials/header') %>
<h1>Rooms</h1>
<a href="/rooms/create" class="btn btn-primary">Create Room</a>
<table class="table">
<thead>
<tr>
<th>Room Number</th>
<th>Room Type</th>
<th>Price</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% rooms.forEach(room => { %>
<tr>
<td><%= room.RoomNumber %></td>
<td><%= room.RoomType %></td>
<td><%= room.Price %></td>
<td><%= room.Status %></td>
<td>
<a href="/rooms/<%= room.RoomId %>" class="btn btn-warning">Edit</a>
<form action="/rooms/<%= room.RoomId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/rooms/create.ejs):
<%- include('partials/header') %>
<h1>Create Room</h1>
<form action="/rooms" method="POST">
<div class="mb-3">
<label for="RoomNumber" class="form-label">Room Number</label>
<input type="text" class="form-control" id="RoomNumber" name="RoomNumber" required>
</div>
<div class="mb-3">
<label for="RoomType" class="form-label">Room Type</label>
<input type="text" class="form-control" id="RoomType" name="RoomType" required>
</div>
<div class="mb-3">
<label for="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" 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 Room</button>
</form>
<%- include('partials/footer') %>
Edit View (views/rooms/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Room</h1>
<form action="/rooms/<%= room.RoomId %>" method="POST">
<div class="mb-3">
<label for="RoomNumber" class="form-label">Room Number</label>
<input type="text" class="form-control" id="RoomNumber" name="RoomNumber" value="<%= room.RoomNumber %>" required>
</div>
<div class="mb-3">
<label for="RoomType" class="form-label">Room Type</label>
<input type="text" class="form-control" id="RoomType" name="RoomType" value="<%= room.RoomType %>" required>
</div>
<div class="mb-3">
<label for="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" value="<%= room.Price %>" 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="<%= room.Status %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Room</button>
</form>
<%- include('partials/footer') %>
Invoice Views:
Index View (views/invoices/index.ejs):
<%- include('partials/header') %>
<h1>Invoices</h1>
<a href="/invoices/create" class="btn btn-primary">Create Invoice</a>
<table class="table">
<thead>
<tr>
<th>Reservation ID</th>
<th>Amount</th>
<th>Payment Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% invoices.forEach(invoice => { %>
<tr>
<td><%= invoice.ReservationId %></td>
<td><%= invoice.Amount %></td>
<td><%= invoice.PaymentStatus %></td>
<td>
<a href="/invoices/<%= invoice.InvoiceId %>" class="btn btn-warning">Edit</a>
<form action="/invoices/<%= invoice.InvoiceId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/invoices/create.ejs):
<%- include('partials/header') %>
<h1>Create Invoice</h1>
<form action="/invoices" method="POST">
<div class="mb-3">
<label for="ReservationId" class="form-label">Reservation ID</label>
<input type="number" class="form-control" id="ReservationId" name="ReservationId" required>
</div>
<div class="mb-3">
<label for="Amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="Amount" name="Amount" required>
</div>
<div class="mb-3">
<label for="PaymentStatus" class="form-label">Payment Status</label>
<input type="text" class="form-control" id="PaymentStatus" name="PaymentStatus" required>
</div>
<button type="submit" class="btn btn-primary">Create Invoice</button>
</form>
<%- include('partials/footer') %>
Edit View (views/invoices/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Invoice</h1>
<form action="/invoices/<%= invoice.InvoiceId %>" method="POST">
<div class="mb-3">
<label for="ReservationId" class="form-label">Reservation ID</label>
<input type="number" class="form-control" id="ReservationId" name="ReservationId" value="<%= invoice.ReservationId %>" required>
</div>
<div class="mb-3">
<label for="Amount" class="form-label">Amount</label>
<input type="number" class="form-control" id="Amount" name="Amount" value="<%= invoice.Amount %>" required>
</div>
<div class="mb-3">
<label for="Payment Status" class="form-label">Payment Status</label>
<input type="text" class="form-control" id="PaymentStatus" name="PaymentStatus" value="<%= invoice.PaymentStatus %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Invoice</button>
</form>
<%- include('partials/footer') %>
HousekeepingTask Views:
Index View (views/housekeeping-tasks/index.ejs):
<%- include('partials/header') %>
<h1>Housekeeping Tasks</h1>
<a href="/housekeeping-tasks/create" class="btn btn-primary">Create Task</a>
<table class="table">
<thead>
<tr>
<th>Room ID</th>
<th>Task Description</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% tasks.forEach(task => { %>
<tr>
<td><%= task.RoomId %></td>
<td><%= task.TaskDescription %></td>
<td><%= task.Status %></td>
<td>
<a href="/housekeeping-tasks/<%= task.TaskId %>" class="btn btn-warning">Edit</a>
<form action="/housekeeping-tasks/<%= task.TaskId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/housekeeping-tasks/create.ejs):
<%- include('partials/header') %>
<h1>Create Housekeeping Task</h1>
<form action="/housekeeping-tasks" method="POST">
<div class="mb-3">
<label for="RoomId" class="form-label">Room ID</label>
<input type="number" class="form-control" id="RoomId" name="RoomId" required>
</div>
<div class="mb-3">
<label for="TaskDescription" class="form-label">Task Description</label>
<input type="text" class="form-control" id="TaskDescription" name="TaskDescription" 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 Task</button>
</form>
<%- include('partials/footer') %>
Edit View (views/housekeeping-tasks/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Housekeeping Task</h1>
<form action="/housekeeping-tasks/<%= task.TaskId %>" method="POST">
<div class="mb-3">
<label for="RoomId" class="form-label">Room ID</label>
<input type="number" class="form-control" id="RoomId" name="RoomId" value="<%= task.RoomId %>" required>
</div>
<div class="mb-3">
<label for="TaskDescription" class="form-label">Task Description</label>
<input type="text" class="form-control" id="TaskDescription" name="TaskDescription" value="<%= task.TaskDescription %>" 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="<%= task.Status %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Task</button>
</form>
<%- include('partials/footer') %>
Guest Views:
Index View (views/guests/index.ejs):
<%- include('partials/header') %>
<h1>Guests</h1>
<a href="/guests/create" class="btn btn-primary">Create Guest</a>
<table class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Phone</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% guests.forEach(guest => { %>
<tr>
<td><%= guest.FirstName %></td>
<td><%= guest.LastName %></td>
<td><%= guest.Email %></td>
<td><%= guest.Phone %></td>
<td>
<a href="/guests/<%= guest.GuestId %>" class="btn btn-warning">Edit</a>
<form action="/guests/<%= guest.GuestId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/guests/create.ejs):
<%- include('partials/header') %>
<h1>Create Guest</h1>
<form action="/guests" method="POST">
<div class="mb-3">
<label for="FirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="FirstName" name="FirstName" required>
</div>
<div class="mb-3">
<label for="LastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="LastName" name="LastName" required>
</div>
<div class="mb-3">
<label for="Email" class="form-label">Email</label>
<input type="email" class="form-control" id="Email" name="Email" required>
</div>
<div class="mb-3">
<label for="Phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="Phone" name="Phone">
</div>
<button type="submit" class="btn btn-primary">Create Guest</button>
</form>
<%- include('partials/footer') %>
Edit View (views/guests/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Guest</h1>
<form action="/guests/<%= guest.GuestId %>" method="POST">
<div class="mb-3">
<label for="FirstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="FirstName" name="FirstName" value="<%= guest.FirstName %>" required>
</div>
<div class="mb-3">
<label for="LastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="LastName" name="LastName" value="<%= guest.LastName %>" 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="<%= guest.Email %>" required>
</div>
<div class="mb-3">
<label for="Phone" class="form-label">Phone</label>
<input type="text" class="form-control" id="Phone" name="Phone" value="<%= guest.Phone %>">
</div>
<button type="submit" class="btn btn-primary">Update Guest</button>
</form>
<%- include('partials/footer') %>
Feedback Views:
Index View (views/feedbacks/index.ejs):
<%- include('partials/header') %>
<h1>Feedbacks</h1>
<a href="/feedbacks/create" class="btn btn-primary">Create Feedback</a>
<table class="table">
<thead>
<tr>
<th>Guest ID</th>
<th>Rating</th>
<th>Comments</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% feedbacks.forEach(feedback => { %>
<tr>
<td><%= feedback.GuestId %></td>
<td><%= feedback.Rating %></td>
<td><%= feedback.Comments %></td <td>
<a href="/feedbacks/<%= feedback.FeedbackId %>" class="btn btn-warning">Edit</a>
<form action="/feedbacks/<%= feedback.FeedbackId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/feedbacks/create.ejs):
<%- include('partials/header') %>
<h1>Create Feedback</h1>
<form action="/feedbacks" method="POST">
<div class="mb-3">
<label for="GuestId" class="form-label">Guest ID</label>
<input type="number" class="form-control" id="GuestId" name="GuestId" required>
</div>
<div class="mb-3">
<label for="Rating" class="form-label">Rating</label>
<input type="number" class="form-control" id="Rating" name="Rating" min="1" max="5" required>
</div>
<div class="mb-3">
<label for="Comments" class="form-label">Comments</label>
<textarea class="form-control" id="Comments" name="Comments"></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Feedback</button>
</form>
<%- include('partials/footer') %>
Edit View (views/feedbacks/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Feedback</h1>
<form action="/feedbacks/<%= feedback.FeedbackId %>" method="POST">
<div class="mb-3">
<label for="GuestId" class="form-label">Guest ID</label>
<input type="number" class="form-control" id="GuestId" name="GuestId" value="<%= feedback.GuestId %>" required>
</div>
<div class="mb-3">
<label for="Rating" class="form-label">Rating</label>
<input type="number" class="form-control" id="Rating" name="Rating" value="<%= feedback.Rating %>" min="1" max="5" required>
</div>
<div class="mb-3">
<label for="Comments" class="form-label">Comments</label>
<textarea class="form-control" id="Comments" name="Comments"><%= feedback.Comments %></textarea>
</div>
<button type="submit" class="btn btn-primary">Update Feedback</button>
</form>
<%- include('partials/footer') %>
MenuItem Views:
Index View (views/menu-items/index.ejs):
<%- include('partials/header') %>
<h1>Menu Items</h1>
<a href="/menu-items/create" class="btn btn-primary">Create Menu Item</a>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% menuItems.forEach(menuItem => { %>
<tr>
<td><%= menuItem.Name %></td>
<td><%= menuItem.Description %></td>
<td><%= menuItem.Price %></td>
<td>
<a href="/menu-items/<%= menuItem.MenuItemId %>" class="btn btn-warning">Edit</a>
<form action="/menu-items/<%= menuItem.MenuItemId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/menu-items/create.ejs):
<%- include('partials/header') %>
<h1>Create Menu Item</h1>
<form action="/menu-items" method="POST">
<div class="mb-3">
<label for="Name" class="form-label">Name</label>
<input type="text" class="form-control" id="Name" name="Name" 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="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" required>
</div>
<button type="submit" class="btn btn-primary">Create Menu Item</button>
</form>
<%- include('partials/footer') %>
Edit View (views/menu-items/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Menu Item</h1>
<form action="/menu-items/<%= menuItem.MenuItemId %>" method="POST">
<div class="mb-3">
<label for="Name" class="form-label">Name</label>
<input type="text" class="form-control" id="Name" name="Name" value="<%= menuItem.Name %>" required>
</div>
<div class="mb-3">
<label for="Description" class="form-label">Description</label>
<textarea class="form-control" id="Description" name="Description"><%= menuItem.Description %></textarea>
</div>
<div class="mb-3">
<label for="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" value="<%= menuItem.Price %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Menu Item</button>
</form>
<%- include('partials/footer') %>
EventBooking Views:
Index View (views/event-bookings/index.ejs):
<%- include('partials/header') %>
<h1>Event Bookings</h1>
<a href="/event-bookings/create" class="btn btn-primary">Create Event Booking</a>
<table class="table">
<thead>
<tr>
<th>Event Name</th>
<th>Booking Date</th>
<th>Number of Guests</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% eventBookings.forEach(eventBooking => { %>
<tr>
<td><%= eventBooking.EventName %></td>
<td><%= eventBooking.BookingDate %></td>
<td><%= eventBooking.NumberOfGuests %></td>
<td>
<a href="/event-bookings/<%= eventBooking.EventBookingId %>" class="btn btn-warning">Edit</a>
<form action="/event-bookings/<%= eventBooking.EventBookingId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/event-bookings/create.ejs):
<%- include('partials/header') %>
<h1>Create Event Booking</h1>
<form action="/event-bookings" method="POST">
<div class="mb-3">
<label for="EventName" class="form-label">Event Name</label>
<input type="text" class="form-control" id="EventName" name="EventName" required>
</div>
<div class="mb-3">
<label for="BookingDate" class="form-label">Booking Date</label>
<input type="datetime-local" class="form-control" id="BookingDate" name="BookingDate" required>
</div>
<div class="mb-3">
<label for="NumberOfGuests" class="form-label">Number of Guests</label>
<input type="number" class="form-control" id="NumberOfGuests" name="NumberOfGuests" required>
</div>
<button type="submit" class="btn btn-primary">Create Event Booking</button>
</form>
<%- include('partials/footer') %>
Edit View (views/event-bookings/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Event Booking</h1>
<form action="/event-bookings/<%= eventBooking.EventBookingId %>" method="POST">
<div class="mb-3">
<label for="EventName" class="form-label">Event Name</label>
<input type="text" class="form-control" id="EventName" name="EventName" value="<%= eventBooking.EventName %>" required>
</div>
<div class="mb-3">
<label for="BookingDate" class="form-label">Booking Date</label>
<input type="datetime-local" class="form-control" id="BookingDate" name="BookingDate" value="<%= eventBooking.BookingDate.toISOString().slice(0, 16) %>" required>
</div>
<div class="mb-3">
<label for="NumberOfGuests" class="form-label">Number of Guests</label>
<input type="number" class="form-control" id="NumberOfGuests" name="NumberOfGuests" value="<%= eventBooking.NumberOfGuests %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Event Booking</button>
</form>
<%- include('partials/footer') %>
Promotion Views:
Index View (views/promotions/index.ejs):
<%- include('partials/header') %>
<h1>Promotions</h1>
<a href="/promotions/create" class="btn btn-primary">Create Promotion</a>
<table class="table">
<thead>
<tr>
<th>Code</th>
<th>Discount Amount</th>
<th>Expiration Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% promotions.forEach(promotion => { %>
<tr>
<td><%= promotion.Code %></td>
<td><%= promotion.DiscountAmount %></td>
<td><%= promotion.ExpirationDate %></td>
<td><%= promotion.IsActive ? 'Active' : 'Inactive' %></td>
<td>
<a href="/promotions/<%= promotion.PromotionId %>" class="btn btn-warning">Edit</a>
<form action="/promotions/<%= promotion.PromotionId %>?_method=DELETE" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<%- include('partials/footer') %>
Create View (views/promotions/create.ejs):
<%- include('partials/header') %>
<h1>Create Promotion</h1>
<form action="/promotions" method="POST">
<div class="mb-3">
<label for="Code" class="form-label">Code</label>
<input type="text" class="form-control" id="Code" name="Code" required>
</div>
<div class="mb-3">
<label for="DiscountAmount" class="form-label">Discount Amount</label>
<input type="number" class="form-control" id="DiscountAmount" name="DiscountAmount" required>
</div>
<div class="mb-3">
<label for="ExpirationDate" class="form-label">Expiration Date</label>
<input type="date" class="form-control" id="ExpirationDate" name="ExpirationDate" required>
</div>
<div class="mb-3">
<label for="IsActive" class="form-label">Is Active</label>
<select class="form-control" id="IsActive" name="IsActive">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Create Promotion</button>
</form>
<%- include('partials/footer') %>
Edit View (views/promotions/edit.ejs):
<%- include('partials/header') %>
<h1>Edit Promotion</h1>
<form action="/promotions/<%= promotion.PromotionId %>" method="POST">
<div class="mb-3">
<label for="Code" class="form-label">Code</label>
<input type="text" class="form-control" id="Code" name="Code " value="<%= promotion.Code %>" required>
</div>
<div class="mb-3">
<label for="DiscountAmount" class="form-label">Discount Amount</label>
<input type="number" class="form-control" id="DiscountAmount" name="DiscountAmount" value="<%= promotion.DiscountAmount %>" required>
</div>
<div class="mb-3">
<label for="ExpirationDate" class="form-label">Expiration Date</label>
<input type="date" class="form-control" id="ExpirationDate" name="ExpirationDate" value="<%= promotion.ExpirationDate.toISOString().slice(0, 10) %>" required>
</div>
<div class="mb-3">
<label for="IsActive" class="form-label">Is Active</label>
<select class="form-control" id="IsActive" name="IsActive">
<option value="1" <%= promotion.IsActive ? 'selected' : '' %>>Yes</option>
<option value="0" <%= !promotion.IsActive ? 'selected' : '' %>>No</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Update Promotion</button>
</form>
<%- include('partials/footer') %>
Step 6: Update Main Application File
Update the main application file to include all the new routes.
Main Application File (app.js):
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const path = require('path');
const userRoutes = require('./routes/userRoutes');
const reservationRoutes = require('./routes/reservationRoutes');
const roomRoutes = require('./routes/roomRoutes');
const invoiceRoutes = require('./routes/invoiceRoutes');
const housekeepingTaskRoutes = require('./routes/housekeepingTaskRoutes');
const guestRoutes = require('./routes/guestRoutes');
const feedbackRoutes = require('./routes/feedbackRoutes');
const menuItemRoutes = require('./routes/menuItemRoutes');
const eventBookingRoutes = require('./routes/eventBookingRoutes');
const promotionRoutes = require('./routes/promotionRoutes');
const sequelize = require('./config');
const app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/users', userRoutes);
app.use('/reservations', reservationRoutes);
app.use('/rooms', roomRoutes);
app.use('/invoices', invoiceRoutes);
app.use('/housekeeping-tasks', housekeepingTaskRoutes);
app.use('/guests', guestRoutes);
app.use('/feedbacks', feedbackRoutes);
app.use('/menu-items', menuItemRoutes);
app.use('/event-bookings', eventBookingRoutes);
app.use('/promotions', promotionRoutes);
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
You now have a complete CRUD application for managing users, reservations, rooms, invoices, housekeeping tasks, guests, feedback, menu items, event bookings, and promotions using Node.js, Sequelize, Express, and EJS with Bootstrap 5 templates. Each model has its own set of routes, controllers, views, and repositories, allowing for a modular and maintainable code structure. You can further enhance this application by adding authentication, validation, and other features as needed.
Creating a Dashboard Page
To create a dashboard page that consolidates data related to the hotel management project, we will follow these steps:
Step 1: Create a Dashboard Route
Create a new file for the dashboard routes (routes/dashboardRoutes.js):
const express = require('express');
const router = express.Router();
const DashboardController = require('../controllers/DashboardController');
router.get('/', DashboardController.showDashboard);
module.exports = router;
Step 2: Create a Dashboard Controller
Create a new file for the dashboard controller (controllers/DashboardController.js):
const UserRepository = require('../repositories/UserRepository');
const ReservationRepository = require('../repositories/ReservationRepository');
const RoomRepository = require('../repositories/RoomRepository');
const InvoiceRepository = require('../repositories/InvoiceRepository');
const GuestRepository = require('../repositories/GuestRepository');
class DashboardController {
async showDashboard(req, res) {
try {
const totalUsers = await UserRepository.getAllUsers();
const totalReservations = await ReservationRepository.getAllReservations();
const totalRooms = await RoomRepository.getAllRooms();
const totalInvoices = await InvoiceRepository.getAllInvoices();
const totalGuests = await GuestRepository.getAllGuests();
res.render('dashboard', {
totalUsers: totalUsers.length,
totalReservations: totalReservations.length,
totalRooms: totalRooms.length,
totalInvoices: totalInvoices.length,
totalGuests: totalGuests.length,
});
} catch (error) {
console.error('Error fetching dashboard data:', error);
res.status(500).send('Internal Server Error');
}
}
}
module.exports = new DashboardController();
Step 3: Create a Dashboard View
Create a new view file for the dashboard (views/dashboard.ejs):
<%- include('partials/header') %>
<h1>Dashboard</h1>
<div class="row">
<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"><%= totalUsers %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Reservations</div>
<div class="card-body">
<h5 class="card-title"><%= totalReservations %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Total Rooms</div>
<div class="card-body">
<h5 class="card-title"><%= totalRooms %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-danger mb-3">
<div class="card-header">Total Invoices</div>
<div class="card-body">
<h5 class="card-title"><%= totalInvoices %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-header">Total Guests</div>
<div class="card-body">
<h5 class="card-title"><%= totalGuests %></h5>
</div>
</div>
</div>
</div>
<%- include('partials/footer') %>
Step 4: Update the Main Application File
Update your main application file (app.js) to include the dashboard route:
const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const path = require('path');
const userRoutes = require('./routes/userRoutes');
const reservationRoutes = require('./routes/reservationRoutes');
const roomRoutes = require('./routes/roomRoutes');
const invoiceRoutes = require('./routes/invoiceRoutes');
const housekeepingTaskRoutes = require('./routes/housekeepingTaskRoutes');
const guestRoutes = require('./routes/guestRoutes');
const feedbackRoutes = require('./routes/feedbackRoutes');
const menuItemRoutes = require('./routes/menuItemRoutes');
const eventBookingRoutes = require('./routes/eventBookingRoutes');
const promotionRoutes = require('./routes/promotionRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes');
const sequelize = require('./config');
const app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/users', userRoutes);
app.use('/reservations', reservationRoutes);
app.use('/rooms', roomRoutes);
app.use('/invoices', invoiceRoutes);
app.use('/housekeeping-tasks', housekeepingTaskRoutes);
app.use('/guests', guestRoutes);
app.use('/feedbacks', feedbackRoutes);
app.use('/menu-items', menuItemRoutes);
app.use('/event-bookings', eventBookingRoutes);
app.use('/promotions', promotionRoutes);
app.use('/dashboard', dashboardRoutes);
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => console.log(`Server is running on http://localhost:${PORT}`);
});
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
You have now created a dashboard page that consolidates data related to the hotel management project. The dashboard displays the total number of users, reservations, rooms, invoices, and guests. The implementation includes a dedicated route, controller, and view for the dashboard, allowing for easy access and management of consolidated data. You can further enhance the dashboard by adding charts, graphs, or additional metrics as needed.