Last active
July 13, 2022 17:30
-
-
Save laughingclouds/ce24b4a775b36b646b9c758e88d60183 to your computer and use it in GitHub Desktop.
Coursera React Course | Assignment 2-3 | Solution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Breadcrumb, BreadcrumbItem, Card, CardBody, CardHeader, Media } from 'reactstrap'; | |
import { Link } from 'react-router-dom'; | |
import RenderLeaders from './RenderLeaders'; | |
export default function About(props) { | |
return ( | |
<div className="container"> | |
<div className="row"> | |
<Breadcrumb> | |
<BreadcrumbItem><Link to="/home">Home</Link></BreadcrumbItem> | |
<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 established itself as a culinary icon par excellence in Hong Kong. With its unique brand 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 plate 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 featured 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 className='text-dark'> | |
<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"> | |
<RenderLeaders leaders={props.leaders} /> | |
</div> | |
</div> | |
</div> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-unused-vars */ | |
import { Route, Routes, useLocation } from 'react-router-dom'; | |
import { useState } from 'react'; | |
import { DISHES } from './shared/dishes'; | |
import { PROMOTIONS } from './shared/promotions'; | |
import { LEADERS } from './shared/leaders'; | |
import { COMMENTS } from './shared/comments'; | |
import Main from './components/MainComponent'; | |
import HomePage from './components/HomeComponent'; | |
import Header from './components/HeaderComponent'; | |
import Footer from './components/FooterComponent'; | |
import Contact from './components/ContactComponent'; | |
import DishWithId from './components/DishdetailComponent'; | |
import About from './routes/aboutus/AboutComponent'; | |
export default function App() { | |
let location = useLocation(); | |
const [dishes, setDishes] = useState(DISHES); | |
const [comments, setComments] = useState(COMMENTS); | |
const [promotions, setPromotions] = useState(PROMOTIONS); | |
const [leaders, setLeaders] = useState(LEADERS); | |
const [selectedDish, setSelectedDish] = useState(null); | |
return ( | |
<> | |
<Header /> | |
<Routes> | |
<Route path='/' element={<HomePage dishes={dishes} promotions={promotions} leaders={leaders} />} /> | |
<Route path='/aboutus' element={<About leaders={leaders} />}/> | |
<Route path='/menu' element={<Main dishes={dishes} selectedDish={selectedDish} setSelectedDish={setSelectedDish} />}> | |
<Route path=':dishId' element={<DishWithId dishes={dishes} comments={comments}/>} /> | |
</Route> | |
<Route path='/contactus' element={<Contact />} /> | |
</Routes> | |
{location.pathname !== '/contactus' && <Footer />} | |
</> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
import { Card, CardImg, CardImgOverlay, CardTitle, Breadcrumb, BreadcrumbItem, CardBody, CardText } from "reactstrap"; | |
import { Link } from 'react-router-dom'; | |
import { | |
Button, Modal, ModalBody, ModalHeader, Label, Row, Col | |
} from "reactstrap"; | |
import { Control, LocalForm, Errors } from 'react-redux-form'; | |
/**........................ comment component ends ................................................. */ | |
//// validators | |
const required = (val) => val && val.length; //value > 0 | |
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 = { | |
isCommentFormModalOpen: false | |
}; | |
this.toggleCommentFormModal = this.toggleCommentFormModal.bind(this); | |
this.handleCommentFormSubmit = this.handleCommentFormSubmit.bind(this); | |
} | |
handleCommentFormSubmit(values) { | |
console.log("Current State is: " + JSON.stringify(values)); | |
alert("Current State is: " + JSON.stringify(values)); | |
} | |
toggleCommentFormModal() { | |
this.setState({ | |
isCommentFormModalOpen: !this.state.isCommentFormModalOpen | |
}); | |
} | |
render() { | |
return ( | |
<React.Fragment> | |
<Button outline onClick={this.toggleCommentFormModal}> | |
<span className="fa fa-comments fa-lg"></span> Submit Comment | |
</Button> | |
{/* commentform Modal */} | |
<Modal isOpen={this.state.isCommentFormModalOpen} toggle={this.toggleCommentFormModal} > | |
<ModalHeader toggle={this.toggleCommentFormModal}> Submit Comment </ModalHeader> | |
<ModalBody> | |
<LocalForm onSubmit={(values) => this.handleCommentFormSubmit(values)}> | |
{/* rating */} | |
<Row className="form-group"> | |
<Label htmlFor="rating" md={12} >Rating</Label> | |
<Col md={12}> | |
<Control.select model=".rating" | |
className="form-control" | |
name="rating" | |
id="rating" | |
validators={{ | |
required | |
}} | |
> | |
<option>Please Select</option> | |
<option>1</option> | |
<option>2</option> | |
<option>3</option> | |
<option>4</option> | |
<option>5</option> | |
</Control.select> | |
<Errors | |
className="text-danger" | |
model=".author" | |
show="touched" | |
messages={{ | |
required: 'Required', | |
}} | |
/> | |
</Col> | |
</Row> | |
{/* author */} | |
<Row className="form-group"> | |
<Label htmlFor="author" md={12}> Your Name </Label> | |
<Col md={12}> | |
<Control.text model=".author" id="author" name="author" | |
placeholder="First Name" | |
className="form-control" | |
validators={{ | |
required, minLength: minLength(3), maxLength: maxLength(15) | |
}} | |
/> | |
<Errors | |
className="text-danger" | |
model=".author" | |
show="touched" | |
messages={{ | |
required: 'Required', | |
minLength: 'Must be greater than 2 characters', | |
maxLength: 'Must be 15 characters or less' | |
}} | |
/> | |
</Col> | |
</Row> | |
{/* comment */} | |
<Row className="form-group"> | |
<Label htmlFor="comment" md={12}>Comment</Label> | |
<Col md={12}> | |
<Control.textarea model=".comment" id="comment" name="comment" | |
rows="6" | |
className="form-control" | |
validators={{ | |
required | |
}} | |
/> | |
<Errors | |
className="text-danger" | |
model=".author" | |
show="touched" | |
messages={{ | |
required: 'Required', | |
}} | |
/> | |
</Col> | |
</Row> | |
{/* submit button */} | |
<Row className="form-group"> | |
<Col> | |
<Button type="submit" color="primary"> | |
Submit | |
</Button> | |
</Col> | |
</Row> | |
</LocalForm> | |
</ModalBody> | |
</Modal> | |
</React.Fragment> | |
); | |
} | |
} | |
/**........................ comment component ends ................................................. */ | |
function RenderDish({dish}) { | |
if (dish != null) { | |
return ( | |
<div className='col-12 col-md-5 m-1'> | |
<Card> | |
<CardImg width="100%" src={dish.image} alt={dish.name} /> | |
<CardBody> | |
<CardTitle> {dish.name}</CardTitle> | |
<CardText> {dish.description} </CardText> | |
</CardBody> | |
</Card> | |
</div> | |
); | |
} | |
else { | |
return ( | |
<div></div> | |
); | |
} | |
} | |
function RenderComments({dish,comments}){ | |
if (comments == null) { | |
return (<div></div>) | |
} | |
const cmnts = comments.map(comment => { | |
return ( | |
<li key={comment.id}> | |
<p>{comment.comment}</p> | |
<p>-- {comment.author}, | |
| |
{new Intl.DateTimeFormat('en-US', { | |
year: 'numeric', | |
month: 'long', | |
day: '2-digit' | |
}).format(new Date(comment.date))} | |
</p> | |
</li> | |
) | |
}) | |
return ( | |
<div className='col-12 col-md-5 m-1'> | |
<h4> Comments </h4> | |
<ul className='list-unstyled'> | |
{cmnts} | |
</ul> | |
<CommentForm dish={dish} comments={comments} /> | |
</div> | |
) | |
} | |
const DishDetail = (props) => { | |
const dish = props.dish | |
if (dish == null) { | |
return (<div></div>); | |
} | |
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.menu}</h3> | |
<hr /> | |
</div> | |
</div> | |
<div className='row'> | |
<RenderDish dish={ props.dish } /> | |
<RenderComments dish={props.dish} comments={ props.comments } /> | |
</div> | |
</div> | |
) | |
} | |
export default DishDetail; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Media } from "reactstrap"; | |
export default function RenderLeaders(props) { | |
let leaders = props.leaders.map((leader) => { | |
return ( | |
<div key={leader.id} className="d-flex p-3"> | |
<div className="flex-shrink-0"> | |
<img src={leader.image} alt={leader.name} /> | |
</div> | |
<div className="flex-grow-1 ms-3"> | |
<h5>{leader.name}</h5> | |
<h6>{leader.designation}</h6> | |
<p>{leader.description}</p> | |
</div> | |
</div> | |
); | |
}); | |
console.log(props.leaders); | |
return ( | |
<> | |
<Media list> | |
{leaders} | |
</Media> | |
</> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment