Project Introduction

The E-commerce System is a comprehensive web application designed to facilitate online shopping and product management. Built using Node.js, this platform allows users to browse products, manage their shopping carts, place orders, and leave reviews. The system supports multiple user roles, including customer, admin, and vendor, ensuring a tailored experience for each user type. The underlying MySQL database schema is structured to manage users, products, categories, orders, reviews, promotions, and wishlists, providing a robust foundation for a seamless e-commerce experience.

Project Objectives

  • To develop a user-friendly interface for customers to browse and purchase products.
  • To implement a secure user authentication system with role-based access control.
  • To allow vendors to manage their products, including adding, updating, and removing listings.
  • To facilitate the management of shopping carts and order processing.
  • To provide a review system for customers to rate and comment on products.
  • To implement promotional codes and discounts to enhance customer engagement.
  • To enable customers to create wishlists for future purchases.
  • 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 based on their designated roles.

  2. Product Management Module:

    This module allows vendors to add, update, and manage product listings, including details such as name, description, price, and stock levels.

  3. Category Management Module:

    This module manages product categories, enabling better organization and searchability of products.

  4. Shopping Cart Module:

    This module allows users to add products to their shopping cart, manage quantities, and proceed to checkout.

  5. Order Management Module:

    This module tracks orders placed by users, including order status and total amounts.

  6. Order Item Management Module:

    This module manages individual items within an order, including quantities and prices.

  7. Review Management Module:

    This module allows customers to leave reviews and ratings for products they have purchased.

  8. Promotion Management Module:

    This module manages promotional codes and discounts, including their validity periods.

  9. Wishlist Module:

    This module allows users to create and manage wishlists for products they are interested in purchasing later.

Step 1: Set Up the Project

 
mkdir ecommerce-app
cd ecommerce-app
npm init -y
npm install express sequelize mysql2 ejs body-parser

Step 2: Configure Sequelize

Create a config folder and a database.js file to configure Sequelize.

 
// config/database.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 models folder and define the models based on the provided schema.

User Model: models/User.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
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,
},
}, {
timestamps: true,
createdAt: 'CreatedAt',
});
module.exports = User;

Role Model: models/Role.js


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

Product Model: models/Product.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Product = sequelize.define('Product', {
ProductId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Stock: {
type: DataTypes.INTEGER,
allowNull: false,
},
CategoryId: {
type: DataTypes.INTEGER,
},
}, {
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Product;

Category Model: models/Category.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Category = sequelize.define('Category', {
CategoryId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
}, {
timestamps: false,
});
module.exports = Category;

CartItem Model: models/CartItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const CartItem = sequelize.define('CartItem', {
CartItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
timestamps: true,
createdAt: 'CreatedAt',
});
module.exports = CartItem;

Order Model: models/Order.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Order = sequelize.define('Order', {
OrderId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
OrderDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
ShippingAddressId: {
type: DataTypes.INTEGER,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
timestamps: false,
});
module.exports = Order;

OrderItem Model: models/OrderItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const OrderItem = sequelize.define('OrderItem', {
OrderItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
OrderId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
}, {
timestamps: false,
});
module.exports = OrderItem;

Review Model: models/Review.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Review = sequelize.define('Review', {
ReviewId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ProductId: {
type: DataTypes.INTEGER,
},
UserId: {
type: DataTypes.INTEGER,
},
Rating: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 1,
max: 5,
},
},
Comment: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = Review;

Wishlist Model: models/Wishlist.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Wishlist = sequelize.define('Wishlist', {
WishlistId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = Wishlist;

WishlistItem Model: models/WishlistItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const WishlistItem = sequelize.define('WishlistItem', {
WishlistItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
WishlistId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
}, {
timestamps: false,
});
module.exports = WishlistItem;

Coupon Model: models/Coupon.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Coupon = sequelize.define('Coupon', {
CouponId: {
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,
},
}, {
timestamps: false,
});
module.exports = Coupon;

ShippingAddress Model: models/ShippingAddress.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const ShippingAddress = sequelize.define('ShippingAddress', {
ShippingAddressId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
AddressLine1: {
type: DataTypes.STRING(256),
allowNull: false,
},
AddressLine2: {
type: DataTypes.STRING(256),
},
City: {
type: DataTypes.STRING(100),
allowNull: false,
},
State: {
type: DataTypes.STRING(100),
allowNull: false,
},
ZipCode: {
type: DataTypes.STRING(20),
allowNull: false,
},
Country: {
type: DataTypes.STRING(100),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = ShippingAddress;

Step 4: Create Repositories

Create a repositories folder and implement repository patterns for data access. For example, for the User repository:


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

Step 5: Create Controllers

Create a controllers folder and implement controllers to handle business logic. For example, for the User controller:


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 ById(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 6: Set Up Routes

Create a routes folder and define routes for the application. For example, for the 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 ById);
router.post('/:id', UserController.updateUser );
router.delete('/:id', UserController.deleteUser );
module.exports = router;

Step 7: Create Views

Create a views folder and use EJS to create views for the application with Bootstrap 5 for styling. For example, for the user index view:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Users</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/5.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1>Users</h1>
<a href="/users/create" class="btn btn-primary">Create User</a>
<table class="table">
<thead>
<tr>
<th>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 %>" class="btn btn-warning">Edit</a>
<form action="/users/<%= user.UserId %>" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

Step 8: Implement CRUD Operations

Repeat the above steps for other entities (Roles, Products, Categories, etc.) by creating their respective models, repositories, controllers, routes, and views. Ensure to follow the same structure for consistency.

With this setup, you now have a complete CRUD application for managing Users, Roles, Products, Categories, and other entities in your Node.js application using Sequelize, Express, EJS, and Bootstrap 5.

Following are the complete implementation for the remaining models : Roles, Products, Categories, CartItems, Orders, OrderItems, Reviews, Wishlists, WishlistItems, Coupons, and ShippingAddresses. Each model will include the following:

Model Definition

Repository

Controller

Routes

Views

1. Roles

Model: models/Role.js


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

Repository: repositories/RoleRepository.js


const Role = require('../models/Role');
class RoleRepository {
async create(roleData) {
return await Role.create(roleData);
}
async findAll() {
return await Role.findAll();
}
async findById(id) {
return await Role.findByPk(id);
}
async update(id, roleData) {
const role = await this.findById(id);
if (role) {
return await role.update(roleData);
}
return null;
}
async delete(id) {
const role = await this.findById(id);
if (role) {
return await role.destroy();
}
return null;
}
}
module.exports = new RoleRepository();

Controller: controllers/RoleController.js


const RoleRepository = require('../repositories/RoleRepository');
class RoleController {
async create(req, res) {
await RoleRepository.create(req.body);
res.redirect('/roles');
}
async findAll(req, res) {
const roles = await RoleRepository.findAll();
res.render('roles/index', { roles });
}
async findById(req, res) {
const role = await RoleRepository.findById(req.params.id);
res.render('roles/edit', { role });
}
async update(req, res) {
await RoleRepository.update(req.params.id, req.body);
res.redirect('/roles');
}
async delete(req, res) {
await RoleRepository.delete(req.params.id);
res.redirect('/roles');
}
}
module.exports = new RoleController();

Routes: routes/roleRoutes.js


const express = require('express');
const router = express.Router();
const RoleController = require('../controllers/RoleController');
router.get('/', RoleController.findAll);
router.get('/create', (req, res) => res.render('roles/create'));
router.post('/', RoleController.create);
router.get('/:id/edit', RoleController.findById);
router.post('/:id', RoleController.update);
router.post('/:id/delete', RoleController.delete);
module.exports = router;

Views

views/roles/index.ejs:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Roles</title>
</head>
<body>
<div class="container">
<h1>Roles</h1>
<a href="/roles/create" class="btn btn-primary">Create Role</a>
<table class="table">
<thead>
<tr>
<th>RoleId</th>
<th>RoleName</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% roles.forEach(role => { %>
<tr>
<td><%= role.RoleId %></td>
<td><%= role.RoleName %></td>
<td>
<a href="/roles/<%= role.RoleId %>/edit" class="btn btn-warning">Edit</a>
<form action="/roles/<%= role.RoleId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/roles/create.ejs:


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Create Role</title>
</head>
<body>
<div class="container">
<h1>Create Role</h1>
<form action="/roles" method="POST">
<div class="mb-3">
<label for="RoleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="RoleName" name="RoleName" required>
</div>
<button type="submit" class="btn btn-primary">Create Role</button>
</form>
</div>
</body>
</html>

views/roles/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 Role</title>
</head>
<body>
<div class="container">
<h1>Edit Role</h1>
<form action="/roles/<%= role.RoleId %>" method="POST">
<div class="mb-3">
<label for="RoleName" class="form-label">Role Name</label>
<input type="text" class="form-control" id="RoleName" name="RoleName" value="<%= role.RoleName %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Role</button>
</form>
</div>
</body>
</html>

2. Products

Model: models/Product.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Product = sequelize .define('Product', {
ProductId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
},
Description: {
type: DataTypes.TEXT,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
Stock: {
type: DataTypes.INTEGER,
allowNull: false,
},
CategoryId: {
type: DataTypes.INTEGER,
},
}, {
timestamps: true,
createdAt: 'CreatedAt',
updatedAt: 'UpdatedAt',
});
module.exports = Product;

Repository: repositories/ProductRepository.js


const Product = require('../models/Product');
class ProductRepository {
async create(productData) {
return await Product.create(productData);
}
async findAll() {
return await Product.findAll();
}
async findById(id) {
return await Product.findByPk(id);
}
async update(id, productData) {
const product = await this.findById(id);
if (product) {
return await product.update(productData);
}
return null;
}
async delete(id) {
const product = await this.findById(id);
if (product) {
return await product.destroy();
}
return null;
}
}
module.exports = new ProductRepository();

Controller: controllers/ProductController.js


const ProductRepository = require('../repositories/ProductRepository');
class ProductController {
async create(req, res) {
await ProductRepository.create(req.body);
res.redirect('/products');
}
async findAll(req, res) {
const products = await ProductRepository.findAll();
res.render('products/index', { products });
}
async findById(req, res) {
const product = await ProductRepository.findById(req.params.id);
res.render('products/edit', { product });
}
async update(req, res) {
await ProductRepository.update(req.params.id, req.body);
res.redirect('/products');
}
async delete(req, res) {
await ProductRepository.delete(req.params.id);
res.redirect('/products');
}
}
module.exports = new ProductController();

Routes: routes/productRoutes.js


const express = require('express');
const router = express.Router();
const ProductController = require('../controllers/ProductController');
router.get('/', ProductController.findAll);
router.get('/create', (req, res) => res.render('products/create'));
router.post('/', ProductController.create);
router.get('/:id/edit', ProductController.findById);
router.post('/:id', ProductController.update);
router.post('/:id/delete', ProductController.delete);
module.exports = router;

Views

views/products/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>Products</title>
</head>
<body>
<div class="container">
<h1>Products</h1>
<a href="/products/create" class="btn btn-primary">Create Product</a>
<table class="table">
<thead>
<tr>
<th>ProductId</th>
<th>Name</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% products.forEach(product => { %>
<tr>
<td><%= product.ProductId %></td>
<td><%= product.Name %></td>
<td><%= product.Price %></td>
<td>
<a href="/products/<%= product.ProductId %>/edit" class="btn btn-warning">Edit</a>
<form action="/products/<%= product.ProductId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/products/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 Product</title>
</head>
<body>
<div class="container">
<h1>Create Product</h1>
<form action="/products" method="POST">
<div class="mb-3">
<label for="Name" class="form-label">Product 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" required></textarea>
</div>
<div class="mb-3">
<label for="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" step="0.01" required>
</div>
<div class="mb-3">
<label for="Stock" class="form-label">Stock</label>
<input type="number" class="form-control" id="Stock" name="Stock" required>
</div>
<div class="mb-3">
<label for="CategoryId" class="form-label">Category ID</label>
<input type="number" class="form-control" id="CategoryId" name="CategoryId">
</div>
<button type="submit" class="btn btn-primary">Create Product</button>
</form>
</div>
</body>
</html>

views/products/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 Product</title>
</head>
<body>
<div class="container">
<h1>Edit Product</h1>
<form action="/products/<%= product.ProductId %>" method="POST">
<div class="mb-3">
<label for="Name" class="form-label">Product Name</label>
<input type="text" class="form-control" id="Name" name="Name" value="<%= product.Name %>" required>
</div>
<div class="mb-3">
<label for="Description" class="form-label">Description</label>
<textarea class="form-control" id="Description" name="Description" required><%= product.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="<%= product.Price %>" step="0.01" required>
</div>
<div class="mb-3">
<label for="Stock" class="form-label">Stock</label>
<input type="number" class="form-control" id="Stock" name="Stock" value="<%= product.Stock %>" required>
</div>
<div class="mb-3">
<label for="CategoryId" class="form-label">Category ID</label>
<input type="number" class="form-control" id="CategoryId" name="CategoryId" value="<%= product.CategoryId %>">
</div>
<button type="submit" class="btn btn-primary">Update Product</button>
</form>
</div>
</body>
</html>

3. Categories

Model: models/Category.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Category = sequelize.define('Category', {
CategoryId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
Name: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
}, {
timestamps: false,
});
module.exports = Category;

Repository: repositories/CategoryRepository.js


const Category = require('../models/Category');
class CategoryRepository {
async create(categoryData) {
return await Category.create(categoryData);
}
async findAll() {
return await Category.findAll();
}
async findById(id) {
return await Category.findByPk(id);
}
async update(id, categoryData) {
const category = await this.findById(id);
if (category) {
return await category.update(categoryData);
}
return null;
}
async delete(id) {
const category = await this.findById(id);
if (category) {
return await category.destroy();
}
return null;
}
}
module.exports = new CategoryRepository();

Controller: controllers/CategoryController.js


const CategoryRepository = require('../repositories/CategoryRepository');
class CategoryController {
async create(req, res) {
await CategoryRepository.create(req.body);
res.redirect('/categories');
}
async findAll(req, res) {
const categories = await CategoryRepository.findAll();
res.render('categories/index', { categories });
}
async findById(req, res) {
const category = await CategoryRepository.findById(req.params.id);
res.render('categories/edit', { category });
}
async update(req, res) {
await CategoryRepository.update(req.params.id, req.body);
res.redirect('/categories');
}
async delete(req, res) {
await CategoryRepository.delete(req.params.id);
res.redirect('/categories');
}
}
module.exports = new CategoryController();

Routes: routes/categoryRoutes.js


const express = require('express');
const router = express.Router();
const CategoryController = require('../controllers/CategoryController');
router.get('/', CategoryController.findAll);
router.get('/create', (req, res) => res.render('categories/create'));
router.post('/', CategoryController.create);
router.get('/:id/edit', CategoryController.findById);
router.post('/:id', CategoryController.update);
router.post('/:id/delete', CategoryController.delete);
module.exports = router;

Views

views/categories/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>Categories</title>
</head>
<body>
<div class="container">
<h1>Categories</h1>
<a href="/categories/create" class="btn btn-primary">Create Category</a>
<table class="table">
<thead>
<tr>
<th>CategoryId</th>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% categories.forEach(category => { %>
<tr>
<td><%= category.CategoryId %></td>
<td><%= category.Name %></td>
<td>
<a href="/categories/<%= category.CategoryId %>/edit" class="btn btn-warning">Edit</a>
<form action="/categories/<%= category.CategoryId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/categories/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 Category</title>
</head>
<body>
<div class="container">
<h1>Create Category</h1>
<form action="/categories" method="POST">
<div class="mb-3">
<label for="Name" class="form-label">Category Name</label>
<input type="text" class="form-control" id="Name" name="Name" required>
</div>
<button type="submit" class="btn btn-primary">Create Category</button>
</form>
</div>
</body>
</html>

views/categories/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 Category</title>
</head>
<body>
<div class="container">
<h1>Edit Category</h1>
<form action="/categories/<%= category.CategoryId %>" method="POST">
<div class="mb-3">
<label for=" Name" class="form-label">Category Name</label>
<input type="text" class="form-control" id="Name" name="Name" value="<%= category.Name %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Category</button>
</form>
</div>
</body>
</html>

4. CartItems

Model: models/CartItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const CartItem = sequelize.define('CartItem', {
CartItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
timestamps: true,
createdAt: 'CreatedAt',
});
module.exports = CartItem;

Repository: repositories/CartItemRepository.js


const CartItem = require('../models/CartItem');
class CartItemRepository {
async create(cartItemData) {
return await CartItem.create(cartItemData);
}
async findAll() {
return await CartItem.findAll();
}
async findById(id) {
return await CartItem.findByPk(id);
}
async update(id, cartItemData) {
const cartItem = await this.findById(id);
if (cartItem) {
return await cartItem.update(cartItemData);
}
return null;
}
async delete(id) {
const cartItem = await this.findById(id);
if (cartItem) {
return await cartItem.destroy();
}
return null;
}
}
module.exports = new CartItemRepository();

Controller: controllers/CartItemController.js


const CartItemRepository = require('../repositories/CartItemRepository');
class CartItemController {
async create(req, res) {
await CartItemRepository.create(req.body);
res.redirect('/cart-items');
}
async findAll(req, res) {
const cartItems = await CartItemRepository.findAll();
res.render('cart-items/index', { cartItems });
}
async findById(req, res) {
const cartItem = await CartItemRepository.findById(req.params.id);
res.render('cart-items/edit', { cartItem });
}
async update(req, res) {
await CartItemRepository.update(req.params.id, req.body);
res.redirect('/cart-items');
}
async delete(req, res) {
await CartItemRepository.delete(req.params.id);
res.redirect('/cart-items');
}
}
module.exports = new CartItemController();

Routes: routes/cartItemRoutes.js


const express = require('express');
const router = express.Router();
const CartItemController = require('../controllers/CartItemController');
router.get('/', CartItemController.findAll);
router.get('/create', (req, res) => res.render('cart-items/create'));
router.post('/', CartItemController.create);
router.get('/:id/edit', CartItemController.findById);
router.post('/:id', CartItemController.update);
router.post('/:id/delete', CartItemController.delete);
module.exports = router;

Views

views/cart-items/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>Cart Items</title>
</head>
<body>
<div class="container">
<h1>Cart Items</h1>
<a href="/cart-items/create" class="btn btn-primary">Add Cart Item</a>
<table class="table">
<thead>
<tr>
<th>CartItemId</th>
<th>UserId</th>
<th>ProductId</th>
<th>Quantity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% cartItems.forEach(cartItem => { %>
<tr>
<td><%= cartItem.CartItemId %></td>
<td><%= cartItem.UserId %></td>
<td><%= cartItem.ProductId %></td>
<td><%= cartItem.Quantity %></td>
<td>
<a href="/cart-items/<%= cartItem.CartItemId %>/edit" class ="btn btn-warning">Edit</a>
<form action="/cart-items/<%= cartItem.CartItemId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/cart-items/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>Add Cart Item</title>
</head>
<body>
<div class="container">
<h1>Add Cart Item</h1>
<form action="/cart-items" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" 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>
<button type="submit" class="btn btn-primary">Add Cart Item</button>
</form>
</div>
</body>
</html>

views/cart-items/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 Cart Item</title>
</head>
<body>
<div class="container">
<h1>Edit Cart Item</h1>
<form action="/cart-items/<%= cartItem.CartItemId %>" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" value="<%= cartItem.UserId %>" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" value="<%= cartItem.ProductId %>" 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="<%= cartItem.Quantity %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Cart Item</button>
</form>
</div>
</body>
</html>

5. Orders

Model: models/Order.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Order = sequelize.define('Order', {
OrderId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
OrderDate: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
TotalAmount: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
ShippingAddressId: {
type: DataTypes.INTEGER,
},
Status: {
type: DataTypes.STRING(50),
allowNull: false,
},
}, {
timestamps: false,
});
module.exports = Order;

Repository: repositories/OrderRepository.js


const Order = require('../models/Order');
class OrderRepository {
async create(orderData) {
return await Order.create(orderData);
}
async findAll() {
return await Order.findAll();
}
async findById(id) {
return await Order.findBy Pk(id);
}
async update(id, orderData) {
const order = await this.findById(id);
if (order) {
return await order.update(orderData);
}
return null;
}
async delete(id) {
const order = await this.findById(id);
if (order) {
return await order.destroy();
}
return null;
}
}
module.exports = new OrderRepository();

Controller: controllers/OrderController.js


const OrderRepository = require('../repositories/OrderRepository');
class OrderController {
async create(req, res) {
await OrderRepository.create(req.body);
res.redirect('/orders');
}
async findAll(req, res) {
const orders = await OrderRepository.findAll();
res.render('orders/index', { orders });
}
async findById(req, res) {
const order = await OrderRepository.findById(req.params.id);
res.render('orders/edit', { order });
}
async update(req, res) {
await OrderRepository.update(req.params.id, req.body);
res.redirect('/orders');
}
async delete(req, res) {
await OrderRepository.delete(req.params.id);
res.redirect('/orders');
}
}
module.exports = new OrderController();

Routes: routes/orderRoutes.js


const express = require('express');
const router = express.Router();
const OrderController = require('../controllers/OrderController');
router.get('/', OrderController.findAll);
router.get('/create', (req, res) => res.render('orders/create'));
router.post('/', OrderController.create);
router.get('/:id/edit', OrderController.findById);
router.post('/:id', OrderController.update);
router.post('/:id/delete', OrderController.delete);
module.exports = router;

Views

views/orders/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>Orders</title>
</head>
<body>
<div class="container">
<h1>Orders</h1>
<a href="/orders/create" class="btn btn-primary">Create Order</a>
<table class="table">
<thead>
<tr>
<th>OrderId</th>
<th>UserId</th>
<th>TotalAmount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% orders.forEach(order => { %>
<tr>
<td><%= order.OrderId %></td>
<td><%= order.UserId %></td>
<td><%= order.TotalAmount %></td>
<td><%= order.Status %></td>
<td>
<a href="/orders/<%= order.OrderId %>/edit" class="btn btn-warning">Edit</a>
<form action="/orders/<%= order.OrderId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/orders/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 Order</title>
</head>
<body>
<div class="container">
<h1>Create Order</h1>
<form action="/orders" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<div class="mb-3">
<label for="TotalAmount" class="form-label">Total Amount</label>
<input type="number" class="form-control" id="TotalAmount" name="TotalAmount" step="0.01" required>
</div>
<div class="mb-3">
<label for="ShippingAddressId" class="form-label">Shipping Address ID</label>
<input type="number" class=" form-control" id="ShippingAddressId" name="ShippingAddressId" 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 Order</button>
</form>
</div>
</body>
</html>

views/orders/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 Order</title>
</head>
<body>
<div class="container">
<h1>Edit Order</h1>
<form action="/orders/<%= order.OrderId %>" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" value="<%= order.UserId %>" required>
</div>
<div class="mb-3">
<label for="TotalAmount" class="form-label">Total Amount</label>
<input type="number" class="form-control" id="TotalAmount" name="TotalAmount" value="<%= order.TotalAmount %>" step="0.01" required>
</div>
<div class="mb-3">
<label for="ShippingAddressId" class="form-label">Shipping Address ID</label>
<input type="number" class="form-control" id="ShippingAddressId" name="ShippingAddressId" value="<%= order.ShippingAddressId %>" 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="<%= order.Status %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Order</button>
</form>
</div>
</body>
</html>

6. OrderItems

Model: models/OrderItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const OrderItem = sequelize.define('OrderItem', {
OrderItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
OrderId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
Quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
Price: {
type: DataTypes.DECIMAL(18, 2),
allowNull: false,
},
}, {
timestamps: false,
});
module.exports = OrderItem;

Repository: repositories/OrderItemRepository.js


const OrderItem = require('../models/OrderItem');
class OrderItemRepository {
async create(orderItemData) {
return await OrderItem.create(orderItemData);
}
async findAll() {
return await OrderItem.findAll();
}
async findById(id) {
return await OrderItem.findByPk(id);
}
async update(id, orderItemData) {
const orderItem = await this.findById(id);
if (orderItem) {
return await orderItem.update(orderItemData);
}
return null;
}
async delete(id) {
const orderItem = await this.findById(id);
if (orderItem) {
return await orderItem.destroy();
}
return null;
}
}
module.exports = new OrderItemRepository();

Controller: controllers/OrderItemController.js


const OrderItemRepository = require('../repositories/OrderItemRepository');
class OrderItemController {
async create(req, res) {
await OrderItemRepository.create(req.body);
res.redirect('/order-items');
}
async findAll(req, res) {
const orderItems = await OrderItemRepository.findAll();
res.render('order-items/index', { orderItems });
}
async findById(req, res) {
const orderItem = await OrderItemRepository.findById(req.params.id);
res.render('order-items/edit', { orderItem });
}
async update(req, res) {
await OrderItemRepository.update(req .params.id, req.body);
res.redirect('/order-items');
}
async delete(req, res) {
await OrderItemRepository.delete(req.params.id);
res.redirect('/order-items');
}
}
module.exports = new OrderItemController();

Routes: routes/orderItemRoutes.js


const express = require('express');
const router = express.Router();
const OrderItemController = require('../controllers/OrderItemController');
router.get('/', OrderItemController.findAll);
router.get('/create', (req, res) => res.render('order-items/create'));
router.post('/', OrderItemController.create);
router.get('/:id/edit', OrderItemController.findById);
router.post('/:id', OrderItemController.update);
router.post('/:id/delete', OrderItemController.delete);
module.exports = router;

Views

views/order-items/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>Order Items</title>
</head>
<body>
<div class="container">
<h1>Order Items</h1>
<a href="/order-items/create" class="btn btn-primary">Add Order Item</a>
<table class="table">
<thead>
<tr>
<th>OrderItemId</th>
<th>OrderId</th>
<th>ProductId</th>
<th>Quantity</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% orderItems.forEach(orderItem => { %>
<tr>
<td><%= orderItem.OrderItemId %></td>
<td><%= orderItem.OrderId %></td>
<td><%= orderItem.ProductId %></td>
<td><%= orderItem.Quantity %></td>
<td><%= orderItem.Price %></td>
<td>
<a href="/order-items/<%= orderItem.OrderItemId %>/edit" class="btn btn-warning">Edit</a>
<form action="/order-items/<%= orderItem.OrderItemId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/order-items/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>Add Order Item</title>
</head>
<body>
<div class="container">
<h1>Add Order Item</h1>
<form action="/order-items" method="POST">
<div class="mb-3">
<label for="OrderId" class="form-label">Order ID</label>
<input type="number" class="form-control" id="OrderId" name="OrderId" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" 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="Price" class="form-label">Price</label>
<input type="number" class="form-control" id="Price" name="Price" step="0.01" required>
</div>
<button type="submit" class="btn btn-primary">Add Order Item</button>
</form>
</div>
</body>
</html>

views/order-items/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 Order Item</title>
</head>
<body>
<div class="container">
<h1>Edit Order Item</h1>
<form action="/order-items/<%= orderItem.OrderItemId %>" method="POST">
<div class="mb-3">
<label for="OrderId" class="form-label">Order ID</label>
<input type="number" class="form-control" id="OrderId" name="OrderId" value="<%= orderItem.OrderId %>" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" value="<%= orderItem.ProductId %>" 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="<%= orderItem.Quantity %>" 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="<%= orderItem.Price %>" step="0.01" required>
</div>
<button type="submit" class="btn btn-primary">Update Order Item</button>
</form>
</div>
</body>
</html>

7. Reviews

Model: models/Review.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Review = sequelize.define('Review', {
ReviewId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
ProductId: {
type: DataTypes.INTEGER,
},
UserId: {
type: DataTypes.INTEGER,
},
Rating: {
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 1,
max: 5,
},
},
Comment: {
type: DataTypes.TEXT,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = Review;

Repository: repositories/ReviewRepository.js


const Review = require('../models/Review');
class ReviewRepository {
async create(reviewData) {
return await Review.create(reviewData);
}
async findAll() {
return await Review.findAll();
}
async findById(id) {
return await Review.findByPk(id);
}
async update(id, reviewData) {
const review = await this.findById(id);
if (review) {
return await review.update(reviewData);
}
return null;
}
async delete(id) {
const review = await this.findById(id);
if (review) {
return await review.destroy();
}
return null;
}
}
module.exports = new ReviewRepository();

Controller: controllers/ReviewController.js


const ReviewRepository = require('../repositories/ReviewRepository');
class ReviewController {
async create(req, res) {
await ReviewRepository.create(req.body);
res.redirect('/reviews');
}
async findAll(req, res) {
const reviews = await ReviewRepository.findAll();
res.render('reviews/index', { reviews });
}
async findById(req, res) {
const review = await ReviewRepository.findById(req.params.id);
res.render('reviews/edit', { review });
}
async update(req, res) {
await ReviewRepository.update(req.params.id, req.body);
res.redirect('/reviews');
}
async delete(req, res) {
await ReviewRepository.delete(req.params.id);
res.redirect('/reviews');
}
}
module.exports = new ReviewController();

Routes: routes/reviewRoutes.js


const express = require('express');
const router = express.Router();
const ReviewController = require('../controllers/ReviewController');
router.get('/', ReviewController.findAll);
router.get('/create', (req, res) => res.render('reviews/create'));
router.post('/', ReviewController.create);
router.get('/:id/edit', ReviewController.findById);
router.post('/:id', ReviewController.update);
router.post('/:id/delete', ReviewController.delete);
module.exports = router;

Views

views/reviews/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>Reviews</title>
</head>
<body>
<div class="container">
<h1>Reviews</h1>
<a href="/reviews/create" class="btn btn-primary">Add Review</a>
<table class="table">
<thead>
<tr>
<th>ReviewId</th>
<th>ProductId</th>
<th>UserId</th>
<th>Rating</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% reviews.forEach(review => { %>
<tr>
<td><%= review.ReviewId %></td>
<td><%= review.ProductId %></td>
<td><%= review.UserId %></td>
<td><%= review.Rating %></td>
<td>
<a href="/reviews/<%= review.ReviewId %>/edit" class="btn btn-warning">Edit</a>
<form action="/reviews/<%= review.ReviewId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/reviews/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>Add Review</title>
</head>
<body>
<div class="container">
<h1>Add Review</h1>
<form action="/reviews" method="POST">
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" required>
</div>
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<div class="mb-3">
<label for="Rating" class="form-label">Rating (1-5)</label>
<input type="number" class="form-control" id="Rating" name="Rating" min="1" max="5" required>
</div>
<div class="mb-3">
<label for="Comment" class="form-label">Comment</label>
<textarea class="form-control" id="Comment" name="Comment"></textarea>
</div>
<button type="submit" class="btn btn-primary">Add Review</button>
</form>
</div>
</body>
</html>

views/reviews/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 Review</title>
</head>
<body>
<div class="container">
<h1>Edit Review</h1>
<form action="/reviews/<%= review.ReviewId %>" method="POST">
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" value="<%= review.ProductId %>" required>
</div>
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" value="<%= review.UserId %>" required>
</div>
<div class="mb-3">
<label for="Rating" class="form-label">Rating (1-5)</label>
<input type="number" class="form-control" id="Rating" name=" Rating" value="<%= review.Rating %>" min="1" max="5" required>
</div>
<div class="mb-3">
<label for="Comment" class="form-label">Comment</label>
<textarea class="form-control" id="Comment" name="Comment"><%= review.Comment %></textarea>
</div>
<button type="submit" class="btn btn-primary">Update Review</button>
</form>
</div>
</body>
</html>

8. Wishlists

Model: models/Wishlist.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Wishlist = sequelize.define('Wishlist', {
WishlistId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = Wishlist;

Repository: repositories/WishlistRepository.js


const Wishlist = require('../models/Wishlist');
class WishlistRepository {
async create(wishlistData) {
return await Wishlist.create(wishlistData);
}
async findAll() {
return await Wishlist.findAll();
}
async findById(id) {
return await Wishlist.findByPk(id);
}
async update(id, wishlistData) {
const wishlist = await this.findById(id);
if (wishlist) {
return await wishlist.update(wishlistData);
}
return null;
}
async delete(id) {
const wishlist = await this.findById(id);
if (wishlist) {
return await wishlist.destroy();
}
return null;
}
}
module.exports = new WishlistRepository();

Controller: controllers/WishlistController.js


const WishlistRepository = require('../repositories/WishlistRepository');
class WishlistController {
async create(req, res) {
await WishlistRepository.create(req.body);
res.redirect('/wishlists');
}
async findAll(req, res) {
const wishlists = await WishlistRepository.findAll();
res.render('wishlists/index', { wishlists });
}
async findById(req, res) {
const wishlist = await WishlistRepository.findById(req.params.id);
res.render('wishlists/edit', { wishlist });
}
async update(req, res) {
await WishlistRepository.update(req.params.id, req.body);
res.redirect('/wishlists');
}
async delete(req, res) {
await WishlistRepository.delete(req.params.id);
res.redirect('/wishlists');
}
}
module.exports = new WishlistController();

Routes: routes/wishlistRoutes.js


const express = require('express');
const router = express.Router();
const WishlistController = require('../controllers/WishlistController');
router.get('/', WishlistController.findAll);
router.get('/create', (req, res) => res.render('wishlists/create'));
router.post('/', WishlistController.create);
router.get('/:id/edit', WishlistController.findById);
router.post('/:id', WishlistController.update);
router.post('/:id/delete', WishlistController.delete);
module.exports = router;

Views

views/wishlists/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>Wishlists</title>
</head>
<body>
<div class="container">
<h1>Wishlists</h1>
<a href="/wishlists/create" class="btn btn-primary">Create Wishlist</a>
<table class="table">
<thead>
<tr>
<th>WishlistId</th>
<th>UserId</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% wishlists.forEach(wishlist => { %>
<tr>
<td><%= wishlist.WishlistId %></td>
<td><%= wishlist.UserId %></td>
<td>
<a href="/wishlists/<%= wishlist.WishlistId %>/edit" class="btn btn-warning">Edit</a>
<form action="/wishlists/<%= wishlist.WishlistId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/wishlists/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 Wishlist</title>
</head>
<body>
<div class="container">
<h1>Create Wishlist</h1>
<form action="/wishlists" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<button type="submit" class="btn btn-primary">Create Wishlist</button>
</form>
</div>
</body>
</html>

views/wishlists/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 Wishlist</title>
</head>
<body>
<div class="container">
<h1>Edit Wishlist</h1>
<form action="/wishlists/<%= wishlist.WishlistId %>" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" value="<%= wishlist.UserId %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Wishlist</button>
</form>
</div>
</body>
</html>

9. WishlistItems

Model: models/WishlistItem.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const WishlistItem = sequelize.define('WishlistItem', {
WishlistItemId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
WishlistId: {
type: DataTypes.INTEGER,
},
ProductId: {
type: DataTypes.INTEGER,
},
}, {
timestamps: false,
});
module.exports = WishlistItem;

Repository: repositories/WishlistItemRepository.js


const WishlistItem = require('../models/WishlistItem');
class WishlistItemRepository {
async create(wishlistItemData) {
return await WishlistItem.create(wishlistItemData);
}
async findAll() {
return await WishlistItem.findAll();
}
async findById(id) {
return await WishlistItem.findByPk(id);
}
async update(id, wishlistItemData) {
const wishlistItem = await this.findById(id);
if (wishlistItem) {
return await wishlistItem.update(wishlistItemData);
}
return null;
}
async delete(id) {
const wishlistItem = await this.findById(id);
if (wishlistItem) {
return await wishlistItem.destroy();
}
return null;
}
}
module.exports = new WishlistItemRepository();

Controller: controllers/WishlistItemController.js


const WishlistItemRepository = require('../repositories/WishlistItemRepository');
class WishlistItemController {
async create(req, res) {
await WishlistItemRepository.create(req.body);
res.redirect('/wishlist-items');
}
async findAll(req, res) {
const wishlistItems = await WishlistItemRepository.findAll();
res.render('wishlist-items/index', { wishlistItems });
}
async findById(req, res) {
const wishlistItem = await WishlistItemRepository.findById(req.params.id);
res.render('wishlist-items/edit', { wishlistItem });
}
async update(req, res) {
await WishlistItemRepository.update(req.params.id, req.body);
res.redirect('/wishlist-items');
}
async delete(req, res) {
await WishlistItemRepository.delete(req.params.id);
res.redirect('/wishlist-items');
}
}
module.exports = new WishlistItemController();

Routes: routes/wishlistItemRoutes.js


const express = require('express');
const router = express.Router();
const WishlistItemController = require('../controllers/WishlistItemController');
router.get('/', WishlistItemController.findAll);
router.get('/create', (req, res)=> res.render('wishlist-items/create'));
router.post('/', WishlistItemController.create);
router.get('/:id/edit', WishlistItemController.findById);
router.post('/:id', WishlistItemController.update);
router.post('/:id/delete', WishlistItemController.delete);
module.exports = router;

Views

views/wishlist-items/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>Wishlist Items</title>
</head>
<body>
<div class="container">
<h1>Wishlist Items</h1>
<a href="/wishlist-items/create" class="btn btn-primary">Add Wishlist Item</a>
<table class="table">
<thead>
<tr>
<th>WishlistItemId</th>
<th>WishlistId</th>
<th>ProductId</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% wishlistItems.forEach(wishlistItem => { %>
<tr>
<td><%= wishlistItem.WishlistItemId %></td>
<td><%= wishlistItem.WishlistId %></td>
<td><%= wishlistItem.ProductId %></td>
<td>
<a href="/wishlist-items/<%= wishlistItem.WishlistItemId %>/edit" class="btn btn-warning">Edit</a>
<form action="/wishlist-items/<%= wishlistItem.WishlistItemId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/wishlist-items/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>Add Wishlist Item</title>
</head>
<body>
<div class="container">
<h1>Add Wishlist Item</h1>
<form action="/wishlist-items" method="POST">
<div class="mb-3">
<label for="WishlistId" class="form-label">Wishlist ID</label>
<input type="number" class="form-control" id="WishlistId" name="WishlistId" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" required>
</div>
<button type="submit" class="btn btn-primary">Add Wishlist Item</button>
</form>
</div>
</body>
</html>

views/wishlist-items/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 Wishlist Item</title>
</head>
<body>
<div class="container">
<h1>Edit Wishlist Item</h1>
<form action="/wishlist-items/<%= wishlistItem.WishlistItemId %>" method="POST">
<div class="mb-3">
<label for="WishlistId" class="form-label">Wishlist ID</label>
<input type="number" class="form-control" id="WishlistId" name="WishlistId" value="<%= wishlistItem.WishlistId %>" required>
</div>
<div class="mb-3">
<label for="ProductId" class="form-label">Product ID</label>
<input type="number" class="form-control" id="ProductId" name="ProductId" value="<%= wishlistItem.ProductId %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Wishlist Item</button>
</form>
</div>
</body>
</html>

10. Coupons

Model: models/Coupon.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Coupon = sequelize.define('Coupon', {
CouponId: {
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,
},
}, {
timestamps: false,
});
module.exports = Coupon;

Repository: repositories/CouponRepository.js


const Coupon = require('../models/Coupon');
class CouponRepository {
async create(couponData) {
return await Coupon.create(couponData);
}
async findAll() {
return await Coupon.findAll();
}
async findById(id) {
return await Coupon.findByPk(id);
}
async update(id, couponData) {
const coupon = await this.findById(id);
if (coupon) {
return await coupon.update(couponData);
}
return null;
}
async delete(id) {
const coupon = await this.findById(id);
if (coupon) {
return await coupon.destroy();
}
return null;
}
}
module.exports = new CouponRepository();

Controller: controllers/CouponController.js


const CouponRepository = require('../repositories/CouponRepository');
class CouponController {
async create(req, res) {
await CouponRepository.create(req.body);
res.redirect('/coupons');
}
async findAll(req, res) {
const coupons = await CouponRepository.findAll();
res.render('coupons/index', { coupons });
}
async findById(req, res) {
const coupon = await CouponRepository.findById(req.params.id);
res.render('coupons/edit', { coupon });
}
async update(req, res) {
await CouponRepository.update(req.params.id, req.body);
res.redirect('/coupons');
}
async delete(req, res) {
await CouponRepository.delete(req.params.id);
res.redirect('/coupons');
}
}
module.exports = new CouponController();

Routes: routes/couponRoutes.js


const express = require('express');
const router = express.Router();
const CouponController = require('../controllers/CouponController');
router.get('/', CouponController.findAll);
router.get('/create', (req, res) => res.render('coupons/create'));
router.post('/', CouponController.create);
router.get('/:id/edit', CouponController.findById);
router.post('/:id', CouponController.update);
router.post('/:id/delete', CouponController.delete);
module.exports = router;

Views

views/coupons/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>Coupons</title>
</head>
<body>
<div class="container">
<h1>Coupons</h1>
<a href="/coupons/create" class="btn btn-primary">Create Coupon</a>
<table class="table">
<thead>
<tr>
<th>CouponId</th>
<th>Code</th>
<th>DiscountAmount</th>
<th>ExpirationDate</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% coupons.forEach(coupon => { %>
<tr>
<td><%= coupon.CouponId %></td>
<td><%= coupon.Code %></td>
<td><%= coupon.DiscountAmount %></td>
<td><%= coupon.ExpirationDate.toLocaleDateString() %></td>
<td>
<a href="/coupons/<%= coupon.CouponId %>/edit" class="btn btn-warning">Edit</a>
<form action="/coupons/<%= coupon.CouponId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/coupons/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 Coupon</title> </head> <body> <div class="container"> <h1>Create Coupon</h1> <form action="/coupons" method="POST"> <div class="mb-3"> <label for="Code" class="form-label">Coupon 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" step="0.01" 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> <button type="submit" class="btn btn-primary">Create Coupon</button> </form> </div> </body> </html>

views/coupons/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 Coupon</title>
</head>
<body>
<div class="container">
<h1>Edit Coupon</h1>
<form action="/coupons/<%= coupon.CouponId %>" method="POST">
<div class="mb-3">
<label for="Code" class="form-label">Coupon Code</label>
<input type="text" class="form-control" id="Code" name="Code" value="<%= coupon.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="<%= coupon.DiscountAmount %>" step="0.01" 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="<%= coupon.ExpirationDate.toISOString().split('T')[0] %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Coupon</button>
</form>
</div>
</body>
</html>

11. ShippingAddresses

Model: models/ShippingAddress.js


const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const ShippingAddress = sequelize.define('ShippingAddress', {
ShippingAddressId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
UserId: {
type: DataTypes.INTEGER,
},
AddressLine1: {
type: DataTypes.STRING(256),
allowNull: false,
},
AddressLine2: {
type: DataTypes.STRING(256),
},
City: {
type: DataTypes.STRING(100),
allowNull: false,
},
State: {
type: DataTypes.STRING(100),
allowNull: false,
},
ZipCode: {
type: DataTypes.STRING(20),
allowNull: false,
},
Country: {
type: DataTypes.STRING(100),
allowNull: false,
},
CreatedAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
}, {
timestamps: false,
});
module.exports = ShippingAddress;

Repository: repositories/ShippingAddressRepository.js


const ShippingAddress = require('../models/ShippingAddress');
class ShippingAddressRepository {
async create(shippingAddressData) {
return await ShippingAddress.create(shippingAddressData);
}
async findAll() {
return await ShippingAddress.findAll();
}
async findById(id) {
return await ShippingAddress.findByPk(id);
}
async update(id, shippingAddressData) {
const shippingAddress = await this.findById(id);
if (shippingAddress) {
return await shippingAddress.update(shippingAddressData);
}
return null;
}
async delete(id) {
const shippingAddress = await this.findById(id);
if (shippingAddress) {
return await shippingAddress.destroy();
}
return null;
}
}
module.exports = new ShippingAddressRepository();

Controller: controllers/ShippingAddressController.js


const ShippingAddressRepository = require('../repositories/ShippingAddressRepository');
class ShippingAddressController {
async create(req, res) {
await ShippingAddressRepository.create(req.body);
res.redirect('/shipping-addresses');
}
async findAll(req, res) {
const shippingAddresses = await ShippingAddressRepository.findAll();
res.render('shipping-addresses/index', { shippingAddresses });
}
async findById(req, res) {
const shippingAddress = await ShippingAddressRepository.findById(req.params.id);
res.render('shipping-addresses/edit', { shippingAddress });
}
async update(req, res) {
await ShippingAddressRepository.update(req.params.id, req.body);
res.redirect('/shipping-addresses');
}
async delete(req, res) {
await ShippingAddressRepository.delete(req.params.id);
res.redirect('/shipping-addresses');
}
}
module.exports = new ShippingAddressController();

Routes: routes/shippingAddressRoutes.js


const express = require('express');
const router = express.Router();
const ShippingAddressController = require('../controllers/ShippingAddressController');
router.get('/', ShippingAddressController.findAll);
router.get('/create', (req, res) => res.render('shipping-addresses/create'));
router.post('/', ShippingAddressController.create);
router.get('/:id/edit', ShippingAddressController.findById);
router.post('/:id', ShippingAddressController.update);
router.post('/:id/delete', ShippingAddressController.delete);
module.exports = router;

Views

views/shipping-addresses/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>Shipping Addresses</title>
</head>
<body>
<div class="container">
<h1>Shipping Addresses</h1>
<a href="/shipping-addresses/create" class="btn btn-primary">Create Shipping Address</a>
<table class="table">
<thead>
<tr>
<th>ShippingAddressId</th>
<th>UserId</th>
<th>City</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% shippingAddresses.forEach(address => { %>
<tr>
<td><%= address.ShippingAddressId %></td>
<td><%= address.UserId %></td>
<td><%= address.City %></td>
<td>
<a href="/shipping-addresses/<%= address.ShippingAddressId %>/edit" class="btn btn-warning">Edit</a>
<form action="/shipping-addresses/<%= address.ShippingAddressId %>/delete" method="POST" style="display:inline;">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</body>
</html>

views/shipping-addresses/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 Shipping Address</title>
</head>
<body>
<div class="container">
<h1>Create Shipping Address</h1>
<form action="/shipping-addresses" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" required>
</div>
<div class="mb-3">
<label for="AddressLine1" class="form-label">Address Line 1</label>
<input type="text" class="form-control" id="AddressLine1" name="AddressLine1" required>
</div>
<div class="mb-3">
<label for="AddressLine2" class="form-label">Address Line 2</label>
<input type="text" class="form-control" id="AddressLine2" name="AddressLine2">
</div>
<div class="mb-3">
<label for="City" class="form-label">City</label>
<input type="text" class="form-control" id="City" name="City" required>
</div>
<div class="mb-3">
<label for="State" class="form-label">State</label>
<input type="text" class="form-control" id="State" name="State" required>
</div>
<div class="mb-3">
<label for="ZipCode" class="form-label">Zip Code</label>
<input type="text" class="form-control" id="ZipCode" name="ZipCode" required>
</div>
<div class="mb-3">
<label for="Country" class="form-label">Country</label>
<input type="text" class="form-control" id="Country" name="Country" required>
</div>
<button type="submit" class="btn btn-primary">Create Shipping Address</button>
</form>
</div>
</body>
</html>

views/shipping-addresses/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 Shipping Address</title>
</head>
<body>
<div class="container">
<h1>Edit Shipping Address</h1>
<form action="/shipping-addresses/<%= shippingAddress.ShippingAddressId %>" method="POST">
<div class="mb-3">
<label for="User Id" class="form-label">User ID</label>
<input type="number" class="form-control" id="User Id" name="User Id" value="<%= shippingAddress.UserId %>" required>
</div>
<div class="mb-3">
<label for="AddressLine1" class="form-label">Address Line 1</label>
<input type="text" class="form-control" id="AddressLine1" name="AddressLine1" value="<%= shippingAddress.AddressLine1 %>" required>
</div>
<div class="mb-3">
<label for="AddressLine2" class="form-label">Address Line 2</label>
<input type="text" class="form-control" id="AddressLine2" name="AddressLine2" value="<%= shippingAddress.AddressLine2 %>">
</div>
<div class="mb-3">
<label for="City" class="form-label">City</label>
<input type="text" class="form-control" id="City" name="City" value="<%= shippingAddress.City %>" required>
</div>
<div class="mb-3">
<label for="State" class="form-label">State</label>
<input type="text" class="form-control" id="State" name="State" value="<%= shippingAddress.State %>" required>
</div>
<div class="mb-3">
<label for="ZipCode" class="form-label">Zip Code</label>
<input type="text" class="form-control" id="ZipCode" name="ZipCode" value="<%= shippingAddress.ZipCode %>" required>
</div>
<div class="mb-3">
<label for="Country" class="form-label">Country</label>
<input type="text" class="form-control" id="Country" name="Country" value="<%= shippingAddress.Country %>" required>
</div>
<button type="submit" class="btn btn-primary">Update Shipping Address</button>
</form>
</div>
</body>
</html>

With the above implementations, you now have a complete CRUD application for managing Users, Roles, Products, Categories, CartItems, Orders, OrderItems, Reviews, Wishlists, WishlistItems, Coupons, and ShippingAddresses in your Node.js application using Sequelize, Express, EJS, and Bootstrap 5. Each entity has its own model, repository, controller, routes, and views, allowing for a structured and maintainable codebase.

To create a dashboard page that displays consolidated data related to your e-commerce project, we will follow these steps:

Create a Dashboard Controller

This controller will fetch data from various models and aggregate it.

Set Up Dashboard Routes

Define a route for accessing the dashboard.

Create a Dashboard View

Use EJS to create a view that will render the dashboard and display the consolidated data.

Step 1: Create the Dashboard Controller

Create a file named DashboardController.js in the controllers directory. This controller will fetch and consolidate data from various models.


// controllers/DashboardController.js
const User = require('../models/User');
const Product = require('../models/Product');
const Order = require('../models/Order');
const Review = require('../models/Review');
const Wishlist = require('../models/Wishlist');
class DashboardController {
async getDashboardData(req, res) {
try {
const userCount = await User.count();
const productCount = await Product.count();
const orderCount = await Order.count();
const reviewCount = await Review.count();
const wishlistCount = await Wishlist.count();
const dashboardData = {
userCount,
productCount,
orderCount,
reviewCount,
wishlistCount,
};
res.render('dashboard', { dashboardData });
} catch (error) {
console.error("Error fetching dashboard data:", error);
res.status(500).send("Internal Server Error");
}
}
}
module.exports = new DashboardController();

Step 2: Set Up Dashboard Routes

Create a file named dashboardRoutes.js in the routes directory. This file will define the route for accessing the dashboard.


// routes/dashboardRoutes.js
const express = require('express');
const router = express.Router();
const DashboardController = require('../controllers/DashboardController');
router.get('/', DashboardController.getDashboardData);
module.exports = router;

Step 3: Create the Dashboard View

Create a file named dashboard.ejs in the views directory. This file will render the dashboard and display the consolidated data.


<!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>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"><%= dashboardData.userCount %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-success mb-3">
<div class="card-header">Total Products</div>
<div class="card-body">
<h5 class="card-title"><%= dashboardData.productCount %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-warning mb-3">
<div class="card-header">Total Orders</div>
<div class="card-body">
<h5 class="card-title"><%= dashboardData.orderCount %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-danger mb-3">
<div class="card-header">Total Reviews</div>
<div class="card-body">
<h5 class="card-title"><%= dashboardData.reviewCount %></h5>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-white bg-info mb-3">
<div class="card-header">Total Wishlists</div>
<div class="card-body">
<h5 class="card-title"><%= dashboardData.wishlistCount %></h5>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

Step 4: Integrate Dashboard Routes

In your main application file (e.g., app.js), integrate the dashboard routes.


// app.js
const express = require('express');
const bodyParser = require('body-parser');
const sequelize = require('./config/database');
const userRoutes = require('./routes/userRoutes');
const roleRoutes = require('./routes/roleRoutes');
const productRoutes = require('./routes/productRoutes');
const categoryRoutes = require('./routes/categoryRoutes');
const cartItemRoutes = require('./routes/cartItemRoutes');
const orderRoutes = require('./routes/orderRoutes');
const orderItemRoutes = require('./routes/orderItemRoutes');
const reviewRoutes = require('./routes/reviewRoutes');
const wishlistRoutes = require('./routes/wishlistRoutes');
const wishlistItemRoutes = require('./routes/wishlistItemRoutes');
const couponRoutes = require('./routes/couponRoutes');
const shippingAddressRoutes = require('./routes/shippingAddressRoutes');
const dashboardRoutes = require('./routes/dashboardRoutes'); // Import dashboard routes
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/users', userRoutes);
app.use('/roles', roleRoutes);
app.use('/products', productRoutes);
app.use('/categories', categoryRoutes);
app.use('/cart-items', cartItemRoutes);
app.use('/orders', orderRoutes);
app.use('/order-items', orderItemRoutes);
app.use('/reviews', reviewRoutes);
app.use('/wishlists', wishlistRoutes);
app.use('/wishlist-items', wishlistItemRoutes);
app.use('/coupons', couponRoutes);
app.use('/shipping-addresses', shippingAddressRoutes);
app.use('/dashboard', dashboardRoutes); // Use dashboard routes
const PORT = process.env.PORT || 3000;
sequelize.sync().then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
});

With this setup, you now have a functional dashboard page that consolidates data from various models in your e-commerce application. The dashboard displays the total number of users, products, orders, reviews, and wishlists, providing a quick overview of the project's status. You can further enhance the dashboard by adding charts, graphs, or additional metrics as needed.