{
userIsAdmin && Users
diff --git a/client/src/components/Customers/CustomerEdit.js b/client/src/components/Customers/CustomerEdit.js
new file mode 100644
index 0000000..3930973
--- /dev/null
+++ b/client/src/components/Customers/CustomerEdit.js
@@ -0,0 +1,48 @@
+import React, { Component, PropTypes } from 'react';
+import { push } from 'react-router-redux';
+import { connect } from 'react-redux';
+
+import { ErrorAlert, Loading, EditHeader } from '../UI';
+import { withResource } from '../../hocs';
+import CustomerForm from './CustomerForm';
+import { getMany, fetchList } from '../../store/api';
+
+export class CustomerEdit extends Component {
+ componentWillMount() {
+ const { params, fetchResource } = this.props;
+ if (params.id) {
+ fetchResource({ id: params.id });
+ }
+ }
+
+ render() {
+ const { isNew, error, loading, resource, onSubmit } = this.props;
+
+ if (error) {
+ return ();
+ }
+
+ if (loading) {
+ return ();
+ }
+
+ return (
+
+ { isNew ? 'New Customer' : resource.company_name }
+
+
+ );
+ }
+}
+
+export const mapStateToProps = (state, props) => ({
+ roles: getMany(state)
+});
+
+export const mapDispatchToProps = dispatch => ({
+ redirectToIndex: () => dispatch(push('/customers'))
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(
+ withResource('customers')(CustomerEdit),
+);
diff --git a/client/src/components/Customers/CustomerForm.js b/client/src/components/Customers/CustomerForm.js
new file mode 100644
index 0000000..6570bb3
--- /dev/null
+++ b/client/src/components/Customers/CustomerForm.js
@@ -0,0 +1,88 @@
+import React, { Component, PropTypes } from 'react';
+import { isEmpty } from 'lodash';
+import { Field, reduxForm } from 'redux-form';
+import { Button, Form } from 'reactstrap';
+
+import { InputField, MultiselectField, required } from '../../forms';
+
+class CustomerForm extends Component {
+ render() {
+ const { handleSubmit, pristine, reset, submitting } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const validate = (values) => {
+ const errors = required(values, 'email');
+ return errors;
+};
+
+export default reduxForm({
+ enableReinitialize: true,
+ form: 'customer',
+ validate,
+})(CustomerForm);
diff --git a/client/src/components/Customers/CustomerList.js b/client/src/components/Customers/CustomerList.js
new file mode 100644
index 0000000..d820fa7
--- /dev/null
+++ b/client/src/components/Customers/CustomerList.js
@@ -0,0 +1,59 @@
+import React, { Component, PropTypes } from 'react';
+import { Link } from 'react-router';
+import { find, keyBy } from 'lodash';
+import { Button } from 'reactstrap';
+
+import { ListTable } from '../UI';
+import { withResourceList } from '../../hocs';
+import CustomerListFilter from './CustomerListFilter';
+
+const formatDate = date => (new Date(date)).toLocaleString();
+
+export class CustomerList extends Component {
+ componentWillMount() {
+ const { resourceList } = this.props;
+ this.props.fetchResourceList({ sort: '-companyName', ...resourceList.params });
+ }
+
+ render() {
+ const { onFilter } = this.props;
+ const columns = [
+ {
+ attribute: 'companyName',
+ header: 'Company Name',
+ rowRender: customer => {customer.companyName},
+ sortable: true,
+ },
+ {
+ attribute: 'contactName',
+ header: 'Contact Name',
+ rowRender: customer => {customer.contactName},
+ sortable: true,
+ },
+ {
+ attribute: 'createdAt',
+ header: 'Created At',
+ rowRender: customer => formatDate(customer.confirmedAt),
+ sortable: true,
+ }
+ ];
+
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export const mapStateToProps = state => ({
+ filter: get(state, 'form.customerListFilter.values') || {}
+});
+
+export default withResourceList('customers')(CustomerList);
diff --git a/client/src/components/Customers/CustomerListFilter.js b/client/src/components/Customers/CustomerListFilter.js
new file mode 100644
index 0000000..d21ce42
--- /dev/null
+++ b/client/src/components/Customers/CustomerListFilter.js
@@ -0,0 +1,35 @@
+import React, { Component, PropTypes } from 'react';
+import { isEmpty } from 'lodash';
+import { Field, reduxForm } from 'redux-form';
+import { Form, Row, Col } from 'reactstrap';
+
+import { InputField, SelectField } from '../../forms';
+
+class CustomerListFilter extends Component {
+ render() {
+ const { handleSubmit, onSubmit } = this.props;
+
+ const submitOnChange = () => setTimeout(() => handleSubmit(onSubmit)(), 0);
+
+
+ return (
+
+ );
+ }
+}
+
+export default reduxForm({
+ form: 'customerListFilter',
+ destroyOnUnmount: false,
+})(CustomerListFilter);
diff --git a/client/src/components/Customers/index.js b/client/src/components/Customers/index.js
new file mode 100644
index 0000000..ad0a602
--- /dev/null
+++ b/client/src/components/Customers/index.js
@@ -0,0 +1,2 @@
+export CustomerList from './CustomerList';
+export CustomerEdit from './CustomerEdit';
diff --git a/client/src/components/Routes.js b/client/src/components/Routes.js
index 9e8cfbe..4114d43 100644
--- a/client/src/components/Routes.js
+++ b/client/src/components/Routes.js
@@ -8,6 +8,7 @@ import Dashboard from './Dashboard';
import { PostList, PostEdit } from './Posts';
import { CategoryList, CategoryEdit } from './Categories';
import { UserList, UserEdit } from './Users';
+import { CustomerList, CustomerEdit } from './Customers';
import { Login } from './Auth';
const UserIsAuthenticated = UserAuthWrapper({ authSelector: getUser });
@@ -34,6 +35,9 @@ export class Routes extends PureComponent {
+
+
+