Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow edit invoices #172

Merged
merged 9 commits into from
Jan 18, 2018
Merged
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
11 changes: 11 additions & 0 deletions app/actions/invoices.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ export const saveInvoice = createAction(
invoiceData => invoiceData
);

// Edit an Invoice
export const editInvoice = createAction(
ACTION_TYPES.INVOICE_EDIT,
invoiceData => invoiceData
);

export const updateInvoice = createAction(
ACTION_TYPES.INVOICE_UPDATE,
(invoiceID, data) => ({ invoiceID, data })
);

// New Invoice from Contact
export const newInvoiceFromContact = createAction(
ACTION_TYPES.INVOICE_NEW_FROM_CONTACT,
Expand Down
12 changes: 12 additions & 0 deletions app/components/form/Discount.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Libraries
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';

// Custom Components
import { Section } from '../shared/Section';
Expand Down Expand Up @@ -42,6 +43,17 @@ export class Discount extends Component {
});
}

// Handle Reset Form
componentWillReceiveProps(nextProps) {
const { discount } = nextProps;
if (isEmpty(discount)) {
this.setState({
amount: '',
type: 'percentage',
});
}
}

shouldComponentUpdate(nextProps, nextState) {
return (
this.state !== nextState || this.props.discount !== nextProps.discount
Expand Down
15 changes: 5 additions & 10 deletions app/components/invoices/Invoice.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libs
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { truncate } from 'lodash';
import styled from 'styled-components';
Expand Down Expand Up @@ -142,7 +142,7 @@ const Field = styled.div`
`;

// Component
class Invoice extends Component {
class Invoice extends PureComponent {
constructor(props) {
super(props);
this.viewInvoice = this.viewInvoice.bind(this);
Expand All @@ -151,20 +151,14 @@ class Invoice extends Component {
this.displayStatus = this.displayStatus.bind(this);
}

shouldComponentUpdate(nextProps) {
if (this.props.invoice.status !== nextProps.invoice.status) {
return true;
}
return false;
}

deleteInvoice() {
const { invoice, deleteInvoice } = this.props;
deleteInvoice(invoice._id);
}

editInvoice() {
// TODO
const { invoice, editInvoice } = this.props;
editInvoice(invoice);
}

viewInvoice() {
Expand Down Expand Up @@ -297,6 +291,7 @@ class Invoice extends Component {
}

Invoice.propTypes = {
editInvoice: PropTypes.func.isRequired,
deleteInvoice: PropTypes.func.isRequired,
invoice: PropTypes.object.isRequired,
setInvoiceStatus: PropTypes.func.isRequired,
Expand Down
15 changes: 15 additions & 0 deletions app/components/invoices/__tests__/Invoice.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const invoice = {
},
};

const editInvoice = jest.fn();
const deleteInvoice = jest.fn();
const setInvoiceStatus = jest.fn();
const dateFormat = 'MM/DD/YY';
Expand All @@ -43,6 +44,7 @@ describe('Renders correctly to the DOM', () => {
wrapper = shallow(
<Invoice
invoice={invoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand All @@ -54,6 +56,7 @@ describe('Renders correctly to the DOM', () => {
const mountWrapper = mount(
<Invoice
invoice={invoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand Down Expand Up @@ -90,6 +93,7 @@ describe('Renders correctly to the DOM', () => {
const paidInvoiceWapper = shallow(
<Invoice
invoice={paidInvoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand All @@ -110,6 +114,7 @@ describe('Renders correctly to the DOM', () => {
const cancelledInvoiceWapper = shallow(
<Invoice
invoice={cancelledInvoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand All @@ -128,6 +133,7 @@ describe('Renders correctly to the DOM', () => {
const refundedInvoiceWapper = shallow(
<Invoice
invoice={refundedInvoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand Down Expand Up @@ -156,6 +162,7 @@ describe('Renders correctly to the DOM', () => {
.create(
<Invoice
invoice={invoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand All @@ -174,6 +181,7 @@ describe('handle clicks correctly', () => {
wrapper = shallow(
<Invoice
invoice={invoice}
editInvoice={editInvoice}
deleteInvoice={deleteInvoice}
setInvoiceStatus={setInvoiceStatus}
dateFormat={dateFormat}
Expand All @@ -190,6 +198,13 @@ describe('handle clicks correctly', () => {
deleteBtn = wrapper.find(Button).first();
});

// TODO
it('handle edit action correctly', () => {
editBtn.simulate('click');
expect(editInvoice).toHaveBeenCalled();
expect(editInvoice).toHaveBeenCalledWith(invoice);
});

it('handle delete action correctly', () => {
deleteBtn.simulate('click');
expect(deleteInvoice).toHaveBeenCalled();
Expand Down
2 changes: 2 additions & 0 deletions app/constants/actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export const SAVED_FORM_SETTING_UPDATE = 'SAVED_FORM_SETTING_UPDATE';

// INVOICE
// ===========================================================
export const INVOICE_EDIT = 'INVOICE_EDIT';
export const INVOICE_UPDATE = 'INVOICE_UPDATE';
export const INVOICE_SAVE = 'INVOICE_SAVE';
export const INVOICE_DELETE = 'INVOICE_DELETE';
export const INVOICE_GET_ALL = 'INVOICE_GET_ALL';
Expand Down
10 changes: 7 additions & 3 deletions app/containers/Form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Form extends Component {
settings,
savedSettings,
} = this.props.currentInvoice;
const { required_fields, open } = settings;
const { required_fields, open, editMode } = settings;
return (
<PageWrapper>
<PageHeader>
Expand All @@ -66,8 +66,12 @@ class Form extends Component {
<Button danger onClick={clearForm}>
Clear
</Button>
<Button primary onClick={saveFormData}>
Save & Preview
<Button
primary={editMode.active}
success={editMode.active === false}
onClick={saveFormData}
>
{editMode.active ? 'Update' : 'Save & Preview'}
</Button>
</PageHeaderActions>
</PageHeader>
Expand Down
7 changes: 7 additions & 0 deletions app/containers/Invoices.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
class Invoices extends PureComponent {
constructor(props) {
super(props);
this.editInvoice = this.editInvoice.bind(this);
this.deleteInvoice = this.deleteInvoice.bind(this);
this.setInvoiceStatus = this.setInvoiceStatus.bind(this);
}
Expand Down Expand Up @@ -72,13 +73,19 @@ class Invoices extends PureComponent {
dispatch(Actions.setInvoiceStatus(invoiceId, status));
}

editInvoice(invoice) {
const { dispatch } = this.props;
dispatch(Actions.editInvoice(invoice));
}

// Render
render() {
const { invoices, dateFormat } = this.props;
const invoicesComponent = invoices.map((invoice, index) => (
<Invoice
key={invoice._id}
deleteInvoice={this.deleteInvoice}
editInvoice={this.editInvoice}
setInvoiceStatus={this.setInvoiceStatus}
index={index}
dateFormat={dateFormat}
Expand Down
12 changes: 12 additions & 0 deletions app/helpers/__mocks__/pouchDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ const saveDoc = jest.fn(
})
);

const updateDoc = jest.fn(
(dbName, doc) =>
new Promise((resolve, reject) => {
!dbName && reject(new Error('No database found!'));
!doc && reject(new Error('No doc found!'));
dbName === 'contacts' && resolve([...mockData.contactsRecords]);
dbName === 'invoices' && resolve([...mockData.invoicesRecords]);
})
);

const deleteDoc = jest.fn(
(dbName, docId) =>
new Promise((resolve, reject) => {
Expand All @@ -70,9 +80,11 @@ const deleteDoc = jest.fn(
})
);


module.exports = {
getAllDocs,
saveDoc,
updateDoc,
deleteDoc,
mockData,
};
14 changes: 12 additions & 2 deletions app/middlewares/FormMW.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as FormActions from '../actions/form';
import * as InvoicesActions from '../actions/invoices';
import * as ContactsActions from '../actions/contacts';
import * as SettingsActions from '../actions/settings';
import * as UIActions from '../actions/ui';

// Helper
import { getInvoiceData, validateFormData } from '../helpers/form';
Expand All @@ -20,9 +21,18 @@ const FormMW = ({ dispatch, getState }) => next => action => {
const currentFormData = getState().form;
// Validate Form Data
if (!validateFormData(currentFormData)) return;
// Save Invoice To DB
const currentInvoiceData = getInvoiceData(currentFormData);
dispatch(InvoicesActions.saveInvoice(currentInvoiceData));
// Check Edit Mode
if (currentFormData.settings.editMode.active) {
const invoiceId = currentFormData.settings.editMode.data._id;
// Update existing invoice
dispatch(InvoicesActions.updateInvoice(invoiceId, currentInvoiceData));
// Change Tab to invoices
dispatch(UIActions.changeActiveTab('invoices'));
} else {
// Save Invoice To DB
dispatch(InvoicesActions.saveInvoice(currentInvoiceData));
}
// Save Contact to DB if it's a new one
if (currentFormData.recipient.newRecipient) {
const newContactData = currentFormData.recipient.new;
Expand Down
39 changes: 39 additions & 0 deletions app/middlewares/InvoicesMW.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const InvoicesMW = ({ dispatch }) => next => action => {
newRecipient: false,
})
);
break;
}

case ACTION_TYPES.INVOICE_GET_ALL: {
Expand Down Expand Up @@ -89,6 +90,44 @@ const InvoicesMW = ({ dispatch }) => next => action => {
});
}

case ACTION_TYPES.INVOICE_EDIT: {
// Continue
next(action);
// Change Tab to Form
dispatch(UIActions.changeActiveTab('form'));
break;
}

case ACTION_TYPES.INVOICE_UPDATE: {
return updateDoc('invoices', action.payload.invoiceID, {
...action.payload.data,
subtotal: getInvoiceValue(action.payload.data).subtotal,
grandTotal: getInvoiceValue(action.payload.data).grandTotal,
})
.then(docs => {
next({
type: ACTION_TYPES.INVOICE_UPDATE,
payload: docs,
});
dispatch({
type: ACTION_TYPES.UI_NOTIFICATION_NEW,
payload: {
type: 'success',
message: 'Invoice Updated Successfully',
},
});
})
.catch(err => {
next({
type: ACTION_TYPES.UI_NOTIFICATION_NEW,
payload: {
type: 'warning',
message: err.message,
},
});
});
}

case ACTION_TYPES.INVOICE_DELETE: {
return deleteDoc('invoices', action.payload)
.then(remainingDocs => {
Expand Down
Loading