Industrial Report 7th Sem - Harsan
Industrial Report 7th Sem - Harsan
REPORT
on
Zomato Clone
Submitted in partial fulfillment of the
Requirements for the award of degree
Of
Bachelor of Technology
in
Information technology
By:
Harsan Singh
(03713203120)
i
CERTIFICATE
ii
DECLARATION
I herby declare that all the work presented in this Industrial Training
Report for the partial fulfilment of the requirement for the award of the
degree of Bachelor of Technology in Information Technology, Guru
Tech Bahadur Institute of Technology, affiliated to Guru Govind Singh
Indraprastha University, New Delhi is an authentic record of my own
work carried out at NEC Corporation Pvt. Ltd. from 17 th July 2023 to 31st
August 2023
iii
ACKNOWLEDGEMENT
I would like to express our great gratitude toward our supervisor, HOD Ms.Savneet
Kaur, Dr Amandeep Kaur and Mr. Amandeep Singh who have given me support and
suggestion. Without their help I would not have presented this dissertation up to the
presented standard. I also take this opportunity to give thanks to all others who gave
me support for the project or in other aspects of my study at Guru Tegh Bahadur
Institute of Technology.
iv
ABSTRACT
Web programming, also known as web development, is the creation of dynamic web
applications. It is the work involved in developing a website for the Internet. Web
development can range from developing a simple single static page of plaintext to
complex web applications.
Zomato is a comprehensive food discovery and delivery platform that enables users
to explore restaurants, read reviews, and place online orders. Users can discover
restaurants based on location and cuisine, read and contribute reviews, and make
table reservations in some regions. This project is a Zomato clone that allows you to
add to cart, make reviews, signup/login and pay for food online.
This project was created using HTML, CSS, Tailwind CSS, JavaScript, ReactJS,
Redux, ExpressJS, MongoDB. We are using Google Auth API for logging in and
signup and Razor Pay API for payments.
v
TABLE OF CONTENT
CONTENT PAGE NO.
Title Page i
Acknowledgement iv
Abstract v
Chapter 1: Introduction 1
1.1: General 2
1.2: Classification 2
2.1: General 12
vi
CONTENT PAGE NO.
3.2: ER Diagram 17
Chapter-4: Testing 21
4.2: Debugging 23
Chapter-6: Conclusion 32
References 34
Appendix A 35
Appendix B 43
vii
LIST OF FIGURES
Figure No Figure Name Page No.
1. Figure 1: Zomato 2
3. Figure 3: HTML 4
4. Figure 4: CSS 4
5. Figure 5: Javascript 5
7. Figure 7: React JS 6
8. Figure 8: Redux 6
viii
CHAPTER 1
INTRODUCTION
1
1.1 GENERAL
Zomato is a comprehensive food discovery and delivery platform that enables
users to explore restaurants, read reviews, and place online orders. Users can
discover restaurants based on location and cuisine, read and contribute reviews,
and make table reservations in some regions. Zomato's food delivery service
allows users to order from a diverse range of restaurants and track deliveries in
real-time. The platform also offers a subscription service, Zomato Pro,
providing members with discounts at partner restaurants. With features like
curated collections, user profiles, and food-related content, Zomato has become
a go-to destination for those seeking convenient and varied dining experiences.
Figure 1: Zomato
1.2 CLASSIFICATION
Web Development can be classified into two ways:
Frontend Development
Backend Development
2
1.3 FRONTEND DEVELOPMENT
The part of a website that the user interacts directly is termed as front end. It is also
referred to as the ‘client side’ of the application. Everything you see on a website,
like buttons, links, animations, and more, were created by a front-end web developer.
It is the front-end developer’s job to take the vision and design concept from the
client and implement it through code. Everything on the page from the logo to the
search bar, buttons, overall layout and how the user interacts with the page was
created by a front-end developer. Front end developers are in charge of the look and
feel of the website. Front end developers also have to make sure the website looks
good on all devices (phones, tablets, and computer screens).
Front-end development refers to constructing what a user sees when they load a web
application – the content, design and how you interact with it.
The basic toolset for front-end is well-defined, it includes HTML, CSS And
JavaScript.
HTML: The Hyper Text Markup Language, or HTML is the standard markup
language for documents designed to be displayed in a web browser. It can be assisted
by technologies such as Cascading Style Sheets and scripting languages such as
3
JavaScript.
Figure 3: HTML
Figure 4: CSS
4
appearance in Netscape 2.0 in 1995 with the name Live Script.
Figure 5: Javascript
Tailwind CSS: Tailwind CSS is basically a utility-first CSS framework for rapidly
building custom user interfaces. It is a highly customizable, low-level CSS
framework that gives you all of the building blocks you need to build bespoke
designs without any annoying opinionated styles you have to fight to override.
The beauty of this thing called tailwind is it doesn’t impose design specifications or
how your site should look, you simply bring tiny components together to construct a
user interface that is unique.
React’s primary role in an application is to handle the view layer of that application
just like the V in a model-view-controller (MVC) pattern by providing the best and
most efficient rendering execution. Rather than dealing with the whole user interface
5
as a single unit, React.js encourages developers to separate these complex UIs into
individual reusable components that form the building blocks of the whole UI. In
doing so, the ReactJS framework combines the speed and efficiency of JavaScript
with a more efficient method of manipulating the DOM to render web pages faster
and create highly dynamic and responsive web applications.
Figure 7: React JS
Redux:
Redux is a JavaScript library commonly used with React for managing the state of
web applications in a predictable and centralized manner. It follows a unidirectional
data flow, where the application state is stored in a central repository called the store.
State changes are triggered by dispatching actions, which are plain JavaScript objects
describing the intention to modify the state. Reducers, functions that specify how the
state changes in response to actions, calculate the next state. Redux provides a
predictable and scalable approach to state management, particularly beneficial in
larger applications, ensuring better debugging and testing capabilities by enforcing
immutability and a clear data flow.
Figure 8: Redux
6
1.4 BACKEND DEVELOPMENT
Backend is the server side of a website. It is the part of the website that users cannot
see and interact. It is the portion of software that does not come in direct contact with
the users. It is used to store and arrange data.
It contains behind-the-scenes activities that occur when performing any action on a
website. There are a wide range of languages that could be used for Backend Web
Development, few of them include JavaScript, Python, PHP, Java etc.
Web development activities that are done at the back end of programs are referred to
as back end development. Back-end development covers server-side web application
logic and integration and activities, like writing APIs, creating libraries, and working
with system components instead of frontend development, which focuses on
customer-facing services and programs. Backend developers build code that allows a
database and an application to communicate with one another. Backend developers
take care and maintain the back-end of a website, Including databases, servers, and
apps, and they control what you don’t see.
7
lightweight design and active open-source community.
Node.js:
Node.js is a runtime environment that allows server-side execution of JavaScript
code. It leverages the V8 JavaScript engine from Chrome and is known for its event-
driven, non-blocking I/O model, making it ideal for building scalable and high-
performance applications. Popular for server-side development, Node.js facilitates
the creation of APIs and real-time applications. Its npm package ecosystem is
extensive, fostering a collaborative environment where developers can easily share
and integrate libraries and tools into their projects, contributing to its widespread
adoption and versatility in web development.
8
scalable database solution.
Browser APIs – Browser APIs are built into your web browser and are able to
expose data from the browser and surrounding computer environment and do useful
complex things with it. For example, the Web Audio API provides JavaScript
constructs for manipulating audio in the browser — taking an audio track, altering its
volume, applying effects to it, etc.
Third party APIs – Third-party APIs are not built into the browser by default,
and you generally have to retrieve their code and information from somewhere on the
Web. For example, the Twitter API allows you to do things like displaying your
latest tweets on your website.
9
Figure 13: Web APIs
Web hosting is a service that allows organizations and individuals to post a website
or web page onto the Internet. A web host, or web hosting service provider, is a
business that provides the technologies and services needed for the website or
webpage to be viewed in the Internet. Websites are hosted, or stored, on special
computers called servers. When Internet users want to view your website, all they
need to do is type your website address or domain into their browser. Their computer
will then connect to your server and your webpages will be delivered to them
through the browser.
10
CHAPTER 2
REQUIREMENT ANALYSIS
11
2.1 GENERAL
System analysis basically involves the processes of gathering and interpreting facts,
diagnosing of problems and using the collected information to recommend any
improvements on the whole system. System analysis can be seen as a problem-
solving activity that requires highly intensive communication links between the
system’s users and the developers of the system. System analysis also known as
system study is a very important phase of any system’s development process. The
system is always viewed as a whole, then the inputs are identified and then the
system is subjected to a very detailed and close study to identify the problematic
areas. The solutions are put forward as a proposal. The proposal is reviewed based on
user’s request and suitable changes are made to it. This loop ends as soon as the users
are fully satisfied with the proposal.
12
Costs for Technology
To produce a database type of website or web application base with not a lot of users,
it does not require a high-speed connection to the Internet. It requires a web server,
and software.
Costs for Technological Development
This will not involve a number of programmers who are able to interpret your
functional requirements and program your website or web application. A single
person or a small group can handle it well.
Costs for the Organization for Piloting Training
During the technological development of a website or web application, it is always a
good idea to allow admin staff who will be using the system on a daily basis to pilot
the system to as a training initiative.
Running Costs
These are an upkeep of the web server and maintenance costs.
Financial Benefits
There will be financial benefits for both the users of this website as well as the
members of the team and organisation. Instead of going anywhere searching for
nearest restaurants now everything can be done from the comfort of their homes or
any place and not just the office, with just a click of the mouse.
13
similar application rather than having many numbers of website views for different
users. Depending upon access rights given, the content will be shown or hidden
Risk associated with laws:
Legal feasibility ensures that your product abides by all rules and is not illegal. In
addition, you need to research about possible legal concerns and how they can affect
your project. Before utilising any copyrighted content, the project must always get
the necessary legal authorizations.
14
CHAPTER 3
SYSTEM DESIGN
15
System design is the solution for the creation of a new system. This phase focuses
on the detailed implementation of the feasible system. This emphasis on translating
design. Specifications to performance specification. System design has two phases
of development
Logical design
Physical design
During logical design phase the analyst describes inputs (sources), outputs
(destinations), databases (data sores) and procedures (dataflow) all in a format that
meets the user requirements. The analyst also specifies the needs of the user at a
level that virtually determines the information flow in and out of the system and the
data resources. Here the logical design is done through data flow diagrams and
database design. The physical design is followed by physical design or coding.
Physical design produces the working system by defining the design specifications,
which specify exactly what the candidate system must do. The programmers write
the necessary programs that accept input from the user, perform necessary
processing on accepted data and produce the required report on a hard copy or
display it on the screen.
16
caller id, passwords and other details are to be entered at the time of signing-in or
logging into the application portal or site. A couple of pages are designed for this
purpose which are user friendly and easy to use. The design is done such that users
get appropriate messages when exceptions occur.
3.2 ER DIAGRAM
An ER diagram (Entity-Relationship diagram) is a visual representation of entities
and the relationships between them in a database or system. It is used to model the
structure of a database, and it is typically used in the design phase of a project to
help understand the requirements and relationships between different entities.
An ER diagram typically includes the following elements:
Entities: Represented by rectangles, entities are the objects or concepts that are stored
in the database, such as customers, orders, and products.
Attributes: Represented by ovals, attributes are the characteristics or properties of an
entity, such as the name of a customer or the price of a product.
Relationships: Represented by diamonds, relationships show how entities are
connected to one another, such as a customer placing an order or a product being
included in an order.
Cardinality: Represented by lines between entities and relationships, cardinality is
used to indicate the number of instances of one entity that can be associated with
another entity.
Primary keys and foreign keys: Represented by underlining, primary keys are unique
identifiers for an entity, and foreign keys are used to link entities together in
relationships.
17
The ER diagram for an online food ordering website would include entities such as
customers, orders, restaurants, menu items, and payments, and the relationships
between them, such as customers placing orders, orders containing menu items, and
payments being made for orders.
It is important to note that this is an high level representation and the actual ER
diagram will be much more complex with many more entities and relationships,
and it depends on the specific requirements and constraints of the website.
18
these reasons DFD’s are often referred to as logical data flow diagrams. It
functions as a component of the system documentation file. The functions or
processes that capture, manipulate, store, and distribute data between a
system and its environment as well as among the system's components are
graphically represented by DFD. It works well as a tool for user and system
designer communication because of the visual
depiction. Because they are so simple to grasp, data flow diagrams can be
understood by both technical and nontechnical people.
EXTERNAL ENTITY
An external entity is a source or destination of a data flow. Only those entities
which originate or receive data are represented on a data flow diagram. The
symbol used is a rectangular box.
PROCESS
A process shows a transformation or manipulation of data flow within the
system. The symbol used is an oval shape.
DATAFLOW
The data flow shows the flow of information from a source to its destination.
Data flow is represented by a line, with arrow heads showing the direction of
flow. Information always flows to or from a process and may be written,
verbal or electronic. Each data flow may be referenced by the processes or
data stores at its head and tail, or by a description of its contents.
DATA STORE
A data store is a holding place for information within the system. It is
represented by an open-ended narrow rectangle. Data stores may belong-term
files such as sales ledgers, or may be short-term accumulations. For example,
batches of documents that are waiting to be processed. Each data store should
be given a reference followed by an arbitrary number.
19
Figure 16: DFD Diagram
20
CHAPTER 4
TESTING
21
4.1 TESTING TECHNIQUES
Testing the website or web application was expedient as it ensured that the intended
system generated the required output given the necessary input. And to determine if
the system is able to complete actions in relation to its function and non-functional
requirement. I actually executed the system to verify that it was free of errors and
function as required. The thorough testing of the system before its release needs to be
done via various test cases and modules so that the software becomes devoid of bugs
and uses minimum space requirements as well as a minimal time to perform,
however software testing process begins when the website is developed, the
documentation and related data structures are designed. During the software test and
implementation, the software as a whole is tested to ensure that all its components
work well together otherwise the website or the project cannot be said to be
completed. If the test is successful, the software is then sent to the user to evaluate
the software against their acceptance criteria. If the software satisfies those criteria,
the website is put to use. Since I developed a website, I had to go through various
website testing methods.
4.1.1 Usability Testing
This involves verifying how the website or web application is easy to use. This is a
process by which human computer interactions characteristics of a system are
measured, and weakness are identified for correction. Ease of learning, navigation,
subjective user satisfaction and general appearance were some of the factors
considered when this system was subject to a usability testing.
Test the navigation and controls.
Content checking.
Check for user intuition.
4.1.2 Compatibility Testing
This testing is done to ensure the compatibility of the website’s or web application’s
operating system and hardware platforms. Compatibility testing can be performed
manually or can be driven by an automated functional or regression test suite.
Compatibility testing is performed based on the context of the website.
Browser compatibility.
Operating system compatibility.
22
Compatible to various devices like notebook, mobile, etc.
4.1.3 Unit Testing
The primary goal of unit testing is to take the smallest piece of testable code or
software in the website/application/system, isolate it from the remainder of the code
and determine if it behaves as it should. The main modules of the system are at best
complex and for them to work seamlessly, each would have to undergo rigorous
repetitive logical, as well as semantic tests (data handling). This test was done at the
development level so as to ensure each piece of the code that was written will work.
It was most often tested independently of other modules of the website.
4.1.4 Integration Testing
Integration testing is a form of testing in which software components, hardware
components or both are combined and tested to evaluate the interaction between
them. This testing determines that components involved are functioning well with
each other. Integration testing including user interface testing and usability testing.
4.2 DEBUGGING
Debugging is the process of identifying and correcting script flaws. Debugging tools,
a unique UI in developer tools that greatly simplifies debugging, are supported by all
contemporary browsers and the majority of other environments. Additionally, it
enables step-by-step code tracing so that you can see exactly what is happening.
4.2.1 Debugging tools
Run the following command in a browser to start client debugging tools:
Chrome: F12 or Ctrl + Shift + I.
Firefox: F12.
Internet Explorer: F12.
All supported browsers offer largely comparable capabilities for client code
debugging. Above listed browsers are one of the most popular and often used for
debugging with their developer’s tools.
4.2.2 Debugging Breakpoints
A breakpoint prevents the script from continuing shortly before the statement where
it is set. You can review and change the values of variables while script execution is
23
halted, as well as perform additional debugger instructions. For the Terminate event,
breakpoints cannot be established.
A breakpoint can be cleared permanently, temporarily disabled, or re-enabled after it
has been established. Red stop signs are used to indicate breakpoints. Red stop signs
with yellow slashes and red stop signs that, when enabled, show a break point Stop
sign with a yellow slash indicating that the break point is disabled.
When stepping and stopping on a breakpoint, the last line of a statement that spans
multiple lines is highlighted. You must choose the last line of a multi-line statement
in order to set, disable, enable, or clear it.
Until you expressly clear it, a breakpoint is still present in the script. Any breakpoints
from the last debugging session that were not cleared reappear when an active script
initially appears in the debugger.
24
CHAPTER 5
ABOUT THE PROJECT
25
Zomato is a leading global food discovery and delivery platform that connects users
with local restaurants. In an attempt to replicate Zomato's user-friendly interface, I
employed ReactJS to create a dynamic landing page. The focus was on showcasing
an array of restaurants, along with detailed information, reviews, and curated
collections. Additionally, I integrated a seamless payment system to enable users to
order food online effortlessly. This ReactJS-based clone aims to capture the essence
of Zomato's platform, allowing users to explore, select, and order from a diverse
range of restaurants, enhancing the overall online food ordering experience.
Back End i.e the server side has the API planning for the frontend along with the
requests made using Express. It consists of following requests:
- Food (food items and their details)
- Restaurant (restaurant and their details)
- Menu (Menu and its details)
- Order (Order and its details)
- Image (Storing all the images related to the project)
- Review (Storing all the list of reviews)
- User (User related details, username, email, password)
1. Learning: Cloning a website like Zomato using React can be a great way to learn
about the inner workings of the website and how it is built.
2. Popularity: React is a very popular JavaScript library for building user interfaces. I
wanted to use React to clone the Zomato website, as it is a popular and in-demand
technology that can help me in my future projects.
26
3. Scalability: React is known for its scalability, it's a perfect choice to build a large-
scale application like Zomato.
This project was created using HTML, CSS, Tailwind CSS, JavaScript, ReactJS,
ExpressJS, MongoDB.
2. Razor Pay API: - This is a Payment API service used to capture and fetch
payments. You can also fetch payments based on orders and card details of payment.
27
Figure 18: Razorpay
Client-side dependencies
1. "@babel/plugin-transform-class-properties": "^7.22.5",
2. "@babel/plugin-transform-object-rest-spread": "^7.22.15",
3. "@headlessui/react": "^1.7.3",
4. "@testing-library/jest-dom": "^5.16.5",
5. "@testing-library/react": "^13.4.0",
6. "@testing-library/user-event": "^13.5.0",
7. "axios": "^0.27.2",
8. "classnames": "^2.3.2",
9. "dayjs": "^1.11.5",
10. "leaflet": "^1.9.1",
11. "react": "^18.2.0",
12. "react-dom": "^18.2.0",
13. "react-icons": "^4.4.0",
28
14. "react-leaflet": "^4.1.0",
15. "react-rating-stars-component": "^2.2.0",
16. "react-redux": "^8.0.4",
17. "react-router-dom": "^6.4.1",
18. "react-scripts": "5.0.1",
19. "react-simple-image-viewer": "^1.2.2",
20. "redux": "^4.2.0",
21. "redux-logger": "^3.0.6",
22. "redux-thunk": "^2.4.1",
23. "swiper": "^8.4.2",
24. "util": "^0.12.5",
25. "web-vitals": "^2.1.4"
This project was built on a Windows 10 (single language) operating system and the
source code was written and debugged through Visual Studio Code – a source-code
editor made by Microsoft for Windows, Linux and macOS. Features include support
for debugging, syntax highlighting, intelligent code completion, snippets, code
refactoring, and embedded Git.
29
The Zomato Clone is compatible to run on any kind of OS, it is a browser dependent
application and not OS-specific. No specific software needs to be installed before
running this project. This website is also mobile friendly.
Components
Components are independent and reusable bits of code. They serve the same
purpose as JavaScript functions, but work in isolation and return HTML.
Why use components in React?
Every React.js component acts separately, so you can change one section of the app
without needing to update everything. This also means you can use the same
component in each area of the app and change the individual pieces. There's less to
update, so it makes the entire process far more efficient.
The components in my Webpage are:-
1. Auth Signin.jsx, Signup.jsx
2. Cart CartContainer.jsx, FoodItem.jsx
3. CheckoutAddressList.jsx
4. Delivery DeliveryCarousel.jsx, DeliveryCategoryCard.jsx, index.jsx
5. Dining DiningCarousel.jsx, index.jsx
30
6. FoodTab index.jsx
7. Navbar CheckoutNavbar.jsx, index.jsx
8. NightLife NightLifeCarousel.jsx, index,jsx
9. Nutrition index.jsx, NutritionCard.jsx, NutritionCarousel,jsx
10. OrderOnline FoodItem.jsx, FoodList.jsx, MenuCategory.jsx
11. Restaurant MapView.jsx, Menu.jsx, Overview.jsx, Reviews.jsx.
HOC(Layouts)
31
CHAPTER 6
CONCLUSION
32
In conclusion, embarking on the journey of building this project using HTML, CSS,
ReactJS, ExpressJS, MongoDB, and Redux has been an invaluable experience that
encapsulates a comprehensive exploration of web development concepts. This
endeavor extends beyond just front-end design, incorporating the utilization of
crucial technologies such as web APIs, server-side development with ExpressJS, and
database management with MongoDB. Navigating through the intricacies of web
APIs has been instrumental in understanding and implementing key functionalities
within the project.
The key takeaways from this endeavor are multifaceted. Firstly, I have developed a
new skill set encompassing a range of technologies that are pivotal in contemporary
web development. Secondly, the project provided a firsthand understanding of the
dynamics and intricacies of the industry, offering practical insights beyond
theoretical knowledge. Thirdly, my research skills have markedly improved, as I
delved into various aspects of web development to address challenges and implement
innovative solutions. Lastly, this journey has been a realization of untapped potential,
demonstrating the ability to translate theoretical concepts into a tangible, functioning
project.
This project, alongside the challenges encountered and triumphs achieved, has
significantly contributed to my personal and professional growth. The culmination of
skills, knowledge, and hands-on experience gained through this project lays a solid
foundation for future endeavors, underscoring the transformative impact of practical
learning in shaping a successful career in web development.
33
REFERENCES
https://razorpay.com/docs/api/payments/#:~:text=Payments%20API,the
%20Razorpay%20Postman%20Public%20Workspace.
https://console.cloud.google.com/apis/dashboard?project=musicify-405206
https://reactjs.org/docs/getting-started.html
https://www.geeksforgeeks.org/html-tutorials/?ref=lbp
https://www.geeksforgeeks.org/working-with-apis-in-javascript/
https://tailwindui.com/documentation
https://www.geeksforgeeks.org/css-tutorials/?ref=lbp
https://www.w3schools.com/jsrEF/default.asp
https://www.geeksforgeeks.org/web-development/
https://react-slick.neostack.com/
https://react-icons.github.io/react-icons/
https://www.npmjs.com/package/axios
https://reactjs.org/docs/react-dom.html
https://www.npmjs.com/package/react-slick-carousel
https://www.mongodb.com
https://redux.js.org/introduction/getting-started
34
APPENDIX A
SCREEN SHOTS
35
HomePage
36
37
Google Auth Page
Signin
Signup
Restaurant Page
38
39
40
Checkout Page
Payemnt
41
42
APPENDIX B
SOURCE CODE
43
CLIENT SIDE
Homepage
import React, { useEffect } from "react";
import { useParams } from "react-router-dom";
// Layout
import HomeLayout from "../layouts/Homepage.layout";
// components
import Delivery from "../components/Delivery";
import Dining from "../components/Dining";
import NightLife from "../components/NightLife";
import Nutrition from "../components/Nutrition";
// redux
import { useDispatch } from "react-redux";
import { getRestaurant } from "../redux/reducers/restaurant/restaurant.action";
useEffect(() => {
dispatch(getRestaurant());
}, []);
return (
<>
<div className="my-5 mb-20 md:mb-10">
{type === "delivery" && <Delivery />}
{type === "dining" && <Dining />}
44
{type === "night" && <NightLife />}
{type === "nutri" && <Nutrition />}
</div>
</>
);
};
Checkout Page
import React from "react";
import { BsShieldLockFill } from "react-icons/bs";
// Layout
import CheckoutLayout from "../layouts/Checkout.layout";
// components
import FoodItem from "../components/Cart/FoodItem";
import AddressList from "../components/Checkout/AddressList";
//redux
import { useSelector } from "react-redux";
const address = [
{
name: "Home",
address: "Palama Street, 123 Main",
},
45
{
name: "Work",
address: "123 Main Street, CP",
},
];
return (
46
<div className="my-3 flex flex-col gap-3 items-center">
<h1 className="text-xl text-center md:text-2xl font-bold">Checkout</h1>
<div className="w-full md:w-3/5 rounded-lg py-3 drop-shadow-2xl bg-white
flex flex-col items-center p-4">
<h3 className="text-lg font-semibold">Summary</h3>
<div className="flex w-full flex-col gap-2 items-center">
<h5 className="text-base tracking-wider">ORDER FROM</h5>
<div className="flex w-full flex-col items-center text-gray-400">
<h4>Domino's Pizza</h4>
<small>GT World Mall, Magadi Road, NCR Noida</small>
</div>
<div className="my-4 h-32 overflow-y-scroll px-4 flex flex-col gap-2 w-full
md:w-3/5">
{cart.map((item) => (
<FoodItem key={item._id} {...item} />
))}
</div>
<div className="flex flex-col gap-3 w-full md:w-3/5 items-center">
<h4 className="text-xl font-semibold">Choose Address</h4>
<AddressList address={address} />
</div>
</div>
<button
onClick={payNow}
className=" flex items-center gap-2 justify-center my-4 md:my-8 w-full px-4
md:w-4/5 h-14 text-white fomt-medium text-lg bg-zomato-400 rounded-lg"
>
Pay Securely <BsShieldLockFill />
</button>
</div>
</div>
);
};
47
export default CheckoutLayout(Checkout);
GoogleAuth Page
import React, { useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
// redux
import { useDispatch } from "react-redux";
import { googleAuth } from "../redux/reducers/auth/auth.action";
useEffect(() => {
if (token) {
dispatch(googleAuth(token)).then(() => navigate("/delivery"));
}
}, [token]);
Restaurant Page
import React from "react";
import { useParams, useLocation, Navigate } from "react-router-dom";
import { Outlet } from "react-router-dom";
48
const Restaurant = () => {
const { id } = useParams();
const { pathname } = useLocation();
return (
<>
<Outlet />
</>
);
};
App.js
import "./App.css";
import { useEffect } from "react";
import { Routes, Route, Navigate } from "react-router-dom";
// pages
import Checkout from "./pages/Checkout.page";
import GoogleAuth from "./pages/GoogleAuth.page";
import Home from "./pages/Home.page";
import Restaurant from "./pages/Restaurant.page";
// components
import Overview from "./components/Restaurant/Overview";
import OrderOnline from "./components/Restaurant/OrderOnline";
import Menu from "./components/Restaurant/Menu";
49
import Reviews from "./components/Restaurant/Reviews";
import Photos from "./components/Restaurant/Photos";
import RestaurantLayout from "./layouts/Restaurant.layout";
// redux
import { useDispatch } from "react-redux";
import { getMySelf } from "./redux/reducers/user/user.action";
import { getCart } from "./redux/reducers/cart/cart.action";
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getMySelf());
dispatch(getCart());
}, [localStorage]);
return (
<>
<Routes>
<Route path="/" element={<Navigate to="/delivery" />} />
<Route path="/:type" element={<Home />} />
{/* <Route path="/restaurant/:id" element={<RedirectRestaurant />} /> */}
<Route path="/google/:token" element={<GoogleAuth />} />
<Route
path="/restaurant/:id"
element={
<RestaurantLayout>
<Restaurant />
</RestaurantLayout>
}
>
50
<Route path="overview" element={<Overview />} />
<Route path="order-online" element={<OrderOnline />} />
<Route path="reviews" element={<Reviews />} />
<Route path="menu" element={<Menu />} />
<Route path="photos" element={<Photos />} />
</Route>
<Route path="/checkout/orders" element={<Checkout />} />
</Routes>
</>
);
}
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import axios from "axios";
if (localStorage.zomatoUser) {
const { token } = JSON.parse(localStorage.zomatoUser);
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
}
51
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>
);
Auth Component
import { Dialog, Transition } from "@headlessui/react";
import { Fragment, useState } from "react";
import { FcGoogle } from "react-icons/fc";
// redux
import { useDispatch } from "react-redux";
import { signIn } from "../../redux/reducers/auth/auth.action";
import { getMySelf } from "../../redux/reducers/user/user.action";
52
const closeModal = () => {
setIsOpen(false);
};
return (
<>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={closeModal}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
53
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
54
<label htmlFor="email">Email</label>
<input
type="text"
id="email"
value={userData.email}
onChange={handleChange}
placeholder="user@email.com"
className="w-full border border-gray-400 px-3 py-2 rounded-lg
focus:border-zomato-400"
/>
</div>
<div className="w-full flex flex-col gap-2">
<label htmlFor="email">Password</label>
<input
type="password"
id="password"
value={userData.password}
onChange={handleChange}
placeholder="*********"
className="w-full border border-gray-400 px-3 py-2 rounded-lg
focus:border-zomato-400"
/>
</div>
<div
className="w-full text-center bg-zomato-400 text-white px-2
rounded-lg py-2 cursor-pointer"
onClick={submit}
>
Sign In
</div>
</form>
55
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
</>
);
};
Card Component
import React from "react";
import { BsTrashFill } from "react-icons/bs";
// redux
import { useDispatch } from "react-redux";
import {
deleteCart,
incrementQuantity,
decrementQuantity,
} from "../../redux/reducers/cart/cart.action";
56
const increment = () => dispatch(incrementQuantity(props._id));
return (
<>
<div className="flex items-center justify-between">
<h5>{props.name}</h5>
<div className="flex items-center justify-center gap-2">
<div className="flex flex-col items-end">
<small>₹ {parseInt(props.price) * parseInt(props.quantity)}</small>
<div className="px-1 bg-zomato-400 text-white rounded flex items-center
gap-1">
<button
onClick={decrement}
className="p-1 bg-zomato-400 text-white rounded"
>
-
</button>
<small>{props.quantity}</small>
<button
onClick={increment}
className="p-1 bg-zomato-400 text-white rounded"
>
+
</button>
</div>
</div>
57
<BsTrashFill
onClick={deleteFoodFromCart}
className="text-zomato-400 text-lg md:text-xl cursor-pointer"
/>
</div>
</div>
</>
);
};
Checkout Component
import React from "react";
import { RadioGroup } from "@headlessui/react";
import { useState } from "react";
return (
<div className="w-full px-4 py-16">
<div className="mx-auto w-full max-w-md">
<RadioGroup value={selected} onChange={setSelected}>
<RadioGroup.Label className="sr-only">
Choose Address
</RadioGroup.Label>
<div className="space-y-2">
{props.address.map((item) => (
<RadioGroup.Option
key={item.name}
58
value={item}
className={({ active, checked }) =>
`${
active
? "ring-2 ring-white ring-opacity-60 ring-offset-2 ring-offset-zomato-
300"
: ""
}
${
checked
? "bg-zomato-100 bg-opacity-75 text-zomato-600"
: "bg-white"
}
relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-
none`
}
>
{({ active, checked }) => (
<>
<div className="flex w-full items-center justify-between">
<div className="flex items-center">
<div className="text-sm">
<RadioGroup.Label
as="p"
className={`font-medium ${
checked ? "text-zomato-600" : "text-gray-900"
}`}
>
{item.name}
</RadioGroup.Label>
<RadioGroup.Description
59
as="span"
className={`inline ${
checked ? "text-zomato-500" : "text-gray-500"
}`}
>
<span>{item.address}</span>{" "}
</RadioGroup.Description>
</div>
</div>
{checked && (
<div className="shrink-0 text-white">
<CheckIcon className="h-6 w-6" />
</div>
)}
</div>
</>
)}
</RadioGroup.Option>
))}
</div>
</RadioGroup>
</div>
</div>
);
};
function CheckIcon(props) {
return (
<svg viewBox="0 0 24 24" fill="none" {...props}>
<circle cx={12} cy={12} r={12} fill="#d13d3d" opacity="0.2" />
60
<path
d="M7 13l3 3 7-7"
stroke="#fff"
strokeWidth={1.5}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
Delivery Component
import React, { useState, useEffect } from "react";
import RestaurantCard from "../RestaurantCard";
// components
import DeliveryCarousel from "./DeliveryCarousel";
// redux
import { useSelector } from "react-redux";
61
useEffect(() => {
reduxState && setRestaurantList(reduxState);
}, [reduxState]);
return (
<>
<DeliveryCarousel />
<h1 className="text-xl mt-4 mb-2 md:mt-8 md:text-3xl md:font-semibold">
Delivery Restaurants in NCR (Delhi)
</h1>
<div className="grid gap-0 md:gap-2 md:grid-cols-2 grid-cols-1 lg:grid-cols-
3">
{restaurantList.map((restaurant) => (
<RestaurantCard {...restaurant} key={restaurant._id} />
))}
</div>
</>
);
};
Dining Component
import React, { useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import { Navigation } from "swiper";
// components
import PictureCarouselCard from "../PictureCarouselCard";
62
const DiningCarousel = () => {
const [dining] = useState([
{
image:
"https://b.zmtcdn.com/data/collections/019acf0c53e2ebf0e8658e471a20a2ab_16652
10805.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/collections/4872d7301e80d72fd18c4e1e43bf8789_16607
38717.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/collections/84317f74208f036be1936e32dc627d88_16608
23494.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/collections/51979569f85f4579e15336825f446188_16607
38438.jpg",
title: "Eid-e-Milad Specials",
63
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/collections/d9eea3ef785def3a1d4e19c89bf19b11_166081
6040.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/collections/ef4da4077aae068ea1e4410eefb5aec5_166073
5784.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
]);
const slideConfig = {
slidesPerView: 1,
spaceBetween: 10,
pagination: {
clickable: true,
},
breakpoints: {
640: {
slidesPerView: 2,
spaceBetween: 20,
},
768: {
64
slidesPerView: 3,
spaceBetween: 10,
},
1024: {
slidesPerView: 4,
spaceBetween: 0,
},
},
modules: [Navigation],
className: "diningSwiper",
navigation: true,
};
return (
<div className="w-full">
<Swiper {...slideConfig}>
{dining.map((item, index) => (
<SwiperSlide key={index}>
<PictureCarouselCard {...item} />
</SwiperSlide>
))}
</Swiper>
</div>
);
};
65
FoodTab Component
import React, { useState } from "react";
import { useParams, Link } from "react-router-dom";
import { RiShoppingBag3Line } from "react-icons/ri";
import { IoFastFoodOutline, IoNutritionOutline } from "react-icons/io5";
import { BiDrink } from "react-icons/bi";
import classnames from "classnames";
66
]);
return (
<>
<div className="lg:hidden flex bg-white shadow-lg fixed bottom-0 z-10 w-full
items-center justify-between md:justify-evenly text-gray-500 border">
{allTypes.map((item) => (
<Link key={item.id} to={`/${item.id}`} className="w-1/4">
<div
className={
type === item.id
? "flex items-center text-center flex-col relative text-xl text-zomato-400"
: "flex text-center flex-col items-center text-xl "
}
>
<div
className={
type === item.id
? "w-full h-full border-t-2 border-zomato-400 flex flex-col items-center
pt-3"
: "flex flex-col items-center pt-3"
}
>
{item.icon}
</div>
<h5 className="text-sm pb-3">{item.name}</h5>
</div>
</Link>
))}
67
</div>
</>
);
};
"https://b.zmtcdn.com/data/o2_assets/246bbd71fbba420d5996452be3024d35161615
0055.png",
imageActive:
"https://b.zmtcdn.com/data/o2_assets/c0bb85d3a6347b2ec070a8db69458826161614
9578.png",
name: "Delivery",
activeColor: "yellow",
},
{
id: "dining",
imageDefault:
"https://b.zmtcdn.com/data/o2_assets/78d25215ff4c1299578ed36eefd5f39d1616149
985.png",
imageActive:
"https://b.zmtcdn.com/data/o2_assets/30fa0a844f3ba82073e5f78c65c18b371616149
662.png",
activeColor: "blue",
name: "Dining Out",
},
68
{
id: `night`,
imageDefault:
"https://b.zmtcdn.com/data/o2_assets/01040767e4943c398e38e3592bb1ba8a161615
0142.png",
imageActive:
"https://b.zmtcdn.com/data/o2_assets/855687dc64a5e06d737dae45b7f6a13b1616149
818.png",
activeColor: "purple",
name: "Night life",
},
{
id: `nutri`,
imageDefault:
"https://b.zmtcdn.com/data/o2_assets/54cad8274d3c3ec7129e0808a13b27c31616582
882.png",
imageActive:
"https://b.zmtcdn.com/data/o2_assets/0f6dcb1aef93fa03ea3f91f37918f3bc16166495
03.png",
activeColor: "yellow",
name: "Nutrition",
},
]);
return (
<>
<div className="hidden lg:flex gap-14 container px-20 my-8 mx-auto">
69
{allTypes.map((item) => (
<Link key={item.id} to={`/${item.id}`} className="w-36">
<div
className={classnames(
"flex items-center gap-3 pb-2 transition duration-700 ease-in-out",
{
"border-b-2 border-zomato-500": type === item.id,
}
)}
>
<div
className={classnames(
"w-16 h-16 bg-gray-100 p-4 rounded-full",
{
[`bg-${item.activeColor}`]: type === item.id,
}
)}
>
<img
src={type === item.id ? item.imageActive : item.imageDefault}
alt={item.id}
className="w-full h-full"
/>
</div>
<h3
className={
type === item.id
? "text-md text-zomato-400"
: "text-md text-gray-700"
}
70
>
{item.name}
</h3>
</div>
</Link>
))}
</div>
</>
);
};
Navbar Component
import React, { useState } from "react";
import { FaUserAlt } from "react-icons/fa";
import { HiLocationMarker } from "react-icons/hi";
import { IoMdArrowDropdown } from "react-icons/io";
import { RiSearch2Line } from "react-icons/ri";
import { Link, useNavigate } from "react-router-dom";
71
// components
import SignUp from "../Auth/Signup";
import SignIn from "../Auth/Signin";
// redux
import { useSelector, useDispatch } from "react-redux";
import { signOut } from "../../redux/reducers/auth/auth.action";
import { clearUser } from "../../redux/reducers/user/user.action";
const MobileNav = ({
user,
isDropdownOpen,
setIsDropdownOpen,
signIn,
signUp,
}) => {
const SignIn = () => {
signIn();
setIsDropdownOpen(false);
};
72
dispatch(signOut());
dispatch(clearUser());
navigate("/delivery");
setIsDropdownOpen(false);
};
return (
<div className="flex w-full items-center justify-between lg:hidden">
<div className="w-28">
<Link to="/">
<img
src="https://b.zmtcdn.com/web_assets/b40b97e677bc7b2ca77c58c61db266fe160395
4218.png"
alt="logo"
className="w-full h-full"
/>
</Link>
</div>
<div className="flex items-center gap-3 relative">
<button className="bg-zomato-400 text-white py-2 px-3 rounded-full">
Use App
</button>
{user?.fullName ? (
<>
<div
onClick={() => setIsDropdownOpen((prev) => !prev)}
className="border border-gray-300 text-zomato-400 w-9 h-9 rounded-full"
>
<img
src="/images/avatar.png"
73
alt="avatar"
className="w-full h-full rounded-full object-cover"
/>
</div>
{isDropdownOpen && (
<div className="absolute shadow-lg py-3 -bottom-14 w-36 z-20 flex flex-
col gap-2 bg-white border border-gray-200">
<button onClick={SignOut}>Sign Out</button>
</div>
)}
</>
):(
<>
<span
onClick={() => setIsDropdownOpen((prev) => !prev)}
className="border p-2 border-gray-400 rounded-full"
>
<FaUserAlt className="w-full h-full" />
</span>
{isDropdownOpen && (
<div className="absolute shadow-lg py-3 -bottom-24 w-full z-20 flex flex-
col gap-2 bg-white border border-gray-200">
<button onClick={SignIn}>Sign In</button>
<button onClick={SignUp}>Sign Up</button>
</div>
)}
</>
)}
</div>
</div>
74
);
};
const LargeNav = ({
user,
isDropdownOpen,
setIsDropdownOpen,
signIn,
signUp,
}) => {
const SignIn = () => {
signIn();
setIsDropdownOpen(false);
};
75
return (
<div className="w-full items-center justify-between hidden lg:flex px-14">
<div className="gap-4 items-center justify-around flex">
<div className="w-20">
<Link to="/">
<img
src="https://b.zmtcdn.com/web_assets/b40b97e677bc7b2ca77c58c61db266fe160395
4218.png"
alt="logo"
className="w-full h-full"
/>
</Link>
</div>
</div>
<div className="w-3/4 bg-white shadow-md p-3 flex items-center gap-3 border
border-gray-200 rounded">
<div className="flex items-center gap-2 border-r-2 border-gray-300 pr-2">
<span className="text-zomato-400">
<HiLocationMarker />
</span>
<input
type="text"
placeholder="Delhi NCR"
className="w-full focus:outline-none"
/>
<IoMdArrowDropdown />
</div>
76
<input
type="search"
placeholder="Search for restaurant, cuisine or a dish"
className="w-full focus:outline-none"
/>
</div>
</div>
<div className="flex items-center gap-3 relative">
{user?.fullName ? (
<>
<div
onClick={() => setIsDropdownOpen((prev) => !prev)}
className="border border-gray-300 text-zomato-400 w-9 h-9 rounded-full"
>
<img
src="/images/avatar.png"
alt="avatar"
className="w-full h-full rounded-full object-cover"
/>
</div>
{isDropdownOpen && (
<div className="absolute shadow-lg py-3 -bottom-14 -right-0 w-36 z-20
flex flex-col gap-2 bg-white border border-gray-200">
<button onClick={SignOut}>Sign Out</button>
</div>
)}
</>
):(
<>
<span
77
onClick={() => setIsDropdownOpen((prev) => !prev)}
className="border p-2 border-gray-400 rounded-full"
>
<FaUserAlt className="w-full h-full" />
</span>
{isDropdownOpen && (
<div className="absolute shadow-lg py-3 -bottom-24 -right-0 w-36 z-20
flex flex-col gap-2 bg-white border border-gray-200">
<button onClick={SignIn}>Sign In</button>
<button onClick={SignUp}>Sign Up</button>
</div>
)}
</>
)}
</div>
</div>
);
};
// const user = {
// // fullName: "Aditya",
78
// };
return (
<>
<SignIn isOpen={openSignIn} setIsOpen={setOpenSignIn} />
<SignUp isOpen={openSignUp} setIsOpen={setOpenSignUp} />
<LargeNav
user={user}
setIsDropdownOpen={setIsDropdownOpen}
isDropdownOpen={isDropdownOpen}
signIn={openSignInModal}
signUp={openSignUpModal}
/>
</nav>
</>
);
};
79
export default Navbar;
NightLife Component
import React, { useState } from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import { Navigation } from "swiper";
// components
import PictureCarouselCard from "../PictureCarouselCard";
"https://b.zmtcdn.com/data/pictures/1/18983041/31109ef52f99ea794d705da5c70662
7a.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/pictures/0/303960/68e61bd2a5fe97adf587d30496d94cfe.
png",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
80
"https://b.zmtcdn.com/data/pictures/5/19577475/a9150506655136673058d180c8167
d9c.jpeg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/pictures/1/19567911/f3e8a1376225dfd3cc32c605097973
c0.jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/pictures/0/309850/4c2cce1c16a40f515a27ecc27075259e.
jpg",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
{
image:
"https://b.zmtcdn.com/data/pictures/2/312902/2e3a98229ef00de30a9c7ad867bc0d5a.
png",
title: "Eid-e-Milad Specials",
places: "9 Places",
},
]);
const slideConfig = {
81
slidesPerView: 1,
spaceBetween: 10,
pagination: {
clickable: true,
},
breakpoints: {
640: {
slidesPerView: 2,
spaceBetween: 20,
},
768: {
slidesPerView: 3,
spaceBetween: 10,
},
1024: {
slidesPerView: 4,
spaceBetween: 0,
},
},
modules: [Navigation],
className: "diningSwiper",
navigation: true,
};
return (
<div className="w-full">
<Swiper {...slideConfig}>
{dining.map((item, index) => (
<SwiperSlide key={index}>
<PictureCarouselCard {...item} />
82
</SwiperSlide>
))}
</Swiper>
</div>
);
};
SERVER SIDE
Auth
import express from "express";
import passport from "passport";
/**
* Route /signup
* Des Create new account
* Params none
* Access Public
* Method POST
*/
Router.post("/signup", async (req, res) => {
83
try {
await ValidateSignup(req.body.credentials);
await UserModel.findByEmailAndPhone(req.body.credentials);
const newUser = await UserModel.create(req.body.credentials);
const token = newUser.generateJwtToken();
return res.status(200).json({ token, status: "success" });
} catch (error) {
return res.status(500).json({ error: error.message });
}
});
/**
* Route /signin
* Des Login to existing account
* Params none
* Access Public
* Method POST
*/
Router.post("/signin", async (req, res) => {
try {
await ValidateSignin(req.body.credentials);
const user = await UserModel.findByEmailAndPassword(req.body.credentials);
const token = user.generateJwtToken();
return res.status(200).json({ token, status: "success" });
} catch (error) {
return res.status(500).json({ error: error.message });
}
});
Router.get(
84
"/google",
passport.authenticate("google", {
scope: [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
],
})
);
Router.get(
"/google/callback",
passport.authenticate("google", { failureRedirect: "/" }),
(req, res) => {
// return res.status(200).json({
// token: req.session.passport.user.token,
// });
return res.redirect(
`http://localhost:3000/google/${req.session.passport.user.token}`
);
}
);
Food
import express from "express";
85
validateCategory,
validateId,
} from "../../validation/common.validation";
/**
* Route /:_id
* Des Get food based on id
* Params _id
* Access Public
* Method GET
*/
Router.get("/:_id", async (req, res) => {
try {
const { _id } = req.params;
await validateId(req.params);
/**
* Route /r/:_id
* Des Get all food based on particular restaurant
* Params _id
86
* Access Public
* Method GET
*/
Router.get("/r/:_id", async (req, res) => {
try {
const { _id } = req.params;
await validateId(req.params);
/**
* Route /c/:category
* Des Get all food based on particular category
* Params category
* Access Public
* Method GET
*/
Router.get("/c/:category", async (req, res) => {
try {
87
const { category } = req.params;
await validateCategory(req.params);
const foods = await FoodModel.find({
category: { $regex: category, $options: "i" },
});
if (!foods)
return res
.status(404)
.json({ error: `No food matched with ${category}` });
// /c/non
// non === non - veg;
// non === nonsdfwae;
Image
import express from "express";
import AWS from "aws-sdk";
import multer from "multer";
88
import { s3Upload } from "../../utils/s3";
// multer configure
const storage = multer.memoryStorage();
const upload = multer({ storage });
/**
* Route /:_id
* Des Get image details
* Params _id
* Access Public
* Method GET
*/
Router.get("/:_id", async (req, res) => {
try {
const image = await ImageModel.findById(req.params._id);
/**
* Route /
* Des Upload given image to s3 bucket and save file link to mongoDB
* Params _id
* Access Public
89
* Method POST
*/
Router.post("/", upload.single("file"), async (req, res) => {
try {
const file = req.file;
const bucketOptions = {
Bucket: "zomato-clone-10567",
Key: file.originalname,
Body: file.buffer,
ContentType: file.mimetype,
ACL: "public-read", // Access Control List
};
90
// Router.post("/", upload.array("file", 4), async (req, res) => {
// try {
// const file = req.files;
// const bucketOptions = {
// Bucket: "zomato-clone-10567",
// Key: file.originalname,
// Body: file.buffer,
// ContentType: file.mimetype,
// ACL: "public-read", // Access Control List
// };
91
Menu
import express from "express";
/**
* Route /list/:_id
* Des Get menu based on menu id
* Params _id
* Access Public
* Method GET
*/
Router.get("/list/:_id", async (req, res) => {
try {
const { _id } = req.params;
const menus = await MenuModel.findById(_id);
if (!menus) {
return res
.status(404)
.json({ error: "No menu present for this restaurant" });
}
92
/**
* Route /image
* Des Get all list of menu images with id
* Params _id
* Access Public
* Method GET
*/
Router.get("/image/:_id", async (req, res) => {
try {
const { _id } = req.params;
if (!menuImages) {
return res.status(404).json({ message: "No menu images found." });
}
Order
import express from "express";
import passport from "passport";
93
import { OrderModel } from "../../database/allModels";
/**
* Route /
* Des Get all orders by user id
* Params none
* Access Private
* Method GET
*/
Router.get(
"/",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
const { user } = req;
if (!getOrders) {
return res.status(400).json({ error: "User not found" });
}
94
/**
* Route /new
* Des Add new order
* Params none
* Access Private
* Method PUT
*/
Router.put(
"/new",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
const { user } = req;
95
}
);
Restaurant
import express from "express";
/**
* Route /
* Des Create new restaurant
* Params none
* Access Public
* Method POST
*/
96
// Homework
/**
* Route /
* Des Get all the restuarant details based on the city
* Params none
* Access Public
* Method GET
*/
Router.get("/", async (req, res) => {
try {
// http://localhost:4000/restaurant/?city=ncr
const { city } = req.query;
// await ValidateRestaurantCity(req.query);
/**
* Route /:_id
97
* Des Get individual restuarant details based on id
* Params _id
* Access Public
* Method GET
*/
Router.get("/:_id", async (req, res) => {
try {
const { _id } = req.params;
const restaurant = await RestaurantModel.findById(_id);
if (!restaurant) {
return res.status(400).json({ error: "Restaurant not found" });
}
/**
* Route /search/:searchString
* Des Get restaurants details based on search string
* Params searchString
* Access Public
* Method GET
*/
Router.get("/search/:searchString", async (req, res) => {
/**
* searchString = Raj
98
* results = {
* RajHotel
* RajRow
* RonRaj
* raJRow
*}
*/
try {
const { searchString } = req.params;
// await ValidateSearchString(req.params);
if (!restaurants.length === 0) {
return res
.status(404)
.json({ error: `No restaurant matched with ${searchString}` });
}
99
Review
import express from "express";
import passport from "passport";
/**
* Route /:resId
* Des Get all review for a particular restaurant
* Params resId
* Access Public
* Method GET
*/
Router.get("/:resId", async (req, res) => {
try {
const { resId } = req.params;
const reviews = await ReviewModel.find({ restaurants: resId }).sort({
createdAt: -1,
});
/**
* Route /new
100
* Des Add new food/restaurant review and rating
* Params none
* Access Private
* Method POST
*/
Router.post(
"/new",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
const { _id } = req.user;
const { reviewData } = req.body;
/**
* Route /delete/:id
* Des Delete a specific review
* Params _id
* Access Private
* Method Delete
*/
Router.delete(
101
"/delete/:id",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
const { user } = req;
const { id } = req.params;
if (!data) {
return res.json({ message: "Review was not deleted" });
}
User
import express from "express";
import { UserModel } from "../../database/allModels";
import passport from "passport";
102
const Router = express.Router();
/**
* Route /
* Des Get authorized user data
* Params none
* Access Private
* Method GET
*/
Router.get(
"/",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
const { email, fullName, phoneNumber, address } = req.user;
/**
* Route /:_id
* Des Get user data (For the review system)
* Params _id
* Access Public
* Method GET
*/
103
Router.get("/:_id", async (req, res) => {
try {
const { _id } = req.params;
if (!getUser) {
return res.status(404).json({ error: "User not found" });
}
/**
* Route /:_id
* Des Update user data
* Params _id
* Access Private
* Method PUT
*/
Router.put(
"/update/:_id",
passport.authenticate("jwt", { session: false }),
async (req, res) => {
try {
104
const { _id } = req.params;
const { userData } = req.body;
userData.password = undefined;
index.js
import express from "express";
import dotenv from "dotenv";
import passport from "passport";
105
import session from "express-session";
import cors from "cors";
import helmet from "helmet";
// Database connection
import ConnectDB from "./database/connection";
dotenv.config();
privateRouteConfig(passport);
googleAuthConfig(passport);
106
zomato.use(helmet());
zomato.use(express.json());
zomato.use(session({ secret: process.env.JWTSECRET }));
zomato.use(passport.initialize());
zomato.use(passport.session());
// /auth/signup
zomato.use("/auth", Auth);
zomato.use("/food", Food);
zomato.use("/restaurant", Restaurant);
zomato.use("/user", User);
zomato.use("/menu", Menu);
zomato.use("/order", Order);
zomato.use("/review", Review);
zomato.use("/image", Image);
zomato.listen(PORT, () => {
ConnectDB()
.then(() => {
console.log("Server is running !!!");
})
.catch((error) => {
107
console.log("Server is running, but database connection failed...");
console.log(error);
});
});
108