Skip to content

Commit 5f46b09

Browse files
maxwellgordonansonws
authored andcommitted
Controlled Form and New Product Page
1 parent 52818d5 commit 5f46b09

5 files changed

Lines changed: 140 additions & 5 deletions

File tree

src/components/App.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from 'react';
2-
import { BrowserRouter as Router, Route } from 'react-router-dom';
2+
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
33
import ProductShowPage from './ProductShowPage';
44
import ProductIndexPage from './ProductIndexPage';
5+
import NewProductPage from './NewProductPage';
56
import HomePage from './HomePage';
67
import NavBar from './NavBar';
78

@@ -10,9 +11,12 @@ const App = () => {
1011
<Router>
1112
<div className="App">
1213
<NavBar />
13-
<Route path="/products/:id" component={ProductShowPage} />
14-
<Route path="/products" exact component={ProductIndexPage} />
15-
<Route path="/" exact component={HomePage} />
14+
<Switch>
15+
<Route path="/products/new" component={NewProductPage} />
16+
<Route path="/products/:id" component={ProductShowPage} />
17+
<Route path="/products" exact component={ProductIndexPage} />
18+
<Route path="/" exact component={HomePage} />
19+
</Switch>
1620
</div>
1721
</Router>
1822
);

src/components/NavBar.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { NavLink } from 'react-router-dom';
44
function NavBar(props) {
55
return (
66
<div className="NavBar">
7-
<NavLink to="/">Home</NavLink>|<NavLink to="/products">Products</NavLink>
7+
<NavLink to="/">Home</NavLink>|<NavLink to="/products">Products</NavLink>|
8+
<NavLink to="/products/new">New Product</NavLink>
89
</div>
910
);
1011
}

src/components/NewProductPage.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { Component } from 'react';
2+
import ProductForm from './ProductForm';
3+
import { Session, Product } from '../requests';
4+
5+
class NewProductPage extends Component {
6+
constructor(props) {
7+
super(props);
8+
this.state = {
9+
...initialProduct,
10+
};
11+
this.updateField = this.updateField.bind(this);
12+
this.createProduct = this.createProduct.bind(this);
13+
}
14+
15+
updateField(param) {
16+
// expecting params to look like the following:
17+
// { title: "someValue" } or
18+
// { decription: "someValue" } or
19+
// { price: 12 }
20+
this.setState(param);
21+
}
22+
23+
createProduct(e) {
24+
e.preventDefault();
25+
const product = this.state;
26+
Session.create({
27+
email: 'js@winterfell.gov',
28+
password: 'supersecret',
29+
})
30+
.then(() => {
31+
return Product.create({
32+
...product,
33+
});
34+
})
35+
.then(({ id }) => {
36+
this.props.history.push(`/products/${id}`);
37+
});
38+
}
39+
40+
render() {
41+
return (
42+
<div className="NewProductPage">
43+
<ProductForm
44+
{...this.state}
45+
onChange={this.updateField}
46+
onSubmit={this.createProduct}
47+
/>
48+
</div>
49+
);
50+
}
51+
}
52+
53+
const initialProduct = {
54+
title: '',
55+
description: '',
56+
price: '',
57+
};
58+
59+
export default NewProductPage;

src/components/ProductForm.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
3+
function ProductForm(props) {
4+
return (
5+
<div className="ProductForm">
6+
<form onSubmit={props.onSubmit}>
7+
<div>
8+
<label htmlFor="title">Title</label>
9+
<input
10+
onChange={e => props.onChange({ title: e.currentTarget.value })}
11+
type="text"
12+
name="title"
13+
value={props.title}
14+
/>
15+
</div>
16+
<div>
17+
<label htmlFor="description">Description</label>
18+
<input
19+
onChange={e =>
20+
props.onChange({ description: e.currentTarget.value })
21+
}
22+
type="text"
23+
name="description"
24+
value={props.description}
25+
/>
26+
</div>
27+
<div>
28+
<label htmlFor="price">Price</label>
29+
<input
30+
onChange={e =>
31+
props.onChange({ price: parseInt(e.currentTarget.value) })
32+
}
33+
type="number"
34+
name="price"
35+
value={props.price}
36+
/>
37+
</div>
38+
<input type="submit" />
39+
</form>
40+
</div>
41+
);
42+
}
43+
44+
export default ProductForm;

src/requests.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,31 @@ export const Product = {
1111
credentials: 'include',
1212
}).then(res => res.json());
1313
},
14+
create(params) {
15+
return fetch(`${BASE_URL}/products`, {
16+
method: 'POST',
17+
credentials: 'include',
18+
headers: {
19+
'Content-Type': 'application/json',
20+
},
21+
body: JSON.stringify(params),
22+
}).then(res => res.json());
23+
},
24+
};
25+
26+
export const Session = {
27+
create(params) {
28+
return fetch(`${BASE_URL}/sessions`, {
29+
method: 'POST',
30+
credentials: 'include',
31+
// to include the cookie when doing fetch, use
32+
// the "credentials" option with "include" for cross-origin
33+
// requests or with "same-origin" for same-origin
34+
// requests.
35+
headers: {
36+
'Content-Type': 'application/json',
37+
},
38+
body: JSON.stringify(params),
39+
}).then(res => res.json());
40+
},
1441
};

0 commit comments

Comments
 (0)