Billmike/More-Recipes

View on GitHub
server/controllers/recipes.js

Summary

Maintainability
A
1 hr
Test Coverage
import Sequelize from 'sequelize';
import db from '../models/index';
import errorMessage from '../errorHandler/errorMessage';

const { Op } = Sequelize;
const recipes = db.Recipe;
const reviews = db.Review;
const favorites = db.Favorite;
const votes = db.Vote;

/**
 * Represents the Recipe class
 *
 * @class
 *
 */

class Recipe {
  /**
   * Creates a new recipe by an logged-in user
   *
   *
   * @param { object } req - The request object
   * @param { object } res - The response object
   *
   * @returns { object } The new recipe object
   */

  static addRecipe(req, res) {
    const {
      name,
      description,
      imageUrl,
      category,
      ingredients,
      instructions
    } = req.body;
    recipes
      .findOne({
        where: {
          name,
          owner: req.userId
        }
      })
      .then((foundRecipe) => {
        if (foundRecipe) {
          return res.status(409).json({
            message: 'You already have a recipe with this name'
          });
        }
        recipes
          .create({
            name,
            description,
            imageUrl,
            category,
            ingredients,
            instructions,
            owner: req.userId
          })
          .then(recipe =>
            res.status(201).json({
              message: 'Recipe created successfully',
              recipeData: recipe
            }));
      })
      .catch(() =>
        res.status(500).json({
          message: errorMessage
        }));
  }

  /**
   * Modifies an existing recipe by the user who created the recipe
   *
   *
   * @param { object } res - The response object
   * @param { object } req - The request object
   *
   * @returns { object } the modified recipe object
   */

  static modifyRecipe(req, res) {
    return recipes
      .findById(req.params.recipeId)
      .then((recipe) => {
        if (!recipe) {
          return res.status(404).json({
            message: 'It seems this recipe does not exist.'
          });
        } else if (recipe.owner !== req.userId) {
          return res.status(403).json({
            message: 'Sorry. You cannot perform this action.'
          });
        }

        return recipe
          .update({
            name: req.body.name || recipe.name,
            description: req.body.description || recipe.description,
            imageUrl: req.body.imageUrl || recipe.imageUrl,
            category: req.body.category || recipe.category,
            ingredients: req.body.ingredients || recipe.ingredients,
            instructions: req.body.instructions || recipe.instructions
          })
          .then(() =>
            res
              .status(201)
              .json({ message: 'Update successful.', recipeData: recipe }));
      })
      .catch(() =>
        res.status(500).json({
          message: errorMessage
        }));
  }

  /**
   * Fetches all the recipes in the database
   * and limits them to six recipes per page
   *
   *
   * @param { object } req - the request object
   * @param { object } res - the response object
   *
   * @returns { object } All recipes in the application
   */

  static getRecipes(req, res) {
    let offset = 0;
    const limit = 6;
    let singlePage;
    let pages;
    recipes
      .findAndCountAll()
      .then((foundRecipes) => {
        const { page } = req.params;
        const pages = Math.ceil(foundRecipes.count / limit);
        offset = limit * (page - 1);

        return recipes
          .findAll({
            limit,
            offset,
            include: [
              {
                model: favorites,
                as: 'favorites',
                attributes: ['userId']
              },
              {
                model: reviews,
                as: 'reviews'
              }
            ]
          })
          .then((allRecipes) => {
            res.status(200).json({
              recipeData: allRecipes,
              pages
            });
          });
      })
      .catch(() =>
        res.status(500).json({
          message: errorMessage
        }));
  }

  /**
   * Deletes a single recipe in the application
   *
   *
   * @param { object } req - the request object
   * @param { object } res - the response object
   *
   * @returns { object } A response with either a success or failure message
   */

  static deleteRecipe(req, res) {
    return recipes
      .findById(req.params.recipeId)
      .then((recipe) => {
        if (!recipe) {
          return res.status(404).json({
            message: 'The recipe you are looking for does not exist.'
          });
        } else if (recipe.owner !== req.userId) {
          return res.status(403).json({
            message:
              'You cannot delete this recipe' + ' as it does not belong to you.'
          });
        }
        return recipe.destroy().then(() =>
          res.status(201).json({
            message: 'Recipe deleted successfully',
            recipeId: recipe.id
          }));
      })
      .catch(() =>
        res.status(500).json({
          message: errorMessage
        }));
  }

  /**
   * Searches the database for recipe(s) using either name or ingredient
   *
   *
   * @param { object } req - The request object
   * @param { object } res - The response object
   *
   * @returns { object } An array of recipes
   * object that matches the request parameter
   */

  static searchRecipes(req, res) {
    const { search } = req.query;
    let offset = 0;
    const limit = 6;
    let singlePage;
    let pages;
    recipes
      .findAndCountAll({
        where: {
          [Op.or]: {
            name: {
              [Op.iLike]: `%${search}`
            },
            ingredients: {
              [Op.iLike]: `%${search}`
            }
          }
        },
        include: [
          {
            model: favorites,
            as: 'favorites'
          },
          {
            model: reviews,
            as: 'reviews'
          }
        ]
      })
      .then((searchRecipesResult) => {
        const { page } = req.query;
        const pages = Math.ceil(searchRecipesResult.count / limit);
        offset = limit * (page - 1);

        return recipes
          .findAll({
            where: {
              [Op.or]: {
                name: {
                  [Op.iLike]: `%${search}`
                },
                ingredients: {
                  [Op.iLike]: `%${search}`
                }
              }
            },
            include: [
              {
                model: favorites,
                as: 'favorites'
              },
              {
                model: reviews,
                as: 'reviews'
              }
            ],
            limit,
            offset
          })
          .then((returnedResult) => {
            res.status(200).json({
              recipeData: returnedResult,
              pages
            });
          });
      })
      .catch(() => {
        return res.status(500).json({
          message: errorMessage
        });
      });

    // recipes.findAll({
    //   where: {
    //     [Op.or]: {
    //       name: {
    //         [Op.iLike]: `%${search}`
    //       },
    //       ingredients: {
    //         [Op.iLike]: `%${search}`
    //       }
    //     }
    //   },
    //   include: [
    //     {
    //       model: favorites,
    //       as: 'favorites'
    //     }, {
    //       model: reviews,
    //       as: 'reviews'
    //     }
    //   ]
    // }).then((foundRecipes) => {
    //   const numberOfRecipesFound = foundRecipes.length;
    //   if (foundRecipes.length <= 0) {
    //     return res.status(200).json({
    //       message: 'No recipes found with this name or ingredient'
    //     });
    //   }
    //   res.status(200).json({
    //     message: `Found ${numberOfRecipesFound} recipe(s)`,
    //     recipeData: foundRecipes
    //   });
    // }).catch(() => {
    //   res.status(500).json({
    //     message: errorMessage
    //   });
    // });
  }

  static popularRecipes(req, res) {
    return recipes
      .findAll({
        include: [
          {
            model: favorites,
            as: 'favorites'
          },
          {
            model: reviews,
            as: 'reviews'
          }
        ],
        order: [
          [
            {
              model: favorites,
              as: 'favorites'
            },
            'id',
            'ASC'
          ]
        ],
        limit: 6
      })
      .then((theFoundrecipes) => {
        return res.status(200).json({
          theFoundrecipes
        });
      })
      .catch((err) => {
        return res.status(400).json({
          message: err.message
        });
      });
  }
}

export default Recipe;