Skip to content

Commit 36acf18

Browse files
authored
Lesson 10 update (#21)
1 parent e66cbc2 commit 36acf18

12 files changed

+632
-41
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
3+
class ExitComponent extends React.Component {
4+
exitPage() {
5+
window.close();
6+
}
7+
8+
render() {
9+
return <>{this.props.renderExit(this.exitPage.bind(this))}</>;
10+
}
11+
}
12+
13+
class ExitButton extends React.Component {
14+
render() {
15+
return (
16+
<ExitComponent
17+
renderExit={exit => (
18+
<button
19+
onClick={() => {
20+
exit();
21+
}}
22+
>
23+
Exit Page
24+
</button>
25+
)}
26+
/>
27+
);
28+
}
29+
}
30+
31+
class ExitLink extends React.Component {
32+
render() {
33+
return (
34+
<ExitComponent
35+
renderExit={exit => (
36+
<a
37+
onClick={e => {
38+
e.preventDefault();
39+
exit();
40+
}}
41+
>
42+
Exit
43+
</a>
44+
)}
45+
/>
46+
);
47+
}
48+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const {createStore} = require('redux');
2+
3+
const counterReducer = (state = 0, action) => {
4+
switch (action.type) {
5+
case 'INCREMENT':
6+
return state + 1;
7+
case 'DECREMENT':
8+
return state - 1;
9+
default:
10+
return state;
11+
}
12+
};
13+
14+
const store = createStore(counterReducer);
15+
16+
console.assert(store.getState() === 0, 'initalises to 0');
17+
18+
store.dispatch({type: 'INCREMENT'});
19+
console.assert(store.getState() === 1, 'incrementing works');
20+
21+
store.dispatch({type: 'DECREMENT'});
22+
console.assert(store.getState() === 0, 'decrementing works');
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<div id="app"></div>
2+
<script src="./activity-3-app-start.js">
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Run with
2+
// npm run server exercise-2-map-to-props.html
3+
import React from 'react';
4+
5+
import ReactDOM from 'react-dom';
6+
import {Provider, connect} from 'react-redux';
7+
import {createStore, applyMiddleware} from 'redux';
8+
import ReduxThunk from 'redux-thunk';
9+
10+
class Basket extends React.Component {
11+
render() {
12+
return (
13+
<div>
14+
<p>You have {this.props.items.length} items in your basket</p>
15+
<div>{this.props.items.map(item => this.props.renderItem(item))}</div>
16+
<button onClick={() => this.props.onCheckout(this.props.items)}>
17+
Proceed to checkout
18+
</button>
19+
</div>
20+
);
21+
}
22+
}
23+
24+
class App extends React.Component {
25+
render() {
26+
const {items, status, product} = this.props;
27+
return (
28+
<div>
29+
{status === 'CHECKING_OUT' && (
30+
<div>
31+
<p>You've started checking out with {items.length} items.</p>
32+
<button onClick={this.props.continueShopping}>
33+
Continue shopping
34+
</button>
35+
<button onClick={this.props.finish}>Finish</button>
36+
</div>
37+
)}
38+
{status === 'SHOPPING' && (
39+
<Basket
40+
items={items}
41+
renderItem={item => (
42+
<div>
43+
x{item.quantity} - {item.name} - $
44+
{(item.price / 100).toFixed(2)} each{' '}
45+
</div>
46+
)}
47+
onCheckout={this.props.handleCheckout}
48+
/>
49+
)}
50+
{status === 'DONE' && <p>Done</p>}
51+
</div>
52+
);
53+
}
54+
}
55+
56+
const defaultState = {
57+
status: 'SHOPPING',
58+
product: {}
59+
};
60+
61+
const START_CHECKOUT = 'START_CHECKOUT';
62+
const CONTINUE_SHOPPING = 'CONTINUE_SHOPPING';
63+
const DONE = 'DONE';
64+
const ADD_PRODUCT = 'ADD_PRODUCT';
65+
const REQUEST_BASKET_SUCCESS = 'REQUEST_BASKET_SUCCESS';
66+
67+
function fetchFromBff(graphQuery) {
68+
return fetch('http://localhost:3000', {
69+
method: 'POST',
70+
headers: {
71+
Accept: 'application/json',
72+
'Content-Type': 'application/json'
73+
},
74+
body: JSON.stringify({
75+
query: graphQuery
76+
})
77+
})
78+
.then(res => {
79+
if (res.ok) {
80+
return res.json();
81+
}
82+
})
83+
.then(response => {
84+
return response.data;
85+
});
86+
}
87+
88+
function startCheckout(items) {
89+
return {
90+
type: START_CHECKOUT,
91+
basket: {
92+
items
93+
}
94+
};
95+
}
96+
97+
function continueShopping() {
98+
return {
99+
type: CONTINUE_SHOPPING
100+
};
101+
}
102+
103+
function done() {
104+
return {
105+
type: DONE
106+
};
107+
}
108+
109+
function addProduct(newProduct) {
110+
return {
111+
type: ADD_PRODUCT,
112+
newProduct: {
113+
...newProduct,
114+
quantity: 1
115+
}
116+
};
117+
}
118+
119+
const selectBasketItems = state =>
120+
(state && state.basket && state.basket.items) || [];
121+
122+
const selectStatus = state => state && state.status;
123+
const selectProduct = state => state && state.product;
124+
125+
const appReducer = (state = defaultState, action) => {
126+
switch (action.type) {
127+
case START_CHECKOUT:
128+
return {
129+
...state,
130+
status: 'CHECKING_OUT'
131+
};
132+
case CONTINUE_SHOPPING:
133+
return {
134+
...state,
135+
status: 'SHOPPING'
136+
};
137+
case DONE:
138+
return {
139+
...state,
140+
status: 'DONE'
141+
};
142+
case ADD_PRODUCT:
143+
return {
144+
...state,
145+
basket: {
146+
items: selectBasketItems(state).concat(action.newProduct)
147+
}
148+
};
149+
default:
150+
return state;
151+
}
152+
};
153+
154+
const store = createStore(appReducer, applyMiddleware(ReduxThunk));
155+
156+
const mapStateToProps = state => {
157+
return {
158+
items: selectBasketItems(state),
159+
status: selectStatus(state),
160+
product: selectProduct(state)
161+
};
162+
};
163+
164+
const mapDispatchToProps = dispatch => {
165+
return {
166+
handleCheckout(items) {
167+
dispatch(startCheckout(items));
168+
},
169+
continueShopping() {
170+
dispatch(continueShopping());
171+
},
172+
finish() {
173+
dispatch(done());
174+
},
175+
addProduct(product) {
176+
dispatch(addProduct(product));
177+
}
178+
};
179+
};
180+
181+
const ConnectedApp = connect(
182+
mapStateToProps,
183+
mapDispatchToProps
184+
)(App);
185+
186+
ReactDOM.render(
187+
<Provider store={store}>
188+
<ConnectedApp />
189+
</Provider>,
190+
document.querySelector('#app')
191+
);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<div id="app"></div>
2+
<script src="./activity-3-app.js">

0 commit comments

Comments
 (0)