Skip to content

Instantly share code, notes, and snippets.

@VasVV
Last active July 21, 2020 14:41
Show Gist options
  • Save VasVV/58a9671b67da3240edbb20962193a926 to your computer and use it in GitHub Desktop.
Save VasVV/58a9671b67da3240edbb20962193a926 to your computer and use it in GitHub Desktop.
Menu - React
<div id='root'>
</div>
const sampleBurger = {name: 'Cheeseburger', price: 1488, description: 'Burger with meat and cheese', image: 'https://www.mcdonalds.com/is/image/content/dam/usa/nfl/nutrition/items/hero/desktop/t-mcdonalds-Cheeseburger.jpg', status: true};
const formatPrice = (cents) => {
return (cents / 100).toLocaleString("en-US", {
style: "currency",
currency: "EUR"
});
}
const removeDuplicates = (arr) => {
let p = {};
arr.forEach( (x) => { p[x] = (p[x] || 0) + 1; });
return Object.keys(p).map( (x) => { return { id: x, count: p[x] }; });
}
class App extends React.Component {
constructor() {
super();
this.state = {
burgers: [],
order: []
}
this.addBurger = this.addBurger.bind(this);
}
addBurger = (e) => {
this.setState({ burgers: [...this.state.burgers, e] });
};
loadSample = () => {
this.setState({ burgers: [...this.state.burgers, sampleBurger] })
};
addToOrder = (e) => {
console.log(this.state.order);
this.setState({ order: [...this.state.order, e.name] });
}
updateBurger = (e, u) => {
const burger = this.state.burgers;
burger[e] = u;
this.setState({ burgers: [...this.state.burgers, burger] });
this.setState({ burgers: [...this.state.burgers.filter(e => {return !Array.isArray(e)})] });
}
deleteBurger = e => {
const burger = this.state.burgers;
burger.splice(e,1);
this.setState({ burgers: [...this.state.burgers, burger] });
this.setState({ burgers: [...this.state.burgers.filter(e => {return !Array.isArray(e)})] });
}
render() {
const burgerlist = this.state.burgers.map((e,i) => {
return <Burger key={e} index={e} details={this.state.burgers[i]} addToOrder = {this.addToOrder}/>})
return (
<div className='catch-of-the-day'>
<div className='menu'>
<Header />
<ul>
{burgerlist}
</ul>
</div>
<Order {...this.state}/>
<Inventory addBurger={this.addBurger} loadSample={this.loadSample} burgers = {this.state.burgers} updateBurger={this.updateBurger} deleteBurger={this.deleteBurger}/>
</div>
)
}
};
const Header = () => (
<header className='top'>
<h1>Menu</h1>
</header>
)
class AddBurger extends React.Component {
constructor(props) {
super(props);
this.nameRef = React.createRef();
this.priceRef = React.createRef();
this.descriptionRef = React.createRef();
this.imageRef = React.createRef();
this.statusRef = React.createRef();
}
addBurger = (e) => {
e.preventDefault();
const burger = {
name: this.nameRef.current.value,
price: Number(this.priceRef.current.value),
description: this.descriptionRef.current.value,
image: this.imageRef.current.value,
status: this.statusRef.current.value === 'yes' ? true : false
};
this.props.addBurger(burger);
e.currentTarget.reset();
}
render() {
return (
<form className='burger-edit' onSubmit={this.addBurger}>
<input name='name' type='text' ref={this.nameRef} placeholder='Name' />
<input name='price' type='text' ref={this.priceRef} placeholder='Price' />
<input name='description' type='text' ref={this.descriptionRef} placeholder='Description' />
<input name='image' type='text' ref={this.imageRef} placeholder='Image' />
<select name='status' ref={this.statusRef}>
<option value='yes'>Available</option>
<option value='no'>Unavailable</option>
</select>
<button type='submit'>Add Burger </button>
</form>
)
}
}
class EditBurger extends React.Component {
constructor(props) {
super(props);
}
handleChange=(e)=>{
const editedBurger = {...this.props.burgers,
[e.currentTarget.name]: e.currentTarget.value}
this.props.updateBurger(this.props.index, editedBurger)
}
render() {
return (<div className='burger-edit'>
<input name='name' type='text' onChange={this.handleChange} value ={this.props.burgers.name} readonly="readonly"/>
<input name='price' type='text' value ={this.props.burgers.price} onChange={this.handleChange} />
<input name='description' type='text' value ={this.props.burgers.description} onChange={this.handleChange} />
<input name='image' type='text' value ={this.props.burgers.image} onChange={this.handleChange}/>
<select name='status' value ={this.props.burgers.status ? 'yes' : 'no'} onChange={this.handleChange}>
<option value='yes'>Available</option>
<option value='no'>Unavailable</option>
</select>
<button onClick={() => this.props.deleteBurger(this.props.index)}>DELETE BURGER</button>
</div>)
}
}
class Inventory extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div> <h2>Stock</h2>
{this.props.burgers.map((e,i) => {
return <EditBurger burgers={Object.values(this.props.burgers)[i]} updateBurger ={this.props.updateBurger} key={i} index={i} deleteBurger={this.props.deleteBurger}/>
})}
<AddBurger addBurger={this.props.addBurger} />
<button onClick={this.props.loadSample} >LOAD SAMPLE BURGER</button>
</div>
)
}
}
class Order extends React.Component {
render() {
const orderIds = Object.values(this.props.order);
const burgerprice = Object.values(this.props.burgers);
let pricer = {};
for (let a = 0; a<burgerprice.length; a++) {
let b = burgerprice[a].name;
for (let c = 0; c< orderIds.length; c++) {
if (orderIds[c] === b) {
pricer[b] = burgerprice[a].price;
break;
}
}
}
let temp = 0;
let total = removeDuplicates(orderIds).forEach(e => {temp+=pricer[e.id]*e.count});
let x = removeDuplicates(orderIds).map(e => {return <ul><li class='prices'>{e.count} {e.id}{e.count>1 ? 's' : ''} { formatPrice(pricer[e.id]*e.count)} </li></ul>});
return (
<div className='order-wrap' id='orders'>
<h2>Your order</h2>
{x}
<div className={temp === 0 ? 'hidden' : ''} ><b>Total: </b>{formatPrice(temp)}</div>
</div>
)
}
}
class Burger extends React.Component {
render() {
const way = this.props.details;
const isAvailiable = way.status ? true : false;
return (
<li className='menu-burger'>
<img src={way.image}/>
<h3 className='burger-name'>{way.name}
<span className='price'>
{formatPrice(way.price)}
</span>
</h3>
<p>{way.description}</p>
<button disabled={!isAvailiable} onClick ={() => {this.props.addToOrder(this.props.index)}}>{isAvailiable ? 'ADD TO CART' : 'SOLD OUT'}</button>
</li>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/5.1.2/react-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/5.1.2/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script>
.order-enter {
-webkit-transform: translateX(-120%);
transform: translateX(-120%);
-webkit-transition: 0.5s;
transition: 0.5s;
max-height: 0;
padding: 0 !important;
}
.order-enter.order-enter-active {
max-height: 60px;
-webkit-transform: translateX(0);
transform: translateX(0);
padding: 2rem 0 !important;
}
.order-exit {
-webkit-transition: 0.5s;
transition: 0.5s;
-webkit-transform: translateX(0);
transform: translateX(0);
}
.order-exit.order-exit-active {
-webkit-transform: translateX(120%);
transform: translateX(120%);
padding: 0;
}
.count-enter {
background: #f00;
-webkit-transition: 0.5s;
transition: 0.5s;
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
.count-enter.count-enter-active {
background: #ff0;
-webkit-transform: translateY(0);
transform: translateY(0);
}
.count-exit {
background: #000;
-webkit-transform: translateY(0);
transform: translateY(0);
-webkit-transition: 0.5s;
transition: 0.5s;
position: absolute;
left: 0;
bottom: 0;
}
.count-exit.count-exit-active {
background: #008000;
-webkit-transform: translateY(-100%) scale(3);
transform: translateY(-100%) scale(3);
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
audio,
canvas,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
[hidden] {
display: none;
}
html {
font-family: sans-serif;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
a:focus {
outline: thin dotted;
}
a:active,
a:hover {
outline: 0;
}
h1 {
font-size: 2em;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: 700;
}
dfn {
font-style: italic;
}
mark {
background: #ff0;
color: #000;
}
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
q {
quotes: 2 1C 2 1D 2 18 2 19;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
img {
border: 0;
}
svg:not(:root) {
overflow: hidden;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
button,
input,
select,
textarea {
font-family: inherit;
font-size: 100%;
margin: 0;
}
button,
input {
line-height: normal;
}
button,
html input[type=button],
input[type=reset],
input[type=submit] {
-webkit-appearance: button;
cursor: pointer;
}
button[disabled],
input[disabled] {
cursor: default;
}
input[type=checkbox],
input[type=radio] {
box-sizing: border-box;
padding: 0;
}
input[type=search] {
-webkit-appearance: textfield;
box-sizing: content-box;
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration {
-webkit-appearance: none;
}
textarea {
overflow: auto;
vertical-align: top;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
body,
figure {
margin: 0;
}
legend,
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
* {
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
background: #d4d4d4;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Open Sans', sans-serif;
font-size: 2rem;
}
h1 {
font-family: 'blanchcaps_inline', sans-serif;
text-align: center;
font-weight: normal;
margin: 0;
}
h2,
h3,
h4,
h5,
h6 {
font-weight: normal;
font-family: 'haymakerregular', sans-serif;
}
h2 {
text-align: center;
margin-top: 0;
margin-bottom: 2rem;
}
h3 {
font-size: 3rem;
}
header.top {
text-align: center;
}
header.top h1 {
font-size: 14.4rem;
line-height: 0.7;
display: -webkit-box;
display: flex;
-webkit-box-pack: center;
justify-content: center;
}
header.top h1 .ofThe {
display: -webkit-box;
display: flex;
font-size: 3rem;
color: #f5a623;
-webkit-box-pack: center;
justify-content: center;
-webkit-box-align: center;
align-items: center;
background: url("images/anchor.svg") center no-repeat;
background-size: cover;
padding: 0 1rem;
}
header.top h1 .ofThe .of {
padding-right: 2rem;
position: relative;
right: -0.5rem;
}
header.top h3 {
margin: 0;
font-size: 2rem;
color: #f5a623;
position: relative;
display: inline-block;
}
header.top h3 span {
background: #fff;
position: relative;
z-index: 2;
padding-left: 1rem;
padding-right: 1rem;
}
header.top h3:before,
header.top h3:after {
display: block;
z-index: 1;
background: #000;
position: absolute;
width: 130%;
height: 1px;
content: '';
top: 5px;
margin-left: -15%;
}
header.top h3:after {
top: auto;
bottom: 7px;
}
.catch-of-the-day {
display: -webkit-box;
display: flex;
height: 90vh;
max-width: 1500px;
margin: 0 auto;
margin-top: 5vh;
-webkit-perspective: 1000px;
perspective: 1000px;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.catch-of-the-day > * {
-webkit-box-flex: 1;
flex: 1 4 auto;
padding: 2rem;
border: 1rem double #1a1a1a;
position: relative;
background: #fff;
-webkit-transition: all 0.3s;
transition: all 0.3s;
box-shadow: 0 5px 5px rgba(0,0,0,0.1);
overflow: scroll;
}
.catch-of-the-day > *:first-child {
flex-shrink: 1;
flex-basis: 50%;
-webkit-transform: translateX(50%) rotateY(6deg) translateX(-50%);
transform: translateX(50%) rotateY(6deg) translateX(-50%);
}
.catch-of-the-day > *:nth-child(2) {
-webkit-transform: translateX(-50%) rotateY(-14deg) translateX(50%);
transform: translateX(-50%) rotateY(-14deg) translateX(50%);
border-left: 0;
border-right: 0;
min-width: 300px;
}
.catch-of-the-day > *:last-child {
flex-shrink: 1;
flex-basis: 50%;
-webkit-transform: translateX(-50%) rotateY(10deg) translateX(50%) scale(1.08) translateX(24px);
transform: translateX(-50%) rotateY(10deg) translateX(50%) scale(1.08) translateX(24px);
}
input#fold:not(:checked) ~ #main .catch-of-the-day > * {
-webkit-transform: none;
transform: none;
}
label[for="fold"] {
position: absolute;
top: 1rem;
left: 1rem;
text-transform: uppercase;
font-size: 1.3rem;
background: #000;
color: #fff;
border: 2px solid #000;
cursor: pointer;
padding: 0.5rem 1rem;
}
input#fold {
display: none;
}
input#fold:checked + label {
background: #fff;
color: #000;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul.order li {
border-bottom: 1px solid #000;
padding: 2rem 0;
display: -webkit-box;
display: flex;
font-size: 1.4rem;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
}
ul.order li:hover button {
display: inline;
}
ul.order li button {
border: 0;
display: none;
line-height: 1;
padding: 0;
}
ul.order li.unavailable {
text-decoration: line-through;
background: #f8d0d2;
}
ul.order li .price {
font-size: 1.2rem;
}
ul.order li span.count {
position: relative;
overflow: hidden;
float: left;
}
ul.order li span.count span {
display: inline-block;
}
.total {
padding: 2rem 0;
font-size: 1.4rem;
border-bottom: 3px solid #000;
border-top: 3px double #000;
}
.total strong {
float: right;
}
.order-title {
text-align: center;
}
.burger-edit {
margin-bottom: 20px;
border: 2px solid #000;
overflow: hidden;
display: -webkit-box;
display: flex;
flex-wrap: wrap;
}
.burger-edit,
.burger-edit textarea,
.burger-edit select {
padding: 10px;
line-height: 1;
font-size: 1.2rem;
border: 0;
border-bottom: 1px solid #000;
border-right: 1px solid #000;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 0;
background: #fff;
}
.burger-edit input:focus,
.burger-edit textarea:focus,
.burger-edit select:focus {
outline: 0;
background: #fef2de;
}
.burger-edit textarea {
width: 100%;
}
.burger-edit input:last-of-type {
width: 100%;
}
.burger-edit button {
width: 100%;
border: 0;
}
.list-of-fish {
border-top: 2px solid #000;
border-bottom: 1px solid #000;
padding-top: 5px;
margin-top: 2rem;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
.menu-burger {
border-bottom: 2px solid #000;
border-top: 1px solid #000;
padding-bottom: 2rem;
padding-top: 2rem;
margin-bottom: 5px;
clear: both;
overflow: hidden;
}
.menu-burger p {
margin: 0;
font-size: 1.8rem;
}
.menu-burger .burger-name {
margin: 0;
display: -webkit-box;
display: flex;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
}
.menu-burger .price {
font-size: 1.4rem;
-webkit-box-pack: end;
justify-content: flex-end;
}
.menu-burger img {
float: left;
width: 150px;
margin-right: 1rem;
}
button,
input[type=submit] {
text-transform: uppercase;
background: none;
border: 1px solid #000;
font-weight: 600;
font-size: 1.5rem;
font-family: 'Open Sans';
-webkit-transition: all 0.2s;
transition: all 0.2s;
position: relative;
z-index: 2;
}
button:disabled,
input[type=submit][disabled] {
color: #d12028;
background: #fff;
border-color: #d12028;
-webkit-transform: rotate(-10deg) scale(2) translateX(50%) translateY(-50%);
transform: rotate(-10deg) scale(2) translateX(50%) translateY(-50%);
}
button[disabled]:hover,
input[type=submit][disabled]:hover {
color: #d12028;
cursor: not-allowed;
}
button[disabled]:after,
input[type=submit][disabled]:after {
display: none;
}
button:after,
input[type=submit]:after {
content: '';
z-index: -1;
display: block;
background: #000;
position: absolute;
width: 100%;
height: 0;
left: 0;
top: 0;
-webkit-transition: all 0.2s;
transition: all 0.2s;
}
button:hover,
input[type=submit]:hover,
button:focus,
input[type=submit]:focus {
color: #fff;
outline: 0;
}
button:hover:after,
input[type=submit]:hover:after,
button:focus:after,
input[type=submit]:focus:after {
height: 100%;
}
button.warning:after,
input[type=submit].warning:after {
background: #d12028;
}
button.success:after,
input[type=submit].success:after {
background: #2dc22d;
}
button.github,
input[type=submit].github,
button.facebook,
input[type=submit].facebook,
button.twitter,
input[type=submit].twitter {
border: 0;
display: block;
margin-bottom: 2rem;
width: 100%;
color: #fff;
padding: 2rem;
}
button.github,
input[type=submit].github {
background: #82d465;
}
button.github:after,
input[type=submit].github:after {
background: #5cc437;
}
button.facebook,
input[type=submit].facebook {
background: #3864a3;
}
button.facebook:after,
input[type=submit].facebook:after {
background: #2d5082;
}
button.twitter,
input[type=submit].twitter {
background: #5ea9dd;
}
button.twitter:after,
input[type=submit].twitter:after {
background: #2c8dd0;
}
.store-selector {
background: #fff;
max-width: 500px;
margin: 50px auto;
padding: 2rem;
border: 2px solid #000;
}
.store-selector input,
.store-selector button {
width: 100%;
}
.store-selector input[type="text"],
.store-selector button[type="text"] {
text-align: center;
font-size: 3rem;
}
.hidden { display:none; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment