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 array of relevant variables for displaying category and its items // get current category from URL const category = await Category.findOne({ simpleName: req.params.category, }) .lean() .exec(); // check if (category === null) { const error = new Error("Category not found"); return next(error); } // get all items from category const items = await Item.find({ category: category._id }).lean().exec(); // render with all relevant vars res.render("category", { category: category, items: items, }); }); exports.category_create_get = (req, res, next) => { res.render("createcategory"); }; exports.category_create_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); // 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, }); // if there are validation errors if (!errors.isEmpty()) { // Render the creation form again with sanitized values/error messages. res.render("createcategory", { errors: errors.array(), }); return; } // Data from form is valid. else { // Check if Category with same name already exists. const categoryExists = await Category.findOne({ name: req.body.name, }).exec(); if (categoryExists) { // Category exists, redirect to its page. res.redirect(`/${categoryExists.simpleName}`); } // else category is unique else { await category.save(); // saved. Redirect to new category page. res.redirect(`/${category.simpleName}`); } } }), ]; exports.category_delete_get = asyncHandler(async (req, res, next) => { // get current category from URL const category = await Category.findOne({ simpleName: req.params.category, }) .lean() .exec(); // check if (category === null) { const error = new Error("Category not found"); return next(error); } // else, continue to find all relevant items (if any) const items = await Item.find({ category: category._id }).lean().exec(); // if items found if (items.length > 0) { // delete all items from db - for loop used for practicality reasons (forEach() doesn't play well with async) for (let i = 0; i < items.length; i++) { const itemID = items[i]._id; await Item.findByIdAndDelete(itemID); } } // delete category await Category.findByIdAndDelete(category._id); // redirects to Home res.redirect("/"); }); exports.category_update_get = asyncHandler(async (req, res, next) => { // 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 = [ // 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}`); } }), ];