Anda di halaman 1dari 37

Ristorante Con Fusion –

A restaurant App
SUMMER TRAINING PROJECT REPORT
B.Tech
Computer Science Engineering
by

Ankush Sharma
160060101016

Front End Development using React

by

College of Engineering Roorkee, Roorkee


Certification of Completion
CANDIDATE’S DECLARATION
I hereby declare that the work presented in this project report titled, “Ristorante Con Fusion –A
restaurant App” submitted by me in the partial fulfillment of the requirement of the award of the degree of
Bachelor of Technology (B.Tech.) Submitted in the Department of Computer Science & Engineering,
College of Engineering Roorkee, is an authentic record of my thesis carried out under the guidance of
Jogesh K.Muppa (Associate Professor, Department of Computer Science and Engineering, Hong Kong
University of Science and Technology).

Date 04/12/2019 Ankush


Place: Roorkee
SUPERVISOR’S CERTIFICATE
It is to certify that the Project entitled “Ristorante Con Fusion –A restaurant App” which is being submitted

by Mr. Ankush to the College of Engineering ,Roorkee in the fulfillment of the requirement for the award of

the degree of Bachelor of Technology (B.Tech.), is a record of bonafide project work carried out by him

under our guidance and supervision. The matter presented in this project report has not been submitted either

in part or full to any University or Institute for award of any degree.

Mrs. Divya Mishra


Introduction about Coursera and training
Coursera :
Coursera is an American online learning platform founded by Stanford professors Andrew Ng and Daphne
Koller that offers massive open online courses (MOOC), specializations, and degrees.
Coursera works with universities and other organizations to offer online courses, specializations, and
degrees in a variety of subjects, such as engineering, humanities, medicine, biology, social
sciences, mathematics, business, computer science, digital marketing, data science, and others.
As of June 2018, Coursera had more than 33 million registered users[3] and more than 2,400 courses.[4] As
of August 2019 the number of course offerings was 3,600.

Training :
What is Front-End Development ?
Front-end web development is the practice of converting data to a graphical interface, through the use of
HTML, CSS, and JavaScript, so that users can view and interact with that data.

Tools used for front-end development


There are several tools and platforms (wordpress, magento etc..) available that can be used to develop the
front end of a website, and understanding which tools are best fit for specific tasks marks the difference
between developing a hacked site and a well designed, scalable site.

• Hyper Text Markup Language (HTML)

Hyper Text Markup Language (HTML) is the backbone of any website development process,
without which a web page doesn't exist. Hypertext means that text has links, termed hyperlinks,
embedded in it. When a user clicks on a word or a phrase that has a hyperlink, it will bring another
web-page. A markup language indicates text can be turned into images, tables, links, and other
representations. It is the HTML code that provides an overall framework of how the site will look.
HTML was developed by Tim Berners-Lee. The latest version of HTML is called HTML5 and was
published on October 28, 2014 by the W3 recommendation. This version contains new and efficient
ways of handling elements such as video and audio files.
• Cascading Style Sheets (CSS)

Cascading Style Sheets (CSS) controls the presentation aspect of the site and allows your site to
have its own unique look. It does this by maintaining style sheets which sit on top of other style
rules and are triggered based on other inputs, such as device
screen size and resolution.

• JavaScript

JavaScript is an event-based imperative programming language (as opposed to HTML's declarative


language model) that is used to transform a static HTML page into a dynamic interface. JavaScript
code can use the [Document Object Model] (DOM), provided by the HTML standard, to manipulate
a web page in response to events, like user input.
Using a technique called AJAX, JavaScript code can also actively retrieve content from the web
(independent of the original HTML page retrieval), and also react to server-side events as well,
adding a truly dynamic nature to the web page experience.

• React

React (also known as React.js or ReactJS) is a JavaScript library[3] for building user interfaces. It is
maintained by Facebook and a community of individual developers and companies.[4][5][6]
React can be used as a base in the development of single-page or mobile applications, as it is optimal
for fetching rapidly changing data that needs to be recorded. However, fetching data is only the
beginning of what happens on a web page, which is why complex React applications usually require
the use of additional libraries for state management, routing, and interaction with
an API:[7][8] Redux[9], React Router[10] and axios[11] are examples of such libraries.
Introduction

Summary
Summary Ristorante Con Fusion it’s a famous restaurant for fusion
foods. In this web application user can view the featured foods,
chef and details about the food with single page application and,
the clear navigation that will enable users to quickly get the food
and review details.

Features
• Featured dish, promotion and leaders display in homepage.
• Nice UI interaction between the pages like on data request loading
the spinner and ease in/out for view pages.
• Comment review in action.
• Rating slider for users.
• User friendly error reporting.
• Storing the feedback details web services
Design and Implementation
Giving the UI design diagram below for a better understanding of the flow.

● For the actual code implementation, need a proper understanding of different


flows in the application and using that i have divided the application into different
components within a page itself. For example

App component consist of Header , Main and footer component. Main component
content will load based on the router. This is basically separation of concerns and gives
more clarity and modularity for the design.
These are the list of libraries/ modules used in the project.

“dependencies”:{
"bootstrap": "^4.0.0", —> for
UI styling "bootstrap-social":
"^5.1.1",

"cross-fetch": "^2.1.0", —> Server


Communication "font-awesome": "^4.7.0",

"prop-types": "^15.6.0",
"react": "^16.11.0", —> React
support "react-animation-
components": "^3.0.0",

"react-dom": "^16.11.0", —> Provides React


Virtual DOM "react-popper": "^0.9.2",

"react-redux": "^5.0.7", —> State


Management "react-redux-form": "^1.16.8",
—> Redux Form "react-router-dom": "^5.1.2",
—> For React Routing "react-scripts":
"3.2.0", —> For Bundling "reactstrap":
"^5.0.0", —> for UI styling "redux":
"^3.7.2", —> Redux Support

"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0", —> Intercepting the
dispatch
},
Project Screenshot
PROJECT STRUCTURE FRONTEND PART
Code
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/f
undamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build
.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will


work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>ConFusion App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.


The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.


To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
AboutComponent.js

import React from 'react';


import { Breadcrumb, BreadcrumbItem, Card, CardBody, CardHeader, Media } from
'reactstrap';
import {Fade, Stagger } from 'react-animation-components';
import { Link } from 'react-router-dom';
import { Loading } from './LoadingComponent';
import { baseUrl } from '../shared/baseUrl';

function About(props) {
let leaders = <div></div>

if (props.leaders.isLoading) {
leaders = <Loading />;
}
else if (props.leaders.errMess) {
leaders = <h4>{props.leaders.errMess}</h4>;
}

else if(props.leaders) {
leaders = props.leaders.leaders.map((leader) => {
return (
<Fade in key={leader.id}>
<RenderLeader key={leader.id} leader={leader} />
</Fade>
);
});
}

function RenderLeader ({leader}) {


return (
<Media className="mb-5">
<Media left className="mr-5 mt-5">
<Media object style={{maxHeight: 160,maxWidth: 150 }} src=
{baseUrl + leader.image} alt={leader.name} />
</Media>
<Media body>
<Media heading>
{leader.name}
</Media>
<div className="mb-3">{leader.designation}</div>
<div>{leader.description}</div>
</Media>
</Media>
);
}

return(
<div className="container">
<div className="row">
<Breadcrumb>
<BreadcrumbItem><Link to="/home">Home</Link></BreadcrumbIt
em>
<BreadcrumbItem active>About Us</BreadcrumbItem>
</Breadcrumb>
<div className="col-12">
<h3>About Us</h3>
<hr />
</div>
</div>
<div className="row row-content">
<div className="col-12 col-md-6">
<h2>Our History</h2>
<p>Started in 2010, Ristorante con Fusion quickly establis
hed itself as a culinary icon par excellence in Hong Kong. With its unique bra
nd of world fusion cuisine that can be found nowhere else, it enjoys patronage
from the A-list clientele in Hong Kong. Featuring four of the best three-
star Michelin chefs in the world, you never know what will arrive on your plat
e the next time you visit us.</p>
<p>The restaurant traces its humble beginnings to <em>The
Frying Pan</em>, a successful chain started by our CEO, Mr. Peter Pan, that fe
atured for the first time the world's best cuisines in a pan.</p>
</div>
<div className="col-12 col-md-5">
<Card>
<CardHeader className="bg-primary text-
white">Facts At a Glance</CardHeader>
<CardBody>
<dl className="row p-1">
<dt className="col-6">Started</dt>
<dd className="col-6">3 Feb. 2013</dd>
<dt className="col-6">Major Stake Holder</dt>
<dd className="col-6">HK Fine Foods Inc.</dd>
<dt className="col-
6">Last Year's Turnover</dt>
<dd className="col-6">$1,250,375</dd>
<dt className="col-6">Employees</dt>
<dd className="col-6">40</dd>
</dl>
</CardBody>
</Card>
</div>
<div className="col-12">
<Card>
<CardBody className="bg-faded">
<blockquote className="blockquote">
<p className="mb-
0">You better cut the pizza in four pieces because
I'm not hungry enough to eat six.</p>
<footer className="blockquote-
footer">Yogi Berra,
<cite title="Source Title">The Wit and Wisdom
of Yogi Berra,
P. Pepe, Diversion Books, 2014</cite>
</footer>
</blockquote>
</CardBody>
</Card>
</div>
</div>
<div className="row row-content">
<div className="col-12">
<h2>Corporate Leadership</h2>
</div>
<div className="col-12">
<Media list>
<Stagger in>
{leaders}
</Stagger>
</Media>
</div>
</div>
</div>
);

export default About;


CommentForm.js

import React, { Component } from 'react';


import {Modal, ModalHeader, ModalBody, Button, Row, Label} from 'reactstrap';
import { Control, LocalForm, Errors } from 'react-redux-form';

const required = (val) => val && val.length;


const maxLength = (len) => (val) => !(val) || (val.length <= len);
const minLength = (len) => (val) => val && (val.length > len);

class CommentForm extends Component {

constructor(props) {
super(props);
this.state = {
isModalOpen: false
};

this.handleSubmit = this.handleSubmit.bind(this);
this.toggleModal = this.toggleModal.bind(this);
}

handleSubmit(values) {
this.toggleModal();
this.props.postComment(this.props.dishId, values.rating, values.yourna
me, values.comment)
}

toggleModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
}

render() {
return(
<>
<Button type="button" className="fa fa-
pencil" outline color="secondary" size="lg"
onClick={this.toggleModal}>
<span className="ml-1">Submit Comment</span>
</Button>
<Modal isOpen={this.state.isModalOpen} toggle={this.toggleModa
l}>
<ModalHeader toggle={this.toggleModal}>Submit Comment</ModalHe
ader>
<ModalBody>
<LocalForm className="container" onSubmit={(values) => this.ha
ndleSubmit(values)}>
<Row className="form-group">
<Label htmlFor="rating">Rating</Label>
<Control.select model=".rating" id="rating" name="rati
ng"
className="form-control" defaultValue="1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="3">4</option>
<option value="3">5</option>
</Control.select>
</Row>
<Row className="form-group">
<Label htmlFor="yourname">Your Name</Label>
<Control.text type="text" model=".yourname" id="yourna
me" name="yourname"
className="form-control"
validators={{
required, minLength: minLength(2), maxLength: maxL
ength(15)
}} />
<Errors
className="text-danger"
model=".yourname"
show="touched"
messages={{
required: 'Required',
minLength: 'Must be greater than 2 characters'
,
maxLength: 'Must be 15 characters or less'
}} />
</Row>
<Row className="form-group">
<Label htmlFor="comment">Comment</Label>
<Control.textarea model=".comment" type="text" id="com
ment" name="comment"
rows="6" className="form-control"/>
</Row>
<Button type="submit" value="submit" color="primary">Submi
t</Button>
</LocalForm>
</ModalBody>
</Modal>
</>
);
}
}

export default CommentForm;

ContactComponent.js
import React, { Component } from 'react';
import { Breadcrumb, BreadcrumbItem,
Button, Row, Label, Col } from 'reactstrap';
import { Link } from 'react-router-dom';
import { Control, Form, Errors } from 'react-redux-form';

const required = (val) => val && val.length;


const maxLength = (len) => (val) => !(val) || (val.length <= len);
const minLength = (len) => (val) => val && (val.length >= len);
const isNumber = (val) => !isNaN(Number(val));
const validEmail = (val) => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-
Z]{2,4}$/i.test(val);

class Contact extends Component {

constructor(props) {
super(props);

this.handleSubmit = this.handleSubmit.bind(this);
}

async handleSubmit(values) {
const feedback = await this.props.postFeedback(values);
console.log('Current State is: ' + JSON.stringify(feedback));
alert('Current State is: ' + JSON.stringify(feedback));
this.props.resetFeedbackForm();
}

render() {

return(
<div className="container">
<div className="row">
<Breadcrumb>
<BreadcrumbItem><Link to="/home">Home</Link></Breadcru
mbItem>
<BreadcrumbItem active>Contact Us</BreadcrumbItem>
</Breadcrumb>
<div className="col-12">
<h3>Contact Us</h3>
<hr />
</div>
</div>
<div className="row row-content">
<div className="col-12">
<h3>Location Information</h3>
</div>
<div className="col-12 col-sm-4 offset-sm-1">
<h5>Our Address</h5>
<address>
121, Clear Water Bay Road<br />
Clear Water Bay, Kowloon<br />
HONG KONG<br />
<i className="fa fa-
phone"></i>: +852 1234 5678<br />
<i className="fa fa-
fax"></i>: +852 8765 4321<br />
<i className="fa fa-
envelope"></i>: <a href="mailto:confusion@food.net">confusion@food.net</a>
</address>
</div>
<div className="col-12 col-sm-6 offset-sm-1">
<h5>Map of our Location</h5>
</div>
<div className="col-12 col-sm-11 offset-sm-1">
<div className="btn-group" role="group">
<a role="button" className="btn btn-
primary" href="tel:+85212345678"><i className="fa fa-phone"></i> Call</a>
<a role="button" className="btn btn-
info"><i className="fa fa-skype"></i> Skype</a>
<a role="button" className="btn btn-
success" href="mailto:confusion@food.net"><i className="fa fa-envelope-
o"></i> Email</a>
</div>
</div>
</div>
<div className="row row-content">
<div className="col-12">
<h3>Send us your Feedback</h3>
</div>
<div className="col-12 col-md-9">
<Form model="feedback" onSubmit={(values) => this.hand
leSubmit(values)}>
<Row className="form-group">
<Label htmlFor="firstname" md={2}>First Name</
Label>
<Col md={10}>
<Control.text model=".firstname" id="firstname" name="firstname"
placeholder="First Name"
className="form-control"
validators={{
required, minLength: minLength(3), maxLength: maxLength(15)
}} />
<Errors
className="text-danger"
model=".firstname"
show="touched"
messages={{
required: 'Required',
minLength: 'Must be greater than 2 characters',
maxLength: 'Must be 15 characters or less'
}}
/>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="lastname" md={2}>Last Name</Label>
<Col md={10}>
<Control.text model=".lastname" type="text" id="lastname" name="lastname"
placeholder="Last Name"
className="form-control"
validators={{
required, minLength: minLength(3), maxLength: maxLength(15)
}}/>
<Errors
className="text-danger"
model=".lastname"
show="touched"
messages={{
required: 'Required',
minLength: 'Must be greater than 2 characters',
maxLength: 'Must be 15 characters or less'
}}
/>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="telnum" md={2}>Contact Tel.</Label>
<Col md={10}>
<Control.text model=".telnum" type="tel" id="telnum" name="telnum"
placeholder="Tel. number"
className="form-control"
validators={{
required, minLength: minLength(3), maxLength: maxLength(15), isNumber
}}/>
<Errors
className="text-danger"
model=".telnum"
show="touched"
messages={{
required: 'Required',
minLength: 'Must be greater than 2 numbers',
maxLength: 'Must be 15 numbers or less',
isNumber: 'Must be a number'
}}
/>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="email" md={2}>Email</Label>
<Col md={10}>
<Control.text model=".email" type="email" id="email" name="email"
placeholder="Email"
className="form-control"
validators={{
required, validEmail
}}
/>
<Errors
className="text-danger"
model=".email"
show="touched"
messages={{
required: 'Required',
validEmail: 'Invalid Email Address'
}}
/>
</Col>
</Row>
<Row className="form-group">
<Col md={{size: 6, offset: 2}}>
<div className="form-check">
<Label check>
<Control.checkbox model=".agree" type="checkbox"
name="agree"
className="form-check-input" /> {' '}
<strong>May we contact you?</strong>
</Label>
</div>
</Col>
<Col md={{size: 3, offset: 1}}>
<Control.select model=".contactType" type="select" name="contactType"
className="form-control">
<option>Tel.</option>
<option>Email</option>
</Control.select>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="message" md={2}>Your Feedback</Label>
<Col md={10}>
<Control.textarea model=".message" type="textarea" id="message" name="message"
rows="12"
className="form-control" />
</Col>
</Row>
<Row className="form-group">
<Col md={{size: 10, offset: 2}}>
<Button type="submit" color="primary">
Send Feedback
</Button>
</Col>
</Row>
</Form>
</div>
</div>
</div>
);
}
}

export default Contact;

DishDetail.js

import React from 'react';


import { Card, CardImg, CardText, CardBody,
CardTitle, Breadcrumb, BreadcrumbItem } from 'reactstrap';
import { FadeTransform, Fade, Stagger } from 'react-animation-components';
import { Link } from 'react-router-dom';
import CommentForm from './CommentForm'
import { Loading } from './LoadingComponent';
import { baseUrl } from '../shared/baseUrl';

const DishDetail = (props) => {

if (props.isLoading) {
return(
<div className="container">
<div className="row">
<Loading />
</div>
</div>
);
}
else if (props.errMess) {
return(
<div className="container">
<div className="row">
<h4>{props.errMess}</h4>
</div>
</div>
);
}
else if(props.dish != null)
return(
<div className="container">
<div className="row">
<Breadcrumb>

<BreadcrumbItem><Link to="/menu">Menu</Link></BreadcrumbItem>
<BreadcrumbItem active>{props.dish.name}</BreadcrumbItem>
</Breadcrumb>
<div className="col-12">
<h3>{props.dish.name}</h3>
<hr />
</div>
</div>
<div className="row">
<div className="col-12 col-md-5 m-1">
<RenderDish dish={props.dish}/>
</div>
<div className="col-12 col-md-5 m-1">
<h4>Comments</h4>
<RenderComments comments={props.comments}
postComment={props.postComment}
dishId={props.dish.id}/>
</div>
</div>
</div>
);
else
return(
<div></div>
);
}

function RenderDish({dish}) {
return (
<FadeTransform
in
transformProps={{
exitTransform: 'scale(0.5) translateY(-50%)'
}}>
<Card>
<CardImg top src={baseUrl + dish.image} alt={dish.name} />
<CardBody>
<CardTitle>{dish.name}</CardTitle>
<CardText>{dish.description}</CardText>
</CardBody>
</Card>
</FadeTransform>)
}

function RenderComments({comments, postComment, dishId}) {


if(comments && comments.length > 0) {

return (
<ul className="list-unstyled mb-4">
<Stagger in>
{ comments.map( comment => {
const date = new Date(comment.date);
return (
<Fade in key={comment.id}>
<li key={comment.id}>
<p className="mb-3">{comment.comment}</p>
<p className="mb-3">-- {comment.author}, {date.toLocaleDateString('en-US', {
day: 'numeric', month: 'short', year: 'numeric'
})}
</p>
</li>
</Fade>
)
})
}
</Stagger>
<li><CommentForm dishId={dishId} postComment={postComment}/></li>
</ul>
)
}
else {
return (<div></div>)
}
}

export default DishDetail;

FooterComponent.js

import React from 'react';


import { Link } from 'react-router-dom';

function Footer(props) {
return(
<div className="footer">
<div className="container">
<div className="row justify-content-center">
<div className="col-4 offset-1 col-sm-2">
<h5>Links</h5>
<ul className="list-unstyled">
<li><Link to='/home'>Home</Link></li>
<li><Link to='/aboutus'>About Us</Link></li>
<li><Link to='/menu'>Menu</Link></li>
<li><Link to='/contactus'>Contact Us</Link></li>
</ul>
</div>
<div className="col-7 col-sm-5">
<h5>Our Address</h5>
<address>
121, Clear Water Bay Road<br />
Clear Water Bay, Kowloon<br />
HONG KONG<br />
<i className="fa fa-phone fa-lg"></i>: +852 1234 5678<br />
<i className="fa fa-fax fa-lg"></i>: +852 8765 4321<br />
<i className="fa fa-envelope fa-lg"></i>: <a href="mailto:confusion@food.net">
confusion@food.net</a>
</address>
</div>
<div className="col-12 col-sm-4 align-self-center">
<div className="text-center">
<a className="btn btn-social-icon btn-
google" href="http://google.com/+"><i className="fa fa-google-plus"></i></a>
<a className="btn btn-social-icon btn-
facebook" href="http://www.facebook.com/profile.php?id="><i className="fa fa-
facebook"></i></a>
<a className="btn btn-social-icon btn-
linkedin" href="http://www.linkedin.com/in/"><i className="fa fa-
linkedin"></i></a>
<a className="btn btn-social-icon btn-
twitter" href="http://twitter.com/"><i className="fa fa-twitter"></i></a>
<a className="btn btn-social-icon btn-
google" href="http://youtube.com/"><i className="fa fa-youtube"></i></a>
<a className="btn btn-social-icon" href="mailto:"><i className="fa fa-
envelope-o"></i></a>
</div>
</div>
</div>
<div className="row justify-content-center">
<div className="col-auto">
<p>© Copyright 2018 Ristorante Con Fusion</p>
</div>
</div>
</div>
</div>
)
}

export default Footer;

HeaderComponent.js

import React, { Component } from 'react';


import { Nav, Navbar, NavbarBrand, NavbarToggler, Collapse, NavItem, Jumbotron
,
Button, Modal, ModalHeader, ModalBody,
Form, FormGroup, Input, Label } from 'reactstrap';
import { NavLink } from 'react-router-dom';

class Header extends Component {

constructor(props) {
super(props);

this.toggleNav = this.toggleNav.bind(this);
this.state = {
isNavOpen: false,
isModalOpen: false
};
this.toggleModal = this.toggleModal.bind(this);
this.handleLogin = this.handleLogin.bind(this);
}

toggleNav() {
this.setState({
isNavOpen: !this.state.isNavOpen
});
}

toggleModal() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
}

handleLogin(event) {
this.toggleModal();
alert("Username: " + this.username.value + " Password: " + this.password.value
+ " Remember: " + this.remember.checked);
event.preventDefault();

render() {
return(
<div>
<Navbar dark expand="md">
<div className="container">
<NavbarToggler onClick={this.toggleNav} />
<NavbarBrand className="mr-
auto" href="/"><img src='assets/images/logo.png' height="30" width="41" alt='R
istorante Con Fusion' /></NavbarBrand>
<Collapse isOpen={this.state.isNavOpen} navbar>
<Nav navbar>
<NavItem>
<NavLink className="nav-link" to='/home'><span className="fa fa-home fa-
lg"></span> Home</NavLink>
</NavItem>
<NavItem>
<NavLink className="nav-link" to='/aboutus'><span className="fa fa-info fa-
lg"></span> About Us</NavLink>
</NavItem>
<NavItem>
<NavLink className="nav-link" to='/menu'><span className="fa fa-list fa-
lg"></span> Menu</NavLink>
</NavItem>
<NavItem>
<NavLink className="nav-link" to='/contactus'><span className="fa fa-address-
card fa-lg"></span> Contact Us</NavLink>
</NavItem>
</Nav>
<Nav className="ml-auto" navbar>
<NavItem>
<Button outline onClick={this.toggleModal}><span className="fa fa-sign-in fa-
lg"></span> Login</Button>
</NavItem>
</Nav>
</Collapse>
</div>
</Navbar>
<Jumbotron>
<div className="container">
<div className="row row-header">
<div className="col-12 col-sm-6">
<h1>Ristorante con Fusion</h1>
<p>We take inspiration from the World's best cuisines, and create a unique fus
ion experience. Our lipsmacking creations will tickle your culinary senses!</p
>
</div>
</div>
</div>
</Jumbotron>
<Modal isOpen={this.state.isModalOpen} toggle={this.toggleModal}>
<ModalHeader toggle={this.toggleModal}>Login</ModalHeader>
<ModalBody>
<Form onSubmit={this.handleLogin}>
<FormGroup>
<Label htmlFor="username">Username</Label>
<Input type="text" id="username" name="username"
innerRef={(input) => this.username = input} />
</FormGroup>
<FormGroup>
<Label htmlFor="password">Password</Label>
<Input type="password" id="password" name="password"
innerRef={(input) => this.password = input} />
</FormGroup>
<FormGroup check>
<Label check>
<Input type="checkbox" name="remember"
innerRef={(input) => this.remember = input} />
Remember me
</Label>
</FormGroup>
<Button type="submit" value="submit" color="primary">Login</Button>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}

export default Header;

HomeComponent.js

import React from 'react';


import { Card, CardImg, CardText, CardBody,
CardTitle, CardSubtitle} from 'reactstrap';
import { FadeTransform } from 'react-animation-components';
import { Loading } from './LoadingComponent';
import { baseUrl } from '../shared/baseUrl';

function RenderCard({item, isLoading, errMess}) {

if (isLoading) {
return(
<Loading />
);
}
else if (errMess) {
return(
<h4>{errMess}</h4>
);
}
else
return(
<FadeTransform
in
transformProps={{
exitTransform: 'scale(0.5) translateY(-50%)'
}}>
<Card>
<CardImg src={baseUrl + item.image} alt={item.name} />
<CardBody>
<CardTitle>{item.name}</CardTitle>
{item.designation ? <CardSubtitle>{item.designation}</
CardSubtitle> : null }
<CardText>{item.description}</CardText>
</CardBody>
</Card>
</FadeTransform>
);

function Home(props) {
return(
<div className="container">
<div className="row align-items-start">
<div className="col-12 col-md m-1">
<RenderCard item={props.dish} isLoading={props.dishesLoading}
errMess={props.dishesErrMess} />
</div>
<div className="col-12 col-md m-1">
<RenderCard item={props.promotion} isLoading={props.promoLoadi
ng} errMess={props.promoErrMess} />
</div>
<div className="col-12 col-md m-1">
<RenderCard item={props.leader} isLoading={props.leadersLoadin
g} errMess={props.leadersErrMess} />
</div>
</div>
</div>
);
}

export default Home;

LoadingComponent.js
import React from 'react';

export const Loading = () => {


return(
<div className="col-12">
<span className="fa fa-spinner fa-pulse fa-3x fa-fw text-
primary"></span>
<p>Loading . . .</p>
</div>
);
};

MainComponent.js
import React, { Component } from 'react';
import { Switch, Route, Redirect, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { actions } from 'react-redux-form';
import Home from './HomeComponent';
import Menu from './MenuComponent';
import About from './AboutComponent';
import Header from './HeaderComponent';
import Footer from './FooterComponent';
import Contact from './ContactComponent';
import DishDetail from './DishdetailComponent';
import { postComment, postFeedback, fetchDishes, fetchComments, fetchPromos, f
etchLeaders } from '../redux/ActionCreators';
import { TransitionGroup, CSSTransition } from 'react-transition-group';

const mapStateToProps = state => {


return {
dishes: state.dishes,
comments: state.comments,
promotions: state.promotions,
leaders: state.leaders
}
}

const mapDispatchToProps = dispatch => ({


postComment: (dishId, rating, author, comment) => dispatch(postComment(dishI
d, rating, author, comment)),
postFeedback: (values) => dispatch(postFeedback(values) ),
fetchDishes: () => { dispatch(fetchDishes())},
resetFeedbackForm: () => { dispatch(actions.reset('feedback'))},
fetchComments: () => dispatch(fetchComments()),
fetchPromos: () => dispatch(fetchPromos()),
fetchLeaders: () => dispatch(fetchLeaders())
});

class Main extends Component {

constructor(props) {
super(props);
}

componentDidMount() {
this.props.fetchDishes();
this.props.fetchComments();
this.props.fetchPromos();
this.props.fetchLeaders();
}

onDishSelect(dishId) {
this.setState({ selectedDish: dishId});
}

render() {
const HomePage = () => {
return(
<Home
dish={this.props.dishes.dishes.filter((dish) => dish.featured)[0]}
dishesLoading={this.props.dishes.isLoading}
dishesErrMess={this.props.dishes.errMess}
promotion={this.props.promotions.promotions.filter((promo) => promo.
featured)[0]}
promoLoading={this.props.promotions.isLoading}
promoErrMess={this.props.promotions.errMess}
leader={this.props.leaders.leaders.filter((leader) => leader.feature
d)[0]}
leadersLoading={this.props.leaders.isLoading}
leadersErrMess={this.props.leaders.errMess}
/>
);
}

const DishWithId = ({match}) => {


return (
<DishDetail
dish={this.props.dishes.dishes.filter((dish) => +dish.id === parseIn
t(match.params.dishId,10))[0]}
isLoading={this.props.dishes.isLoading}
errMess={this.props.dishes.errMess}
comments={this.props.comments.comments.filter((comment) => +comment.
dishId === parseInt(match.params.dishId,10))}
commentsErrMess={this.props.comments.errMess}
postComment={this.props.postComment}
/>
);
};

return (
<div>
<Header />
<TransitionGroup>
<CSSTransition key={this.props.location.key} classNames="page" tim
eout={300}>
<Switch>
<Route path='/home' component={HomePage} />
<Route exact path='/menu' component={() => <Menu dishes={thi
s.props.dishes} />} />
<Route path='/aboutus' component={() => <About leaders={this
.props.leaders} />} />
<Route exact path='/contactus' component={() => <Contact pos
tFeedback={this.props.postFeedback} resetFeedbackForm={this.props.resetFeedbac
kForm} />} />
<Route path='/menu/:dishId' component={DishWithId} />
<Redirect to="/home" />
</Switch>
</CSSTransition>
</TransitionGroup>
<Footer />
</div>
);
}
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Main)


);

MenuComponent.js
import React from 'react';
import { Card, CardImg, CardImgOverlay,
CardTitle, Breadcrumb, BreadcrumbItem } from 'reactstrap';
import { Link } from 'react-router-dom';
import { Loading } from './LoadingComponent';
import { baseUrl } from '../shared/baseUrl';

function RenderMenuItem ({dish, onClick}) {


return (
<Card>
<Link to={`/menu/${dish.id}`} >
<CardImg width="100%" src={baseUrl + dish.image} alt={dish
.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Link>
</Card>
);
}
const Menu = (props) => {

const menu = props.dishes.dishes.map((dish) => {


return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<RenderMenuItem dish={dish} />
</div>
);
});

if (props.dishes.isLoading) {
return(
<div className="container">
<div className="row">
<Loading />
</div>
</div>
);
}
else if (props.dishes.errMess) {
return(
<div className="container">
<div className="row">
<div className="col-12">
<h4>{props.dishes.errMess}</h4>
</div>
</div>
</div>
);
}
else
return (
<div className="container">
<div className="row">
<Breadcrumb>
<BreadcrumbItem><Link to="/home">Home</Link></Brea
dcrumbItem>
<BreadcrumbItem active>Menu</BreadcrumbItem>
</Breadcrumb>
<div className="col-12">
<h3>Menu</h3>
<hr />
</div>
</div>
<div className="row">
{menu}
</div>
</div>
);
}

export default Menu;


Conclusions
• This Restaurant App really helpful for the
users to access the dishes menu in the
restaurant and to access the details of the
dishes.
• In the future we will be adding a cart page and
a payment process flows so that all the users
can easily buy the items online.
• This app will support in all the devices and
doesn’t matter the size and with the good
animations.
References
• React Router and the DOM
• Create React App
• React Official documentation.
• React-strap documentation
• Cross-fetch
• React-transition-group
• React-animation-components

Anda mungkin juga menyukai