diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurencyFormDialogContent.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurencyFormDialogContent.js
deleted file mode 100644
index 84e4046ec..000000000
--- a/client/src/containers/Dialogs/CurrencyFormDialog/CurencyFormDialogContent.js
+++ /dev/null
@@ -1,200 +0,0 @@
-import React, { useMemo, useCallback } from 'react';
-import {
- Button,
- Classes,
- FormGroup,
- InputGroup,
- Intent,
-} from '@blueprintjs/core';
-import * as Yup from 'yup';
-import { useFormik } from 'formik';
-import { useQuery, queryCache } from 'react-query';
-import { FormattedMessage as T, useIntl } from 'react-intl';
-import { pick } from 'lodash';
-import {
- ErrorMessage,
- AppToaster,
- FieldRequiredHint,
- DialogContent,
-} from 'components';
-
-import withDialogActions from 'containers/Dialog/withDialogActions';
-import withCurrencyDetail from 'containers/Currencies/withCurrencyDetail';
-import withCurrenciesActions from 'containers/Currencies/withCurrenciesActions';
-
-import { compose } from 'utils';
-
-import 'style/pages/Currency/CurrencyFormDialog.scss'
-
-function CurencyFormDialogContent({
- // #withCurrencyDetail
- currency,
-
- // #wihtCurrenciesActions
- requestFetchCurrencies,
- requestSubmitCurrencies,
- requestEditCurrency,
-
- // #withDialogActions
- closeDialog,
-
- // #ownProp
- action,
- currencyId,
- dialogName,
-}) {
- const { formatMessage } = useIntl();
- const fetchCurrencies = useQuery('currencies', () =>
- requestFetchCurrencies(),
- );
-
- const validationSchema = Yup.object().shape({
- currency_name: Yup.string()
- .required()
- .label(formatMessage({ id: 'currency_name_' })),
- currency_code: Yup.string()
- .max(4)
- .required()
- .label(formatMessage({ id: 'currency_code_' })),
- });
- const initialValues = useMemo(
- () => ({
- currency_name: '',
- currency_code: '',
- }),
- [],
- );
- const {
- values,
- errors,
- touched,
- isSubmitting,
- getFieldProps,
- handleSubmit,
- resetForm,
- } = useFormik({
- enableReinitialize: true,
- initialValues: {
- ...(action === 'edit' && pick(currency, Object.keys(initialValues))),
- },
- validationSchema: validationSchema,
- onSubmit: (values, { setSubmitting }) => {
- if (action === 'edit') {
- requestEditCurrency(currency.id, values)
- .then((response) => {
- closeDialog(dialogName);
- AppToaster.show({
- message: formatMessage({
- id: 'the_currency_has_been_edited_successfully',
- }),
- intent: Intent.SUCCESS,
- });
- setSubmitting(false);
- queryCache.invalidateQueries('currencies');
- })
- .catch((error) => {
- setSubmitting(false);
- });
- } else {
- requestSubmitCurrencies(values)
- .then((response) => {
- closeDialog(dialogName);
- AppToaster.show({
- message: formatMessage({
- id: 'the_currency_has_been_created_successfully',
- }),
- intent: Intent.SUCCESS,
- });
- setSubmitting(false);
- queryCache.invalidateQueries('currencies');
- })
- .catch((error) => {
- setSubmitting(false);
- });
- }
- },
- });
- const handleClose = useCallback(() => {
- closeDialog(dialogName);
- }, [dialogName, closeDialog]);
-
- const onDialogOpening = useCallback(() => {
- fetchCurrencies.refetch();
- }, [fetchCurrencies]);
-
- const onDialogClosed = useCallback(() => {
- resetForm();
- closeDialog(dialogName);
- }, [closeDialog, dialogName, resetForm]);
-
- return (
-
-
-
- );
-}
-
-export default compose(
- withCurrencyDetail,
- withDialogActions,
- withCurrenciesActions,
-)(CurencyFormDialogContent);
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.js
new file mode 100644
index 000000000..440802aed
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.js
@@ -0,0 +1,97 @@
+import React, { useMemo, useCallback } from 'react';
+import { Intent } from '@blueprintjs/core';
+import { Formik } from 'formik';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import { AppToaster } from 'components';
+import { pick } from 'lodash';
+import CurrencyFormContent from './CurrencyFormContent';
+
+import { useCurrencyFormContext } from './CurrencyFormProvider';
+import {
+ CreateCurrencyFormSchema,
+ EditCurrencyFormSchema,
+} from './CurrencyForm.schema';
+import withDialogActions from 'containers/Dialog/withDialogActions';
+
+import { compose, transformToForm } from 'utils';
+
+const defaultInitialValues = {
+ currency_name: '',
+ currency_code: '',
+};
+
+/**
+ * Currency form.
+ */
+function CurrencyForm({
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { formatMessage } = useIntl();
+
+ const {
+ createCurrencyMutate,
+ editCurrencyMutate,
+ dialogName,
+ currency,
+ isEditMode,
+ } = useCurrencyFormContext();
+
+ // Form validation schema in create and edit mode.
+ const validationSchema = isEditMode
+ ? EditCurrencyFormSchema
+ : CreateCurrencyFormSchema;
+
+ const initialValues = useMemo(
+ () => ({
+ ...defaultInitialValues,
+ // ...(isEditMode && pick(currency, Object.keys(defaultInitialValues))),
+ ...transformToForm(currency, defaultInitialValues),
+ }),
+ [],
+ );
+
+ // Handles the form submit.
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ setSubmitting(true);
+
+ // Handle close the dialog after success response.
+ const afterSubmit = () => {
+ closeDialog(dialogName);
+ };
+
+ const onSuccess = ({ response }) => {
+ AppToaster.show({
+ message: formatMessage({
+ id: isEditMode
+ ? 'the_currency_has_been_edited_successfully'
+ : 'the_currency_has_been_created_successfully',
+ }),
+ intent: Intent.SUCCESS,
+ });
+ afterSubmit(response);
+ };
+
+ // Handle the response error.
+ const onError = (errors) => {
+ setSubmitting(false);
+ };
+ if (isEditMode) {
+ editCurrencyMutate([currency.id, values]).then(onSuccess).catch(onError);
+ } else {
+ createCurrencyMutate(values).then(onSuccess).catch(onError);
+ }
+ };
+
+ return (
+
+
+
+ );
+}
+
+export default compose(withDialogActions)(CurrencyForm);
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.schema.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.schema.js
new file mode 100644
index 000000000..31c6dfe8b
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyForm.schema.js
@@ -0,0 +1,16 @@
+import * as Yup from 'yup';
+import { formatMessage } from 'services/intl';
+import { DATATYPES_LENGTH } from 'common/dataTypes';
+
+const Schema = Yup.object().shape({
+ currency_name: Yup.string()
+ .required()
+ .label(formatMessage({ id: 'currency_name_' })),
+ currency_code: Yup.string()
+ .max(4)
+ .required()
+ .label(formatMessage({ id: 'currency_code_' })),
+});
+
+export const CreateCurrencyFormSchema = Schema;
+export const EditCurrencyFormSchema = Schema;
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormContent.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormContent.js
new file mode 100644
index 000000000..8b70d2add
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormContent.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import { Form } from 'formik';
+
+import CurrencyFormFields from './CurrencyFormFields';
+import CurrencyFormFooter from './CurrencyFormFooter';
+
+export default function CurrencyFormContent() {
+ return (
+
+ );
+}
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormDialogContent.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormDialogContent.js
new file mode 100644
index 000000000..439e16a71
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormDialogContent.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import { CurrencyFormProvider } from './CurrencyFormProvider';
+import { pick } from 'lodash';
+
+import CurrencyForm from './CurrencyForm';
+import withCurrencyDetail from 'containers/Currencies/withCurrencyDetail';
+
+import { compose } from 'utils';
+import 'style/pages/Currency/CurrencyFormDialog.scss';
+
+function CurrencyFormDialogContent({
+ // #ownProp
+ action,
+ currency,
+ dialogName,
+}) {
+ return (
+
+
+
+ );
+}
+
+export default compose(withCurrencyDetail)(CurrencyFormDialogContent);
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js
new file mode 100644
index 000000000..31f10bed2
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFields.js
@@ -0,0 +1,62 @@
+import React, { useMemo, useCallback } from 'react';
+import {
+ Button,
+ Classes,
+ FormGroup,
+ InputGroup,
+ Intent,
+} from '@blueprintjs/core';
+import { Form, useFormikContext, FastField } from 'formik';
+import { FormattedMessage as T, useIntl } from 'react-intl';
+import { pick } from 'lodash';
+import {
+ ErrorMessage,
+ AppToaster,
+ FieldRequiredHint,
+ DialogContent,
+} from 'components';
+
+import { useAutofocus } from 'hooks';
+import { inputIntent } from 'utils';
+
+export default function CurrencyFormFields() {
+ const currencyNameFieldRef = useAutofocus();
+
+ return (
+
+ {/* ----------- Currency name ----------- */}
+
+ {({ field, field: { value }, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ className={'form-group--currency-name'}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ inline={true}
+ >
+ (currencyNameFieldRef.current = ref)}
+ {...field}
+ />
+
+ )}
+
+ {/* ----------- Currency Code ----------- */}
+
+ {({ field, field: { value }, meta: { error, touched } }) => (
+ }
+ labelInfo={}
+ className={'form-group--currency-code'}
+ intent={inputIntent({ error, touched })}
+ helperText={}
+ inline={true}
+ >
+
+
+ )}
+
+
+ );
+}
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFooter.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFooter.js
new file mode 100644
index 000000000..5191bbb5b
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormFooter.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useFormikContext } from 'formik';
+import { useCurrencyFormContext } from './CurrencyFormProvider';
+
+import { Button, Classes, Intent } from '@blueprintjs/core';
+import { FormattedMessage as T } from 'react-intl';
+
+import withDialogActions from 'containers/Dialog/withDialogActions';
+import { compose } from 'utils';
+
+function CurrencyFormFooter({
+ // #withDialogActions
+ closeDialog,
+}) {
+ const { isSubmitting } = useFormikContext();
+
+ const { dialogName, isEditMode } = useCurrencyFormContext();
+
+ const handleClose = () => {
+ closeDialog(dialogName);
+ };
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+export default compose(withDialogActions)(CurrencyFormFooter);
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js
new file mode 100644
index 000000000..6098b5649
--- /dev/null
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/CurrencyFormProvider.js
@@ -0,0 +1,38 @@
+import React, { createContext } from 'react';
+import { useCurrencies, useEditCurrency, useCreateCurrency } from 'hooks/query';
+import { DialogContent } from 'components';
+
+const CurrencyFormContext = createContext();
+
+/**
+ * Currency Form page provider.
+ */
+
+function CurrencyFormProvider({ isEditMode, currency, dialogName, ...props }) {
+ // Create and edit item currency mutations.
+ const { mutateAsync: createCurrencyMutate } = useCreateCurrency();
+ const { mutateAsync: editCurrencyMutate } = useEditCurrency();
+
+ // fetch Currencies list.
+ const { data: currencies, isFetching: isCurrenciesLoading } = useCurrencies();
+
+ // Provider state.
+ const provider = {
+ createCurrencyMutate,
+ editCurrencyMutate,
+ dialogName,
+ currency,
+ isCurrenciesLoading,
+ isEditMode,
+ };
+
+ return (
+
+
+
+ );
+}
+
+const useCurrencyFormContext = () => React.useContext(CurrencyFormContext);
+
+export { CurrencyFormProvider, useCurrencyFormContext };
diff --git a/client/src/containers/Dialogs/CurrencyFormDialog/index.js b/client/src/containers/Dialogs/CurrencyFormDialog/index.js
index 19a1a82fc..f97747430 100644
--- a/client/src/containers/Dialogs/CurrencyFormDialog/index.js
+++ b/client/src/containers/Dialogs/CurrencyFormDialog/index.js
@@ -5,7 +5,7 @@ import withDialogRedux from 'components/DialogReduxConnect';
import { compose } from 'utils';
const CurrencyFormDialogContent = lazy(() =>
- import('./CurencyFormDialogContent'),
+ import('./CurrencyFormDialogContent'),
);
/**
diff --git a/client/src/hooks/query/currencies.js b/client/src/hooks/query/currencies.js
index 47a6e3ef5..4dc2cac46 100644
--- a/client/src/hooks/query/currencies.js
+++ b/client/src/hooks/query/currencies.js
@@ -25,7 +25,7 @@ export function useCreateCurrency(props) {
export function useEditCurrency(props) {
const queryClient = useQueryClient();
- return useMutation((currencyCode, values) =>
+ return useMutation(([currencyCode, values]) =>
ApiService.post(`currencies/${currencyCode}`, values),
{
onSuccess: () => {