Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var path = require("path"); //The node:path module provides utilities for working with file and directory paths
var cookieParser = require("cookie-parser");
var logger = require("morgan");
var expressLayouts = require("express-ejs-layouts");
var expressLayouts = require("express-ejs-layouts"); //Layout support for ejs in express
var indexRouter = require("./routes/index");
var protectedRouter = require("./routes/protected");
var sessionAuth = require("./middlewares/sessionAuth");
Expand All @@ -12,11 +12,6 @@ var apiauth = require("./middlewares/apiauth");
var session = require("express-session");
var app = express();

var bodyParser = require("body-parser");

app.use(bodyParser.json());
// for parsing application/xwww-
app.use(bodyParser.urlencoded({ extended: true }));
var config = require("config");
app.use(
session({
Expand All @@ -29,20 +24,30 @@ app.use(
// const { startCronJobs } = require("./croneJobs/index");
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.use(expressLayouts);
app.set("view engine", "ejs"); //tells express that we are using ejs as rendering engine
//view engine is responsible for rendering dynamic content on the server side
app.use(expressLayouts); //add express layouts middleware
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false })); //is a middleware function that is used to parse incoming requests with urlencoded payloads e.g. form submissions
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));
// his middleware is used to serve static files, such as images, CSS files, and JavaScript files, directly from a specified directory.

app.use("/api/public/products", require("./routes/api/public/products"));
app.use("/api/categories", require("./routes/api/catagories"));
app.use("/api/products", apiauth, require("./routes/api/products"));
app.use("/api/calculator", require("./routes/api/calculator"));
app.use("/api/auth", require("./routes/api/auth"));
app.use("/", sessionAuth, indexRouter);
app.use("/my-account", sessionAuth, checkSessionAuth, protectedRouter);
app.use("/", sessionAuth, require("./routes/shop"));
app.use(sessionAuth); // add a middleware which should run on all server side rendering routes
app.use("/calculator", require("./routes/calculator")); //add a calculator router on all methods with /calculator prefix
app.use(
"/cookies-session-example",
require("./routes/cookies-session-example")
); //add a calculator router on all methods with /calculator prefix
app.use("/", indexRouter);
app.use("/my-account", checkSessionAuth, protectedRouter);
app.use("/", require("./routes/shop"));
app.get("/admin", async (req, res) => {
res.sendFile(path.join(__dirname, "admin", "build", "index.html"));
});
Expand Down
5 changes: 4 additions & 1 deletion middlewares/sessionAuth.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//sets user variable for pug files
//sets user variable for ejs files
let Category = require("../models/Category");
async function sessionAuth(req, res, next) {
let allCategories = await Category.find();
res.locals.allCategories = allCategories;
res.locals.user = req.session.user;
res.locals.isAdmin = false;
if (req.session.user) {
Expand Down
53 changes: 53 additions & 0 deletions models/CalculatorOperation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const mongoose = require("mongoose");
const calculatorOperationSchema = mongoose.Schema(
{
operand1: String,
operand2: String,
operation: String,
result: String,
description: String,
},
{ timestamps: true, toJSON: { virtuals: true } }
);
// The pre-save middleware is executed before a document is saved to the MongoDB database.
//This is useful for performing tasks or modifications to the document just before it gets persisted to the database.
calculatorOperationSchema.pre("save", function (next) {
this.description =
`You performed ` +
this.operation +
" on " +
this.operand1 +
" and " +
this.operand2;
next();
});
// a virtual is a property that is not stored in the MongoDB document itself but is computed or derived from other properties.
//Virtuals are typically used for computed properties or for formatting data in a specific way without persisting it in the database.
calculatorOperationSchema.virtual("virtual_result").get(function () {
switch (this.operation) {
case "+":
return (
this.operand1 +
this.operation +
this.operand2 +
"=" +
Number(Number(this.operand1) + Number(this.operand2))
);
case "-":
return (
this.operand1 +
this.operation +
this.operand2 +
"=" +
Number(Number(this.operand1) - Number(this.operand2))
);

default:
return 0;
}
});
const CalculatorOperation = mongoose.model(
"CalculatorOperation",
calculatorOperationSchema
);
module.exports = CalculatorOperation;
1 change: 1 addition & 0 deletions models/Product.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const productSchema = mongoose.Schema({
department: String,
description: String,
image: String,
category: { type: mongoose.Types.ObjectId, ref: "Category" },
});
const Product = mongoose.model("Product", productSchema);
module.exports = Product;
79 changes: 79 additions & 0 deletions public/js/calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
console.log("From Calculator");

$(function () {
//this function will be executed after page load
$("#calculatorPostFormAjax").on("submit", handleFormSubmit);
// $("#calculationResultsTbl .btn-warning").on("click", deleteBtnClicked); // default binding
$(document).on(
"click",
"#calculationResultsTbl .btn-warning",
deleteBtnClicked
); // event delegation countered
$("#deleteAllBtn").on("click", function (e) {
e.preventDefault();
$.ajax({
url: "/api/calculator/delete-all",
method: "post",
success: function () {
$("#calculationResultsTbl tbody").empty();
},
});
});
});

function handleFormSubmit(e) {
console.log(e);
e.preventDefault(); //stop form submission
let data = {
operand1: $("#operand1").val(),
operand2: $("#operand2").val(),
operation: $("#operation").val(),
};

// initiate ajax call
$.ajax({
url: "/api/calculator",
method: "post",
data,
success: function (res) {
//function to be executed after successful ajax call
console.log(res);
$("#calculationResultsTbl tbody").append(`<tr>
<td><a class="btn btn-sm btn-warning" data-id="${res._id}" href="/calculator/delete/${res._id}">Del</a></td>
<td>${res.operand1}</td>
<td>${res.operation}</td>
<td>${res.operand2}</td>
<td>${res.result}</td>
<td>${res.description}</td>
<td>${res.virtual_result}</td>
</tr>`);
// $("#calculationResultsTbl .btn-warning").on("click", deleteBtnClicked);
// above line is required as new table rows are not binded by default
// this is not a good way to do that
},
error: function (err) {
//function to be executed after ajax call failure
console.log(err);
},
});
console.log(data);
}

function deleteBtnClicked(e) {
// alert("del btn clicked");
let id = $(this).attr("data-id");
let tr = $(this).closest("tr");
$.ajax({
url: `/api/calculator/${id}`,
method: "delete",
success: function (res) {
tr.remove();
},
error: function (err) {
//function to be executed after ajax call failure
console.log(err);
},
});

e.preventDefault();
}
30 changes: 30 additions & 0 deletions routes/api/calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var express = require("express");
var router = express.Router();
var CalculatorOperation = require("../../models/CalculatorOperation");
router.post("/delete-all", async (req, res) => {
let record = await CalculatorOperation.deleteMany({});
return res.send("Records Deleted");
});
router.post("/", async (req, res) => {
let data = req.body;
data.result = 0;
switch (req.body.operation) {
case "+":
data.result = Number(req.body.operand1) + Number(req.body.operand2);
break;
case "-":
data.result = Number(req.body.operand1) - Number(req.body.operand2);
break;

default:
break;
}
let calculatorOp = new CalculatorOperation(data);
await calculatorOp.save();
return res.send(calculatorOp);
});
router.delete("/:id", async (req, res) => {
let record = await CalculatorOperation.findByIdAndDelete(req.params.id);
return res.send("Record Deleted");
});
module.exports = router;
47 changes: 47 additions & 0 deletions routes/calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const express = require("express");
const CalculatorOperation = require("../models/CalculatorOperation");
let router = express.Router();
router.get("/ajax-example", async (req, res) => {
console.log("get method /calculator");
let results = await CalculatorOperation.find();
// return res.send(results);
return res.render("calculator/calculator-example-ajax", { results });
});
router.get("/delete-all", async (req, res) => {
await CalculatorOperation.deleteMany({});
return res.redirect("/calculator");
});
router.get("/delete/:id", async (req, res) => {
await CalculatorOperation.findByIdAndDelete(req.params.id);
return res.redirect("/calculator");
});

router.get("/", async (req, res) => {
console.log("get method /calculator");
let results = await CalculatorOperation.find();
// return res.send(results);
return res.render("calculator/calculator-example", { results });
});
router.post("/", async (req, res) => {
// return res.send(req.body);
console.log("post /calculator");
let data = req.body;
data.result = 0;
switch (req.body.operation) {
case "+":
data.result = Number(req.body.operand1) + Number(req.body.operand2);
break;
case "-":
data.result = Number(req.body.operand1) - Number(req.body.operand2);
break;

default:
break;
}
let calculatorOp = new CalculatorOperation(data);
await calculatorOp.save();
// return res.send(data); // we do not send data from server side form submissions
// return res.render("calculator/calculator-example"); //we do not render responses in form submissions either
return res.redirect("/calculator");
});
module.exports = router;
21 changes: 21 additions & 0 deletions routes/cookies-session-example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const express = require("express");
let router = express.Router();
router.get("/cookies", (req, res) => {
// return res.send(req.cookies);
let city = req.cookies.city;
return res.render("cookies-session-example/cookies", { city });
});
router.post("/cookies", (req, res) => {
res.cookie("city", req.body.city);
res.redirect("/cookies-session-example/cookies");
});
router.get("/session", (req, res) => {
// return res.send(req.cookies);
let university = req.session.university;
return res.render("cookies-session-example/session", { university });
});
router.post("/session", (req, res) => {
req.session.university = req.body.university;
res.redirect("/cookies-session-example/session");
});
module.exports = router;
37 changes: 25 additions & 12 deletions routes/shop.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var express = require("express");
var router = express.Router();
var Product = require("../models/Product");
var Category = require("../models/Category");
router.get("/cart", async function (req, res, next) {
let cart = req.cookies.cart;
if (!cart) cart = [];
Expand All @@ -21,36 +22,48 @@ router.get("/add-cart/:id", function (req, res, next) {
req.flash("success", "Product Added To Cart");
res.redirect("/");
});

router.get("/:page?", async function (req, res, next) {
router.get("/collections/:slug/:page?", async function (req, res, next) {
let category = await Category.findOne({ slug: req.params.slug });
if (!category) return next();
let page = Number(req.params.page);
let pageSize = 10;
let skip = (page - 1) * pageSize;
if (!page) page = 1;
if (!skip) skip = 0;

// return res.send({ page, pageSize, skip });
let products = await Product.find().skip(skip).limit(pageSize);
let totalProducts = await Product.countDocuments();
let products = await Product.find({ category: category._id })
.skip(skip)
.limit(pageSize);
let totalProducts = await Product.countDocuments({ category: category._id });
let totalPages = Math.ceil(totalProducts / pageSize);
return res.render("site/homepage", {

return res.render("site/category", {
pagetitle: "Awesome Products",
products,
page,
pageSize,
totalPages,
category,
});
});

router.get("/:Catagory?", async function (req, res, next) {
let Catagory = Number(req.params.page);
let Catagoies_items = [shirts, pants, begs, trousels, dresses];
router.get("/:page?", async function (req, res, next) {
let page = Number(req.params.page);
let pageSize = 10;
let skip = (page - 1) * pageSize;
if (!page) page = 1;
if (!skip) skip = 0;

// return res.send({ page, pageSize, skip });
let products = await Product.find().skip(skip).limit(pageSize);
let totalProducts = await Product.countDocuments();
let totalPages = Math.ceil(totalProducts / pageSize);
return res.render("site/homepage", {
pagetitle: "All Catagories",
Catagory,
Catagoies_items,
pagetitle: "Awesome Products",
products,
page,
pageSize,
totalPages,
});
});

Expand Down
Loading