From 6e10ac96ddb6f6164aa2a0bdae4766d847af3270 Mon Sep 17 00:00:00 2001 From: Harshita Date: Mon, 1 Jan 2024 22:54:04 +0530 Subject: [PATCH 1/8] recipe card modified, more recipe data fetched --- src/components/Recipe.css | 31 ++++ src/components/Recipe.js | 330 +++++++++++++------------------------- src/pages/Home.js | 69 +++----- 3 files changed, 168 insertions(+), 262 deletions(-) create mode 100644 src/components/Recipe.css diff --git a/src/components/Recipe.css b/src/components/Recipe.css new file mode 100644 index 0000000..2572ad6 --- /dev/null +++ b/src/components/Recipe.css @@ -0,0 +1,31 @@ +.card-title{ + font-size: 1.5rem; + font-weight: bold; + color: #FFFFEC; +} + +.tablerow{ + color: #F1E4C3; + font-size: 0.87rem; +} + +.tablerow-comp{ + font-size: 1rem; +} + +.morebtn{ + color: #FFB534; + font-size: 7px; + border: 1px solid #FFB534; + margin: 2px 5px; +} + +.inged-title{ + color: #F1E4C3; + font-size: 1.1rem; +} + +.inged-comp{ + color: #F1E4C3; + font-size: 0.87rem; +} \ No newline at end of file diff --git a/src/components/Recipe.js b/src/components/Recipe.js index e8ff0e9..075c0fa 100644 --- a/src/components/Recipe.js +++ b/src/components/Recipe.js @@ -1,209 +1,31 @@ import React, { useState,useEffect } from "react"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faStar, faArrowUp } from '@fortawesome/free-solid-svg-icons'; +import { faStar, faPlus, faArrowUp } from '@fortawesome/free-solid-svg-icons'; +import './Recipe.css'; export default function Recipe(props) { - const[starStyle1,setStar1]=useState( - { display:"inline-block", - width:20, - height:20, - color:"white", - margin:3 - - } - ); - const[starStyle2,setStar2]=useState( - { display:"inline-block", - width:20, - height:20, - color:"white", - margin:3 - - } - ); - const[starStyle3,setStar3]=useState( - { display:"inline-block", - width:20, - height:20, - color:"white", - margin:3 - - } - ); - const[starStyle4,setStar4]=useState( - { display:"inline-block", - width:20, - height:20, - color:"white", - margin:3 - - } - ); - const[starStyle5,setStar5]=useState( - { display:"inline-block", - width:20, - height:20, - color:"white", - margin:3 + const [stars, setStars] = useState(Array(5).fill({ color: "white" })); + const [showMoreHealth, setShowMoreHealth] = useState(false); + const [showMoreTags, setShowMoreTags] = useState(false); + + + const handleStarClick = (index) => { + const updatedStars = stars.map((star, i) => ({ + color: i <= index ? "yellow" : "white", + })); + setStars(updatedStars); + }; + + const handleShowMoreHealth = () => { + setShowMoreHealth(!showMoreHealth); + }; + + const handleShowMoreTags = () => { + setShowMoreTags(!showMoreTags); + }; - } - ); - function StarClicked(e) - {var target=parseInt(e.currentTarget.id); - console.log(target); - if(target===1) - { - setStar1( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - } - if(e.currentTarget.id==="2") - { - setStar1( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ); - setStar2( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - } - if(e.currentTarget.id==="3") - { - setStar1( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar2( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar3( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - } - if(e.currentTarget.id==="4") - { - setStar1( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar2( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar3( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar4( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - } - if(e.currentTarget.id==="5") - { - setStar1( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar2( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar3( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar4( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - setStar5( - { - display:"inline-block", - width:20, - height:20, - color:"yellow", - margin:3 - } - ) - } - } const scrollToTop = () => { window.scrollTo({ top: 0, @@ -228,25 +50,91 @@ export default function Recipe(props) { return ( <> -
+
-
-
+
+
{props.title}
-
+
+
{props.title} -
-

- Calories - {props.calories} -

-
    - {props.ingredients.map((i) => ( -
  1. {i.text}
  2. +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Calories{Math.floor(props.calories) || "NA"}
Diet{props.diet && props.diet.length > 0 ? props.diet.slice(0, 3).join(", ") : "NA"}
Cuisine Type{props.cuisineType && props.cuisineType.length > 0 ? props.cuisineType.slice(0, 3).join(", ") : "NA"}
Meal Type{props.mealType && props.mealType.length > 0 ? props.mealType.slice(0, 3).join(", ") : "NA"}
Dish Type{props.dishType && props.dishType.length > 0 ? props.dishType.slice(0, 3).join(", ") : "NA"}
Total Time{props.time > 0 ? `${props.time} minutes` : "NA"}
Health Labels + {props.health && props.health.length > 0 ? ( + <> + {showMoreHealth ? props.health.join(", ") : props.health.slice(0, 3).join(", ")} + {props.health.length > 3 && ( + + )} + + ) : "NA"} +
Tags + {props.tags && props.tags.length > 0 ? ( + <> + {showMoreTags ? props.tags.join(", ") : props.tags.slice(0, 3).join(", ")} + {props.tags.length > 3 && ( + + )} + + ) : "NA"} +
+
+ + +

Ingredients

+
    + {props.ingredients.map((ingredient, index) => ( +
  1. + {ingredient.text} +
  2. ))}
See the recipe -
- - - - - - +
+ {stars.map((star, index) => ( + handleStarClick(index)} + /> + ))}
); -} +}; diff --git a/src/pages/Home.js b/src/pages/Home.js index 22d244b..5a6471f 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -5,17 +5,22 @@ import mainLogo from "../components/icon.png"; import "../App.css"; export default function Home() { - const [visible, setVisible] = useState(3); + const [visible, setVisible] = useState(3); + const [recipes, setRecipes] = useState([]); + const [search, setSearch] = useState(""); + const [query, setQuery] = useState("bread"); + const [mode, setMode] = useState("light"); const showMoreItems = () => { setVisible((prevValue) => prevValue + 3); }; + const APP_ID = "d7811cd0"; const APP_KEY = "3baec572c48af715772e8deac52d7572"; const getRecipes = () => { fetch( - `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}` + `https://api.edamam.com/api/recipes/v2?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}&type=public` ) .then((response) => { return response.json(); @@ -26,10 +31,6 @@ export default function Home() { }); }; - const [recipes, setRecipes] = useState([]); - const [search, setSearch] = useState(""); - const [query, setQuery] = useState("bread"); - useEffect(() => { getRecipes(); }, [query]); @@ -37,12 +38,12 @@ export default function Home() { const handleSearch = (event) => { setSearch(event.target.value); }; + const getSearch = (e) => { e.preventDefault(); setQuery(search); }; - const [mode, setMode] = useState("light"); const [myStyle, setStyle] = useState({ color: "rgb(242, 198, 140)", }); @@ -61,46 +62,19 @@ export default function Home() { })*/ const toggleMode = () => { - if (mode === "light") { - setMode("dark"); - document.querySelector(".App").style.backgroundImage = - "radial-gradient(black,black,black)"; - - setStyle({ - color: "white", - }); - setCard({ - display: "inline-block", - width: 300, - marginLeft: 100, - marginTop: 5, - marginRight: 5, - backgroundColor: "black", - }); - } else { - setMode("light"); - document.querySelector(".App").style.backgroundImage = - "linear-gradient(to right, #aa8b56 0%, #f0ebce 100%)"; + const isLightMode = mode === "light"; + setMode(isLightMode ? "dark" : "light"); - setStyle({ - color: "black", - }); - setCard({ - display: "inline-block", - /* borderWidth:2, - borderStyle:"solid",*/ - backgroundColor: "#4e6c50", - width: 300, - marginLeft: 100, - marginTop: 5, - marginRight: 5, - }); - } + document.querySelector(".App").style.backgroundImage = isLightMode + ? "radial-gradient(black,black,black)" + : "linear-gradient(to right, #aa8b56 0%, #f0ebce 100%)"; }; return ( - <> + <> +
+
@@ -159,6 +140,8 @@ export default function Home() { Load More Recipes
+
+
) } \ No newline at end of file From 7e66fe00579b0a4af4a2b7af2a89094090467903 Mon Sep 17 00:00:00 2001 From: Harshita Date: Tue, 2 Jan 2024 17:33:57 +0530 Subject: [PATCH 2/8] filter feature added --- src/App.css | 35 +++++- src/components/FilterModal.css | 103 +++++++++++++++++ src/components/FilterModal.js | 199 +++++++++++++++++++++++++++++++++ src/pages/Home.js | 63 ++++++++--- 4 files changed, 384 insertions(+), 16 deletions(-) create mode 100644 src/components/FilterModal.css create mode 100644 src/components/FilterModal.js diff --git a/src/App.css b/src/App.css index b37f1fa..c7435ae 100644 --- a/src/App.css +++ b/src/App.css @@ -4,6 +4,17 @@ min-height: 100vh; background-image: linear-gradient(to right, #FFffff 0%, #B4CEFF 100%); } + +.light-mode { + background-image: linear-gradient(to right, #FFffff 0%, #B4CEFF 100%); + /* Other light mode styles */ +} + +.dark-mode { + background-image: radial-gradient(black, black, black); + /* Other dark mode styles */ +} + .search-form { min-height: 10vh; display: flex; @@ -11,6 +22,24 @@ align-items: center; margin-bottom: 50px; transition: 1s; + position: relative; +} + +.filter-btn { + background-color: #4caf50; + color: #fff; + border: none; + padding: 10px; + cursor: pointer; + margin: 10px; + border-radius: 5px; + display: flex; + align-items: center; + transition: background-color 0.3s ease; +} + +.filter-btn:hover { + background-color: #45a049; } .heading { display: flex; @@ -33,7 +62,7 @@ outline: 5px solid #4B3100; } .search-form:hover { - transform: scale(1.1); + transform: scale(0.97); } .search-btn:hover { background: rgb(255, 238, 170); @@ -67,7 +96,7 @@ } .button-container:hover { - transform: scale(1.1); + transform: scale(0.97); } .card { transition: 0.3s; @@ -153,6 +182,6 @@ body { } .btn-hover:hover { background-color: white; - color: black !important; /* Change text color on hover if needed */ + color: black !important; } diff --git a/src/components/FilterModal.css b/src/components/FilterModal.css new file mode 100644 index 0000000..3cd6736 --- /dev/null +++ b/src/components/FilterModal.css @@ -0,0 +1,103 @@ +.filter-modal { + display: none; + flex-wrap: wrap; + position: fixed; + top: 55%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1001; + background: #fff; + padding: 20px; + border-radius: 10px; + box-shadow: 0 0 15px rgba(0, 0, 0, 0.3); + max-height: 80vh; + overflow-y: auto; +} + +.modal-content { + border: #f6dc81 2px solid; +} + + +.filter-modal.open { + display: flex; +} + +.filter-section { + flex: 1 1 45%; + margin: 10px ; +} + +.checkbox-container { + display: flex; + flex-wrap: wrap; +} + +.checkbox-container label { + margin-right: 15px; +} + +.filter-modal h3 { + color: #333; + font-size: 1.2rem; + margin-bottom: 10px; +} + +.filter-modal label { + display: block; + margin-bottom: 8px; +} + +.filter-modal input { + margin-right: 8px; +} + +.filter-modal button { + background-color: #4caf50; + color: #f7eabe; + border: none; + padding: 10px 20px; + cursor: pointer; + border-radius: 5px; + margin: 0px 15px; + transition: background-color 0.3s ease; +} + +.filter-modal button:hover { + background-color: #45a049; + color: #f9f9f9; +} + +.modal-close-btn { + background: #ccc; + border: none; + padding: 10px 20px; + cursor: pointer; + border-radius: 5px; + margin-top: 15px; + margin-left: 10px; +} + +.buttons-container { + display: flex; + justify-content: center; + margin-top: 15px; + margin-bottom: 15px; +} + +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; + cursor: pointer; +} + +.separator { + width: 80%; + border-top: 2px solid #cba725; + margin: 10px auto; +} \ No newline at end of file diff --git a/src/components/FilterModal.js b/src/components/FilterModal.js new file mode 100644 index 0000000..3dcfcea --- /dev/null +++ b/src/components/FilterModal.js @@ -0,0 +1,199 @@ +import React from "react"; +import "./FilterModal.css"; + + +const FilterModal = ({ isOpen, onClose, onFilterApply }) => { + const diet = [ + "balanced", + "high-fiber", + "high-protein", + "low-carb", + "low-fat", + "low-sodium", + ]; + + const health = [ + "alcohol-cocktail", + "alcohol-free", + "celery-free", + "dairy-free", + "crustacean-free", + "DASH", + "egg-free", + "fish-free", + "fodmap-free", + "gluten-free", + "immuno-supportive", + "keto-friendly", + "kidney-friendly", + "kosher", + "low-fat-abs", + "low-potassium", + "low-sugar", + "lupine-free", + "Mediterranean", + "mollusk-free", + "mustard-free", + "no-oil-added", + "paleo", + "peanut-free", + "pascatarian", + "pork-free", + "red-meat-free", + "sesame-free", + "shellfish-free", + "soy-free", + "sugar-conscious", + "tree-nut-free", + "vegan", + "vegetarian", + "wheat-free" + ]; + + const cuisineType = [ + "American", + "Asian", + "British", + "Caribbean", + "Central Europe", + "Chinese", + "Eastern Europe", + "French", + "Indian", + "Italian", + "Japanese", + "Kosher", + "Mediterranean", + "Mexican", + "Middle Eastern", + "Nordic", + "South American", + "South East Asian" + ]; + + const mealType = ["Breakfast", "Lunch", "Dinner", "Snack", "Teatime"]; + + const dishType = [ + "biscuits and cookies", + "bread", + "cereals", + "condiments and sauces", + "Desserts", + "Drinks", + "Main course", + "Pancake", + "Preps", + "preserve", + "Salad", + "Sandwiches", + "Side dish", + "Soup", + "Starter", + "Sweets" + ]; + + const handleApplyFilters = () => { + // Combine selected values from all filters and pass them to the parent component + const selectedFilters = { + diet: diet.filter((label) => document.getElementById(`diet-${label}`).checked), + health: health.filter((label) => document.getElementById(`health-${label}`).checked), + cuisineType: cuisineType.filter((type) => document.getElementById(`cuisineType-${type}`).checked), + mealType: mealType.filter((type) => document.getElementById(`mealType-${type}`).checked), + dishType: dishType.filter((type) => document.getElementById(`dishType-${type}`).checked), + }; + + onFilterApply(selectedFilters); + }; + + return ( + <> + {isOpen && (
)} +
+
+ {/* Diet Labels */} +
+

Diet Labels

+
+ {diet.map((label) => ( + + ))} +
+
+ +
+ + {/* Meal Types */} +
+

Meal Types

+
+ {mealType.map((type) => ( + + ))} +
+
+ +
+ + {/* Health Labels */} +
+

Health Labels

+
+ {health.map((label) => ( + + ))} +
+
+ +
+ + {/* Cuisine Types */} +
+

Cuisine Types

+
+ {cuisineType.map((type) => ( + + ))} +
+
+ +
+ + {/* Dish Types */} +
+

Dish Types

+
+ {dishType.map((type) => ( + + ))} +
+
+ + {/* Apply and Close buttons */} +
+ + +
+
+
+ + ); +}; + +export default FilterModal; diff --git a/src/pages/Home.js b/src/pages/Home.js index 5a6471f..730ca4a 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import Recipe from "../components/Recipe"; import Navbar from "../components/Navbar"; import mainLogo from "../components/icon.png"; +import FilterModal from "../components/FilterModal"; import "../App.css"; export default function Home() { @@ -10,6 +11,8 @@ export default function Home() { const [search, setSearch] = useState(""); const [query, setQuery] = useState("bread"); const [mode, setMode] = useState("light"); + const [filterModalOpen, setFilterModalOpen] = useState(false); + const [selectedFilters, setSelectedFilters] = useState({}); const showMoreItems = () => { setVisible((prevValue) => prevValue + 3); @@ -19,21 +22,37 @@ export default function Home() { const APP_KEY = "3baec572c48af715772e8deac52d7572"; const getRecipes = () => { - fetch( - `https://api.edamam.com/api/recipes/v2?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}&type=public` - ) - .then((response) => { - return response.json(); - }) + let apiUrl = `https://api.edamam.com/api/recipes/v2?app_id=${APP_ID}&app_key=${APP_KEY}&type=public&q=${query}`; + + //console.log("selectedFilters: ", selectedFilters); + // Check if there are selected filters + if (Object.keys(selectedFilters).length > 0) { + const queryString = Object.entries(selectedFilters) + .map(([key, values]) => { + if (Array.isArray(values)) { + return values.map((value) => `${key}=${value}`).join("&"); + } else { + return `${key}=${values}`; + } + }) + .join("&"); + + apiUrl = `${apiUrl}&${queryString}`; + } + + //console.log("apiUrl: ", apiUrl); + + fetch(apiUrl) + .then((response) => response.json()) .then((data) => { setRecipes(data.hits); - //console.log(data); }); }; + useEffect(() => { getRecipes(); - }, [query]); + }, [query, selectedFilters]); const handleSearch = (event) => { setSearch(event.target.value); @@ -42,6 +61,7 @@ export default function Home() { const getSearch = (e) => { e.preventDefault(); setQuery(search); + setSelectedFilters({}); }; const [myStyle, setStyle] = useState({ @@ -63,17 +83,30 @@ export default function Home() { })*/ const toggleMode = () => { const isLightMode = mode === "light"; + setMode(isLightMode ? "dark" : "light"); document.querySelector(".App").style.backgroundImage = isLightMode ? "radial-gradient(black,black,black)" : "linear-gradient(to right, #aa8b56 0%, #f0ebce 100%)"; - }; + }; + + const openFilterModal = () => { + setFilterModalOpen(true); + }; + + const closeFilterModal = () => { + setFilterModalOpen(false); + }; + + const applyFilters = (filters) => { + setSelectedFilters(filters); + setFilterModalOpen(false); + }; return ( <> -
Search - + + + +
-
) } \ No newline at end of file From 4ce43843b5bb919576aac5d9a6a4f2df7e9e212c Mon Sep 17 00:00:00 2001 From: Harshita Date: Tue, 2 Jan 2024 18:38:56 +0530 Subject: [PATCH 3/8] routing and rendering of contact us page done --- src/App.js | 2 ++ src/components/Navbar.js | 6 +++--- src/pages/ContactUs.js | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 src/pages/ContactUs.js diff --git a/src/App.js b/src/App.js index ab5521e..e5f88c4 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,7 @@ import "./App.css"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import Profile from "./pages/Profile"; import Home from "./pages/Home"; +import ContactUs from "./pages/ContactUs"; function App() { return ( @@ -11,6 +12,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/components/Navbar.js b/src/components/Navbar.js index 20f62bc..5f7a9ee 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -89,9 +89,9 @@ export default function App() { diff --git a/src/pages/ContactUs.js b/src/pages/ContactUs.js new file mode 100644 index 0000000..b9dd7ea --- /dev/null +++ b/src/pages/ContactUs.js @@ -0,0 +1,11 @@ +import react from "react"; + +const ContactUs = () => { + return ( + <> +

Contact Us

+ + ) +} + +export default ContactUs; \ No newline at end of file From 76b90e48f6b9f58102afd005b8ef948ece16547e Mon Sep 17 00:00:00 2001 From: Harshita Date: Tue, 2 Jan 2024 20:04:35 +0530 Subject: [PATCH 4/8] contact us page frontend ready --- src/App.css | 2 +- src/components/ContactUs.css | 116 +++++++++++++++++++++++++++++++++++ src/components/ContactUs.js | 101 ++++++++++++++++++++++++++++++ src/pages/ContactUs.js | 19 +++++- 4 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 src/components/ContactUs.css create mode 100644 src/components/ContactUs.js diff --git a/src/App.css b/src/App.css index c7435ae..be1ddf2 100644 --- a/src/App.css +++ b/src/App.css @@ -11,7 +11,7 @@ } .dark-mode { - background-image: radial-gradient(black, black, black); + background-image: radial-gradient(black, rgb(9, 7, 43), rgb(3, 67, 67)); /* Other dark mode styles */ } diff --git a/src/components/ContactUs.css b/src/components/ContactUs.css new file mode 100644 index 0000000..e5b2cbb --- /dev/null +++ b/src/components/ContactUs.css @@ -0,0 +1,116 @@ + +.contact-us-container { + display: flex; + max-width: 900px; + margin: 0 auto; + margin-top: 10px; + padding: 20px; + background-color: #f4f4f4; + border-radius: 10px; + box-shadow: 0 0 15px rgba(0, 0, 0, 0.1); +} + +.left-section, +.right-section { + flex: 1; + padding: 20px; +} + +.right-heading{ + text-align: center; + font-size: 28px; + color: #000000; + margin-bottom: 20px; + text-transform: uppercase; + letter-spacing: 2px; + font-weight: bold; +} + +.left-heading{ + font-size: 21px; + color: #000000; + margin-bottom: 20px; + text-transform: uppercase; + letter-spacing: 2px; + font-weight: bold; +} + + +.left-section { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + background-color: #86c7c7; + border-radius: 10px; + padding: 30px; +} + +.right-section { + margin-left: 20px; +} + + +.form { + display: flex; + flex-direction: column; +} + +.label { + margin-bottom: 8px; + color:#4caf50; + font-weight: bold; + width: 100%; +} + +.input { + padding: 12px; + margin-bottom: 10px; + border: 1px solid #052e70; + border-radius: 6px; + background-color: #f9f9f9; + width: 100%; + transition: border-color 0.3s, box-shadow 0.3s; +} + +.input:focus { + border-color: #4caf50; + box-shadow: 0 0 8px rgba(76, 175, 80, 0.3); +} + +.submit-button { + background-color: #4caf50; + color: white; + padding: 12px; + border: none; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.3s; + width: 100%; +} + +.submit-button:hover { + background-color: #45a049; +} + +/* Updated Styles for Left Section */ +.left-section h2, +.left-section p { + color: #333; +} + +.left-section p { + margin-bottom: 20px; +} + +/* Add responsive styles as needed */ +@media screen and (max-width: 768px) { + .contact-us-container { + flex-direction: column; + } + + .right-section { + margin-left: 0; + margin-top: 20px; + } +} \ No newline at end of file diff --git a/src/components/ContactUs.js b/src/components/ContactUs.js new file mode 100644 index 0000000..0938d89 --- /dev/null +++ b/src/components/ContactUs.js @@ -0,0 +1,101 @@ +import React, { useState } from 'react'; +import './ContactUs.css'; + +const ContactUs = () => { + const [formData, setFormData] = useState({ + name: '', + email: '', + subject: '', + message: '', + }); + + const handleChange = (e) => { + setFormData({ + ...formData, + [e.target.name]: e.target.value, + }); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + // Add your logic for handling form submission (e.g., sending data to the server) + console.log('Form submitted:', formData); + // You may want to reset the form after submission + setFormData({ + name: '', + email: '', + subject: '', + message: '', + }); + }; + + return ( +
+
+

🌮 Discover Culinary Delights with Tasty Tips! 🍰

+

+ Have inquiries, thoughts, or delightful recipe ideas? Reach out to us through the form on the right. Your feedback is our recipe for success, and we're eager to connect with you! 📩 +

+

+ Ensure you share precise details in the form, enabling us to offer tailored assistance for a more delightful culinary experience. 🍳👩‍🍳 +

+
+ +
+

Contact Us

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ ); +}; + +export default ContactUs; \ No newline at end of file diff --git a/src/pages/ContactUs.js b/src/pages/ContactUs.js index b9dd7ea..ec340f0 100644 --- a/src/pages/ContactUs.js +++ b/src/pages/ContactUs.js @@ -1,11 +1,24 @@ import react from "react"; +import ContactUs from "../components/ContactUs"; +import Navbar from "../components/Navbar"; +import mainLogo from "../components/icon.png"; -const ContactUs = () => { + +const ContactUsP = () => { return ( <> -

Contact Us

+ + + ) } -export default ContactUs; \ No newline at end of file +export default ContactUsP; \ No newline at end of file From ee66a36f179825ef937d5feb174cb0a8bbef3b56 Mon Sep 17 00:00:00 2001 From: Harshita Date: Wed, 3 Jan 2024 15:29:05 +0530 Subject: [PATCH 5/8] backend server setup and contact us backend done --- backend/.gitignore | 130 ++++ backend/app.js | 28 + backend/config/config.env | 3 + backend/config/db.js | 12 + backend/controller/contact.js | 44 ++ backend/middleware/error.js | 27 + backend/models/contact.js | 30 + backend/package-lock.json | 1339 +++++++++++++++++++++++++++++++++ backend/package.json | 23 + backend/routers/contact.js | 12 + backend/server.js | 32 + backend/utils/errorHandler.js | 9 + 12 files changed, 1689 insertions(+) create mode 100644 backend/.gitignore create mode 100644 backend/app.js create mode 100644 backend/config/config.env create mode 100644 backend/config/db.js create mode 100644 backend/controller/contact.js create mode 100644 backend/middleware/error.js create mode 100644 backend/models/contact.js create mode 100644 backend/package-lock.json create mode 100644 backend/package.json create mode 100644 backend/routers/contact.js create mode 100644 backend/server.js create mode 100644 backend/utils/errorHandler.js diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..54eac45 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,130 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/backend/app.js b/backend/app.js new file mode 100644 index 0000000..99be9fe --- /dev/null +++ b/backend/app.js @@ -0,0 +1,28 @@ +import * as dotenv from "dotenv"; +import express from "express"; +import cors from "cors"; +import ErrorMiddleware from "./middleware/error.js"; + +//routes +import contact from "./routers/contact.js"; + +const app = express(); + +//config +dotenv.config({ path: "./config/config.env" }); + +//CORS +app.use(cors({origin:"*"})); + + +app.use(express.json({ limit: "10mb" })); +app.use(express.urlencoded({ limit: "10mb", extended: true })); + + +app.use("/api", contact); + + +// Custom Error Middleware +app.use(ErrorMiddleware); + +export default app; \ No newline at end of file diff --git a/backend/config/config.env b/backend/config/config.env new file mode 100644 index 0000000..39a6c63 --- /dev/null +++ b/backend/config/config.env @@ -0,0 +1,3 @@ +PORT = 7007 + +MONGO= mongodb+srv://chefbook:chefbook@cluster0.o3y0dz5.mongodb.net/ChefBook diff --git a/backend/config/db.js b/backend/config/db.js new file mode 100644 index 0000000..3598613 --- /dev/null +++ b/backend/config/db.js @@ -0,0 +1,12 @@ +import mongoose from "mongoose"; + +const Database = () => { + mongoose.connect(process.env.MONGO, { + }).then(() => { + console.log(`MongoDB Connected Successfully`); + }).catch((error) => { + console.error(`MongoDB Connection Error: ${error}`); + }); +} + +export default Database; \ No newline at end of file diff --git a/backend/controller/contact.js b/backend/controller/contact.js new file mode 100644 index 0000000..d10c08f --- /dev/null +++ b/backend/controller/contact.js @@ -0,0 +1,44 @@ +import Contact from "../models/contact.js"; + +//Create Faq Query +export const createContactQuery = async (req,res) => { + try{ + const newContactData = { + name: req.body.name, + email: req.body.email, + subject: req.body.subject, + message: req.body.message, + }; + + const contact = await Contact.create(newContactData); + + res.status(201).json({ + success: true, + message: "Your Tasty Inquiry is cooking! 🌮👩‍🍳 We've received your message and will whip up a response for you shortly. Stay tuned for more Tasty Tips!", + contact + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message, + }); + } +}; + + +// Get All Faq Queries +export const getallContactQ = async (req, res) => { + try { + const contact = await Contact.find().sort({ createdAt: -1 }); + + res.status(200).json({ + success: true, + contact, + }); + } catch (error) { + res.status(500).json({ + success: false, + message: error.message, + }); + } +}; \ No newline at end of file diff --git a/backend/middleware/error.js b/backend/middleware/error.js new file mode 100644 index 0000000..1f9d75a --- /dev/null +++ b/backend/middleware/error.js @@ -0,0 +1,27 @@ +import ErrorHandler from "../utils/errorHandler.js"; + +const errorHandlerMiddleware = (err, req, res, next) => { + err.statusCode = err.statusCode || 500; + err.message = err.message || "Internal server error"; + + // wrong MongoDB error + if (err.name === "CastError") { + const message = `Mongo DB Error: Resource not found. Invalid: ${err.path}`; + err = new ErrorHandler(message, 400); + } + + if (err.code === 11000) { + const existKey = Object.keys(err.keyValue)[0].split(".")[0]; + const message = `Already Exists ${existKey}`; + err = new ErrorHandler(message, 400); + } + + console.log(err); + res.status(err.statusCode).json({ + success: false, + error: err.message, + }); +}; + +export default errorHandlerMiddleware; + diff --git a/backend/models/contact.js b/backend/models/contact.js new file mode 100644 index 0000000..3eecee3 --- /dev/null +++ b/backend/models/contact.js @@ -0,0 +1,30 @@ +import mongoose from "mongoose"; +import validator from "validator"; + + +const ContactSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + }, + email:{ + type: String, + required: true, + validate: [validator.isEmail, "Please enter a valid email address"] + }, + subject: { + type: String, + required: true, + }, + message: { + type: String, + required: true, + }, + timestamp: { + type: Date, + default: Date.now, + }, +}); + + +export default mongoose.model("Contact", ContactSchema, "Contact"); diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000..da504ad --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,1339 @@ +{ + "name": "chefbook-backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "chefbook-backend", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.2", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-validator": "^7.0.1", + "mongoose": "^8.0.3", + "nodemon": "^3.0.2", + "validator": "^13.11.0" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.1.tgz", + "integrity": "sha512-t7c5K033joZZMspnHg/gWPE4kandgc2OxE74aYOtGKfgB9VPuVJPix0H6fhmm2erj5PBJ21mqcx34lpIGtUCsQ==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@types/node": { + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bson": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", + "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-validator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", + "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "dependencies": { + "lodash": "^4.17.21", + "validator": "^13.9.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz", + "integrity": "sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^2.6.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.0.3.tgz", + "integrity": "sha512-LJRT0yP4TW14HT4r2RkxqyvoTylMSzWpl5QOeVHTnRggCLQSpkoBdgbUtORFq/mSL2o9cLCPJz+6uzFj25qbHw==", + "dependencies": { + "bson": "^6.2.0", + "kareem": "2.5.1", + "mongodb": "6.2.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz", + "integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..d9bba8d --- /dev/null +++ b/backend/package.json @@ -0,0 +1,23 @@ +{ + "name": "chefbook-backend", + "version": "1.0.0", + "description": "", + "type": "module", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "nodemon server.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.2", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-validator": "^7.0.1", + "mongoose": "^8.0.3", + "nodemon": "^3.0.2", + "validator": "^13.11.0" + } +} diff --git a/backend/routers/contact.js b/backend/routers/contact.js new file mode 100644 index 0000000..dcb4fb5 --- /dev/null +++ b/backend/routers/contact.js @@ -0,0 +1,12 @@ +import {createContactQuery, getallContactQ} from "../controller/contact.js"; +import express from "express"; + + +const router = express.Router(); + +router.post("/contact", createContactQuery); + +router.get("/", getallContactQ); + + +export default router; \ No newline at end of file diff --git a/backend/server.js b/backend/server.js new file mode 100644 index 0000000..c7c391f --- /dev/null +++ b/backend/server.js @@ -0,0 +1,32 @@ +import app from "./app.js"; +import dotenv from "dotenv"; +import Database from "./config/db.js"; + +// config +dotenv.config({ path: "./config/config.env" }); + +// handling uncaught exception +process.on("uncaughtException", (err) => { + console.log(`Error: ${err.message}`); + console.log(`closing server due to uncaught exception!`); + + process.exit(1); +}); + +// Database Connection +Database(); + +// listening to PORT +app.listen(process.env.PORT, () => { + console.log(`Listenting on port ${process.env.PORT}`); +}); + + +// unhandled promise rejection +// process.on("unhandledRejection", (err) => { +// console.log(`Error: ${err.message}`); +// console.log(`closing server due to unhandled error!`); +// server.close(() => { +// process.exit(1); +// }); +// }); \ No newline at end of file diff --git a/backend/utils/errorHandler.js b/backend/utils/errorHandler.js new file mode 100644 index 0000000..d6ea0dd --- /dev/null +++ b/backend/utils/errorHandler.js @@ -0,0 +1,9 @@ +class ErrorHandler extends Error { + constructor(message, statusCode) { + super(message); + this.statusCode = statusCode; + Error.captureStackTrace(this, this.constructor); + } +} + +export default ErrorHandler; \ No newline at end of file From d27d7c27828c06dcd921c37e4e58f6938b3d4881 Mon Sep 17 00:00:00 2001 From: Harshita Date: Wed, 3 Jan 2024 15:57:36 +0530 Subject: [PATCH 6/8] contact api integrated --- package-lock.json | 34 +++++++++++++++++++++++ package.json | 1 + src/components/ContactUs.js | 55 ++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index a841913..cf05e23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "react-dom": "^17.0.2", "react-router-dom": "^6.21.1", "react-scripts": "^5.0.1", + "react-toastify": "^9.1.3", "web-vitals": "^2.1.2" } }, @@ -5417,6 +5418,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -13831,6 +13840,18 @@ } } }, + "node_modules/react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -20574,6 +20595,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -26495,6 +26521,14 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-toastify": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.1.3.tgz", + "integrity": "sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==", + "requires": { + "clsx": "^1.1.1" + } + }, "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", diff --git a/package.json b/package.json index 778ce08..6b63bb2 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react-dom": "^17.0.2", "react-router-dom": "^6.21.1", "react-scripts": "^5.0.1", + "react-toastify": "^9.1.3", "web-vitals": "^2.1.2" }, "scripts": { diff --git a/src/components/ContactUs.js b/src/components/ContactUs.js index 0938d89..cef5219 100644 --- a/src/components/ContactUs.js +++ b/src/components/ContactUs.js @@ -1,4 +1,6 @@ import React, { useState } from 'react'; +import { ToastContainer, toast } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; import './ContactUs.css'; const ContactUs = () => { @@ -16,17 +18,49 @@ const ContactUs = () => { }); }; - const handleSubmit = (e) => { + const handleSubmit = async (e) => { e.preventDefault(); - // Add your logic for handling form submission (e.g., sending data to the server) - console.log('Form submitted:', formData); - // You may want to reset the form after submission - setFormData({ - name: '', - email: '', - subject: '', - message: '', - }); + try{ + const response = await fetch('http://localhost:7007/api/contact', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData), + }); + + if(response.ok){ + const data = await response.json(); + //console.log(response); + toast.success(data.message, { + position: toast.POSITION.TOP_CENTER, + style: { + width: '400px', + }, + }); + + setFormData({ + name: '', + email: '', + subject: '', + message: '', + }); + + setTimeout(() => { + window.location.href = '/'; + }, 10000); + } else { + toast.error('Oops! Something went wrong. Please try again.', { + position: toast.POSITION.TOP_CENTER, + }); + console.error('Oops! Something went wrong.'); + } + } catch (error) { + toast.error('Oops! Something went wrong. Please try again.', { + position: toast.POSITION.TOP_CENTER, + }); + console.error('Error:', error); + } }; return ( @@ -94,6 +128,7 @@ const ContactUs = () => { + ); }; From 9cedd02817062df473bed37771fe2d030aaf4791 Mon Sep 17 00:00:00 2001 From: Harshita Deep <98738210+acecoder7@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:04:26 +0530 Subject: [PATCH 7/8] Update package.json --- backend/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index d9bba8d..dddf5c1 100644 --- a/backend/package.json +++ b/backend/package.json @@ -6,7 +6,8 @@ "main": "server.js", "scripts": { "start": "node server.js", - "dev": "nodemon server.js" + "dev": "nodemon server.js", + "build": "echo 'No build step needed for backend'" }, "author": "", "license": "ISC", From 2ba11636cc459aa1c7c672d4b147a6f9e59eacc8 Mon Sep 17 00:00:00 2001 From: Harshita Date: Wed, 3 Jan 2024 16:20:28 +0530 Subject: [PATCH 8/8] deployed backend and api endpoint updated --- backend/routers/contact.js | 4 ++-- src/components/ContactUs.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/routers/contact.js b/backend/routers/contact.js index dcb4fb5..c20c893 100644 --- a/backend/routers/contact.js +++ b/backend/routers/contact.js @@ -4,9 +4,9 @@ import express from "express"; const router = express.Router(); -router.post("/contact", createContactQuery); +router.post("/contact", createContactQuery); // https://codechef-bk.onrender.com/api/contact -router.get("/", getallContactQ); +router.get("/", getallContactQ); //https://codechef-bk.onrender.com/api/ export default router; \ No newline at end of file diff --git a/src/components/ContactUs.js b/src/components/ContactUs.js index cef5219..5efbeb9 100644 --- a/src/components/ContactUs.js +++ b/src/components/ContactUs.js @@ -21,7 +21,7 @@ const ContactUs = () => { const handleSubmit = async (e) => { e.preventDefault(); try{ - const response = await fetch('http://localhost:7007/api/contact', { + const response = await fetch('https://codechef-bk.onrender.com/api/contact', { method: 'POST', headers: { 'Content-Type': 'application/json'