Skip to content

Commit 4da7a7c

Browse files
committed
orders list and new order form
1 parent 8184917 commit 4da7a7c

File tree

7 files changed

+231
-0
lines changed

7 files changed

+231
-0
lines changed

client/src/api/normalize.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,28 @@ const serializers = {
6969
keyForAttribute: 'camelCase',
7070
}),
7171
},
72+
73+
orders: {
74+
serializer: new Serializer('orders', {
75+
keyForAttribute: 'camelCase',
76+
attributes: [
77+
'orderDate',
78+
'requiredDate',
79+
'shippedDate',
80+
'shipVia',
81+
'freight',
82+
'shipName',
83+
'shipAddress',
84+
'shipCity',
85+
'shipRegion',
86+
'shipPostalCode',
87+
'shipCountry',
88+
],
89+
}),
90+
deserializer: new Deserializer({
91+
keyForAttribute: 'camelCase',
92+
}),
93+
},
7294
};
7395

7496
export const normalize = (type, data) => {

client/src/components/App.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ export class App extends Component {
3838
<NavItem>
3939
<NavLink href="/#/categories">Categories</NavLink>
4040
</NavItem>
41+
<NavItem>
42+
<NavLink href="/#/orders">Orders</NavLink>
43+
</NavItem>
4144
<NavItem>
4245
{
4346
userIsAdmin && <NavLink href="/#/users">Users</NavLink>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React, { Component, PropTypes } from 'react';
2+
import { push } from 'react-router-redux';
3+
import { connect } from 'react-redux';
4+
import { get, find, omit } from 'lodash';
5+
6+
import { ErrorAlert, Loading, EditHeader } from '../UI';
7+
import { withResource } from '../../hocs';
8+
import OrderForm from './OrderForm';
9+
import {
10+
fetchList,
11+
getMany,
12+
} from '../../store/api';
13+
14+
export class OrderEdit extends Component {
15+
componentWillMount() {
16+
const { params, fetchResource } = this.props;
17+
18+
if (params.id) {
19+
fetchResource({ id: params.id });
20+
}
21+
}
22+
23+
render() {
24+
const { isNew, error, loading, resource, onSubmit, orders } = this.props;
25+
26+
if (error) {
27+
return (<ErrorAlert {...error} />);
28+
}
29+
30+
if (loading) {
31+
return (<Loading/>);
32+
}
33+
34+
return (
35+
<div>
36+
<EditHeader {...this.props}>{ isNew ? 'New Order' : resource.title }</EditHeader>
37+
<OrderForm initialValues={resource} isNew={isNew} onSubmit={onSubmit} />
38+
</div>
39+
);
40+
}
41+
}
42+
43+
export const mapStateToProps = (state, props) => ({
44+
categories: getMany(state, 'orders'),
45+
});
46+
47+
export const mapDispatchToProps = dispatch => ({
48+
redirectToIndex: () => dispatch(push('/orders')),
49+
});
50+
51+
export default connect(mapStateToProps, mapDispatchToProps)(
52+
withResource('orders')(OrderEdit),
53+
);
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React, { Component, PropTypes } from 'react';
2+
import { isEmpty } from 'lodash';
3+
import { Field, reduxForm } from 'redux-form';
4+
import { Button, Form, Col, Row } from 'reactstrap';
5+
6+
import { InputField, required } from '../../forms';
7+
8+
class OrderForm extends Component {
9+
render() {
10+
const { handleSubmit, onSubmit, onDelete, reset, isNew, submitSucceeded } = this.props;
11+
12+
if (isNew && submitSucceeded) {
13+
setTimeout(() => reset());
14+
}
15+
16+
const submitOnChange = () => {
17+
if (!isNew) {
18+
setTimeout(() => handleSubmit(onSubmit)(), 0);
19+
}
20+
};
21+
22+
return (
23+
<Form onSubmit={handleSubmit}>
24+
<Row>
25+
<Col xs="10" sm="8" md="6">
26+
<Field
27+
name="orderDate"
28+
label="Order date"
29+
component={InputField}
30+
onChange={submitOnChange}
31+
/>
32+
<Field
33+
name="shippedDate"
34+
label="Shipped date"
35+
component={InputField}
36+
onChange={submitOnChange}
37+
/>
38+
<Field
39+
name="shipAddress"
40+
label="Ship address"
41+
component={InputField}
42+
onChange={submitOnChange}
43+
/>
44+
<Field
45+
name="shipCity"
46+
label="Ship city"
47+
component={InputField}
48+
onChange={submitOnChange}
49+
/>
50+
<Field
51+
name="shipRegion"
52+
label="Ship region"
53+
component={InputField}
54+
onChange={submitOnChange}
55+
/>
56+
</Col>
57+
<Col xs="2">
58+
{
59+
isNew
60+
? <Button color="success">+</Button>
61+
: <Button color="danger" onClick={onDelete}>X</Button>
62+
}
63+
</Col>
64+
</Row>
65+
</Form>
66+
);
67+
}
68+
}
69+
70+
export default reduxForm({
71+
enableReinitialize: true,
72+
form: 'order',
73+
})(OrderForm);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React, { Component, PropTypes } from 'react';
2+
import { Link } from 'react-router';
3+
import { connect } from 'react-redux';
4+
import { get, find, keyBy } from 'lodash';
5+
import { Button } from 'reactstrap';
6+
7+
import { fetchList, getMap, getMany } from '../../store/api';
8+
import { withResourceList } from '../../hocs';
9+
import { ListHeader, ListTable } from '../UI';
10+
11+
const formatDate = date => (new Date(date)).toLocaleString();
12+
13+
export class OrderList extends Component {
14+
componentWillMount() {
15+
const {resourceList} = this.props;
16+
this.props.fetchResourceList({sort: '-orderDate', ...resourceList.params});
17+
}
18+
19+
render() {
20+
const { resourceList, onFilter, categories } = this.props;
21+
const columns = [
22+
{
23+
attribute: 'order_date',
24+
header: 'Order date',
25+
minWidth: '50px',
26+
rowRender: order => formatDate(order.orderDate),
27+
},
28+
{
29+
attribute: 'shippedDate',
30+
header: 'Shipped date',
31+
rowRender: order => formatDate(order.shippedDate),
32+
sortable: true,
33+
},
34+
{
35+
attribute: 'shipAddress',
36+
header: 'Ship address',
37+
rowRender: order => order.shipAddress,
38+
sortable: true,
39+
},
40+
{
41+
attribute: 'shipCity',
42+
header: 'Ship city',
43+
rowRender: order => order.shipCity,
44+
sortable: true,
45+
},
46+
{
47+
attribute: 'shipRegion',
48+
header: 'Ship region',
49+
rowRender: order => order.shipRegion,
50+
sortable: true,
51+
},
52+
];
53+
54+
return (
55+
<div>
56+
<Button tag={Link} to={'/orders/new'}>New Order</Button>
57+
<ListTable {...this.props} columns={columns} />
58+
</div>
59+
);
60+
}
61+
}
62+
63+
export const mapStateToProps = state => ({
64+
ordersById: getMap(state, 'orders'),
65+
orders: getMany(state, 'orders'),
66+
});
67+
68+
export const mapDispatchToProps = dispatch => ({
69+
fetchOrders: () => dispatch(fetchList('orders', { page: { size: 999 } })),
70+
});
71+
72+
export default connect(mapStateToProps, mapDispatchToProps)(
73+
withResourceList('orders')(OrderList),
74+
);

client/src/components/Orders/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export OrderList from './OrderList';
2+
export OrderEdit from './OrderEdit';

client/src/components/Routes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { PostList, PostEdit } from './Posts';
99
import { CategoryList, CategoryEdit } from './Categories';
1010
import { UserList, UserEdit } from './Users';
1111
import { Login } from './Auth';
12+
import { OrderList, OrderEdit } from './Orders';
1213

1314
const UserIsAuthenticated = UserAuthWrapper({ authSelector: getUser });
1415
const UserIsAdmin = UserAuthWrapper({
@@ -28,6 +29,9 @@ export class Routes extends PureComponent {
2829
<Router history={history}>
2930
<Route path="/" component={UserIsAuthenticated(App)}>
3031
<IndexRoute component={Dashboard}/>
32+
<Route path="/orders" component={OrderList}/>
33+
<Route path="/orders/new" component={OrderEdit}/>
34+
<Route path="/orders/:id" component={OrderEdit}/>
3135
<Route path="/posts" component={PostList}/>
3236
<Route path="/posts/new" component={PostEdit}/>
3337
<Route path="/posts/:id" component={PostEdit}/>

0 commit comments

Comments
 (0)