Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"test": "jest",
"dev": "webpack --mode development",
"build": "webpack --mode production"
"build": "webpack --mode production",
"start": "nodemon server.js"
},
"author": "",
"license": "ISC",
Expand All @@ -18,6 +19,7 @@
},
"dependencies": {
"body-parser": "^1.18.3",
"classnames": "^2.2.6",
"express": "^4.16.3",
"hbs": "^4.0.1",
"jest": "^22.3.0",
Expand Down
27 changes: 20 additions & 7 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,30 @@ app.use(bodyParser.json());
app.use('/static', express.static('static'));
app.set('view engine', 'hbs');

const menu = {
1: {
id: 1,
name: "Strawberry cheesecake",
price: 6
}
};
const {getMenu, addOrder, getOrders} = require('./storage');

/// verbs ///

app.get('/', function(req, res){
res.render('index');
});
app.get('/api/menu', function(req, res){
const menu = getMenu();
res.json(menu);
});

app.get("/api/orders", function(req, res) {
const orders = getOrders();
res.json(orders);
});

app.post('/api/orders', function(req, res){
const order = req.body;
res.json(addOrder(order));
});

// app.patch("/api/order/:orderid", function(req, res) {
// }

app.listen(8080, function(){
console.log('Listening on port 8080');
Expand Down
100 changes: 97 additions & 3 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,110 @@
import React from 'react';
// import '../styles/App.scss';
import Menu from './Menu';
import MakeOrder from './MakeOrder';
import OrderAdmin from './OrderAdmin';

import '../styles/App.scss';
import '../styles/base/base.scss';
import '../styles/components/app.scss';

class App extends React.Component {
constructor(){
super();

this.state = {
menu: [],
currentOrder: [],
orders: []
}
this.receiveItemOrder = this.receiveItemOrder.bind(this)
this.removeItemOrder = this.removeItemOrder.bind(this)
this.fetchMenu = this.fetchMenu.bind(this)
this.receiveOrderAdmin = this.receiveOrderAdmin.bind(this)
this.fetchOrders = this.fetchOrders.bind(this)
this.sendOrderToApi = this.sendOrderToApi.bind(this)
}

fetchMenu() {
const api = "/api/menu/"
fetch(api)
.then(response => response.json())
.then(content => {
this.setState({menu: content});
})
}
fetchOrders() {
const api = "/api/orders/"
fetch(api)
.then(response => response.json())
.then(content => {
this.setState({orders: content})
})
}

sendOrderToApi() {
fetch("/api/orders", {
method: "POST",
body: JSON.stringify(this.state.currentOrder),
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(order => {
alert(`We are making stuff for you! Your order ID is ${order.orderid}`)
});
}

componentDidMount() {
this.fetchMenu();
this.fetchOrders();
}

receiveItemOrder(order) {
const updatedOrder = Object.assign({}, this.state.currentOrder, { [order.id]: order } )
this.setState({currentOrder: updatedOrder})
}
removeItemOrder(id) {
const array = [...this.state.currentOrder];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be easier to store orders in an object that uses ids as keys as it would make look ups much simpler

let index = array.indexOf(id);
array.splice(index, 1);
this.setState({currentOrder: array});
}
receiveOrderAdmin() {
this.setState({orders : orders})
}

render(){
return (
<div>
Delivereat app
<div className="app container">
<header className="masthead">
<h1 className="masthead__title">Cullercoats Coffee</h1>
<div className="masthead__description">
<p>Where good coffee and grub meets geordie banter, run by brummie Matt. Down-to-earth fare, NOW any time, any where (in the North East).</p>
</div>

</header>

<main className="maincontent">

<Menu
menu={this.state.menu}
receiveItemOrder={this.receiveItemOrder}
removeItemOrder={this.removeItemOrder}
/>

<MakeOrder
menu={this.state.menu}
currentOrder={this.state.currentOrder}
sendOrderToApi={this.sendOrderToApi}
/>

<OrderAdmin
orders={this.state.orders}
receiveOrderAdmin={this.receiveOrderAdmin}
/>

</main>
</div>
)
}
Expand Down
38 changes: 38 additions & 0 deletions src/components/MakeOrder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import '../styles/components/makeorder.scss';
import MakeOrderItem from './MakeOrderItem';

function MakeOrder({ currentOrder, sendOrderToApi }) {

function renderOrder() {
return Object.values(currentOrder).map(currentorderitem => {
return <MakeOrderItem
currentorderitem={currentorderitem}
key={currentorderitem.id}
/>
})
}

// create array of prices out of currentOrder object;
let orderKeys = Object.keys(currentOrder);
let orderPrices = []
orderKeys.forEach(key => {
orderPrices.push(currentOrder[key].price)
})

// reducer for total
let totalPrice = orderPrices.reduce((acc, item) => acc = acc + item, 0);
let orderPlusDelivery = totalPrice + 2.95;

return (
<section className="customerOrder">
<h2 className="customerOrder__title">Your Order</h2>
<ul className="customerOrder__order menu--settings">{renderOrder()}
<li>Delivery charge &pound;2.95</li>
<li>Total: &pound;{orderPlusDelivery}</li>
</ul>
<button className="customerOrder__submit" onClick={sendOrderToApi} type="submit">Place order</button>
</section>
)
}
export default MakeOrder;
21 changes: 21 additions & 0 deletions src/components/MakeOrderItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import '../styles/components/makeorderitem.scss';

class MakeOrderItem extends React.Component {
constructor(){
super();
}

render(){

const pricedisplay = this.props.currentorderitem.price.toFixed(2);

return (
<li>
<span>{this.props.currentorderitem.quantity}</span> * <strong>{this.props.currentorderitem.item}</strong> : &pound;{pricedisplay}
</li>
)
}
}

export default MakeOrderItem;
36 changes: 36 additions & 0 deletions src/components/Menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import MenuItem from './MenuItem';

class Menu extends React.Component {
constructor(){
super();

this.getCourse = this.getCourse.bind(this)
}

getCourse(course) {
// values = Object.values(this.props.menu);
// values.map();
return this.props.menu.filter(menuitem => menuitem.category === course)
.map(menuitem => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation here would make code easier to read

return <MenuItem
menuitem={menuitem}
key={menuitem.id}
receiveItemOrder={this.props.receiveItemOrder}
removeItemOrder={this.props.removeItemOrder} />
})
};


render(){
return (
<ul className="menu menu--settings">
<h2>Drinks</h2> {this.getCourse("drinks")}
<h2>Cakes</h2> {this.getCourse("cakes")}
<h2>Breakfast</h2> {this.getCourse("breakfast")}
</ul>
)
}
}

export default Menu;
110 changes: 110 additions & 0 deletions src/components/MenuItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React from 'react';
import '../styles/components/menuitem.scss';
import cx from 'classnames';

class MenuItem extends React.Component {
constructor(){
super();

this.state = {
menuitemQuantity: 0,
added: false,
error: false
};

this.handleClick = this.handleClick.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.itemOrder = this.itemOrder.bind(this)
}

handleSubmit(event) {
event.preventDefault();
if (this.state.menuitemQuantity <= 0) {
this.setState({
error: !this.state.error
});
} else {
if (this.state.added === false) {
this.itemOrder();
this.setState({
added: !this.state.added
});
} else {
this.props.removeItemOrder(this.props.menuitem.id);
this.setState({
added: !this.state.added
});
}
}
}

handleClick(event) {
if (event.target.value === "-" && this.state.menuitemQuantity > 0) {
this.setState({
menuitemQuantity: this.state.menuitemQuantity - 1
});
} else if (event.target.value === "+") {
this.setState({
menuitemQuantity: this.state.menuitemQuantity + 1
});
if (this.state.error === true) {
this.setState({
error: false
});
}
}
}

itemOrder() {
let price = (this.props.menuitem.price * this.state.menuitemQuantity);
const order = {
id: this.props.menuitem.id,
item: this.props.menuitem.name,
price: price,
quantity: this.state.menuitemQuantity,
};
this.props.receiveItemOrder(order);
}

render(){

const buttonclasses = cx('menuitem__submit', {
'added': this.state.added,
'': !this.state.added
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think this can be removed as it does not add any classes

});
const errorclasses = cx('menuitem__error', {
'show--error': this.state.error,
'': this.state.error
});

const pricedisplay = this.props.menuitem.price.toFixed(2);

return (
<li className="menuitem">
<form className="menuitem__form" onSubmit={this.handleSubmit}>

<div className="quantity">
<input className="quantity__change" onClick={this.handleClick} value="-" type="button"/>
<input className="quantity__display" type="text" size='1' value={this.state.menuitemQuantity} readOnly/>
<input className="quantity__change" onClick={this.handleClick} value="+" type="button"/>
</div>

<div className="menuitem__details">
<div className="menuitem__select">
<label className="menuitem__item">{this.props.menuitem.name}
<span className="menuitem__price">&nbsp;&pound;{pricedisplay}</span>
</label>
<button type="submit" className={buttonclasses}></button>
<span className={errorclasses}>Please select quantity</span>
</div>

</div>


</form>
</li>
)
}
}

export default MenuItem;
Loading