├── .babelrc ├── .gitignore ├── .postcssrc ├── New Text Document.txt ├── Notes ├── 4. Notes provided.txt ├── Assignment1.txt ├── Assignment10 + notes.txt ├── Assignment11 + notes.txt ├── Assignment12 + notes.txt ├── Assignment13 + notes.txt ├── Assignment3.txt ├── Assignment4.txt ├── Assignment5 + notes.txt ├── Assignment6 + notes.txt ├── Assignment8.txt └── Assignment9 + notes.txt ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src ├── components │ ├── About.js │ ├── Body.js │ ├── Cart.js │ ├── Config.js │ ├── Contact.js │ ├── Error.js │ ├── Footer.js │ ├── Header.js │ ├── InputControl.js │ ├── ItemCardComponent.js │ ├── Login.js │ ├── MealComponent.js │ ├── OrderHistory.js │ ├── ProfileClass.js │ ├── ProfileFunction.js │ ├── RestaurantCard.js │ ├── RestaurantMenu.js │ ├── RestaurantMenuShimmer.js │ ├── SearchBar.js │ ├── ShimmerUI.js │ ├── ShimmerUICard.js │ ├── SignUp.js │ └── UpdateCartOnUserChange.js ├── firebase.js ├── script.js └── utils │ ├── PathContext.js │ ├── RestaurantContext.js │ ├── SearchTextContext.js │ ├── Store.js │ ├── UserContext.js │ ├── cartSlice.js │ ├── useOnlineStatus.js │ ├── useRestaurantMenu.js │ ├── userSlice.js │ └── utils.js ├── style.css └── tailwind.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | // with options 2 | // { 3 | // "plugins": [ ["transform-remove-console" , { 4 | // "exclude" : ["log"] 5 | // } 6 | // ]] 7 | // } 8 | //no options 9 | { 10 | "plugins": [ 11 | [ 12 | "transform-remove-console" 13 | ] 14 | ] 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | /.parcel-cache 8 | /dist 9 | 10 | # testing 11 | /coverage 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /.postcssrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": { 3 | "tailwindcss": {} 4 | } 5 | } -------------------------------------------------------------------------------- /New Text Document.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ajeet1606/Namaste-React/0bdb17a3a606be45de3ba27872dd7c21d8a833e6/New Text Document.txt -------------------------------------------------------------------------------- /Notes/4. Notes provided.txt: -------------------------------------------------------------------------------- 1 | Running Notes of @akshaymarch7 's session on 01-01-2023: 2 | 3 | Writing Scripts in package.json. 4 | 5 | *Q. What converts New Code to Older Code(For older version Browsers)? 6 | A: Babel 7 | We do not need to write polyfill. Babel does it automatically. 8 | 9 | npx - executing commands without downloading packages 10 | npm - will download required packages 11 | 12 | Note: Parcel will not remove console.log automatically. We need to configure for it. There is a package for it, named 'babel-plugin-transform-remove-console' either from babel website or npmjs website: npm install babel-plugin-transform-remove-console --save-dev /-D 13 | 14 | Usage: 1.via .babelrc (recommended) 15 | 2. via CLI 16 | 3. via NodeAPI 17 | 18 | React-key Reconciliation : 19 | When there are siblings in an array, we need to give keys for each sibling 20 | HW: Read about React-key Reconciliation from React Docs. 21 | 22 | React.createElement gives us an Object, which is then converted to html and puts into DOM 23 | JSX uses React.createElement (behind the scenes), which gives Object, and then into HTML, and it is put into DOM 24 | Babel does it. Babel converts JSX. JSX was developed by Facebook. 25 | Babel is must to use JSX. 26 | 27 | Q. Is JSX HTML inside JS? No. 28 | A: JSX is a HTML like Syntax, and not HTML inside JS. 29 | 30 | Babel: Compiler for JS. 31 | Read Babel Docs: babeljs.io 32 | Play with Babel in it's website. 33 | Babel comes along with Parcel. 34 | 35 | Also Go to it's GitHub Repo, and read about its algorithms. 36 | 37 | React Component: 38 | 2 Types: 39 | 1. Functional Component- NEW 40 | 2. Class Based Component - OLD 41 | 42 | Functional Comp is just a normal function that returns some piece of JSX, or a react element, or a function. 43 | 44 | Name of a Component starts with a Capital Letter (not mandatory, but good practice to use) 45 | 46 | If we have to write multiple lines to be returned in a component, we need to use ()and ; at the end. 47 | 48 | For Homework, use Normal Convention. 49 | 50 | Continued... Part 2 51 | 52 | Hope it was Helpful ?? 53 | Notes Part 2: 54 | 55 | Diff b/n React Element & React Component: 56 | 57 | React Element is returning an Object. 58 | React Component is a function that returns JSX, or a react element, or a function. 59 | 60 | Syntax When rendering: 61 | For React Element, We use root.render(element_name); 62 | For React Component, We use Angular brackets: root.render(); 63 | 64 | Any piece of Javascript code can be written within {} 65 | 66 | XSS - Cross site scripting (XSS) is an attack in which an attacker injects malicious executable scripts into the code of a trusted application or website. Attackers often initiate an XSS attack by sending a malicious link to a user and enticing the user to click it. 67 | 68 | JSX takes care of XSS. 69 | 70 | *Interview Q: Component Composition: 71 | A: Writing/ Passing component inside component. 72 | 73 | Home Work: 74 | 1. Read about React-key Reconciliation from React Docs. 75 | 2. Do Whatever Akshay did in the Session. 76 | 77 | * 78 | 79 | Hope it was Helpful ?? -------------------------------------------------------------------------------- /Notes/Assignment1.txt: -------------------------------------------------------------------------------- 1 | CHAPTER 1 - INCEPTION 2 | 3 | Ques: 1. What is Emmet? 4 | 5 | Ans: Emmet is a plug in for many popular text editors which greatly improves HTML & CSS workflow. 6 | 7 | Ques: 2. Difference between a Library & a Framework? 8 | 9 | Ans: Both frameworks and libraries are code written by someone else that is used to help solve common problems. 10 | A library is like going to Ikea. You already have a home, but you need a bit of help with furniture. You don’t feel like making your own table from scratch. Ikea allows you to pick and choose different things to go in your home. You are in control. 11 | 12 | A framework, on the other hand, is like building a model home. You have a set of blueprints and a few limited choices when it comes to architecture and design. Ultimately, the contractor and blueprint are in control. And they will let you know when and where you can provide your input. 13 | 14 | The Technical Difference 15 | The technical difference between a framework and library lies in a term called inversion of control. 16 | 17 | When you use a library, you are in charge of the flow of the application. You are choosing when and where to call the library. When you use a framework, the framework is in charge of the flow. It provides some places for you to plug in your code, but it calls the code you plugged in as needed. 18 | 19 | Ques: 3. What is CDN? Why we use it? 20 | Ans: A CDN improves efficiency by introducing intermediary servers between the client and the website server. These CDN servers manage some of the client-server communications. They decrease web traffic to the web server, reduce bandwidth consumption, and improve the user experience of your applications. 21 | 22 | Ques: 4. Why is React known as React? 23 | Ans: React is called "React" because of its core feature, which is its ability to "react" or respond dynamically to changes in data. React was originally created by Facebook in 2011 for use in their own web applications, and it was released as an open-source project in 2013. 24 | In a traditional JavaScript application, you need to look at what data changed and imperatively make changes to the DOM to keep it up-to-date. 25 | React takes a different approach. 26 | 27 | When your component is first initialized, the render method is called, generating a lightweight representation of your view. From that representation, a string of markup is produced, and injected into the document. When your data changes, the render method is called again. In order to perform updates as efficiently as possible, we diff the return value from the previous call to render with the new one, and generate a minimal set of changes to be applied to the DOM. 28 | 29 | Ques: 5. What is cross origin in script tag? 30 | Ans: The crossorigin attribute sets the mode of the request to an HTTP CORS Request. Web pages often make requests to load resources on other servers. Here is where CORS comes in. A cross-origin request is a request for a resource (e.g. style sheets, iframes, images, fonts, or scripts) from another domain. 31 | 32 | Ques: 6. Difference between React & ReactDOM? 33 | Ans: React: React is a javascript library, designed for building better user interfaces. 34 | 35 | React-DOM: React-DOM is a complimentary library to React which glues React to the browser DOM 36 | 37 | In a nutshell, Whenever we use component, classes, elements, etc. We’re using React and whenever we use methods like render() or findDOMNode() we’re using React-DOM. 38 | 39 | 40 | Ques: 7. Difference between React.development.js and React.production.js files via CDN? 41 | Ans: The development build is used - as the name suggests - for development reasons. You have Source Maps, debugging and often times hot reloading ability in those builds. The production build, on the other hand, runs in production mode which means this is the code running on your client's machine. 42 | 43 | Ques: 8: What is async and defer in script? 44 | Ans: When browser reads the web page, there are 2 things happening: 45 | 1. Parsing the HTML 46 | 2. Loading & Executing Scripts. 47 | There are 3 ways to define scripts in HTML file. 48 | 1. Direct way: 19 | 20 | 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "namaste-react", 3 | "version": "1.0.0", 4 | "description": "This is the start of Namaste React", 5 | "scripts": { 6 | "start": "parcel index.html", 7 | "build": "parcel build index.html", 8 | "test": "jest" 9 | }, 10 | "author": "Ajeet Patel", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@babel/core": "^7.21.3", 14 | "babel-plugin-transform-remove-console": "^6.9.4", 15 | "parcel": "^2.8.3", 16 | "postcss": "^8.4.21", 17 | "process": "^0.11.10", 18 | "tailwindcss": "^3.3.1" 19 | }, 20 | "dependencies": { 21 | "@reduxjs/toolkit": "^1.9.5", 22 | "firebase": "^9.21.0", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "react-loading-skeleton": "^3.2.0", 26 | "react-redux": "^8.0.5", 27 | "react-router-dom": "^6.10.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/About.js: -------------------------------------------------------------------------------- 1 | import { useLocation } from "react-router-dom"; 2 | import { useContext, useEffect } from "react"; 3 | import PathContext from "../utils/PathContext"; 4 | 5 | const About = () => { 6 | const {setCurrentPath} = useContext(PathContext); 7 | const {pathname} = useLocation(); 8 | 9 | useEffect(() => { 10 | setCurrentPath(pathname); 11 | }, []) 12 | 13 | return ( 14 | <> 15 |
16 | ″Our mission is to elevate the quality of life for the urban consumer 17 | with unparalleled convenience. Convenience is what makes us tick. It's 18 | what makes us get out of bed and say, "Let's do this." 19 |
20 | 21 | 22 | 23 |

What’s In Store For The Future?

24 | 25 |

Food Studio has grand plans to be India’s most loved hyperlocal player. It aims to be the most accessible platform on the network - reimagining the meaning of convenience in the country through a variety of service offerings.

26 | 27 |
28 |

Changing the Game

29 |
30 | 31 |

150000+ Restaurant Partners Countrywide

32 | 33 |

260000+ Delivery Executives

34 | 35 |

5000+ Employees across the Country

36 | 37 |

500+ Cites PAN India

38 | 39 |
40 |
41 | 42 | ); 43 | }; 44 | 45 | export default About; 46 | -------------------------------------------------------------------------------- /src/components/Body.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | import useOnlineStatus from "../utils/useOnlineStatus"; 4 | import { filterRestaurants } from "../utils/utils"; 5 | import { restaurants } from "./Config"; 6 | import RestaurantCard from "./RestaurantCard"; 7 | import ShimmerUI from "./ShimmerUI"; 8 | import SearchTextContext from "../utils/SearchTextContext"; 9 | import PathContext from "../utils/PathContext"; 10 | 11 | const Body = () => { 12 | const [filteredRestaurants, setFilteredRestaurants] = useState([]); 13 | const { searchTxt, setsearchTxt, searchTxtFound } = 14 | useContext(SearchTextContext); 15 | 16 | const { pathname } = useLocation(); 17 | const { setCurrentPath } = useContext(PathContext); 18 | 19 | useEffect(() => { 20 | setCurrentPath(pathname); 21 | setsearchTxt(""); 22 | }, []); 23 | 24 | // searching 25 | useEffect(() => { 26 | const result = filterRestaurants(searchTxt, restaurants); 27 | if (result.length === 0) { 28 | alert("No Restaurant Found"); 29 | } else { 30 | setFilteredRestaurants(result); 31 | } 32 | }, [searchTxtFound]); 33 | 34 | const isOnline = useOnlineStatus(); 35 | if (!isOnline) { 36 | alert("You're offline, Please check your internet connection"); 37 | return ; 38 | } 39 | 40 | return restaurants.length === 0 || filteredRestaurants.length === 0 ? ( 41 | 42 | ) : ( 43 | <> 44 |
45 | {filteredRestaurants.map((restaurant) => { 46 | return ; 47 | })} 48 |
49 | 50 | ); 51 | }; 52 | 53 | export default Body; 54 | -------------------------------------------------------------------------------- /src/components/Cart.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from "react"; 2 | import { useDispatch, useSelector, useStore } from "react-redux"; 3 | import { Link, useLocation } from "react-router-dom"; 4 | import { addItem, clearCart, removeItem } from "../utils/cartSlice"; 5 | import { IMG_CDN_URL } from "./Config"; 6 | import { auth, database } from "../firebase"; 7 | import OrderHistory from "./OrderHistory"; 8 | import PathContext from "../utils/PathContext"; 9 | 10 | const Cart = () => { 11 | //------------------------------------------- Initialisation area --------------------------------------- 12 | // State variables 13 | const [totalBill, setTotalBill] = useState(0); 14 | const [currentUser, setCurrentUser] = useState(null); 15 | 16 | // Subscribe to items array of cart slice in the store. 17 | const cartItems = useSelector((store) => store.cart.cartItems); 18 | 19 | //path will take you to respective restaurnat menu. 20 | const path = "/restaurant/" + cartItems.restaurant_id; 21 | 22 | const {setCurrentPath} = useContext(PathContext); 23 | const {pathname} = useLocation(); 24 | 25 | //--------------------------------------- useEffects -------------------------------------------------- 26 | useEffect(()=> { 27 | setCurrentPath(pathname); 28 | }, []) 29 | 30 | useEffect(() => { 31 | let total = 0; 32 | cartItems.items.forEach((cur) => { 33 | if (cur.price != "NaN") total += (cur.price / 100) * cur.quantity; 34 | }); 35 | total.toFixed(2); 36 | setTotalBill(total); 37 | }, []); 38 | 39 | useEffect(() => { 40 | const unsubscribe = auth.onAuthStateChanged((user) => { 41 | if (user) { 42 | setCurrentUser(user); 43 | } else { 44 | setCurrentUser(null); 45 | } 46 | }); 47 | 48 | return () => { 49 | unsubscribe(); 50 | }; 51 | }, []); 52 | 53 | //--------------------------------------- Cart modifications ------------------------------------------ 54 | 55 | const dispatch = useDispatch(); 56 | const store = useStore(); 57 | 58 | // Add menu in cart 59 | const addMenu = (curItem) => { 60 | dispatch(addItem(curItem)); 61 | setTotalBill(totalBill + curItem.price / 100); 62 | }; 63 | 64 | //remove menu 65 | const removeMenu = (curItem) => { 66 | dispatch(removeItem(curItem)); 67 | const bill = Math.max(0, totalBill - curItem.price / 100); 68 | setTotalBill(bill); 69 | }; 70 | 71 | //---------------------------------------- Checkout -> Push data to Firebase RTDB ----------------------- 72 | 73 | const handleClick = () => { 74 | //check if user is logged in. 75 | if (!currentUser) { 76 | alert("Please Login/Sign up first to place an order"); 77 | return; 78 | } 79 | 80 | //fetch cart items from redux store. 81 | const cartState = store.getState().cart; 82 | const cartItems = cartState.cartItems; 83 | 84 | //user details 85 | const uid = currentUser.uid; 86 | const databaseRef = database.ref("users/" + uid); 87 | const newChildRef = databaseRef.push(); 88 | newChildRef.set(cartItems); 89 | 90 | alert("Order Successful"); 91 | dispatch(clearCart()); 92 | }; 93 | 94 | //---------------------------------------- Rendering area ----------------------------------------------- 95 | 96 | return ( 97 | <> 98 |
99 | {/* account details side */} 100 |
101 | {/* Account */} 102 |
103 |

Account

104 | 105 | {currentUser ? ( 106 |
107 | {/* personal information */} 108 |
109 |

110 | Personal Information 111 |

112 |

113 | Name: {currentUser.displayName} 114 |

115 |

116 | Email: {currentUser.email} 117 |

118 |
119 | {/* Order History */} 120 |
121 |

122 | Order History 123 |

124 | 125 |
126 |
127 | ) : ( 128 |
129 |

130 | To place your order now, log in to your existing account or 131 | sign up. 132 |

133 | 134 | 138 | 139 | 140 | 144 | 145 |
146 | )} 147 |
148 | {/* Delivery Address */} 149 |
150 |

Delivery Address

151 |
152 | {/* payment */} 153 |
154 |

Payment

155 |
156 |
157 | 158 | {/* Cart details side */} 159 | {cartItems.items.length > 0 && ( 160 |
161 | {/* restaurant details */} 162 |
163 |
164 | 165 | 170 | 171 |
172 |
173 |

174 | {cartItems.restaurantName} 175 |

176 |

{cartItems.areaName}

177 |
178 |
179 | 180 | {/* menu items list */} 181 | {/* Title, buttons to change quantity, price per piece */} 182 |
183 | {cartItems.items.map((curItem) => { 184 | return ( 185 |
186 |

{curItem.name}

187 |
188 | 189 | 190 |

{curItem.quantity}

191 | 192 | 193 |
194 |

195 | {(curItem.price / 100) * curItem.quantity}Rs 196 |

197 |
198 | ); 199 | })} 200 |
201 | {/* Total Charge */} 202 | 203 |
204 |

Total Amount to Pay:

205 |

{totalBill}Rs

206 |
207 | 208 |
209 | 217 | 223 |
224 |
225 | )} 226 |
227 | 228 | ); 229 | }; 230 | 231 | export default Cart; 232 | -------------------------------------------------------------------------------- /src/components/Config.js: -------------------------------------------------------------------------------- 1 | //Store all constants data. 2 | export const FOOD_STDUIO_LOGO = 3 | "https://corsproxy.io/?https://food-studio.co.za/wp-content/uploads/2019/08/Food-Studio-Logo.png"; 4 | 5 | export const IMG_CDN_URL = 6 | "https://corsproxy.io/?https://res.cloudinary.com/swiggy/image/upload/fl_lossy,f_auto,q_auto,w_508,h_320,c_fill/"; 7 | 8 | //unused 9 | export const GET_RESTAURANT_URL = 10 | "https://corsproxy.io/?https://www.swiggy.com/dapi/restaurants/list/v5?lat=25.4358011&lng=81.846311&is-seo-homepage-enabled=true&page_type=DESKTOP_WEB_LISTING"; 11 | 12 | export const FETCH_MENU_URL_FIRST_PART = 13 | "https://corsproxy.io/?https://www.swiggy.com/dapi/menu/pl?page-type=REGULAR_MENU&complete-menu=true&lat=25.4358011&lng=81.846311&restaurantId="; 14 | 15 | export const FETCH_MENU_URL_SECOND_PART = "&submitAction=ENTER"; 16 | 17 | // whole array 18 | 19 | export const restaurants = [ 20 | { 21 | info: { 22 | id: "224920", 23 | name: "Chandralok Kachouri", 24 | cloudinaryImageId: "qbo11lh7l43xpkd7wqts", 25 | locality: "Kp Kakkar Road", 26 | areaName: "Rambagh", 27 | costForTwo: "₹150 for two", 28 | cuisines: ["Snacks", "South Indian", "Chinese", "Fast Food", "Pizzas"], 29 | avgRating: 4, 30 | veg: true, 31 | feeDetails: { 32 | restaurantId: "224920", 33 | fees: [ 34 | { name: "BASE_DISTANCE", fee: 1900 }, 35 | { name: "BASE_TIME" }, 36 | { name: "ANCILLARY_SURGE_FEE" }, 37 | ], 38 | totalFee: 1900, 39 | }, 40 | parentId: "57887", 41 | avgRatingString: "4.0", 42 | totalRatingsString: "5K+", 43 | }, 44 | }, 45 | { 46 | info: { 47 | id: "147619", 48 | name: "Jai Shree Shankar Punjabi Dhaba", 49 | cloudinaryImageId: "slfbprrckr7jk1zm58rd", 50 | locality: "Mahatma Gandhi Marg", 51 | areaName: "Civil Lines", 52 | costForTwo: "₹250 for two", 53 | cuisines: [ 54 | "Indian", 55 | "North Indian", 56 | "Chinese", 57 | "South Indian", 58 | "Snacks", 59 | "Punjabi", 60 | "Beverages", 61 | ], 62 | avgRating: 3.6, 63 | veg: true, 64 | feeDetails: { 65 | restaurantId: "147619", 66 | fees: [ 67 | { name: "BASE_DISTANCE", fee: 2500 }, 68 | { name: "BASE_TIME" }, 69 | { name: "ANCILLARY_SURGE_FEE" }, 70 | ], 71 | totalFee: 2500, 72 | }, 73 | parentId: "108723", 74 | avgRatingString: "3.6", 75 | totalRatingsString: "10K+", 76 | }, 77 | }, 78 | { 79 | info: { 80 | id: "127614", 81 | name: "Statesman House", 82 | cloudinaryImageId: "98588793791dd32f2daa7e3595fcb69c", 83 | locality: "Hewett Road", 84 | areaName: "Rambagh", 85 | costForTwo: "₹300 for two", 86 | cuisines: ["North Indian", "Chinese"], 87 | avgRating: 3.8, 88 | feeDetails: { 89 | restaurantId: "127614", 90 | fees: [ 91 | { name: "BASE_DISTANCE", fee: 1900 }, 92 | { name: "BASE_TIME" }, 93 | { name: "ANCILLARY_SURGE_FEE" }, 94 | ], 95 | totalFee: 1900, 96 | }, 97 | parentId: "195577", 98 | avgRatingString: "3.8", 99 | totalRatingsString: "5K+", 100 | }, 101 | }, 102 | { 103 | info: { 104 | id: "380152", 105 | name: "The Quick Curry", 106 | cloudinaryImageId: "aq5uredkyfrmct6a99cv", 107 | locality: "Vivekanand Marg", 108 | areaName: "Leader Road", 109 | costForTwo: "₹250 for two", 110 | cuisines: ["Thalis", "North Indian"], 111 | avgRating: 3.8, 112 | veg: true, 113 | feeDetails: { 114 | restaurantId: "380152", 115 | fees: [ 116 | { name: "BASE_DISTANCE", fee: 1900 }, 117 | { name: "BASE_TIME" }, 118 | { name: "ANCILLARY_SURGE_FEE" }, 119 | ], 120 | totalFee: 1900, 121 | }, 122 | parentId: "212902", 123 | avgRatingString: "3.8", 124 | totalRatingsString: "1K+", 125 | }, 126 | }, 127 | { 128 | info: { 129 | id: "666981", 130 | name: "Fire House Pizza", 131 | cloudinaryImageId: "906c0affa7d8ff78a3e4db88b4433cde", 132 | locality: "Neta nagar", 133 | areaName: "Civil Lines", 134 | costForTwo: "₹600 for two", 135 | cuisines: ["Pizzas"], 136 | avgRating: 3.6, 137 | veg: true, 138 | feeDetails: { 139 | restaurantId: "666981", 140 | fees: [ 141 | { name: "BASE_DISTANCE", fee: 1900 }, 142 | { name: "BASE_TIME" }, 143 | { name: "ANCILLARY_SURGE_FEE" }, 144 | ], 145 | totalFee: 1900, 146 | }, 147 | parentId: "79622", 148 | avgRatingString: "3.6", 149 | totalRatingsString: "10+", 150 | }, 151 | }, 152 | { 153 | info: { 154 | id: "481918", 155 | name: "Al-Baik Zone", 156 | cloudinaryImageId: "mra2lrsmgduhwswzzee0", 157 | locality: "Nakhas Kona", 158 | areaName: "Leader Road", 159 | costForTwo: "₹200 for two", 160 | cuisines: ["Fast Food", "Arabian", "Biryani"], 161 | avgRating: 4, 162 | feeDetails: { 163 | restaurantId: "481918", 164 | fees: [ 165 | { name: "BASE_DISTANCE", fee: 1900 }, 166 | { name: "BASE_TIME" }, 167 | { name: "ANCILLARY_SURGE_FEE" }, 168 | ], 169 | totalFee: 1900, 170 | }, 171 | parentId: "8049", 172 | avgRatingString: "4.0", 173 | totalRatingsString: "100+", 174 | }, 175 | }, 176 | { 177 | info: { 178 | id: "80312", 179 | name: "Raju Kitchen Restaurant", 180 | cloudinaryImageId: "u8m5sxxbwuwfjolzdf69", 181 | locality: "Tandon Road", 182 | areaName: "Civil Lines", 183 | costForTwo: "₹200 for two", 184 | cuisines: [ 185 | "Indian", 186 | "Chinese", 187 | "Mughlai", 188 | "North Indian", 189 | "Snacks", 190 | "Lucknowi", 191 | "Biryani", 192 | ], 193 | avgRating: 3.7, 194 | feeDetails: { 195 | restaurantId: "80312", 196 | fees: [ 197 | { name: "BASE_DISTANCE", fee: 2500 }, 198 | { name: "BASE_TIME" }, 199 | { name: "ANCILLARY_SURGE_FEE" }, 200 | ], 201 | totalFee: 2500, 202 | }, 203 | parentId: "165971", 204 | avgRatingString: "3.7", 205 | totalRatingsString: "10K+", 206 | }, 207 | }, 208 | { 209 | info: { 210 | id: "404669", 211 | name: "Momos castle", 212 | cloudinaryImageId: "lubiprpdt4cgnunga3rr", 213 | locality: "Sardar Patel Marg", 214 | areaName: "Civil Lines", 215 | costForTwo: "₹150 for two", 216 | cuisines: ["Chinese"], 217 | avgRating: 4.3, 218 | feeDetails: { 219 | restaurantId: "404669", 220 | fees: [ 221 | { name: "BASE_DISTANCE", fee: 2500 }, 222 | { name: "BASE_TIME" }, 223 | { name: "ANCILLARY_SURGE_FEE" }, 224 | ], 225 | totalFee: 2500, 226 | }, 227 | parentId: "250870", 228 | avgRatingString: "4.3", 229 | totalRatingsString: "100+", 230 | }, 231 | }, 232 | { 233 | info: { 234 | id: "147244", 235 | name: "Delight The Pastry Shop", 236 | cloudinaryImageId: "dlx59kcbntvnlf8igifw", 237 | locality: "Jahid Complex", 238 | areaName: "Kareli", 239 | costForTwo: "₹200 for two", 240 | cuisines: ["Bakery", "Chinese", "Biryani", "Snacks"], 241 | avgRating: 4.1, 242 | feeDetails: { 243 | restaurantId: "147244", 244 | fees: [ 245 | { name: "BASE_DISTANCE", fee: 2500 }, 246 | { name: "BASE_TIME" }, 247 | { name: "ANCILLARY_SURGE_FEE" }, 248 | ], 249 | totalFee: 2500, 250 | }, 251 | parentId: "70572", 252 | avgRatingString: "4.1", 253 | totalRatingsString: "1K+", 254 | }, 255 | }, 256 | { 257 | info: { 258 | id: "80427", 259 | name: "Jai Shree Shankar Bhojanalaya", 260 | cloudinaryImageId: "qhdec9rh38ewnb80tkim", 261 | locality: "Mahatma Gandhi Marg", 262 | areaName: "Civil Lines", 263 | costForTwo: "₹250 for two", 264 | cuisines: [ 265 | "North Indian", 266 | "Thalis", 267 | "South Indian", 268 | "Chinese", 269 | "Snacks", 270 | "Indian", 271 | ], 272 | avgRating: 3.7, 273 | veg: true, 274 | feeDetails: { 275 | restaurantId: "80427", 276 | fees: [ 277 | { 278 | name: "BASE_DISTANCE", 279 | fee: 1900, 280 | }, 281 | { 282 | name: "BASE_TIME", 283 | }, 284 | { 285 | name: "ANCILLARY_SURGE_FEE", 286 | }, 287 | ], 288 | totalFee: 1900, 289 | }, 290 | parentId: "108722", 291 | avgRatingString: "3.7", 292 | totalRatingsString: "10K+", 293 | }, 294 | }, 295 | { 296 | info: { 297 | id: "80703", 298 | name: "Aryan Family's Delight", 299 | cloudinaryImageId: "kb34u4pywk49ksbyn4g5", 300 | locality: "Sardar Patel Marg", 301 | areaName: "Civil Lines", 302 | costForTwo: "₹400 for two", 303 | cuisines: [ 304 | "North Indian", 305 | "South Indian", 306 | "Fast Food", 307 | "Snacks", 308 | "Burgers", 309 | "Chinese", 310 | ], 311 | avgRating: 4.2, 312 | feeDetails: { 313 | restaurantId: "80703", 314 | fees: [ 315 | { 316 | name: "BASE_DISTANCE", 317 | fee: 2500, 318 | }, 319 | { 320 | name: "BASE_TIME", 321 | }, 322 | { 323 | name: "ANCILLARY_SURGE_FEE", 324 | }, 325 | ], 326 | totalFee: 2500, 327 | }, 328 | parentId: "6001", 329 | avgRatingString: "4.2", 330 | totalRatingsString: "10K+", 331 | }, 332 | }, 333 | { 334 | info: { 335 | id: "87514", 336 | name: "Haldiram Bhujiawala", 337 | cloudinaryImageId: "nkd7purcqzconoypeto9", 338 | locality: "Tashkent Marg", 339 | areaName: "Civil Lines", 340 | costForTwo: "₹300 for two", 341 | cuisines: [ 342 | "Sweets", 343 | "North Indian", 344 | "South Indian", 345 | "Chinese", 346 | "Desserts", 347 | "Indian", 348 | "Fast Food", 349 | ], 350 | avgRating: 3.7, 351 | veg: true, 352 | feeDetails: { 353 | restaurantId: "87514", 354 | fees: [ 355 | { 356 | name: "BASE_DISTANCE", 357 | fee: 2500, 358 | }, 359 | { 360 | name: "BASE_TIME", 361 | }, 362 | { 363 | name: "ANCILLARY_SURGE_FEE", 364 | }, 365 | ], 366 | totalFee: 2500, 367 | }, 368 | parentId: "92848", 369 | avgRatingString: "3.7", 370 | totalRatingsString: "10K+", 371 | }, 372 | }, 373 | { 374 | info: { 375 | id: "128962", 376 | name: "Pizza Club 99", 377 | cloudinaryImageId: "yxkkxyhgvcb0mkmneoj6", 378 | locality: "Gulteria", 379 | areaName: "Dhoomanganj", 380 | costForTwo: "₹300 for two", 381 | cuisines: ["Pizzas", "Fast Food", "Beverages"], 382 | avgRating: 3.7, 383 | feeDetails: { 384 | restaurantId: "128962", 385 | fees: [ 386 | { 387 | name: "BASE_DISTANCE", 388 | fee: 4400, 389 | }, 390 | { 391 | name: "BASE_TIME", 392 | }, 393 | { 394 | name: "ANCILLARY_SURGE_FEE", 395 | }, 396 | ], 397 | totalFee: 4400, 398 | }, 399 | parentId: "13512", 400 | avgRatingString: "3.7", 401 | totalRatingsString: "5K+", 402 | }, 403 | }, 404 | { 405 | info: { 406 | id: "80216", 407 | name: "Hot Stuff", 408 | cloudinaryImageId: "beeaadg3lqjics4fzuvw", 409 | locality: "Lal Bhadhur Shastri Marg", 410 | areaName: "Civil Lines", 411 | costForTwo: "₹200 for two", 412 | cuisines: ["North Indian", "Beverages", "Desserts", "Pizzas"], 413 | avgRating: 3.8, 414 | feeDetails: { 415 | restaurantId: "80216", 416 | fees: [ 417 | { 418 | name: "BASE_DISTANCE", 419 | fee: 2500, 420 | }, 421 | { 422 | name: "BASE_TIME", 423 | }, 424 | { 425 | name: "ANCILLARY_SURGE_FEE", 426 | }, 427 | ], 428 | totalFee: 2500, 429 | }, 430 | parentId: "97558", 431 | avgRatingString: "3.8", 432 | totalRatingsString: "1K+", 433 | }, 434 | }, 435 | { 436 | info: { 437 | id: "150376", 438 | name: "Shri Ram Shakahari Bhojnalaya", 439 | cloudinaryImageId: "suz4we5x7dgznrquxvu9", 440 | locality: "Katju Road", 441 | areaName: "Leader Road", 442 | costForTwo: "₹200 for two", 443 | cuisines: ["North Indian"], 444 | avgRating: 4.1, 445 | veg: true, 446 | feeDetails: { 447 | restaurantId: "150376", 448 | fees: [ 449 | { 450 | name: "BASE_DISTANCE", 451 | fee: 1900, 452 | }, 453 | { 454 | name: "BASE_TIME", 455 | }, 456 | { 457 | name: "ANCILLARY_SURGE_FEE", 458 | }, 459 | ], 460 | totalFee: 1900, 461 | }, 462 | parentId: "186817", 463 | avgRatingString: "4.1", 464 | totalRatingsString: "10K+", 465 | }, 466 | }, 467 | { 468 | info: { 469 | id: "314904", 470 | name: "Capsicum", 471 | cloudinaryImageId: "60d52c0fb85ea4f566864b2709538d6f", 472 | locality: "Mahewa Purab Patti", 473 | areaName: "Naini", 474 | costForTwo: "₹200 for two", 475 | cuisines: ["Chinese", "Pizzas", "Pastas", "Snacks", "Beverages"], 476 | avgRating: 3.5, 477 | feeDetails: { 478 | restaurantId: "314904", 479 | fees: [ 480 | { 481 | name: "BASE_DISTANCE", 482 | fee: 2500, 483 | }, 484 | { 485 | name: "BASE_TIME", 486 | }, 487 | { 488 | name: "ANCILLARY_SURGE_FEE", 489 | }, 490 | ], 491 | totalFee: 2500, 492 | }, 493 | parentId: "55813", 494 | avgRatingString: "3.5", 495 | totalRatingsString: "100+", 496 | }, 497 | }, 498 | { 499 | info: { 500 | id: "380494", 501 | name: "Chinese Hunger", 502 | cloudinaryImageId: "h5zwpqi3jquzonhjq8bn", 503 | locality: "Mahewa Naini", 504 | areaName: "Naini", 505 | costForTwo: "₹200 for two", 506 | cuisines: ["Chinese"], 507 | avgRating: 4.3, 508 | feeDetails: { 509 | restaurantId: "380494", 510 | fees: [ 511 | { 512 | name: "BASE_DISTANCE", 513 | fee: 2500, 514 | }, 515 | { 516 | name: "BASE_TIME", 517 | }, 518 | { 519 | name: "ANCILLARY_SURGE_FEE", 520 | }, 521 | ], 522 | totalFee: 2500, 523 | }, 524 | parentId: "61783", 525 | avgRatingString: "4.3", 526 | totalRatingsString: "20+", 527 | }, 528 | }, 529 | { 530 | info: { 531 | id: "591407", 532 | name: "Sardar G Malai Chaap Junction", 533 | cloudinaryImageId: "sk6saam8uteg0kuoxkas", 534 | locality: "Tashkand Marg", 535 | areaName: "Civil Lines", 536 | costForTwo: "₹300 for two", 537 | cuisines: ["Indian", "Tandoor", "Arabian", "Punjabi"], 538 | avgRating: 4, 539 | feeDetails: { 540 | restaurantId: "591407", 541 | fees: [ 542 | { 543 | name: "BASE_DISTANCE", 544 | fee: 2500, 545 | }, 546 | { 547 | name: "BASE_TIME", 548 | }, 549 | { 550 | name: "ANCILLARY_SURGE_FEE", 551 | }, 552 | ], 553 | totalFee: 2500, 554 | }, 555 | parentId: "14511", 556 | avgRatingString: "4.0", 557 | totalRatingsString: "50+", 558 | }, 559 | }, 560 | { 561 | info: { 562 | id: "80226", 563 | name: "Pizza Hut", 564 | cloudinaryImageId: "2b4f62d606d1b2bfba9ba9e5386fabb7", 565 | locality: "Sardar Patel Marg", 566 | areaName: "Civil Lines", 567 | costForTwo: "₹350 for two", 568 | cuisines: ["Pizzas"], 569 | avgRating: 3.8, 570 | feeDetails: { 571 | restaurantId: "80226", 572 | fees: [ 573 | { 574 | name: "BASE_DISTANCE", 575 | fee: 2500, 576 | }, 577 | { 578 | name: "BASE_TIME", 579 | }, 580 | { 581 | name: "ANCILLARY_SURGE_FEE", 582 | }, 583 | ], 584 | totalFee: 2500, 585 | }, 586 | parentId: "721", 587 | avgRatingString: "3.8", 588 | totalRatingsString: "10K+", 589 | }, 590 | }, 591 | { 592 | info: { 593 | id: "238136", 594 | name: "La Pino'z Pizza", 595 | cloudinaryImageId: "a3poc70wqkajnw3zxpsl", 596 | locality: "Tashkand Marg", 597 | areaName: "Civil Lines", 598 | costForTwo: "₹200 for two", 599 | cuisines: ["Pizzas", "Pastas", "Italian", "Desserts", "Beverages"], 600 | avgRating: 3.7, 601 | feeDetails: { 602 | restaurantId: "238136", 603 | fees: [ 604 | { 605 | name: "BASE_DISTANCE", 606 | fee: 2500, 607 | }, 608 | { 609 | name: "BASE_TIME", 610 | }, 611 | { 612 | name: "ANCILLARY_SURGE_FEE", 613 | }, 614 | ], 615 | totalFee: 2500, 616 | }, 617 | parentId: "4961", 618 | avgRatingString: "3.7", 619 | totalRatingsString: "5K+", 620 | }, 621 | }, 622 | { 623 | info: { 624 | id: "332194", 625 | name: "Kwality Walls Frozen Dessert and Ice Cream Shop", 626 | cloudinaryImageId: "mlhwn3yictyis4cey2ai", 627 | locality: "Lajpat Rai Road", 628 | areaName: "Meergunj", 629 | costForTwo: "₹300 for two", 630 | cuisines: ["Desserts", "Ice Cream", "Ice Cream Cakes"], 631 | avgRating: 4.4, 632 | veg: true, 633 | feeDetails: { 634 | restaurantId: "332194", 635 | fees: [ 636 | { 637 | name: "BASE_DISTANCE", 638 | fee: 1900, 639 | }, 640 | { 641 | name: "BASE_TIME", 642 | }, 643 | { 644 | name: "ANCILLARY_SURGE_FEE", 645 | }, 646 | ], 647 | totalFee: 1900, 648 | }, 649 | parentId: "582", 650 | avgRatingString: "4.4", 651 | totalRatingsString: "1K+", 652 | }, 653 | }, 654 | { 655 | info: { 656 | id: "442057", 657 | name: "Shravan Specials by Lunchbox", 658 | cloudinaryImageId: "crakciwcxxy6jfoqxzkj", 659 | locality: "Civil Lines", 660 | areaName: "Stanley Road", 661 | costForTwo: "₹200 for two", 662 | cuisines: ["Biryani", "North Indian", "Desserts", "Beverages"], 663 | avgRating: 3.3, 664 | feeDetails: { 665 | restaurantId: "442057", 666 | fees: [ 667 | { 668 | name: "BASE_DISTANCE", 669 | fee: 2500, 670 | }, 671 | { 672 | name: "BASE_TIME", 673 | }, 674 | { 675 | name: "ANCILLARY_SURGE_FEE", 676 | }, 677 | ], 678 | totalFee: 2500, 679 | }, 680 | parentId: "21938", 681 | avgRatingString: "3.3", 682 | totalRatingsString: "6", 683 | }, 684 | }, 685 | { 686 | info: { 687 | id: "442056", 688 | name: "The Biryani Life", 689 | cloudinaryImageId: "uu7a0fqio5jygufj8lul", 690 | locality: "Stanley Road", 691 | areaName: "Civil Lines", 692 | costForTwo: "₹250 for two", 693 | cuisines: [ 694 | "Biryani", 695 | "Mughlai", 696 | "Lucknowi", 697 | "Hyderabadi", 698 | "Kebabs", 699 | "Desserts", 700 | "Beverages", 701 | ], 702 | avgRating: 3.7, 703 | feeDetails: { 704 | restaurantId: "442056", 705 | fees: [ 706 | { 707 | name: "BASE_DISTANCE", 708 | fee: 2500, 709 | }, 710 | { 711 | name: "BASE_TIME", 712 | }, 713 | { 714 | name: "ANCILLARY_SURGE_FEE", 715 | }, 716 | ], 717 | totalFee: 2500, 718 | }, 719 | parentId: "8496", 720 | avgRatingString: "3.7", 721 | totalRatingsString: "100+", 722 | }, 723 | }, 724 | { 725 | info: { 726 | id: "723874", 727 | name: "Hudson Chopsticks", 728 | cloudinaryImageId: "1952cde9bea82274227516f5caa99123", 729 | locality: "PD Tandon Road", 730 | areaName: "Civil Lines", 731 | costForTwo: "₹300 for two", 732 | cuisines: [ 733 | "Chinese", 734 | "Thai", 735 | "Asian", 736 | "Snacks", 737 | "Tibetan", 738 | "Nepalese", 739 | "Pan-Asian", 740 | "Seafood", 741 | "Beverages", 742 | ], 743 | avgRating: 4.2, 744 | feeDetails: { 745 | restaurantId: "723874", 746 | fees: [ 747 | { 748 | name: "BASE_DISTANCE", 749 | fee: 2500, 750 | }, 751 | { 752 | name: "BASE_TIME", 753 | }, 754 | { 755 | name: "ANCILLARY_SURGE_FEE", 756 | }, 757 | ], 758 | totalFee: 2500, 759 | }, 760 | parentId: "7129", 761 | avgRatingString: "4.2", 762 | totalRatingsString: "50+", 763 | }, 764 | }, 765 | ]; 766 | -------------------------------------------------------------------------------- /src/components/Contact.js: -------------------------------------------------------------------------------- 1 | import { useState, useContext, useEffect } from "react"; 2 | import { useLocation } from "react-router-dom"; 3 | import PathContext from "../utils/PathContext"; 4 | import InputControl from "./InputControl"; 5 | 6 | const Contact = () => { 7 | 8 | const {setCurrentPath} = useContext(PathContext); 9 | const {pathname} = useLocation(); 10 | 11 | const [data, setData] = useState({ 12 | name: "", 13 | email: "", 14 | message: "", 15 | }); 16 | 17 | 18 | const handleClick = () => { 19 | if(!data.name || !data.email || !data.message){ 20 | alert("fill every field"); 21 | } 22 | else alert("Message Submitted Successfully"); 23 | setData({ 24 | name: "", 25 | email: "", 26 | message: "" 27 | }) 28 | } 29 | 30 | useEffect(() => { 31 | setCurrentPath(pathname); 32 | }, []) 33 | 34 | return ( 35 | <> 36 |
37 | setData((prev) => ({ 40 | ...prev, 41 | name: event.target.value, 42 | })) 43 | } 44 | > 45 | 46 | setData((prev) => ({ 51 | ...prev, 52 | email: event.target.value, 53 | }))} 54 | > 55 | 56 | setData((prev) => ({ 61 | ...prev, 62 | message: event.target.value, 63 | }))} 64 | 65 | > 66 | 67 | 72 |
73 | 74 | ); 75 | }; 76 | 77 | export default Contact; 78 | -------------------------------------------------------------------------------- /src/components/Error.js: -------------------------------------------------------------------------------- 1 | import { useRouteError } from "react-router-dom"; 2 | 3 | const Error = () => { 4 | const err = useRouteError(); 5 | 6 | return ( 7 | <> 8 |

Oops !! You followed a wrong path.

9 |

{err.status + " " + err.statusText}

10 | 11 | ) 12 | } 13 | 14 | export default Error; -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | const Footer = () => { 3 | 4 | 5 | return ( 6 |
7 |
8 |

COMPANY

9 |
    10 |
  • About Us
  • 11 |
  • Team
  • 12 |
  • Careers
  • 13 |
  • Food Studio Blog
  • 14 |
  • Bug Bounty
  • 15 |
  • Food Studio One
  • 16 |
  • Food Studio Corporate
  • 17 |
18 |
19 | 20 |
21 |

CONTACT

22 |
    23 |
  • Help and Support
  • 24 |
  • Partner With Us
  • 25 |
  • Ride With Us
  • 26 |
27 |
28 | 29 |
30 |

LEGAL

31 |
    32 |
  • Terms and Conditions
  • 33 |
  • Refund and Cancellation
  • 34 |
  • Privacy Policy
  • 35 |
  • Cookie Policy
  • 36 |
  • Offer Terms
  • 37 |
38 |
39 | 40 |
41 | 42 | 43 |
44 |
45 | ) 46 | }; 47 | 48 | export default Footer; 49 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState, useContext } from "react"; 2 | import SearchBar from "./SearchBar"; 3 | import {Link} from "react-router-dom"; 4 | import { useSelector } from "react-redux"; 5 | import { FOOD_STDUIO_LOGO } from "./Config"; 6 | import { auth } from "../firebase"; 7 | import PathContext from "../utils/PathContext"; 8 | 9 | 10 | const Header = () => { 11 | 12 | const {currentPath} = useContext(PathContext); 13 | 14 | const [userName, setUserName] = useState(null); 15 | 16 | // Subscribe to the redux store 17 | const cartItems = useSelector(store => store.cart.cartItems); 18 | const path = "/signup"; 19 | 20 | // console.log("Header rendering"); 21 | useEffect(() => { 22 | const unsubscribe = auth.onAuthStateChanged(async(user) => { 23 | // console.log(user); 24 | if(user != null){ 25 | // console.log(user.displayName); 26 | if(!user.displayName){ 27 | await user.reload(); 28 | } 29 | setUserName(user.displayName); 30 | }else{ 31 | setUserName(null); 32 | } 33 | }) 34 | 35 | return () => { 36 | unsubscribe(); 37 | } 38 | }) 39 | 40 | const handleClick = () => { 41 | // console.log("log out"); 42 | auth.signOut(); 43 | // setUser(null); 44 | } 45 | 46 | return ( 47 |
48 | 49 | 53 | 54 | 55 | { 56 | currentPath === "/" && 57 | } 58 | 59 |
60 |
    61 |
  • Home
  • 62 |
  • About Us
  • 63 |
  • Contact Us
  • 64 |
  • Cart ({cartItems.items.length})
  • 65 | 66 |
67 |
68 | { 69 | !userName ? () : 71 | () 74 | } 75 | 76 |
77 |
78 |
79 | ); 80 | }; 81 | 82 | export default Header; 83 | -------------------------------------------------------------------------------- /src/components/InputControl.js: -------------------------------------------------------------------------------- 1 | 2 | const InputControl = (props) => { 3 | return ( 4 |
5 | { props.label && } 6 | 7 |
8 | ) 9 | } 10 | 11 | export default InputControl; -------------------------------------------------------------------------------- /src/components/ItemCardComponent.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import MealComponent from "./MealComponent"; 3 | 4 | const ItemCardComponent = (itemCard) => { 5 | 6 | //state variables 7 | const [expanded, setexpanded] = useState(false); 8 | 9 | //extracting data from props 10 | const title = itemCard?.itemCard?.card?.card?.title; 11 | const menu = itemCard?.itemCard?.card?.card?.itemCards; 12 | // console.warn(menu); 13 | //when there is no dish 14 | if (menu === undefined) { 15 | return; 16 | } 17 | 18 | return ( 19 | <> 20 |
21 |
22 |
setexpanded(!expanded)} 25 | > 26 |

27 | {title} ({menu.length}) 28 |

29 |

{expanded ? "✖️" : "➕"}

30 |
31 | 32 | {expanded && 33 | menu.map((curMenu, index) => { 34 | return ; 35 | }) 36 | } 37 |
38 |
39 | 40 | ); 41 | }; 42 | 43 | export default ItemCardComponent; 44 | -------------------------------------------------------------------------------- /src/components/Login.js: -------------------------------------------------------------------------------- 1 | import { useState, useContext} from "react"; 2 | import InputControl from "./InputControl"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import { signInWithEmailAndPassword } from "firebase/auth"; 5 | import { auth } from "../firebase"; 6 | import { useDispatch } from "react-redux"; 7 | import { setUser } from "../utils/userSlice"; 8 | 9 | const Login = () => { 10 | const [loginInProcess, setLoginInProcess] = useState(false); 11 | const [errorMessage, setErrorMessage] = useState(""); 12 | const [localUserData, setLocalUserData] = useState({ 13 | email: "", 14 | password: "", 15 | }); 16 | 17 | //react-router-dom hook to navigate to home once logged in. 18 | const navigate = useNavigate(); 19 | 20 | //store operations 21 | const dispatch = useDispatch(); 22 | 23 | const handleClick = () => { 24 | if (!localUserData.email || !localUserData.password) { 25 | setErrorMessage("Please fill every field"); 26 | setTimeout(() => { 27 | setErrorMessage(""); 28 | }, 2000); 29 | 30 | return; 31 | } 32 | 33 | //verify details from firebase database 34 | setLoginInProcess(true); 35 | signInWithEmailAndPassword( 36 | auth, 37 | localUserData.email, 38 | localUserData.password 39 | ) 40 | .then((res) => { 41 | setLoginInProcess(false); 42 | //dispatch this user to user slice in store. 43 | dispatch(setUser(localUserData.email)); 44 | navigate("/"); 45 | }) 46 | .catch((err) => { 47 | setErrorMessage(err.code + " " + err.message); 48 | console.log(errorMessage); 49 | setTimeout(() => { 50 | setErrorMessage(""); 51 | }, 5000); 52 | setLoginInProcess(false); 53 | }); 54 | 55 | setLocalUserData({ 56 | email: "", 57 | password: "", 58 | }); 59 | }; 60 | 61 | return ( 62 | <> 63 |
64 |
65 | 71 | setLocalUserData((prev) => ({ 72 | ...prev, 73 | email: event.target.value, 74 | })) 75 | } 76 | /> 77 | 78 | 84 | setLocalUserData((prev) => ({ 85 | ...prev, 86 | password: event.target.value, 87 | })) 88 | } 89 | /> 90 | 91 | {errorMessage != "" && ( 92 |

{errorMessage}

93 | )} 94 | 95 |
96 | { 97 | loginInProcess ? ( 98 | 104 | ): ( 105 | 111 | ) 112 | } 113 |
114 | 115 |

116 | Don't have an account, 117 | 118 | 119 | {" "} 120 | Sign Up{" "} 121 | 122 | {" "} 123 | to continue. 124 |

125 |
126 |
127 | 128 | ); 129 | }; 130 | 131 | export default Login; 132 | -------------------------------------------------------------------------------- /src/components/MealComponent.js: -------------------------------------------------------------------------------- 1 | import {useState, useContext, useEffect} from "react"; 2 | import { IMG_CDN_URL } from "./Config"; 3 | import { useDispatch ,useSelector } from "react-redux"; 4 | import { checkAvailability, findQuantity, removeMenu } from "../utils/utils"; 5 | import { useParams } from "react-router-dom"; 6 | import RestaurantContext from "../utils/RestaurantContext"; 7 | 8 | const MealComponent = (curMenu) => { 9 | 10 | //destructure props 11 | const {name, price, description, imageId} = curMenu?.curMenu?.card?.info; 12 | 13 | //state variables 14 | const [itemQuantity, setItemQuantity] = useState(0); 15 | 16 | //Read data from context API 17 | const myData = useContext(RestaurantContext); 18 | 19 | //fetch the id of opened restaurant 20 | const { id } = useParams(); 21 | 22 | //Cart operations 23 | //susbcribe to cart 24 | const cartItems = useSelector(store => store.cart.cartItems); 25 | //push to cart 26 | const dispatch = useDispatch(); 27 | 28 | //action functions 29 | const handleAdd = (meal) => { 30 | const check = checkAvailability(id, meal, cartItems, dispatch, myData); 31 | if(check){ 32 | setItemQuantity(itemQuantity+1); 33 | } 34 | } 35 | 36 | const handleRemove = (meal) => { 37 | removeMenu(meal, cartItems, dispatch); 38 | setItemQuantity(Math.max(0, itemQuantity-1)); 39 | } 40 | 41 | useEffect(() => { 42 | setItemQuantity(findQuantity(curMenu?.curMenu?.card?.info?.id, cartItems)); 43 | }, []); 44 | 45 | 46 | return ( 47 | <> 48 |
49 |
50 |

{name}

51 |
52 | {price / 100}Rs 53 |
54 |

55 | {description} 56 |

57 |
58 |
59 | {imageId ? ( 60 | meal-image 65 | ) : ( 66 | <> 67 | )} 68 |
69 | 75 | 76 |

{itemQuantity}

77 | 78 | 84 |
85 |
86 |
87 |
88 | {/* {index < menu.length - 1 ? ( 89 |
90 | 91 |
92 | ) : ( 93 | <> 94 | )} */} 95 | 96 | ); 97 | }; 98 | 99 | export default MealComponent; 100 | -------------------------------------------------------------------------------- /src/components/OrderHistory.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { database } from "../firebase"; 3 | import { IMG_CDN_URL } from "./Config"; 4 | import { Link } from "react-router-dom"; 5 | 6 | const OrderHistory = (currentUser) => { 7 | const [orders, setOrders] = useState(null); 8 | const uid = currentUser.currentUser.uid; 9 | 10 | useEffect(() => { 11 | const fetchData = () => { 12 | const databaseRef = database.ref("users/" + uid); 13 | 14 | databaseRef.on("value", (snapshot) => { 15 | const val= snapshot.val(); 16 | if(val){ 17 | const data = Object.values(val); 18 | setOrders(data); 19 | } 20 | // const data = Object?.values(snapshot.val()); 21 | // setOrders(data); 22 | }); 23 | console.log(orders); 24 | // databaseRef.off("value"); 25 | }; 26 | 27 | fetchData(); 28 | }, []); 29 | 30 | 31 | return ( 32 | <> 33 | {orders != null && 34 | orders.length > 0 && 35 | orders.map((order) => { 36 | const path = "/restaruant/" + order.restaurant_id; 37 | return ( 38 |
39 | {/* left side: logo */} 40 |
41 | 42 | restaurant logo 47 | 48 |
49 | {/* right side for other details: top restaruant, below menu */} 50 |
51 | {/* restaurant */} 52 |
53 |

{order.restaurantName}

54 |
55 | {/* menu */} 56 | {order.items.map((item) => { 57 | return ( 58 |
59 |

{item.name}

60 |

{item.price / 100}

61 |

{item.quantity}

62 |
63 | ); 64 | })} 65 |
66 |
67 | ); 68 | })} 69 | 70 | ); 71 | }; 72 | 73 | export default OrderHistory; 74 | -------------------------------------------------------------------------------- /src/components/ProfileClass.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class ProfileClass extends React.Component { 4 | 5 | //step 1 of execution 6 | constructor(props){ 7 | super(props); 8 | //create state here. 9 | this.state = { 10 | count: 1, 11 | count2: 2, 12 | } 13 | console.log("Constructor called"); 14 | 15 | } 16 | 17 | //step 3 of execution 18 | componentDidMount(){ 19 | //API calls here. 20 | console.log("componentDidMount called"); 21 | } 22 | 23 | //step 2 of execution 24 | render(){ 25 | console.log("render"); 26 | return( 27 |
28 |

Profile Component in Class

29 |

{this.props.name}

30 |

{this.state.count}

31 | 32 | 38 |
39 | ) 40 | } 41 | } 42 | 43 | export default ProfileClass -------------------------------------------------------------------------------- /src/components/ProfileFunction.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | const ProfileFunction = (props) => { 4 | 5 | 6 | const [count, setcount] = useState(1); 7 | return ( 8 | <> 9 |

Profile Function componenet

10 |

{props.name}

11 |

{count}

12 | 14 | 15 | ) 16 | } 17 | 18 | export default ProfileFunction; -------------------------------------------------------------------------------- /src/components/RestaurantCard.js: -------------------------------------------------------------------------------- 1 | import { IMG_CDN_URL } from "./Config"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const RestaurantCard = ({ 5 | name, 6 | cloudinaryImageId, 7 | cuisines, 8 | areaName, 9 | id, 10 | avgRating, 11 | }) => { 12 | // console.warn(id); 13 | const path = "/restaurant/" + id; 14 | // console.warn(path); 15 | if (!name) return; 16 | return ( 17 | 18 |
19 | restaurants-logo 24 | 25 |

{name}

26 |
27 |
28 |
29 | {cuisines?.join(", ")} 30 |
31 |
32 | 37 |
{areaName}
38 |
39 |
40 | 41 | {avgRating != "--" && ( 42 |
43 | 44 | {avgRating} 45 | 46 |
47 | )} 48 |
49 | 50 |
51 | 56 | 57 | 58 | 40% Off | Use TRYNEW 59 | 60 |
61 |
62 | 63 | ); 64 | }; 65 | 66 | export default RestaurantCard; 67 | -------------------------------------------------------------------------------- /src/components/RestaurantMenu.js: -------------------------------------------------------------------------------- 1 | import { useParams } from "react-router-dom"; 2 | import useRestaurantMenu from "../utils/useRestaurantMenu"; 3 | import ItemCardComponent from "./ItemCardComponent"; 4 | import RestaurantContext from "../utils/RestaurantContext"; 5 | 6 | const RestaurantMenu = () => { 7 | const { id } = useParams(); 8 | const restaurant = useRestaurantMenu(id); 9 | const { 10 | name, 11 | cuisines, 12 | areaname, 13 | deliverymsg, 14 | avgrating, 15 | totalratings, 16 | itemCards, 17 | logo, 18 | } = restaurant; 19 | // console.warn(itemCards); 20 | //we've to pass the name, id, areaname & logo of restaurant to MealComponent so that they can be added to cart details along with a meal. Hence we create a context and put these into it. 21 | 22 | console.log(name); 23 | const myData = { 24 | name: name, 25 | id: id, 26 | areaname: areaname, 27 | logo: logo, 28 | }; 29 | 30 | //---------------------- Context ends ---------------------- 31 | 32 | return ( 33 | <> 34 |
35 | {/* Restaurant details */} 36 |
37 |
38 |

{name}

39 |
40 | {cuisines.join(", ")} 41 |
42 |
43 | 48 |
{areaname}
49 |
50 |
{deliverymsg}
51 |
52 |
53 | 54 | {" "} 55 | {avgrating != "--" ? avgrating : "0.0"} 56 | 57 | {totalratings != null && ( 58 | 59 | {totalratings} 60 | 61 | )} 62 |
63 |
64 | 65 |
66 | 67 | {/* Offers area */} 68 | 69 |
70 |
71 |
30% upto 75rs
72 | 73 | use TRYNEW above 149rs 74 | 75 |
76 |
77 |
30% upto 75rs
78 | 79 | use TRYNEW above 149rs 80 | 81 |
82 |
83 |
30% upto 75rs
84 | 85 | use TRYNEW above 149rs 86 | 87 |
88 |
89 |
30% upto 75rs
90 | 91 | use TRYNEW above 149rs 92 | 93 |
94 |
95 |
30% upto 75rs
96 | 97 | use TRYNEW above 149rs 98 | 99 |
100 |
101 |
30% upto 75rs
102 | 103 | use TRYNEW above 149rs 104 | 105 |
106 |
107 | 108 | {/* Veg/non veg declaration */} 109 | 110 |
111 |

112 | Pure Veg 113 |

114 |
115 | 116 |
117 | 118 | {/* Menu items with categories */} 119 | 120 | 121 |
122 | {itemCards?.map((itemCard, index) => { 123 | if (index != 0) { 124 | return ; 125 | } 126 | })} 127 |
128 |
129 |
130 | 131 | ); 132 | }; 133 | 134 | export default RestaurantMenu; 135 | -------------------------------------------------------------------------------- /src/components/RestaurantMenuShimmer.js: -------------------------------------------------------------------------------- 1 | import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; 2 | import "react-loading-skeleton/dist/skeleton.css"; 3 | 4 | const RestaurantMenuShimmer = () => { 5 | return ( 6 | 7 |
8 | {/* Restaurant details */} 9 |
10 |
11 |

12 |
13 | 14 |
15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 |
32 | 33 | {/* Offers area */} 34 | 35 |
36 |
37 |
38 | 39 | 40 | 41 |
42 |
43 |
44 | 45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 | 55 | 56 | 57 |
58 |
59 | 60 | 61 | 62 |
63 |
64 | 65 | 66 | 67 |
68 |
69 | 70 | {/* Veg/non veg declaration */} 71 | 72 |
73 |

74 | 75 |

76 |
77 | 78 |
79 | 80 | {/* Menu items with categories */} 81 | 82 |
83 | 84 |
85 |
86 |
87 | ); 88 | }; 89 | 90 | export default RestaurantMenuShimmer; 91 | -------------------------------------------------------------------------------- /src/components/SearchBar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useContext } from "react"; 3 | import SearchTextContext from "../utils/SearchTextContext"; 4 | 5 | function SearchBar() { 6 | const {searchTxt, setsearchTxt, setsearchTxtFound} = useContext(SearchTextContext); 7 | 8 | // built for search when enter is pressed. 9 | // function handleKeyPress(event) { 10 | // if (event.key === "Enter") { 11 | // setsearchTxtFound(!searchTxtFound); 12 | // } 13 | // } 14 | return ( 15 |
16 | { 21 | setsearchTxt(e.target.value); 22 | setsearchTxtFound((prev) => !prev); 23 | }} 24 | // onKeyDown={handleKeyPress} 25 | /> 26 |
27 | ); 28 | } 29 | 30 | export default SearchBar; 31 | -------------------------------------------------------------------------------- /src/components/ShimmerUI.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ShimmerUICard from './ShimmerUICard' 3 | 4 | 5 | function ShimmerUI() { 6 | 7 | return ( 8 | <> 9 |
10 | {Array(15).fill("").map((e, index) => ( 11 | 12 | ))} 13 |
14 | 15 | ) 16 | } 17 | 18 | export default ShimmerUI -------------------------------------------------------------------------------- /src/components/ShimmerUICard.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; 3 | import "react-loading-skeleton/dist/skeleton.css"; 4 | 5 | function ShimmerUICard() { 6 | return ( 7 | 8 |
9 | 10 |

11 | 12 |

13 |
14 | 15 |
16 |
17 |
18 | 19 | ); 20 | } 21 | 22 | export default ShimmerUICard; 23 | -------------------------------------------------------------------------------- /src/components/SignUp.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import InputControl from "./InputControl"; 3 | import { Link, useNavigate } from "react-router-dom"; 4 | import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth"; 5 | import { auth } from "../firebase"; 6 | 7 | const SignUp = () => { 8 | const [errorMessage, setErrorMessage] = useState(""); 9 | const [signUpInProcess, setSignUpInProcess] = useState(false); 10 | 11 | const [localUserData, setLocalUserData] = useState({ 12 | name: "", 13 | email: "", 14 | password: "", 15 | }); 16 | 17 | 18 | const navigate = useNavigate(); 19 | 20 | const handleClick = () => { 21 | if ( 22 | !localUserData.name || 23 | !localUserData.email || 24 | !localUserData.password 25 | ) { 26 | setErrorMessage("Please fill every field"); 27 | setTimeout(() => { 28 | setErrorMessage(""); 29 | }, 2000); 30 | 31 | return; 32 | } 33 | 34 | //create user in firebase 35 | setSignUpInProcess(true); 36 | 37 | createUserWithEmailAndPassword( 38 | auth, 39 | localUserData.email, 40 | localUserData.password 41 | ) 42 | .then (async(res) => { 43 | console.log(res.user.displayName); 44 | console.log("Updating profile name"); 45 | await updateProfile(res.user, { 46 | displayName: localUserData.name, 47 | }); 48 | console.log("profile updated"); 49 | console.log(res.user.displayName); 50 | setSignUpInProcess(false); 51 | navigate("/"); 52 | }) 53 | .catch((err) => { 54 | setErrorMessage(err.code + " " + err.message); 55 | setTimeout(() => { 56 | setErrorMessage(""); 57 | }, 5000); 58 | setSignUpInProcess(false); 59 | }); 60 | 61 | setLocalUserData({ 62 | name: "", 63 | email: "", 64 | password: "", 65 | }); 66 | }; 67 | 68 | return ( 69 |
70 |
71 | 72 | 78 | setLocalUserData((prev) => ({ ...prev, name: event.target.value })) 79 | } 80 | /> 81 | 82 | 88 | setLocalUserData((prev) => ({ ...prev, email: event.target.value })) 89 | } 90 | /> 91 | 92 | 98 | setLocalUserData((prev) => ({ 99 | ...prev, 100 | password: event.target.value, 101 | })) 102 | } 103 | /> 104 | 105 | {errorMessage != "" && ( 106 |

{errorMessage}

107 | )} 108 | 109 |
110 | { 111 | signUpInProcess ? ( 112 | 118 | ): ( 119 | 125 | ) 126 | } 127 | 128 |
129 | 130 | 131 |

132 | Already have an account, 133 | 134 | Log In 135 | {" "} 136 | to continue. 137 |

138 |
139 |
140 | ); 141 | }; 142 | 143 | export default SignUp; 144 | -------------------------------------------------------------------------------- /src/components/UpdateCartOnUserChange.js: -------------------------------------------------------------------------------- 1 | import { useSelector } from "react-redux"; 2 | 3 | const UpdateCartOnUserChange = () => { 4 | 5 | //subscribe to user slice to get his respective cart from firebase, is rendered whenever user is changed 6 | const user = useSelector((store) => store.user); 7 | 8 | //we've to fetch the cart details of this user then update cart slice. 9 | 10 | 11 | return ( 12 | <> 13 | 14 | ) 15 | } 16 | 17 | export default UpdateCartOnUserChange; -------------------------------------------------------------------------------- /src/firebase.js: -------------------------------------------------------------------------------- 1 | // Import the functions you need from the SDKs you need 2 | import firebase from "firebase/compat/app" 3 | import "firebase/compat/database"; 4 | import {getAuth} from "firebase/auth" 5 | 6 | const firebaseConfig = { 7 | apiKey: "AIzaSyAJLfZ6u1AUL3Ne0J-qJRLRAeQxCH0Bvnk", 8 | authDomain: "food-studio-a10b7.firebaseapp.com", 9 | projectId: "food-studio-a10b7", 10 | storageBucket: "food-studio-a10b7.appspot.com", 11 | messagingSenderId: "182884177059", 12 | appId: "1:182884177059:web:5bc7d7e2960f578d54db16", 13 | measurementId: "G-R2YQXX0RR4" 14 | }; 15 | 16 | // Initialize Firebase 17 | firebase.initializeApp(firebaseConfig); 18 | // const app = initializeApp(firebaseConfig); 19 | const database = firebase.database(); 20 | const auth = getAuth(); 21 | 22 | export {firebase, auth, database}; -------------------------------------------------------------------------------- /src/script.js: -------------------------------------------------------------------------------- 1 | import { useState, lazy, Suspense } from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { createBrowserRouter, Outlet, RouterProvider } from "react-router-dom"; 4 | 5 | import Header from "./components/Header"; 6 | import Body from "./components/Body"; 7 | import Footer from "./components/Footer"; 8 | // import About from "./components/About"; 9 | import Error from "./components/Error"; 10 | import Contact from "./components/Contact"; 11 | import Cart from "./components/Cart"; 12 | import Login from "./components/Login"; 13 | import RestaurantMenu from "./components/RestaurantMenu"; 14 | import { Provider } from "react-redux"; 15 | import store from "./utils/Store"; 16 | import SearchTextContext from "./utils/SearchTextContext"; 17 | import SignUp from "./components/SignUp"; 18 | import PathContext from "./utils/PathContext"; 19 | 20 | const About = lazy(() => import("./components/About")); 21 | // ----------------------------------------- BUILDING FOOD STUDIO ------------------------------ 22 | 23 | const AppComponent = () => { 24 | const [searchTxt, setsearchTxt] = useState(""); 25 | const [searchTxtFound, setsearchTxtFound] = useState(false); 26 | const [currentPath, setCurrentPath] = useState("home"); 27 | 28 | return ( 29 | // Provider is used to inform our app about the redux store 30 | 31 | {/* User Context is the context we created for logged in user, this provider will pass this context to all the components */} 32 | 35 | 36 |
37 | Loading.......}> 38 | {/**dynamic pages will be rendered here */} 39 | 40 | 41 | 42 |