all CRUD operations functional
This commit is contained in:
parent
2ca5dd5238
commit
1006d28b71
7 changed files with 272 additions and 35 deletions
13
app.js
13
app.js
|
|
@ -1,4 +1,3 @@
|
|||
const createError = require("http-errors");
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
const cookieParser = require("cookie-parser");
|
||||
|
|
@ -36,16 +35,4 @@ const router = require("./routes/index");
|
|||
|
||||
app.use("/", router);
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function (req, res, next) {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function (err, req, res, next) {
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render("error");
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
|
|
|
|||
|
|
@ -111,9 +111,58 @@ exports.category_delete_get = asyncHandler(async (req, res, next) => {
|
|||
});
|
||||
|
||||
exports.category_update_get = asyncHandler(async (req, res, next) => {
|
||||
res.send("ligma");
|
||||
// get current category from URL
|
||||
const category = await Category.findOne({
|
||||
simpleName: req.params.category,
|
||||
})
|
||||
.lean()
|
||||
.exec();
|
||||
res.render("editcategory", { category: category });
|
||||
});
|
||||
|
||||
exports.category_update_post = asyncHandler(async (req, res, next) => {
|
||||
res.send("ligma");
|
||||
});
|
||||
exports.category_update_post = [
|
||||
// Validate and sanitize name
|
||||
body("name", "Category must have a name!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
.escape(),
|
||||
|
||||
// Validate and sanitize description
|
||||
body("description", "Category must have a description!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
.escape(),
|
||||
|
||||
// Process request after validation and sanitization.
|
||||
asyncHandler(async (req, res, next) => {
|
||||
// Extract the validation errors from a request.
|
||||
const errors = validationResult(req);
|
||||
|
||||
// find existing category in database
|
||||
const dbCat = await Category.findOne({ simpleName: req.params.category })
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
// Create a new category with escaped and trimmed data.
|
||||
const category = new Category({
|
||||
name: req.body.name,
|
||||
simpleName: req.body.name.toLowerCase().replace(" ", ""),
|
||||
description: req.body.description,
|
||||
_id: dbCat._id, // copy original category ID to prevent overwrite errors
|
||||
});
|
||||
|
||||
// if there are validation errors
|
||||
if (!errors.isEmpty()) {
|
||||
// Render the creation form again with sanitized values/error messages.
|
||||
res.render("editcategory", {
|
||||
category: dbCat,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Data from form is valid.
|
||||
else {
|
||||
await Category.findByIdAndUpdate(dbCat._id, category, {});
|
||||
res.redirect(`/${category.simpleName}`);
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ exports.item_create_post = [
|
|||
.isLength({ min: 2, max: 2 })
|
||||
.escape(),
|
||||
|
||||
// Validate and sanitize price (formatting has already been taken care of)
|
||||
// Validate and sanitize quantity
|
||||
body("quantity", "Item must have a quantity!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
|
|
@ -75,15 +75,6 @@ exports.item_create_post = [
|
|||
.lean()
|
||||
.exec();
|
||||
|
||||
console.log([
|
||||
req.body.name,
|
||||
category._id,
|
||||
req.body.description,
|
||||
req.body.dollars,
|
||||
req.body.cents,
|
||||
req.body.quantity,
|
||||
]);
|
||||
|
||||
// Create a new Item with escaped and trimmed data.
|
||||
const item = new Item({
|
||||
name: req.body.name,
|
||||
|
|
@ -96,8 +87,9 @@ exports.item_create_post = [
|
|||
// if there are validation errors
|
||||
if (!errors.isEmpty()) {
|
||||
// Render the creation form again with sanitized values/error messages.
|
||||
res.render("createcategory", {
|
||||
res.render("createitem", {
|
||||
errors: errors.array(),
|
||||
category: category,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -144,9 +136,81 @@ exports.item_delete_get = asyncHandler(async (req, res, next) => {
|
|||
});
|
||||
|
||||
exports.item_update_get = asyncHandler(async (req, res, next) => {
|
||||
res.send("ligma");
|
||||
// get current category from URL
|
||||
const category = await Category.findOne({
|
||||
simpleName: req.params.category,
|
||||
})
|
||||
.lean()
|
||||
.exec();
|
||||
const item = await Item.findOne({ _id: req.params.item });
|
||||
res.render("edititem", { category: category, item: item });
|
||||
});
|
||||
|
||||
exports.item_update_post = asyncHandler(async (req, res, next) => {
|
||||
res.send("ligma");
|
||||
});
|
||||
exports.item_update_post = [
|
||||
// Validate and sanitize name
|
||||
body("name", "Item must have a name!").trim().isLength({ min: 1 }).escape(),
|
||||
|
||||
// Validate and sanitize description
|
||||
body("description", "Item must have a description!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
.escape(),
|
||||
|
||||
// Validate and sanitize price (formatting has already been taken care of)
|
||||
body("dollars", "Item must have a dollar amount!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
.escape(),
|
||||
body("cents", "Item must have a cent amount!")
|
||||
.trim()
|
||||
.isLength({ min: 2, max: 2 })
|
||||
.escape(),
|
||||
|
||||
// Validate and sanitize quantity
|
||||
body("quantity", "Item must have a quantity!")
|
||||
.trim()
|
||||
.isLength({ min: 1 })
|
||||
.escape(),
|
||||
|
||||
// Process request after validation and sanitization.
|
||||
asyncHandler(async (req, res, next) => {
|
||||
// Extract the validation errors from a request.
|
||||
const errors = validationResult(req);
|
||||
|
||||
// get current category from URL
|
||||
const category = await Category.findOne({
|
||||
simpleName: req.params.category,
|
||||
})
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
// get item in db
|
||||
const dbItem = await Item.findOne({ _id: req.params.item });
|
||||
|
||||
// Create a new Item with escaped and trimmed data.
|
||||
const item = new Item({
|
||||
name: req.body.name,
|
||||
category: category._id,
|
||||
description: req.body.description,
|
||||
price: Number(`${req.body.dollars}.${req.body.cents}`),
|
||||
quantity: req.body.quantity,
|
||||
_id: dbItem._id,
|
||||
});
|
||||
|
||||
// if there are validation errors
|
||||
if (!errors.isEmpty()) {
|
||||
// Render the creation form again with sanitized values/error messages.
|
||||
res.render("edititem", {
|
||||
errors: errors.array(),
|
||||
category: category,
|
||||
item: dbItem,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Data from form is valid.
|
||||
else {
|
||||
await Item.findByIdAndUpdate(dbItem._id, item, {});
|
||||
res.redirect(`/${req.params.category}/${req.params.item}`);
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@
|
|||
+ Create new item
|
||||
</a>
|
||||
<div class="pb-4"></div>
|
||||
<a
|
||||
href="/<%= category.simpleName %>/update"
|
||||
type="button"
|
||||
class="btn btn-primary px-4"
|
||||
>
|
||||
Edit this category
|
||||
</a>
|
||||
<div class="pb-4"></div>
|
||||
<a
|
||||
href="/<%= category.simpleName %>/delete"
|
||||
type="button"
|
||||
|
|
|
|||
48
views/editcategory.ejs
Normal file
48
views/editcategory.ejs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Good Pickin's - Editing <%= category.name %></title>
|
||||
<link rel="stylesheet" href="/styles/css/bootstrap.min.css" />
|
||||
</head>
|
||||
<body class="bg-dark text-light">
|
||||
<div class="d-flex flex-column py-4 px-4 align-items-center">
|
||||
<h1 class="mb-4">Editing <%= category.name %></h1>
|
||||
<form class="d-flex flex-column align-items-center w-50" method="post">
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="name">Category Name:</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="category name"
|
||||
aria-describedby="name"
|
||||
name="name"
|
||||
value="<%= category.name %>"
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="description">
|
||||
Category Description:
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="category description"
|
||||
aria-describedby="description"
|
||||
name="description"
|
||||
value="<%= category.description %>"
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-light px-4 py-2">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<footer
|
||||
class="position-fixed bottom-0 border-light border-top w-100 py-2 d-flex justify-content-center bg-dark"
|
||||
>
|
||||
<a href="/" type="button" class="btn btn-outline-light px-4 py-1">
|
||||
Back to Home
|
||||
</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
84
views/edititem.ejs
Normal file
84
views/edititem.ejs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Good Pickin's - <%= category.name %> - Editing <%= item.name %>
|
||||
</title>
|
||||
<link rel="stylesheet" href="/styles/css/bootstrap.min.css" />
|
||||
</head>
|
||||
<body class="bg-dark text-light">
|
||||
<div class="d-flex flex-column py-4 px-4 align-items-center">
|
||||
<h1 class="mb-4">Editing <%= item.name %></h1>
|
||||
<form class="d-flex flex-column align-items-center w-50" method="post">
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="name">Item Name:</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="item name"
|
||||
aria-describedby="name"
|
||||
name="name"
|
||||
value="<%= item.name %>"
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="description">
|
||||
Item Description:
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="item description"
|
||||
aria-describedby="description"
|
||||
name="description"
|
||||
value="<%= item.description %>"
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="price"> Item Price: </span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="dollars"
|
||||
aria-describedby="price"
|
||||
name="dollars"
|
||||
value="<%= Math.trunc(item.price) %>"
|
||||
oninput="this.value = this.value.replace(/[^0-9]/g, '')"
|
||||
/>
|
||||
<span class="input-group-text" id="price">.</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="cents"
|
||||
aria-describedby="price"
|
||||
name="cents"
|
||||
oninput="this.value < 3 ? this.value = this.value.replace(/[^0-9]{1,2}/g, '') : this.value = this.value.substring(0, 2)"
|
||||
value="<%= Number.parseFloat(item.price).toFixed(2).toString().match(/(?<=\.)(\d+)/gi) %>"
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group mb-4" data-bs-theme="dark">
|
||||
<span class="input-group-text" id="quantity"> Item Quantity: </span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
aria-label="item quantity"
|
||||
aria-describedby="quantity"
|
||||
name="quantity"
|
||||
value="<%= item.quantity %>"
|
||||
oninput="this.value = this.value.replace(/[^0-9]/g, '')"
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-light px-4 py-2">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<footer
|
||||
class="position-fixed bottom-0 border-light border-top w-100 py-2 d-flex justify-content-center bg-dark"
|
||||
>
|
||||
<a href="/" type="button" class="btn btn-outline-light px-4 py-1">
|
||||
Back to Home
|
||||
</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<h1><%= message = 'Error!' %></h1>
|
||||
<h2><%= error.status %></h2>
|
||||
<pre><%= error.stack %></pre>
|
||||
Loading…
Add table
Reference in a new issue