refactoring: account form.

refactoring: expense form.
refactoring: manual journal form.
refactoring: invoice form.
This commit is contained in:
a.bouhuolia
2021-02-15 12:03:47 +02:00
parent 692f3b333a
commit 760c38b54b
124 changed files with 2694 additions and 2967 deletions

View File

@@ -0,0 +1,27 @@
import React from 'react';
import { AccountDialogProvider } from './AccountDialogProvider';
import AccountDialogForm from './AccountDialogForm';
/**
* Account dialog content.
*/
export default function AccountDialogContent({
dialogName,
accountId,
action,
parentAccountId,
accountType,
}) {
return (
<AccountDialogProvider
dialogName={dialogName}
accountId={accountId}
action={action}
parentAccountId={parentAccountId}
accountType={accountType}
>
<AccountDialogForm />
</AccountDialogProvider>
);
}

View File

@@ -3,27 +3,20 @@ import { Intent } from '@blueprintjs/core';
import { Formik } from 'formik';
import { useIntl } from 'react-intl';
import { omit } from 'lodash';
import { AppToaster, DialogContent } from 'components';
import { AppToaster } from 'components';
import AccountFormDialogFields from './AccountFormDialogFields';
import AccountDialogFormContent from './AccountDialogFormContent';
import withDialogActions from 'containers/Dialog/withDialogActions';
import {
EditAccountFormSchema,
CreateAccountFormSchema,
} from './AccountForm.schema';
import {
useAccounts,
useAccountsTypes,
useCreateAccount,
useAccount,
useEditAccount
} from 'hooks/query';
import { compose, transformToForm } from 'utils';
import { transformApiErrors, transformAccountToForm } from './utils';
import 'style/pages/Accounts/AccountFormDialog.scss';
import { useAccountDialogContext } from './AccountDialogProvider';
// Default initial form values.
const defaultInitialValues = {
@@ -41,43 +34,28 @@ const defaultInitialValues = {
function AccountFormDialogContent({
// #withDialogActions
closeDialog,
// #ownProp
dialogName,
accountId,
action,
parentAccountId,
accountType,
}) {
const { formatMessage } = useIntl();
const isNewMode = !accountId;
// Account form context.
const {
editAccountMutate,
createAccountMutate,
account,
accountId,
action,
parentAccountId,
accountType,
isNewMode,
dialogName
} = useAccountDialogContext();
// Form validation schema in create and edit mode.
const validationSchema = isNewMode
? CreateAccountFormSchema
: EditAccountFormSchema;
const { mutateAsync: createAccountMutate } = useCreateAccount();
const { mutateAsync: editAccountMutate } = useEditAccount();
// Fetches accounts list.
const {
data: accounts,
isLoading: isAccountsLoading,
} = useAccounts();
// Fetches accounts types.
const {
data: accountsTypes,
isLoading: isAccountsTypesLoading
} = useAccountsTypes();
// Fetches the specific account details.
const {
data: account,
isLoading: isAccountLoading,
} = useAccount(accountId, { enabled: !!accountId });
// Callbacks handles form submit.
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
const form = omit(values, ['subaccount']);
@@ -106,18 +84,22 @@ function AccountFormDialogContent({
};
// Handle request error.
const handleError = (error) => {
const { response: { data: { errors } } } = error;
const {
response: {
data: { errors },
},
} = error;
const errorsTransformed = transformApiErrors(errors);
setErrors({ ...errorsTransformed });
setSubmitting(false);
};
if (accountId) {
editAccountMutate(accountId, form)
editAccountMutate([accountId, form]).then(handleSuccess).catch(handleError);
} else {
createAccountMutate({ ...form })
.then(handleSuccess)
.catch(handleError);
} else {
createAccountMutate({ ...form }).then(handleSuccess).catch(handleError);
}
};
@@ -144,30 +126,19 @@ function AccountFormDialogContent({
closeDialog(dialogName);
}, [closeDialog, dialogName]);
const isFetching =
isAccountsLoading ||
isAccountsTypesLoading ||
isAccountLoading;
return (
<DialogContent isLoading={isFetching}>
<Formik
validationSchema={validationSchema}
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
<AccountFormDialogFields
accounts={accounts}
accountsTypes={accountsTypes}
dialogName={dialogName}
action={action}
onClose={handleClose}
/>
</Formik>
</DialogContent>
<Formik
validationSchema={validationSchema}
initialValues={initialValues}
onSubmit={handleFormSubmit}
>
<AccountDialogFormContent
dialogName={dialogName}
action={action}
onClose={handleClose}
/>
</Formik>
);
}
export default compose(
withDialogActions,
)(AccountFormDialogContent);
export default compose(withDialogActions)(AccountFormDialogContent);

View File

@@ -23,6 +23,7 @@ import withAccounts from 'containers/Accounts/withAccounts';
import { inputIntent } from 'utils';
import { compose } from 'redux';
import { useAutofocus } from 'hooks';
import { useAccountDialogContext } from './AccountDialogProvider';
/**
* Account form dialogs fields.
@@ -31,12 +32,13 @@ function AccountFormDialogFields({
// #ownProps
onClose,
action,
accounts,
accountsTypes,
}) {
const { values, isSubmitting } = useFormikContext();
const accountNameFieldRef = useAutofocus();
// Account form context.
const { accounts, accountsTypes } = useAccountDialogContext();
return (
<Form>
<div className={Classes.DIALOG_BODY}>

View File

@@ -0,0 +1,75 @@
import React, { createContext, useContext } from 'react';
import { DialogContent } from 'components';
import {
useCreateAccount,
useAccountsTypes,
useAccount,
useAccounts,
useEditAccount,
} from 'hooks/query';
const AccountDialogContext = createContext();
/**
* Account form provider.
*/
function AccountDialogProvider({
accountId,
parentAccountId,
action,
accountType,
dialogName,
...props
}) {
// Create and edit account mutations.
const { mutateAsync: createAccountMutate } = useCreateAccount();
const { mutateAsync: editAccountMutate } = useEditAccount();
// Fetches accounts list.
const { data: accounts, isLoading: isAccountsLoading } = useAccounts();
// Fetches accounts types.
const {
data: accountsTypes,
isLoading: isAccountsTypesLoading,
} = useAccountsTypes();
// Fetches the specific account details.
const { data: account, isLoading: isAccountLoading } = useAccount(accountId, {
enabled: !!accountId,
});
const isNewMode = !accountId;
// Provider payload.
const provider = {
dialogName,
accountId,
parentAccountId,
action,
accountType,
createAccountMutate,
editAccountMutate,
accounts,
accountsTypes,
account,
isAccountsLoading,
isNewMode
};
const isLoading =
isAccountsLoading || isAccountsTypesLoading || isAccountLoading;
return (
<DialogContent isLoading={isLoading}>
<AccountDialogContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useAccountDialogContext = () => useContext(AccountDialogContext);
export { AccountDialogProvider, useAccountDialogContext };

View File

@@ -4,7 +4,7 @@ import { Dialog, DialogSuspense } from 'components';
import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
const AccountFormDialogContent = lazy(() => import('./AccountFormDialogContent'));
const AccountDialogContent = lazy(() => import('./AccountDialogContent'));
/**
* Account form dialog.
@@ -28,7 +28,7 @@ function AccountFormDialog({
isOpen={isOpen}
>
<DialogSuspense>
<AccountFormDialogContent
<AccountDialogContent
dialogName={dialogName}
accountId={payload.id}
action={payload.action}

View File

@@ -1,7 +1,7 @@
import React, { useCallback } from 'react';
import { DialogContent } from 'components';
import { useQuery, queryCache } from 'react-query';
import { useSaveSettings } from 'hooks/query';
import { InvoiceNumberDialogProvider } from './InvoiceNumberDialogProvider';
import ReferenceNumberForm from 'containers/JournalNumber/ReferenceNumberForm';
import withDialogActions from 'containers/Dialog/withDialogActions';
@@ -19,52 +19,41 @@ function InvoiceNumberDialogContent({
// #withSettings
nextNumber,
numberPrefix,
// #withSettingsActions
requestFetchOptions,
requestSubmitOptions,
// #withDialogActions
closeDialog,
// #withInvoicesActions
// setInvoiceNumberChanged,
}) {
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
const { mutateAsync: saveSettings } = useSaveSettings();
const handleSubmitForm = (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => {
return { key: option.key, ...option, group: 'sales_invoices' };
});
requestSubmitOptions({ options })
saveSettings({ options })
.then(() => {
setSubmitting(false);
closeDialog('invoice-number-form');
setTimeout(() => {
queryCache.invalidateQueries('settings');
// setInvoiceNumberChanged(true);
}, 250);
})
.catch(() => {
setSubmitting(false);
});
};
// Handle the dialog close.
const handleClose = useCallback(() => {
closeDialog('invoice-number-form');
}, [closeDialog]);
return (
<DialogContent isLoading={fetchSettings.isFetching}>
<InvoiceNumberDialogProvider>
<ReferenceNumberForm
initialNumber={nextNumber}
initialPrefix={numberPrefix}
onSubmit={handleSubmitForm}
onClose={handleClose}
/>
</DialogContent>
</InvoiceNumberDialogProvider>
);
}

View File

@@ -0,0 +1,28 @@
import React, { createContext, useContext } from 'react';
import { DialogContent } from 'components';
import { useSettings } from 'hooks/query';
const InvoiceNumberDialogContext = createContext();
/**
* Invoice number dialog provider.
*/
function InvoiceNumberDialogProvider({ query, ...props }) {
const { isLoading } = useSettings();
// Provider payload.
const provider = {
};
return (
<DialogContent isLoading={isLoading}>
<InvoiceNumberDialogContext.Provider value={provider} {...props} />
</DialogContent>
);
}
const useInvoiceNumberDialogContext = () =>
useContext(InvoiceNumberDialogContext);
export { InvoiceNumberDialogProvider, useInvoiceNumberDialogContext };

View File

@@ -43,10 +43,6 @@ function JournalNumberDialogContent({
setSubmitting(false);
closeDialog('journal-number-form');
setTimeout(() => {
queryCache.invalidateQueries('settings');
// setJournalNumberChanged(true);
}, 250);
}).catch(() => {
setSubmitting(false);
});