mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
refactoring: invoice form.
refactoring: receipt form. refactoring: bill form. refactoring: estimate form.
This commit is contained in:
@@ -83,7 +83,6 @@ export default function BillFloatingActions() {
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
type="submit"
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
text={<T id={'save_open'} />}
|
||||
/>
|
||||
@@ -116,7 +115,6 @@ export default function BillFloatingActions() {
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
type="submit"
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
@@ -150,7 +148,6 @@ export default function BillFloatingActions() {
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
type="submit"
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
|
||||
@@ -1,85 +1,51 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Formik, Form } from 'formik';
|
||||
import moment from 'moment';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import classNames from 'classnames';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { pick, sumBy, isEmpty, omit } from 'lodash';
|
||||
import { sumBy, isEmpty, omit } from 'lodash';
|
||||
import { CLASSES } from 'common/classes';
|
||||
|
||||
import { EditBillFormSchema, CreateBillFormSchema } from './BillForm.schema';
|
||||
import BillFormHeader from './BillFormHeader';
|
||||
import BillFloatingActions from './BillFloatingActions';
|
||||
import BillFormFooter from './BillFormFooter';
|
||||
import BillItemsEntriesEditor from './BillItemsEntriesEditor';
|
||||
|
||||
import { AppToaster } from 'components';
|
||||
|
||||
import { ERROR } from 'common/errors';
|
||||
import { repeatValue, orderingLinesIndexes } from 'utils';
|
||||
import BillFormBody from './BillFormBody';
|
||||
import { useBillFormContext } from './BillFormProvider';
|
||||
|
||||
const MIN_LINES_NUMBER = 5;
|
||||
|
||||
const defaultBill = {
|
||||
index: 0,
|
||||
item_id: '',
|
||||
rate: '',
|
||||
discount: 0,
|
||||
quantity: 1,
|
||||
description: '',
|
||||
};
|
||||
|
||||
const defaultInitialValues = {
|
||||
vendor_id: '',
|
||||
bill_number: '',
|
||||
bill_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
due_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
reference_no: '',
|
||||
note: '',
|
||||
open: '',
|
||||
entries: [...repeatValue(defaultBill, MIN_LINES_NUMBER)],
|
||||
};
|
||||
import { orderingLinesIndexes, safeSumBy } from 'utils';
|
||||
import { defaultBill, transformToEditForm } from './utils';
|
||||
|
||||
/**
|
||||
* Bill form.
|
||||
*/
|
||||
export default function BillForm({
|
||||
|
||||
}) {
|
||||
export default function BillForm() {
|
||||
const { formatMessage } = useIntl();
|
||||
const history = useHistory();
|
||||
|
||||
// Bill form context.
|
||||
const {
|
||||
bill,
|
||||
billId,
|
||||
isNewMode,
|
||||
submitPayload,
|
||||
createBillMutate,
|
||||
editBillMutate,
|
||||
} = useBillFormContext();
|
||||
|
||||
const isNewMode = !billId;
|
||||
|
||||
// Initial values in create and edit mode.
|
||||
const initialValues = useMemo(
|
||||
() => ({
|
||||
...(!isEmpty(bill)
|
||||
? {
|
||||
...pick(bill, Object.keys(defaultInitialValues)),
|
||||
entries: [
|
||||
...bill.entries.map((bill) => ({
|
||||
...pick(bill, Object.keys(defaultBill)),
|
||||
})),
|
||||
...repeatValue(
|
||||
defaultBill,
|
||||
Math.max(MIN_LINES_NUMBER - bill.entries.length, 0),
|
||||
),
|
||||
],
|
||||
...transformToEditForm(bill),
|
||||
}
|
||||
: {
|
||||
...defaultInitialValues,
|
||||
entries: orderingLinesIndexes(defaultInitialValues.entries),
|
||||
...defaultBill,
|
||||
entries: orderingLinesIndexes(defaultBill.entries),
|
||||
}),
|
||||
}),
|
||||
[bill],
|
||||
@@ -102,7 +68,7 @@ export default function BillForm({
|
||||
const entries = values.entries.filter(
|
||||
(item) => item.item_id && item.quantity,
|
||||
);
|
||||
const totalQuantity = sumBy(entries, (entry) => parseInt(entry.quantity));
|
||||
const totalQuantity = safeSumBy(entries, (entry) => entry.quantity);
|
||||
|
||||
if (totalQuantity === 0) {
|
||||
AppToaster.show({
|
||||
@@ -146,10 +112,10 @@ export default function BillForm({
|
||||
handleErrors(errors, { setErrors });
|
||||
setSubmitting(false);
|
||||
};
|
||||
if (bill && bill.id) {
|
||||
editBillMutate(bill.id, form).then(onSuccess).catch(onError);
|
||||
} else {
|
||||
if (isNewMode) {
|
||||
createBillMutate(form).then(onSuccess).catch(onError);
|
||||
} else {
|
||||
editBillMutate([bill.id, form]).then(onSuccess).catch(onError);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,7 +134,7 @@ export default function BillForm({
|
||||
>
|
||||
<Form>
|
||||
<BillFormHeader />
|
||||
<BillFormBody defaultBill={defaultBill} />
|
||||
<BillItemsEntriesEditor />
|
||||
<BillFormFooter />
|
||||
<BillFloatingActions />
|
||||
</Form>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { useBillFormContext } from './BillFormProvider';
|
||||
|
||||
export default function BillFormBody({ defaultBill }) {
|
||||
const { items } = useBillFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -16,22 +16,15 @@ import {
|
||||
tansformDateValue,
|
||||
handleDateChange,
|
||||
inputIntent,
|
||||
saveInvoke,
|
||||
} from 'utils';
|
||||
|
||||
/**
|
||||
* Fill form header.
|
||||
*/
|
||||
function BillFormHeader({
|
||||
onBillNumberChanged,
|
||||
}) {
|
||||
function BillFormHeader() {
|
||||
// Bill form context.
|
||||
const { vendors } = useBillFormContext();
|
||||
|
||||
const handleBillNumberBlur = (event) => {
|
||||
saveInvoke(onBillNumberChanged, event.currentTarget.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
{/* ------- Vendor name ------ */}
|
||||
@@ -121,11 +114,7 @@ function BillFormHeader({
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="bill_number" />}
|
||||
>
|
||||
<InputGroup
|
||||
minimal={true}
|
||||
{...field}
|
||||
onBlur={handleBillNumberBlur}
|
||||
/>
|
||||
<InputGroup minimal={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
@@ -148,6 +137,4 @@ function BillFormHeader({
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withDialogActions,
|
||||
)(BillFormHeader);
|
||||
export default compose(withDialogActions)(BillFormHeader);
|
||||
|
||||
@@ -46,12 +46,15 @@ function BillFormProvider({ billId, ...props }) {
|
||||
const { mutateAsync: createBillMutate } = useCreateBill();
|
||||
const { mutateAsync: editBillMutate } = useEditBill();
|
||||
|
||||
const isNewMode = !billId;
|
||||
|
||||
const provider = {
|
||||
accounts,
|
||||
vendors,
|
||||
items,
|
||||
bill,
|
||||
submitPayload,
|
||||
isNewMode,
|
||||
|
||||
isSettingLoading,
|
||||
isBillLoading,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FastField } from 'formik';
|
||||
import { CLASSES } from 'common/classes';
|
||||
import { useBillFormContext } from './BillFormProvider';
|
||||
import ItemsEntriesTable from 'containers/Entries/ItemsEntriesTable';
|
||||
|
||||
export default function BillFormBody({ defaultBill }) {
|
||||
const { items } = useBillFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<FastField name={'entries'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<ItemsEntriesTable
|
||||
entries={value}
|
||||
onUpdateData={(entries) => {
|
||||
form.setFieldValue('entries', entries);
|
||||
}}
|
||||
items={items}
|
||||
errors={error}
|
||||
linesNumber={4}
|
||||
/>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
39
client/src/containers/Purchases/Bills/BillForm/utils.js
Normal file
39
client/src/containers/Purchases/Bills/BillForm/utils.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import moment from 'moment';
|
||||
import { transformToForm, repeatValue } from 'utils';
|
||||
|
||||
export const MIN_LINES_NUMBER = 4;
|
||||
|
||||
export const defaultBillEntry = {
|
||||
index: 0,
|
||||
item_id: '',
|
||||
rate: '',
|
||||
discount: 0,
|
||||
quantity: 1,
|
||||
description: '',
|
||||
};
|
||||
|
||||
export const defaultBill = {
|
||||
vendor_id: '',
|
||||
bill_number: '',
|
||||
bill_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
due_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||
reference_no: '',
|
||||
note: '',
|
||||
open: '',
|
||||
entries: [...repeatValue(defaultBillEntry, MIN_LINES_NUMBER)],
|
||||
};
|
||||
|
||||
export const transformToEditForm = (bill) => {
|
||||
return {
|
||||
...transformToForm(bill, defaultBill),
|
||||
entries: [
|
||||
...bill.entries.map((bill) => ({
|
||||
...transformToForm(bill, defaultBill.entries[0]),
|
||||
})),
|
||||
...repeatValue(
|
||||
defaultBill,
|
||||
Math.max(MIN_LINES_NUMBER - bill.entries.length, 0),
|
||||
),
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user