diff --git a/.github/workflows/Code_Formatter_and_Syntax_Check.yml b/.github/workflows/Code_Formatter_and_Syntax_Check.yml index ad6ff4fc..f9a908b0 100644 --- a/.github/workflows/Code_Formatter_and_Syntax_Check.yml +++ b/.github/workflows/Code_Formatter_and_Syntax_Check.yml @@ -1,17 +1,15 @@ name: Code Formatter and Syntax Check on: pull_request: - branches: - - master + branches: ["master"] push: - branches: - - master + branches: ["master"] jobs: test: name: Check the source code runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages run: | cd Code/backend @@ -19,4 +17,4 @@ jobs: - name: Lint run: | cd Code/backend - npx eslint ./dao + npx eslint ./controllers diff --git a/.github/workflows/Style_Checker_and_Prettify_Code.yml b/.github/workflows/Style_Checker_and_Prettify_Code.yml index fb49592a..1704fdfa 100644 --- a/.github/workflows/Style_Checker_and_Prettify_Code.yml +++ b/.github/workflows/Style_Checker_and_Prettify_Code.yml @@ -1,9 +1,9 @@ name: Style Checker and Prettify Code on: pull_request: + branches: ["master"] push: - branches: - - master + branches: ["master"] jobs: prettier: @@ -11,11 +11,11 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ github.head_ref }} - name: Prettify code - uses: creyD/prettier_action@v4.0 + uses: creyD/prettier_action@v4.3 with: prettier_options: --write **/*.{js,md} diff --git a/.github/workflows/codeFormatter.yml b/.github/workflows/codeFormatter.yml index 4f5c1884..6e8292c0 100644 --- a/.github/workflows/codeFormatter.yml +++ b/.github/workflows/codeFormatter.yml @@ -1,17 +1,15 @@ name: Check the source code on: pull_request: - branches: - - master + branches: ["master"] push: - branches: - - master + branches: ["master"] jobs: test: name: Check the source code runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install packages run: | cd Code/backend diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ff14fbc1..62d4022e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,6 +1,10 @@ name: Running Code Coverage -on: [push, pull_request] +on: + pull_request: + branches: ["master"] + push: + branches: ["master"] jobs: build: @@ -9,16 +13,16 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x] + node-version: [18.x] steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} @@ -34,7 +38,7 @@ jobs: - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml index 1882c233..e5d38bc2 100644 --- a/.github/workflows/greetings.yml +++ b/.github/workflows/greetings.yml @@ -1,6 +1,10 @@ name: Greetings -on: [pull_request, issues] +on: + pull_request: + branches: ["master"] + issues: + branches: ["master"] jobs: greeting: diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index 5cdc45e6..239c3ed3 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -6,7 +6,9 @@ # https://github.com/actions/labeler name: Labeler -on: [pull_request] +on: + pull_request: + branches: ["master"] jobs: label: diff --git a/Code/backend/app.js b/Code/backend/app.js index 94d8fb9a..0d35f799 100644 --- a/Code/backend/app.js +++ b/Code/backend/app.js @@ -1,33 +1,38 @@ -const express = require('express'); -const dotenv = require('dotenv'); -const morgan = require('morgan'); +const express = require("express"); +const dotenv = require("dotenv"); +const morgan = require("morgan"); const app = express(); const colors = require("colors"); -const connectDB = require('./config/db.js'); -const {notFound, errorHandling} = require('./utils/errorhandling.js') +const connectDB = require("./config/db.js"); +const { notFound, errorHandling } = require("./utils/errorhandling.js"); colors.enable(); -const cors = require('cors'); +const cors = require("cors"); app.use(express.json()); dotenv.config(); connectDB(); -app.use(express.urlencoded({extended:true})); +app.use(express.urlencoded({ extended: true })); app.use(cors({ credentials: true })); app.use(cors()); -if (process.env.NODE_ENV === 'development') { - app.use(morgan('dev')); +if (process.env.NODE_ENV === "development") { + app.use(morgan("dev")); } -const {signInRouter, signUpRouter, signOutRouter, userProfileRouter } = require('./routes/user.js'); -const {getRecipe, getCuisine, postRecipe} = require('./routes/recipe.js') -const parsingRecipeData = require('./utils/parsingRecipeData.js') +const { + signInRouter, + signUpRouter, + signOutRouter, + userProfileRouter, +} = require("./routes/user.js"); +const { getRecipe, getCuisine, postRecipe } = require("./routes/recipe.js"); +const parsingRecipeData = require("./utils/parsingRecipeData.js"); -app.get("/", async(req, res) => { +app.get("/", async (req, res) => { console.log("Hello"); res.send("Hello"); }); @@ -37,20 +42,21 @@ app.use("/api/v4/signUp", signUpRouter); app.use("/api/v4/signOut", signOutRouter); app.use("/api/v4/userProfile", userProfileRouter); -app.use("/api/v4/recipes", getRecipe) -app.use("/api/v4/recipes/cuisines", getCuisine) +app.use("/api/v4/recipes", getRecipe); +app.use("/api/v4/recipes/cuisines", getCuisine); app.use("/api/v4/recipes/Addrecipes", parsingRecipeData, postRecipe); -app.use(notFound, errorHandling) +app.use(notFound, errorHandling); const PORT = process.env.PORT || 5000; app.listen( PORT, console.log( - `Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold - ) + `Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow + .bold, + ), ); module.exports = { - app -} + app, +}; diff --git a/Code/backend/config/db.js b/Code/backend/config/db.js index ba42861b..8aa61e6e 100644 --- a/Code/backend/config/db.js +++ b/Code/backend/config/db.js @@ -1,5 +1,5 @@ -const mongoose = require( 'mongoose'); -const colors = require('colors'); +const mongoose = require("mongoose"); +const colors = require("colors"); const connectDB = async () => { try { @@ -15,4 +15,4 @@ const connectDB = async () => { } }; -module.exports = connectDB; \ No newline at end of file +module.exports = connectDB; diff --git a/Code/backend/controllers/recipe.js b/Code/backend/controllers/recipe.js index ab8b7b68..39d3bf06 100644 --- a/Code/backend/controllers/recipe.js +++ b/Code/backend/controllers/recipe.js @@ -3,13 +3,13 @@ const { default: mongoose } = require("mongoose"); const getRecipe = express.Router(); const getCuisine = express.Router(); const postRecipe = express.Router(); -const Recipe = require('../models/recipe'); -const Error = require('../errors/error') +const Recipe = require("../models/recipe"); +const Error = require("../errors/error"); //************* Database Queries***************** */ async function postRecipes(addRecipeDetails) { console.log("inside model"); - console.log(typeof Recipe) + console.log(typeof Recipe); try { const res = await Recipe.create(addRecipeDetails); console.log("1 document inserted"); @@ -19,32 +19,36 @@ async function postRecipes(addRecipeDetails) { } } -async function getRecipes({ filters = null, page = 0, recipesPerPage = 10,} = {}){ +async function getRecipes({ + filters = null, + page = 0, + recipesPerPage = 10, +} = {}) { let query = {}; console.log("Filters in getRecipes", filters); if (filters) { if (filters.CleanedIngredients) { var str = "(?i)"; - + for (var i = 0; i < filters["CleanedIngredients"].length; i++) { const str1 = filters["CleanedIngredients"][i]; str += "(?=.*" + str1 + ")"; } - query.CleanedIngredients = { $regex: str } - console.log("the search string",str); + query.CleanedIngredients = { $regex: str }; + console.log("the search string", str); } var time = parseInt(filters["totalTime"]); var budget = parseInt(filters["budget"]); if (time) { - query.TotalTimeInMins = { $lte: time } + query.TotalTimeInMins = { $lte: time }; } if (budget) { - query.budget = {$lte: budget} - } - if (filters["typeOfDiet"]){ - query.typeOfDiet = filters["typeOfDiet"]; - } - if(filters.Cuisine){ + query.budget = { $lte: budget }; + } + if (filters["typeOfDiet"]) { + query.typeOfDiet = filters["typeOfDiet"]; + } + if (filters.Cuisine) { query["Cuisine"] = filters["Cuisine"]; } console.log("Final Query for Database", query); @@ -55,53 +59,51 @@ async function getRecipes({ filters = null, page = 0, recipesPerPage = 10,} = {} let totalNumRecipes; try { - cursor = await Recipe - .find(query) - .collation({ locale: "en", strength: 2 }); + cursor = await Recipe.find(query).collation({ locale: "en", strength: 2 }); // console.log(cursor); } catch (e) { console.error(`Unable to issue find command, ${e}`); return { recipesList: [], totalNumRecipess: 0 }; } - + // const displayCursor = cursor.skip(page*recipesPerPage).limit(recipesPerPage); try { - recipesList = cursor //displayCursor.toArray(); + recipesList = cursor; //displayCursor.toArray(); totalNumRecipes = cursor.length; - return { recipesList, totalNumRecipes}; + return { recipesList, totalNumRecipes }; } catch (e) { console.error( - `Unable to convert cursor to array or problem counting documents, ${e}` + `Unable to convert cursor to array or problem counting documents, ${e}`, ); - return { recipesList: [], totalNumRecipes: 0}; + return { recipesList: [], totalNumRecipes: 0 }; } // try { - // some code was deleted from before. - - // ********************Calori calculator code**************** - // var total_cal = 0; - // await axios - // .get("https://api.calorieninjas.com/v1/nutrition?query=" + new_str, { - // headers: { - // "X-Api-Key": "XSCESI7dxnCa7WydS0dZdQ==2nqZmMFF8hXOwdkE", - // }, - // }) - // .then(function (response) { - // // handle success - // for (let i = 0; i < response.data.items.length; i++) { - // var temp = response.data.items[i].calories; - // // console.log(temp); - // total_cal += temp; - // } - // }) - // .catch(function (error) { - // // handle error - // console.log("error:" + error); - // }) - // .then(function () { - // // always executed - // });} - } + // some code was deleted from before. + + // ********************Calori calculator code**************** + // var total_cal = 0; + // await axios + // .get("https://api.calorieninjas.com/v1/nutrition?query=" + new_str, { + // headers: { + // "X-Api-Key": "XSCESI7dxnCa7WydS0dZdQ==2nqZmMFF8hXOwdkE", + // }, + // }) + // .then(function (response) { + // // handle success + // for (let i = 0; i < response.data.items.length; i++) { + // var temp = response.data.items[i].calories; + // // console.log(temp); + // total_cal += temp; + // } + // }) + // .catch(function (error) { + // // handle error + // console.log("error:" + error); + // }) + // .then(function () { + // // always executed + // });} +} async function getCuisines() { let cuisines = []; @@ -120,10 +122,12 @@ async function apiPostRecipes(req, res, next) { try { console.log("inside controller"); let obj = await postRecipes(req.body); - res.status(201).json({obj, msg: "Success"}); + res.status(201).json({ obj, msg: "Success" }); } catch (err) { console.log(err); - throw new Error.BadRequestError("There is something wrong with the Add Recipe Form") + throw new Error.BadRequestError( + "There is something wrong with the Add Recipe Form", + ); } } @@ -134,27 +138,26 @@ async function apiGetRecipes(req, res, next) { const page = req.query.page ? parseInt(req.query.page, 10) : 0; let filters = {}; - console.log("Query from FrontEnd", {...req.query}); + console.log("Query from FrontEnd", { ...req.query }); if (req.query.CleanedIngredients && req.query.CleanedIngredients != '""') { filters.CleanedIngredients = req.query.CleanedIngredients; } - if(req.query.Cuisine && req.query.Cuisine != '""') { + if (req.query.Cuisine && req.query.Cuisine != '""') { filters.Cuisine = req.query.Cuisine; } - if(req.query.totalTime){ + if (req.query.totalTime) { filters.totalTime = req.query.totalTime; } - if(req.query.budget){ + if (req.query.budget) { filters.budget = req.query.budget; } - if(req.query.typeOfDiet){ + if (req.query.typeOfDiet) { filters.typeOfDiet = req.query.typeOfDiet; } - + try { - const { recipesList, totalNumRecipes} = - await getRecipes({ + const { recipesList, totalNumRecipes } = await getRecipes({ filters, page, recipesPerPage, @@ -167,28 +170,29 @@ async function apiGetRecipes(req, res, next) { entries_per_page: recipesPerPage, total_results: totalNumRecipes, }; - return res.status(200).json({response, msg:"Success"}); + return res.status(200).json({ response, msg: "Success" }); } catch (error) { console.log(error); - throw new Error.BadRequestError("There was error processing your queries. Please try again"); + throw new Error.BadRequestError( + "There was error processing your queries. Please try again", + ); } - } //Function to get the cuisines async function apiGetRecipeCuisines(req, res, next) { try { let cuisines = await getCuisines(); - console.log(cuisines); - return res.status(200).json({cuisines, msg:"Success"}); + // console.log(cuisines); + return res.status(200).json({ cuisines, msg: "Success" }); } catch (e) { console.log(e); - throw new Error.BadRequestError(`Something went wrong. Please try again`) + throw new Error.BadRequestError(`Something went wrong. Please try again`); } } module.exports = { apiGetRecipes, apiPostRecipes, - apiGetRecipeCuisines -} \ No newline at end of file + apiGetRecipeCuisines, +}; diff --git a/Code/backend/controllers/user.js b/Code/backend/controllers/user.js index e0f24f59..6322c9c5 100644 --- a/Code/backend/controllers/user.js +++ b/Code/backend/controllers/user.js @@ -1,94 +1,98 @@ -const express = require('express'); -const User = require('../models/user'); +const express = require("express"); +const User = require("../models/user"); const { generateToken } = require("../utils/generateToken"); const signUpGet = async (req, res) => { - try { - res.status = 200; - res.send("Sign up page"); - } catch (err) { - throw err; - } + try { + res.status = 200; + res.send("Sign up page"); + } catch (err) { + throw err; + } }; const signUpPost = async (req, res) => { - try { - const userExists = await User.findOne({username: req.body.username}); - if (userExists) { - throw new Error('User already exists'); - } - const user = User.create({ - username: req.body.username, - password: req.body.password - }); - if (user) { - let token = generateToken(req.body.username); - return res.status(200).json({ message: 'You have been signed up successfully' }); - } else { - throw new Error('Invalid user data'); - } - - } catch (err) { - throw err; + try { + const userExists = await User.findOne({ username: req.body.username }); + if (userExists) { + throw new Error("User already exists"); + } + const user = User.create({ + username: req.body.username, + password: req.body.password, + }); + if (user) { + let token = generateToken(req.body.username); + return res + .status(200) + .json({ message: "You have been signed up successfully" }); + } else { + throw new Error("Invalid user data"); } -} + } catch (err) { + throw err; + } +}; const signInGet = async (req, res) => { - try { - res.send("Sign in page"); - } catch (err) { - throw err; - } -} + try { + res.send("Sign in page"); + } catch (err) { + throw err; + } +}; const signInPost = async (req, res) => { - try { - const user = await User.findOne({username: req.body.username}); - if (user) { - if (await user.matchPassword(req.body.password)) { - const token = generateToken(req.body.username); - return res.status(200).json({ message: 'You have been logged in successfully' }); - } else { - res.status(500).send('Incorrect username or password'); - throw new Error('Incorrect username or password'); - } - } else { - res.status(500).send('Incorrect username or password'); - throw new Error('Incorrect username or password'); - } - } catch (err) { - throw err; + try { + const user = await User.findOne({ username: req.body.username }); + if (user) { + if (await user.matchPassword(req.body.password)) { + const token = generateToken(req.body.username); + return res + .status(200) + .json({ message: "You have been logged in successfully" }); + } else { + res.status(500).send("Incorrect username or password"); + throw new Error("Incorrect username or password"); + } + } else { + res.status(500).send("Incorrect username or password"); + throw new Error("Incorrect username or password"); } -} + } catch (err) { + throw err; + } +}; const signOutGet = async (req, res) => { - try { - return res.status(200).json({ message: 'You have been logged out successfully' }); - } catch (err) { - throw err; - } + try { + return res + .status(200) + .json({ message: "You have been logged out successfully" }); + } catch (err) { + throw err; + } }; const userProfileGet = async (req, res) => { - try { - const user = await User.findOne({username: req.body.username}); - if (user) { - return res.status(200).send(user); - } else { - res.status(500).send('No such user found'); - throw new Error('No such user found'); - } - - } catch (err) { - throw err; + try { + const user = await User.findOne({ username: req.body.username }); + if (user) { + return res.status(200).send(user); + } else { + res.status(500).send("No such user found"); + throw new Error("No such user found"); } -} + } catch (err) { + throw err; + } +}; module.exports = { - signInGet, - signInPost, - signUpGet, - signUpPost, - signOutGet, - userProfileGet, -}; \ No newline at end of file + signInGet, + signInPost, + signUpGet, + signUpPost, + signOutGet, + userProfileGet, +}; diff --git a/Code/backend/errors/bad-request.js b/Code/backend/errors/bad-request.js index c65b25aa..c76bf735 100644 --- a/Code/backend/errors/bad-request.js +++ b/Code/backend/errors/bad-request.js @@ -1,5 +1,5 @@ -const { StatusCodes } = require('http-status-codes'); -const CustomAPIError = require('./custom-api'); +const { StatusCodes } = require("http-status-codes"); +const CustomAPIError = require("./custom-api"); class BadRequestError extends CustomAPIError { constructor(message) { @@ -8,4 +8,4 @@ class BadRequestError extends CustomAPIError { } } -module.exports = BadRequestError; \ No newline at end of file +module.exports = BadRequestError; diff --git a/Code/backend/errors/custom-api.js b/Code/backend/errors/custom-api.js index e5a8a8d4..8ed087de 100644 --- a/Code/backend/errors/custom-api.js +++ b/Code/backend/errors/custom-api.js @@ -1,8 +1,8 @@ class CustomAPIError extends Error { constructor(message, statusCode = 500) { - super(message) - this.statusCode = statusCode + super(message); + this.statusCode = statusCode; } } -module.exports = CustomAPIError +module.exports = CustomAPIError; diff --git a/Code/backend/errors/error.js b/Code/backend/errors/error.js index c2af4ada..79e0abc3 100644 --- a/Code/backend/errors/error.js +++ b/Code/backend/errors/error.js @@ -1,11 +1,11 @@ -const CustomAPIError = require('./custom-api') -const UnauthenticatedError = require('./unauthenticated') -const NotFoundError = require('./not-found') -const BadRequestError = require('./bad-request') +const CustomAPIError = require("./custom-api"); +const UnauthenticatedError = require("./unauthenticated"); +const NotFoundError = require("./not-found"); +const BadRequestError = require("./bad-request"); module.exports = { CustomAPIError, UnauthenticatedError, NotFoundError, BadRequestError, -} \ No newline at end of file +}; diff --git a/Code/backend/errors/not-found.js b/Code/backend/errors/not-found.js index 40142110..2f8f56bb 100644 --- a/Code/backend/errors/not-found.js +++ b/Code/backend/errors/not-found.js @@ -1,5 +1,5 @@ -const { StatusCodes } = require('http-status-codes'); -const CustomAPIError = require('./custom-api'); +const { StatusCodes } = require("http-status-codes"); +const CustomAPIError = require("./custom-api"); class NotFoundError extends CustomAPIError { constructor(message) { @@ -8,4 +8,4 @@ class NotFoundError extends CustomAPIError { } } -module.exports = NotFoundError; \ No newline at end of file +module.exports = NotFoundError; diff --git a/Code/backend/errors/unauthenticated.js b/Code/backend/errors/unauthenticated.js index e177949f..99485dd4 100644 --- a/Code/backend/errors/unauthenticated.js +++ b/Code/backend/errors/unauthenticated.js @@ -1,5 +1,5 @@ -const { StatusCodes } = require('http-status-codes'); -const CustomAPIError = require('./custom-api'); +const { StatusCodes } = require("http-status-codes"); +const CustomAPIError = require("./custom-api"); class UnauthenticatedError extends CustomAPIError { constructor(message) { @@ -8,4 +8,4 @@ class UnauthenticatedError extends CustomAPIError { } } -module.exports = UnauthenticatedError; \ No newline at end of file +module.exports = UnauthenticatedError; diff --git a/Code/backend/models/recipe.js b/Code/backend/models/recipe.js index a1a1047a..faa5abee 100644 --- a/Code/backend/models/recipe.js +++ b/Code/backend/models/recipe.js @@ -1,45 +1,46 @@ -const mongoose = require('mongoose'); -const {Schema} = mongoose +const mongoose = require("mongoose"); +const { Schema } = mongoose; const recipeSchema = new Schema( - { - TranslatedRecipeName:{ - type: String, - required: [true, "Recipe Name is required"], - }, - TotalTimeInMins:{ - type: Number, - required: [true, "Total Time is required"] - }, - Cuisine:{ - type: String, - required: [true, "Cuisine is required"] - }, - imageUrl:{ - type: String - }, - CleanedIngredients:{ - type: String, - required: [true, "Ingredients is required"] - }, - TranslatedInstructions:{ - type: String, - required: [true, "Instructions is required"] - }, - budget:{ - type: Number - }, - typeOfDiet: { - type: String, - enum: ['Vegan', 'Vegetarian', 'Non-Vegetarian'], - message: '${VALUE} is not a diet type.' - }, - user:{ - type: mongoose.Schema.Types.ObjectId, - ref: 'user' - } - }, { collection: 'recipe' } + { + TranslatedRecipeName: { + type: String, + required: [true, "Recipe Name is required"], + }, + TotalTimeInMins: { + type: Number, + required: [true, "Total Time is required"], + }, + Cuisine: { + type: String, + required: [true, "Cuisine is required"], + }, + imageUrl: { + type: String, + }, + CleanedIngredients: { + type: String, + required: [true, "Ingredients is required"], + }, + TranslatedInstructions: { + type: String, + required: [true, "Instructions is required"], + }, + budget: { + type: Number, + }, + typeOfDiet: { + type: String, + enum: ["Vegan", "Vegetarian", "Non-Vegetarian"], + message: "${VALUE} is not a diet type.", + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: "user", + }, + }, + { collection: "recipe" }, ); -const Recipe = mongoose.model('Recipe', recipeSchema); +const Recipe = mongoose.model("Recipe", recipeSchema); -module.exports = Recipe; \ No newline at end of file +module.exports = Recipe; diff --git a/Code/backend/models/user.js b/Code/backend/models/user.js index 01070ba4..3f2ee425 100644 --- a/Code/backend/models/user.js +++ b/Code/backend/models/user.js @@ -1,33 +1,31 @@ -const mongoose = require('mongoose'); -const bcrypt = require('bcryptjs'); +const mongoose = require("mongoose"); +const bcrypt = require("bcryptjs"); -const userSchema = mongoose.Schema( - { - username: { - type: String, - required: true, - unique: true, - }, - password: { - type: String, - required: true, - } - } -); +const userSchema = mongoose.Schema({ + username: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, +}); userSchema.methods.matchPassword = async function (enteredPassword) { - return await bcrypt.compare(enteredPassword, this.password); + return await bcrypt.compare(enteredPassword, this.password); }; -userSchema.pre('save', async function (next) { - if (!this.isModified('password')) { - next(); - } - - const salt = await bcrypt.genSalt(10); - this.password = await bcrypt.hash(this.password, salt); +userSchema.pre("save", async function (next) { + if (!this.isModified("password")) { + next(); + } + + const salt = await bcrypt.genSalt(10); + this.password = await bcrypt.hash(this.password, salt); }); - -const User = mongoose.model('User', userSchema); -module.exports = User; \ No newline at end of file +const User = mongoose.model("User", userSchema); + +module.exports = User; diff --git a/Code/backend/populate.js b/Code/backend/populate.js index 4c874d6a..c0823868 100644 --- a/Code/backend/populate.js +++ b/Code/backend/populate.js @@ -1,8 +1,7 @@ -require('dotenv').config(); -const connectDB = require('./config/db'); -const Recipe = require('./models/recipe'); -const mockData = require('./output.json'); - +require("dotenv").config(); +const connectDB = require("./config/db"); +const Recipe = require("./models/recipe"); +const mockData = require("./output.json"); const populating = async () => { await connectDB(); @@ -12,5 +11,5 @@ const populating = async () => { } catch (error) { console.log(error, "Something went wrong"); } -} -populating() \ No newline at end of file +}; +populating(); diff --git a/Code/backend/routes/recipe.js b/Code/backend/routes/recipe.js index a24739d8..260b8062 100644 --- a/Code/backend/routes/recipe.js +++ b/Code/backend/routes/recipe.js @@ -1,21 +1,22 @@ -const express = require('express') -const {apiGetRecipeCuisines, apiGetRecipes, apiPostRecipes} = require('../controllers/recipe') +const express = require("express"); +const { + apiGetRecipeCuisines, + apiGetRecipes, + apiPostRecipes, +} = require("../controllers/recipe"); const getRecipe = express.Router(); const getCuisine = express.Router(); const postRecipe = express.Router(); //URl to get the recipes -getRecipe.route("/") -.get(apiGetRecipes); +getRecipe.route("/").get(apiGetRecipes); -postRecipe.route("/") -.post(apiPostRecipes); +postRecipe.route("/").post(apiPostRecipes); -getCuisine.route("/") -.get(apiGetRecipeCuisines); +getCuisine.route("/").get(apiGetRecipeCuisines); module.exports = { getRecipe, postRecipe, - getCuisine -}; \ No newline at end of file + getCuisine, +}; diff --git a/Code/backend/routes/user.js b/Code/backend/routes/user.js index 2880fe16..9d6393d3 100644 --- a/Code/backend/routes/user.js +++ b/Code/backend/routes/user.js @@ -1,39 +1,29 @@ -const express = require('express'); +const express = require("express"); const signInRouter = express.Router(); const signUpRouter = express.Router(); const signOutRouter = express.Router(); const userProfileRouter = express.Router(); const { - signInGet, - signUpGet, - signInPost, - signUpPost, - signOutGet, - userProfileGet, + signInGet, + signUpGet, + signInPost, + signUpPost, + signOutGet, + userProfileGet, } = require("../controllers/user"); -signInRouter - .route("/") - .get(signInGet) - .post(signInPost) +signInRouter.route("/").get(signInGet).post(signInPost); -signUpRouter - .route("/") - .get(signUpGet) - .post(signUpPost) +signUpRouter.route("/").get(signUpGet).post(signUpPost); -signOutRouter - .route("/") - .get(signOutGet) +signOutRouter.route("/").get(signOutGet); -userProfileRouter - .route("/") - .get(userProfileGet) +userProfileRouter.route("/").get(userProfileGet); module.exports = { - signInRouter, - signUpRouter, - signOutRouter, - userProfileRouter, -} \ No newline at end of file + signInRouter, + signUpRouter, + signOutRouter, + userProfileRouter, +}; diff --git a/Code/backend/test/user.js b/Code/backend/test/user.js index 4ae06ea7..299a05fe 100644 --- a/Code/backend/test/user.js +++ b/Code/backend/test/user.js @@ -1,96 +1,102 @@ -const chai = require('chai'); -const chaiHttp = require('chai-http'); -const { app }= require("../app"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); +const { app } = require("../app"); chai.use(chaiHttp); chai.should(); -describe('Sign In Route', () => { - describe('Get Request', () => { - it('should return sign in page', (done) => { - chai.request(app) - .get('/api/v4/signIn') - .end((err, res) => { - if (err) { +describe("Sign In Route", () => { + describe("Get Request", () => { + it("should return sign in page", (done) => { + chai + .request(app) + .get("/api/v4/signIn") + .end((err, res) => { + if (err) { console.log(err); } res.should.have.status(200); done(); - }); - }); + }); }); - describe('Post Request', () => { - it('should return successfully signed in', (done) => { - chai.request(app) - .post('/api/v4/signIn') + }); + describe("Post Request", () => { + it("should return successfully signed in", (done) => { + chai + .request(app) + .post("/api/v4/signIn") .send({ - username: 'tanay', - password: 'tanay' + username: "tanay", + password: "tanay", }) - .end((err, res) => { - if (err) { + .end((err, res) => { + if (err) { console.log(err); } res.should.have.status(200); done(); - }); - }); - it('should return incorrect username or password', (done) => { - chai.request(app) - .post('/api/v4/signIn') + }); + }); + it("should return incorrect username or password", (done) => { + chai + .request(app) + .post("/api/v4/signIn") .send({ - username: 'tanay', - password: 'abcd' + username: "tanay", + password: "abcd", }) - .end((err, res) => { + .end((err, res) => { res.should.have.status(500); done(); - }); - }); + }); + }); }); }); -describe('Sign Up Route', () => { - describe('Get Request', () => { - it('should return sign up page', (done) => { - chai.request(app) - .get('/api/v4/signUp') - .end((err, res) => { - if (err) { - console.log(err); +describe("Sign Up Route", () => { + describe("Get Request", () => { + it("should return sign up page", (done) => { + chai + .request(app) + .get("/api/v4/signUp") + .end((err, res) => { + if (err) { + console.log(err); } - res.should.have.status(200); - done(); - }); - }); + res.should.have.status(200); + done(); + }); }); - describe("Post request", () => { - it('should return signed up', (done) => { - chai.request(app) - .post('/api/v4/signUp') - .send({ - username: 'tanny', - password: 'tanay', - }) - .end((err, res) => { - if (err) { - console.log(err); - } - res.should.have.status(200); - done(); - }); + }); + describe("Post request", () => { + it("should return signed up", (done) => { + chai + .request(app) + .post("/api/v4/signUp") + .send({ + username: "tanny", + password: "tanay", + }) + .end((err, res) => { + if (err) { + console.log(err); + } + res.should.have.status(200); + done(); }); - }) + }); + }); }); -describe('Sign Out Route', () => { +describe("Sign Out Route", () => { describe("Get Request", () => { - it('should return successfully logged out', (done) => { - chai.request(app) - .get('/api/v4/signOut') + it("should return successfully logged out", (done) => { + chai + .request(app) + .get("/api/v4/signOut") .end((err, res) => { if (err) { - console.log(err); + console.log(err); } res.should.have.status(200); done(); @@ -99,23 +105,23 @@ describe('Sign Out Route', () => { }); }); -describe('Get User Profile Test', () => { +describe("Get User Profile Test", () => { describe("Get Request", () => { - it('should return the user profile', (done) => { - chai.request(app) - .get('/api/v4/userProfile') + it("should return the user profile", (done) => { + chai + .request(app) + .get("/api/v4/userProfile") .send({ - username: 'tanay' + username: "tanay", }) - .end((err, res) => { - if (err) { + .end((err, res) => { + if (err) { console.log(err); } res.should.have.status(200); - res.body.should.be.a('object'); + res.body.should.be.a("object"); done(); - }); - }); + }); + }); }); }); - diff --git a/Code/backend/utils/errorhandling.js b/Code/backend/utils/errorhandling.js index 14117887..06b2b356 100644 --- a/Code/backend/utils/errorhandling.js +++ b/Code/backend/utils/errorhandling.js @@ -1,13 +1,18 @@ -const CustomAPIError = require('../errors/custom-api'); +const CustomAPIError = require("../errors/custom-api"); -const notFound = (req, res, next) => res.status(404).json({msg:`We couldn't currently provide the resource you requested`}); +const notFound = (req, res, next) => + res + .status(404) + .json({ msg: `We couldn't currently provide the resource you requested` }); -const errorHandling = (err,req,res,next) => { - if(err instanceof CustomAPIError){ - return res.status(err.statusCode).json({msg:err.message}); +const errorHandling = (err, req, res, next) => { + if (err instanceof CustomAPIError) { + return res.status(err.statusCode).json({ msg: err.message }); } console.log(err); - return res.status(500).json({msg:`Something went wrong please try again later`}); -} + return res + .status(500) + .json({ msg: `Something went wrong please try again later` }); +}; -module.exports = {notFound, errorHandling}; \ No newline at end of file +module.exports = { notFound, errorHandling }; diff --git a/Code/backend/utils/generateToken.js b/Code/backend/utils/generateToken.js index 1ba2eabf..a547f6d4 100644 --- a/Code/backend/utils/generateToken.js +++ b/Code/backend/utils/generateToken.js @@ -1,10 +1,10 @@ -const jwt = require('jsonwebtoken'); -const { model } = require('mongoose'); +const jwt = require("jsonwebtoken"); +const { model } = require("mongoose"); const generateToken = async (id) => { - return jwt.sign( { id }, process.env.JWT_SECRET, { - expiresIn: '1h', - }); + return jwt.sign({ id }, process.env.JWT_SECRET, { + expiresIn: "1h", + }); }; -module.exports = { generateToken }; \ No newline at end of file +module.exports = { generateToken }; diff --git a/Code/backend/utils/parsingRecipeData.js b/Code/backend/utils/parsingRecipeData.js index f244348c..a5844dfc 100644 --- a/Code/backend/utils/parsingRecipeData.js +++ b/Code/backend/utils/parsingRecipeData.js @@ -1,12 +1,11 @@ - const parsingRecipeData = (req, res, next) => { - req.body.TranslatedRecipeName = req.body.recipe_name - req.body.CleanedIngredients = req.body.recipe_ingredients - req.body.Cuisine = req.body.recipe_cuisine - req.body.TotalTimeInMins = req.body.recipe_time - req.body.imageUrl = req.body.recipe_url - req.body.TranslatedInstructions = req.body.recipe_instructions + req.body.TranslatedRecipeName = req.body.recipe_name; + req.body.CleanedIngredients = req.body.recipe_ingredients; + req.body.Cuisine = req.body.recipe_cuisine; + req.body.TotalTimeInMins = req.body.recipe_time; + req.body.imageUrl = req.body.recipe_url; + req.body.TranslatedInstructions = req.body.recipe_instructions; next(); -} +}; -module.exports = parsingRecipeData \ No newline at end of file +module.exports = parsingRecipeData; diff --git a/Code/frontend/src/App.js b/Code/frontend/src/App.js index 17d935b8..c8aacd07 100644 --- a/Code/frontend/src/App.js +++ b/Code/frontend/src/App.js @@ -4,7 +4,7 @@ import AddRecipeForm from "./components/AddRecipeForm.js"; import Header from "./components/Header"; import recipeDB from "./apis/recipeDB"; import RecipeCard from "./components/RecipeCard"; -import styled from 'styled-components'; +import styled from "styled-components"; import React, { Component } from "react"; import { Route, @@ -57,7 +57,7 @@ class App extends Component { console.log("inside app.js", addRecipeDetails); const response = await recipeDB.post( "recipes/Addrecipes", - addRecipeDetails + addRecipeDetails, ); // this.setState({ // recipeList: response.data.recipes, @@ -77,7 +77,7 @@ class App extends Component { budget: formDict["budget"], }); - const items = Array.from(formDict["ingredient"]).join(' '); + const items = Array.from(formDict["ingredient"]).join(" "); const cuis = formDict["cuisine"]; const cook_time = formDict["time_to_cook"]; const budget = formDict["budget"]; @@ -85,12 +85,7 @@ class App extends Component { // alert(typeof(ingredientsInput["cuisine"])); }; - getRecipeDetails = async ( - ingredient, - cuis, - cook_time, - budget, - ) => { + getRecipeDetails = async (ingredient, cuis, cook_time, budget) => { console.log(ingredient, cuis, cook_time, budget); try { const response = await recipeDB.get(`/recipes?CleanedIngredients=${ingredient}&Cuisine=${cuis}&budget=${budget}&TotalTimeInMins=${cook_time}`).catch((err) => { @@ -137,9 +132,7 @@ class App extends Component { setLoginFlag={this.setLoginFlag} /> - +
@@ -191,4 +184,4 @@ const StyledFlexer = styled.div` align-items: flex-start; flex-wrap: wrap; margin-top: 28px; -`; \ No newline at end of file +`; diff --git a/Code/frontend/src/components/AddRecipeForm.js b/Code/frontend/src/components/AddRecipeForm.js index fabab18c..56ccdff5 100644 --- a/Code/frontend/src/components/AddRecipeForm.js +++ b/Code/frontend/src/components/AddRecipeForm.js @@ -1,13 +1,13 @@ import React, { Component } from "react"; -import { Redirect } from 'react-router-dom'; +import { Redirect } from "react-router-dom"; import recipeDB from "../apis/recipeDB"; -import styled from 'styled-components'; +import styled from "styled-components"; // Form component to maintain input form class Form extends Component { // constructor for Form Component // We maintain user input as a state object - + constructor() { super(); @@ -18,7 +18,7 @@ class Form extends Component { cuisineState: 0, cuisine: "", error: false, - redirect: false + redirect: false, }; } // function to send the data to the parent App component @@ -31,24 +31,24 @@ class Form extends Component { dict["recipe_ingredients"] = document.getElementById("recipe_ingredients").value; dict["recipe_instructions"] = document.getElementById( - "recipe_instructions" + "recipe_instructions", ).value; dict["recipe_time"] = document.getElementById("recipe_time").value; dict["recipe_url"] = document.getElementById("recipe_url").value; dict["recipe_budget"] = document.getElementById("recipe_budget").value; console.log(dict); - let all_val_filled = [] + let all_val_filled = []; Object.keys(dict).map((key, value) => { console.log(key, dict[key]); - if (dict[key] != ""){ - all_val_filled.push(key) - } - }) + if (dict[key] != "") { + all_val_filled.push(key); + } + }); // this.props.sendRecipeFormData(dict); console.log(all_val_filled); - if(all_val_filled.length == 6){ + if (all_val_filled.length == 6) { this.submitToApi(dict); this.setState({ // cuisine : "Any", @@ -57,7 +57,7 @@ class Form extends Component { cuisineState: 0, cuisine: "", redirect: true, - error: true + error: true, }); } else { this.setState({ @@ -67,7 +67,7 @@ class Form extends Component { cuisineState: 0, cuisine: "", redirect: false, - error: true + error: true, }); } }; @@ -79,14 +79,14 @@ class Form extends Component { console.log(err, err.message); }); if (response) { - console.log("Added...") + console.log("Added..."); } else { - console.log("Failed...") + console.log("Failed..."); } }; renderRedirect = () => { - return + return ; }; // render function dispays the UI content i.e the form content @@ -99,12 +99,14 @@ class Form extends Component {
Add a Recipe
- {this.state.error && Kindly fill all the fields.} + {this.state.error && ( + Kindly fill all the fields. + )}
- +
- +
@@ -113,7 +115,7 @@ class Form extends Component {

- +
@@ -122,7 +124,7 @@ class Form extends Component {

- +
@@ -131,7 +133,7 @@ class Form extends Component {

- +
@@ -140,15 +142,20 @@ class Form extends Component {

- +
- -
- @@ -199,4 +206,4 @@ const StyledError = styled.div` padding: 8px; margin: 8px auto; border-radius: 8px; -`; \ No newline at end of file +`; diff --git a/Code/frontend/src/components/Form.js b/Code/frontend/src/components/Form.js index 48a3d164..7f87eb82 100644 --- a/Code/frontend/src/components/Form.js +++ b/Code/frontend/src/components/Form.js @@ -1,7 +1,7 @@ import React, { Component } from "react"; -import { useHistory } from 'react-router-dom'; +import { useHistory } from "react-router-dom"; import recipeDB from "../apis/recipeDB"; -import styled from 'styled-components'; +import styled from "styled-components"; import RecipeCard from "./RecipeCard"; // Form component to maintain input form @@ -17,7 +17,7 @@ class Form extends Component { ingredients: new Set(), cuisineState: 0, cuisine: "", - recipes: [] + recipes: [], }; } @@ -52,7 +52,12 @@ class Form extends Component { // mapping each item to be displayed as a list item const list_items = items.map((item) => ( -
+
{" "} {item}
@@ -66,13 +71,18 @@ class Form extends Component { addHandler = (event) => { const ingredient = document.getElementById("ingredient").value; + if (ingredient.trim() === "") { + alert("Ingredient cannot be empty"); + return; + } + this.setState( { //cuisine : this.state.cuisine, //numberIngredients : this.state.numberIngredients, ingredients: new Set(this.state.ingredients).add(ingredient), }, - () => console.log(this.state) + () => console.log(this.state), ); document.getElementById("ingredient").value = ""; @@ -92,7 +102,7 @@ class Form extends Component { //numberIngredients : this.state.numberIngredients, ingredients: ingredientList, }, - () => console.log(this.state) + () => console.log(this.state), ); }; @@ -101,10 +111,22 @@ class Form extends Component { searchRecipe = async () => { const budget = document.getElementById("budget").value; - const time = document.getElementById("time_to_cook").value + const time = document.getElementById("time_to_cook").value; + + if (isNaN(budget) || budget <= 0) { + alert("Budget should be a positive number"); + return; + } + + if (isNaN(time) || time <= 0) { + alert("Time to cook should be a positive number"); + return; + } const response = await recipeDB - .get(`/recipes?CleanedIngredients=${this.state.ingredients}&Cuisine=${this.state.ingredients}&budget=${budget}&TotalTimeInMins=${time}`) + .get( + `/recipes?CleanedIngredients=${this.state.ingredients}&Cuisine=${this.state.ingredients}&budget=${budget}&TotalTimeInMins=${time}`, + ) .catch((err) => { console.log(err, err.message); }); @@ -116,34 +138,36 @@ class Form extends Component { ingredients: new Set(), cuisineState: 0, cuisine: "", - recipes: response.data.recipes + recipes: response.data.recipes, }); } else { - console.log("Failed...") + console.log("Failed..."); } }; - - handleSubmit = (event) => { - this.setState( { cuisine: document.getElementById("cuisine").value, }, - () => console.log(this.state) + () => console.log(this.state), ); + if (this.state.cuisine.trim() === "") { + alert("Cuisine cannot be empty"); + return; + } + event.preventDefault(); var dict = {}; dict["ingredient"] = this.state.ingredients; dict["cuisine"] = document.getElementById("cuisine").value; dict["time_to_cook"] = document.getElementById("time_to_cook").value; dict["budget"] = document.getElementById("budget").value; - dict["time_to_cook"] = document.getElementById("time_to_cook").value - + dict["time_to_cook"] = document.getElementById("time_to_cook").value; + console.log(dict); - + this.props.sendFormData(dict); document.getElementById("cuisine").value = ""; document.getElementById("time_to_cook").value = ""; @@ -160,18 +184,18 @@ class Form extends Component {
Search a Recipe
- +
-
+
- -
+ +
@@ -195,7 +219,11 @@ class Form extends Component {

- @@ -215,18 +243,14 @@ class Form extends Component {
- +
-
- -
-
+
+ +
+
); @@ -236,8 +260,8 @@ class Form extends Component { export default Form; const StyledHeader = styled.div` - font-size: 32px; - text-align: center; - margin: 22px auto; - font-weight: 800; -`; \ No newline at end of file + font-size: 32px; + text-align: center; + margin: 22px auto; + font-weight: 800; +`; diff --git a/Code/frontend/src/components/Header.js b/Code/frontend/src/components/Header.js index 5d4a036d..39ae0170 100644 --- a/Code/frontend/src/components/Header.js +++ b/Code/frontend/src/components/Header.js @@ -1,7 +1,6 @@ import React, { useState } from "react"; import { Redirect } from "react-router"; -import { useHistory } from 'react-router-dom'; - +import { useHistory } from "react-router-dom"; function Header(props) { const history = useHistory(); @@ -22,10 +21,28 @@ function Header(props) { ) : (
    -
  • history.push('/home')} style={{ cursor: "pointer" }}>Recipe Recommender
  • - -
  • history.push('/add-recipe')} style={{ cursor: "pointer" }}>Add Recipes
  • -
  • history.push('/search-recipe')} style={{ cursor: "pointer" }}>Search Recipes
  • +
  • history.push("/home")} + style={{ cursor: "pointer" }} + > + Recipe Recommender +
  • + +
  • history.push("/add-recipe")} + style={{ cursor: "pointer" }} + > + Add Recipes +
  • +
  • history.push("/search-recipe")} + style={{ cursor: "pointer" }} + > + Search Recipes +
)} @@ -35,4 +52,4 @@ function Header(props) { // ); } -export default Header; \ No newline at end of file +export default Header; diff --git a/Code/frontend/src/components/RecipeCard.js b/Code/frontend/src/components/RecipeCard.js index acc135be..ec5b72f7 100644 --- a/Code/frontend/src/components/RecipeCard.js +++ b/Code/frontend/src/components/RecipeCard.js @@ -1,7 +1,7 @@ -import React from 'react'; -import '../pages/auth/login.css'; +import React from "react"; +import "../pages/auth/login.css"; -import styled from 'styled-components'; +import styled from "styled-components"; const RecipeCard = ({ CleanedIngredients, @@ -12,20 +12,20 @@ const RecipeCard = ({ imageUrl, budget, }) => { - console.log(Cuisine); - const fetchYTId = url => { - if(url.length > 0){ - let tmp = url.split('be/')[1]; - tmp = tmp.split('?')[0]; - return tmp; - } - }; + console.log(Cuisine); + const fetchYTId = (url) => { + if (url.length > 0) { + let tmp = url.split("be/")[1]; + tmp = tmp.split("?")[0]; + return tmp; + } + }; - const ingredientList = CleanedIngredients => { - return CleanedIngredients.split(','); - }; + const ingredientList = (CleanedIngredients) => { + return CleanedIngredients.split(","); + }; - const url = fetchYTId(imageUrl); + const url = fetchYTId(imageUrl); return ( @@ -53,64 +53,66 @@ const RecipeCard = ({ ))} - - Instructions: {TranslatedInstructions} - - - ); + + Instructions: + {TranslatedInstructions} + + + ); }; -{/* +{ + /* -https://youtu.be/yDLPnEMzvYA?feature=shared */} +https://youtu.be/yDLPnEMzvYA?feature=shared */ +} export default RecipeCard; const StyledContainer = styled.div` - display: flex; - flex-direction: column; - width: 320px; - border-radius: 16px; - padding: 12px; - margin: 6px; - max-height: 500px; - overflow-y: scroll; + display: flex; + flex-direction: column; + width: 320px; + border-radius: 16px; + padding: 12px; + margin: 6px; + max-height: 500px; + overflow-y: scroll; `; const StyledFlexer = styled.div` - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: 100%; `; - const StyledRecipeName = styled.div` - font-weight: bold; - text-transform: uppercase; - font-size: 16px; - - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + font-weight: bold; + text-transform: uppercase; + font-size: 16px; + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; `; const StyledTime = styled.div` - background-color: #c8e6c9; - /* color: #43a047; + background-color: #c8e6c9; + /* color: #43a047; border: 2px solid #43a047; */ - padding: 4px; - border-radius: 8px; - min-width: 60px; + padding: 4px; + border-radius: 8px; + min-width: 60px; `; const StyledYtIFrame = styled.div` - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - margin: 8px auto; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + margin: 8px auto; `; const StyledIngridients = styled.div` @@ -130,16 +132,16 @@ const StyledIngridients = styled.div` `; const StyledIngredient = styled.div` - padding: 2px; - border-radius: 6px; + padding: 2px; + border-radius: 6px; `; const StyledInstructions = styled.div` - padding-top: 4px; - word-wrap: break-word; - text-align: left !important; - border-top: 4px solid #eeeeee; - margin-top: 10px; + padding-top: 4px; + word-wrap: break-word; + text-align: left !important; + border-top: 4px solid #eeeeee; + margin-top: 10px; `; const StyledBudget = styled.div` diff --git a/Code/frontend/src/index.js b/Code/frontend/src/index.js index ad9cbbbf..211e34a6 100644 --- a/Code/frontend/src/index.js +++ b/Code/frontend/src/index.js @@ -8,7 +8,7 @@ ReactDOM.render( , - document.getElementById("root") + document.getElementById("root"), ); // If you want to start measuring performance in your app, pass a function diff --git a/Code/frontend/src/pages/auth/login.js b/Code/frontend/src/pages/auth/login.js index e132c2d3..64000bb8 100644 --- a/Code/frontend/src/pages/auth/login.js +++ b/Code/frontend/src/pages/auth/login.js @@ -3,8 +3,8 @@ import recipeDB from "../../apis/recipeDB"; import { Redirect, withRouter } from "react-router"; import "./login.css"; import Header from "../../components/Header"; -import styled from 'styled-components'; -import { useHistory } from 'react-router-dom'; +import styled from "styled-components"; +import { useHistory } from "react-router-dom"; // import '../../node_modules/bootstrap/dist/css/bootstrap.css' function loginForm(props) { @@ -34,21 +34,16 @@ function loginForm(props) { username: state.username, password: state.password, }; - const response = await recipeDB - .post("/signIn", stateTemp) - .catch((err) => { - console.log(err, err.message); - }); + const response = await recipeDB.post("/signIn", stateTemp).catch((err) => { + console.log(err, err.message); + }); if (response) { setState((prevState) => ({ ...prevState, successMessage: "Login successful. Redirecting to home page..", failMessage: null, })); - sessionStorage.setItem( - "login_recipe_recommender", - state.username - ); + sessionStorage.setItem("login_recipe_recommender", state.username); props.setLoginFlag; props.history.push("/home"); } else { @@ -62,10 +57,10 @@ function loginForm(props) { return ( -
+
- SIGN IN + SIGN IN {state.failMessage}
) : null} - history.push("/sign-up")}>Sign-Up instead! + + history.push("/sign-up")}> + Sign-Up + {" "} + instead! +
diff --git a/Code/frontend/src/pages/auth/signup.js b/Code/frontend/src/pages/auth/signup.js index 7c5c1cc0..764d7071 100644 --- a/Code/frontend/src/pages/auth/signup.js +++ b/Code/frontend/src/pages/auth/signup.js @@ -2,8 +2,8 @@ import React, { useState, useContext } from "react"; import recipeDB from "../../apis/recipeDB"; import { Redirect, withRouter } from "react-router"; import "./login.css"; -import styled from 'styled-components'; -import { useHistory } from 'react-router-dom'; +import styled from "styled-components"; +import { useHistory } from "react-router-dom"; // import '../../node_modules/bootstrap/dist/css/bootstrap.css' function signupForm(props) { @@ -33,21 +33,16 @@ function signupForm(props) { username: state.username, password: state.password, }; - const response = await recipeDB - .post("/signUp", stateTemp) - .catch((err) => { - console.log(err, err.message); - }); + const response = await recipeDB.post("/signUp", stateTemp).catch((err) => { + console.log(err, err.message); + }); if (response) { setState((prevState) => ({ ...prevState, successMessage: "Sign Up successful. Redirecting to home page..", failMessage: null, })); - sessionStorage.setItem( - "login_recipe_recommender", - state.username - ); + sessionStorage.setItem("login_recipe_recommender", state.username); props.setLoginFlag; props.history.push("/login"); } else { @@ -61,10 +56,10 @@ function signupForm(props) { return ( -
+
- SIGN UP + SIGN UP {state.failMessage}
) : null} - history.push("/login")}>Sign-In instead! + + history.push("/login")}> + Sign-In + {" "} + instead! +
diff --git a/Code/frontend/src/pages/home/Home.js b/Code/frontend/src/pages/home/Home.js index 9701998b..d92edb84 100644 --- a/Code/frontend/src/pages/home/Home.js +++ b/Code/frontend/src/pages/home/Home.js @@ -1,20 +1,23 @@ -import React, { useState, useEffect } from 'react'; -import './Home.css' -import styled from 'styled-components'; +import React, { useState, useEffect } from "react"; +import "./Home.css"; +import styled from "styled-components"; -import recipeDB from '../../apis/recipeDB'; -import RecipeCard from '../../components/RecipeCard'; +import recipeDB from "../../apis/recipeDB"; +import RecipeCard from "../../components/RecipeCard"; const Home = () => { - const [allRecipes, setAllRecipes] = useState([{ - CleanedIngredients: "tmp", - Cuisine: "tmp", - TotalTimeInMins: "", - TranslatedInstructions: "", - TranslatedRecipeName: "", - imageUrl: "" - }]); + const [allRecipes, setAllRecipes] = useState([ + { + CleanedIngredients: "tmp", + Cuisine: "tmp", + TotalTimeInMins: "", + TranslatedInstructions: "", + TranslatedRecipeName: "", + imageUrl: "", + }, + ]); +<<<<<<< HEAD const fetchAllRecipe = async (dict) => { const response = await recipeDB .get("/recipes") @@ -28,15 +31,29 @@ const Home = () => { console.log("Failed...") } }; +======= + const fetchAllRecipe = async (dict) => { + const response = await recipeDB.get("/recipes").catch((err) => { + console.log(err, err.message); + }); + if (response) { + console.log(response.data); + setAllRecipes(response.data.recipes); + } else { + console.log("Failed..."); + } + }; +>>>>>>> bceff2b6e85447091cb39a5adbb268354d7c530b - useEffect(() => { - fetchAllRecipe(); - }, []); + useEffect(() => { + fetchAllRecipe(); + }, []); - useEffect(() => { - console.log(allRecipes) - }, [allRecipes]); + useEffect(() => { + console.log(allRecipes); + }, [allRecipes]); +<<<<<<< HEAD return ( My Recipes 😋 @@ -55,30 +72,49 @@ const Home = () => { ); +======= + return ( + + My Recipes 😋 + + {allRecipes.map((recipe) => ( + + ))} + + + ); +>>>>>>> bceff2b6e85447091cb39a5adbb268354d7c530b }; export default Home; const StyledHeader = styled.div` - font-size: 32px; - text-align: center; - margin: 22px auto; - font-weight: 800; + font-size: 32px; + text-align: center; + margin: 22px auto; + font-weight: 800; `; const StyledCenterFlexer = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - margin: auto; - text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: auto; + text-align: center; `; const StyledFlexer = styled.div` - display: flex; - flex-direction: row; - justify-content: center; - align-items: flex-start; - flex-wrap: wrap; -`; \ No newline at end of file + display: flex; + flex-direction: row; + justify-content: center; + align-items: flex-start; + flex-wrap: wrap; +`; diff --git a/README.md b/README.md index b7ad9b65..dfaebc38 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,10 @@ Source documentation can be found at: [Recipe Recommender Docs] https://github.c ### Installation: -- clone repository using `git clone https://github.com/PvPatel-1001/Recipe_Recommender.git` +- clone repository- + ``` + git clone https://github.com/Shubh-Nisar/Recipe_Recommender.git + ``` - setup for frontend open terminal and navigate to the **frontend** folder and execute the following: ``` @@ -230,7 +233,7 @@ Source documentation can be found at: [Recipe Recommender Docs] https://github.c - [x] Improved the code test coverage by adding more specialized test cases. - [x] Added demo video which shows how the user will interact with our software. --> -### Phase 3: + + +### Phase 4: + +- [x] Refurbished the backend code by cleaning the code +- [x] Built proper database schema and models +- [x] Developed codes for controllers and routes +- [x] Introduced Morgan for logging and cors +- [x] Introduced a proper authentication system by assigning and deleting json web tokens on log in and log out respectively +- [x] Encrypted the password on sign up which provides authenticity to the user password +- [x] Automated and wrote clean tests using chai and mocha +- [x] Revamped UI for seamless UI Exp +- [x] Added a signup page to add new users +- [x] Protected routes (unauthenticated users cannot view website contents) +- [x] Added react-router-dom to separate pages of interest (previously all cluttered in one page) +- [x] Home page now shows all the added recipes +- [x] add-recipe route to add a new recipe. +- [x] A budget field to later filter recipes using budget +- [x] search-recipe route filters recipes on the basis of filters provided by the user. +- [x] Folder restructuring to aid in code maintainability. +- [x] Organized file extensions. +- [x] Basic form validation added on forms +- [x] Use of functional components and ES6 format over the older class-based ES5 syntax +- [x] Use of react hooks and arrow functions +- [x] Styling using styled-components + +Regenerate ## Scope of improvement: @@ -274,6 +303,6 @@ Please see our [CONTRIBUTING.md](https://github.com/PvPatel-1001/Recipe_Recommen ## Acknowlegements -We would like to thank Professor Dr. Timothy Menzies for helping us understand the process of building a good Software Engineering project. We would also like to thank the teaching assistants Xiao Ling, Andre Lustosa, Kewen Peng and Weichen Shi for their support throughout the project. We would also like to extend our gratitude to previous group: (https://github.com/PvPatel-1001/Recipe_Recommender) +We would like to thank Professor Dr. Timothy Menzies for helping us understand the process of building a good Software Engineering project. We would also like to thank the teaching assistants San Gilson, Andre Lustosa, Xueqi (Sherry) Yang, Yasitha Rajapaksha and Rahul Yedida for their support throughout the project. We would also like to extend our gratitude to previous group: (https://github.com/thosaniparth/Recipe_Recommender)

Made with ❤️ on GitHub.

diff --git a/docs/README.md b/docs/README.md index 38eae1d5..9e8c861a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,6 +4,6 @@ North Carolina State University, CSC 510: Software Engineering, Group 2 ## Contributors -| | | | | -| --------------------------------------------- | ------------ | -------------- | -------------- | -| [Shubh Nisar](https://github.com/Shubh-Nisar) | Tanay Gandhi | [Neel Dudheliya](https://github.com/Neel317) | Tanishq Todkar | +| | | | | +| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------- | +| [Shubh Nisar](https://github.com/Shubh-Nisar) | Tanay Gandhi | [Neel Dudheliya](https://github.com/Neel317) | Tanishq Todkar |