const Category = require("../models/category.js"); const Item = require("../models/item.js"); const asyncHandler = require("express-async-handler"); const { body, validationResult } = require("express-validator"); exports.index = asyncHandler(async (req, res, next) => { // get current item from URL const item = await Item.findOne({ _id: req.params.item, }) .lean() .exec(); // get current category from item const category = await Category.findById(item.category).lean().exec(); // check if (item === null) { const error = new Error("Item not found"); return next(error); } // render with all relevant vars res.render("item", { item: item, category: category, }); }); exports.item_create_get = asyncHandler(async (req, res, next) => { // get current category from URL const category = await Category.findOne({ simpleName: req.params.category, }) .lean() .exec(); // render create item page res.render("createitem", { category: category, }); }); exports.item_create_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(); // 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, }); // if there are validation errors if (!errors.isEmpty()) { // Render the creation form again with sanitized values/error messages. res.render("createitem", { errors: errors.array(), category: category, }); return; } // Data from form is valid. else { // Check if Item with same name already exists. const itemExists = await Item.findOne({ name: req.body.name, category: category._id, }) .lean() .exec(); if (itemExists) { // Item exists, redirect to its page. res.redirect(`/${req.params.category}/${itemExists._id}`); } // else Item is unique else { // save item and redirect to its ID item.save().then((uploadedItem) => { res.redirect(`/${req.params.category}/${uploadedItem._id}`); }); } } }), ]; exports.item_delete_get = asyncHandler(async (req, res, next) => { // get current item from URL const item = await Item.findOne({ _id: req.params.item, }) .lean() .exec(); // check if (item === null) { const error = new Error("Item not found"); return next(error); } // delete item await Item.findByIdAndDelete(item._id); // redirects to parent category res.redirect(`/${req.params.category}`); }); exports.item_update_get = asyncHandler(async (req, res, next) => { // 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 = [ // 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}`); } }), ];