import React, { useState, useCallback, useEffect, useMemo } from 'react'; import { Button, Classes, FormGroup, InputGroup, Intent, TextArea, MenuItem, Checkbox, Position, } from '@blueprintjs/core'; import { Select } from '@blueprintjs/select'; import * as Yup from 'yup'; import { useFormik } from 'formik'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { omit } from 'lodash'; import { useQuery, queryCache } from 'react-query'; import Dialog from 'components/Dialog'; import AppToaster from 'components/AppToaster'; import AccountFormDialogContainer from 'containers/Dialogs/AccountFormDialog.container'; import classNames from 'classnames'; import Icon from 'components/Icon'; import ErrorMessage from 'components/ErrorMessage'; import { fetchAccountTypes } from 'store/accounts/accounts.actions'; import {ListSelect} from 'components'; function AccountFormDialog({ name, payload, isOpen, // #withAccounts accountsTypes, accounts, // #withAccountDetail account, // #withAccountsActions requestFetchAccounts, requestFetchAccountTypes, requestFetchAccount, requestSubmitAccount, requestEditAccount, // #withDialog closeDialog, }) { const { formatMessage } = useIntl(); const accountFormValidationSchema = Yup.object().shape({ name: Yup.string().required().label(formatMessage({id:'account_name_'})), code: Yup.number(), account_type_id: Yup.string() .nullable() .required().label(formatMessage({id:'account_type_id'})), description: Yup.string().trim() }); const initialValues = useMemo( () => ({ account_type_id: null, name: '', description: '', }), [] ); const [selectedAccountType, setSelectedAccountType] = useState(null); const [selectedSubaccount, setSelectedSubaccount] = useState( payload.action === 'new_child' ? accounts.find((a) => a.id === payload.id) : null ); const transformApiErrors = (errors) => { const fields = {}; if (errors.find((e) => e.type === 'NOT_UNIQUE_CODE')) { fields.code = 'Account code is not unqiue.'; } return fields; }; // Formik const formik = useFormik({ enableReinitialize: true, initialValues: { ...(payload.action === 'edit' && account ? account : initialValues), }, validationSchema: accountFormValidationSchema, onSubmit: (values, { setSubmitting, setErrors }) => { const exclude = ['subaccount']; const toastAccountName = (values.code) ? `${values.code} - ${values.name}` : values.name; if (payload.action === 'edit') { requestEditAccount({ payload: payload.id, form: { ...omit(values, [...exclude, 'account_type_id']) } }).then((response) => { closeDialog(name); AppToaster.show({ message: formatMessage({ id: 'service_has_been_successful_edited', }, { name: toastAccountName, service: formatMessage({ id: 'account' }), }), intent: Intent.SUCCESS, }); }); } else { requestSubmitAccount({ form: { ...omit(values, exclude) } }).then((response) => { closeDialog(name); AppToaster.show({ message: formatMessage({ id: 'service_has_been_successful_created', }, { name: toastAccountName, service: formatMessage({ id: 'account' }), }), intent: Intent.SUCCESS, position: Position.BOTTOM, }); }); } }, }); const { errors, values, touched } = useMemo(() => formik, [formik]); // Set default account type. useEffect(() => { if (account && account.account_type_id) { const defaultType = accountsTypes.find( (t) => t.id === account.account_type_id ); defaultType && setSelectedAccountType(defaultType); } }, [account, accountsTypes]); // Filters accounts types items. const filterAccountTypeItems = (query, accountType, _index, exactMatch) => { const normalizedTitle = accountType.name.toLowerCase(); const normalizedQuery = query.toLowerCase(); if (exactMatch) { return normalizedTitle === normalizedQuery; } else { return normalizedTitle.indexOf(normalizedQuery) >= 0; } }; // Account type item of select filed. const accountTypeItem = (item, { handleClick, modifiers, query }) => { return ; }; // Account item of select accounts field. const accountItem = (item, { handleClick, modifiers, query }) => { return ( ); }; // Filters accounts items. const filterAccountsPredicater = useCallback( (query, account, _index, exactMatch) => { const normalizedTitle = account.name.toLowerCase(); const normalizedQuery = query.toLowerCase(); if (exactMatch) { return normalizedTitle === normalizedQuery; } else { return ( `${account.code} ${normalizedTitle}`.indexOf(normalizedQuery) >= 0 ); } }, [] ); // Handles dialog close. const handleClose = useCallback(() => { closeDialog(name); }, [closeDialog, name]); // Fetches accounts list. const fetchAccountsList = useQuery( 'accounts-list', () => requestFetchAccounts(), { manual: true } ); // Fetches accounts types. const fetchAccountsTypes = useQuery( 'accounts-types-list', async () => { await requestFetchAccountTypes(); }, { manual: true } ); // Fetch the given account id on edit mode. const fetchAccount = useQuery( payload.action === 'edit' && ['account', payload.id], (key, id) => requestFetchAccount(id), { manual: true } ); const isFetching = fetchAccountsList.isFetching || fetchAccountTypes.isFetching || fetchAccount.isFetching; // Fetch requests on dialog opening. const onDialogOpening = useCallback(() => { fetchAccountsList.refetch(); fetchAccountsTypes.refetch(); fetchAccount.refetch(); }, []); const onChangeAccountType = useCallback( (accountType) => { formik.setFieldValue('account_type_id', accountType.id); }, [setSelectedAccountType, formik] ); // Handles change sub-account. const onChangeSubaccount = useCallback( (account) => { setSelectedSubaccount(account); formik.setFieldValue('parent_account_id', account.id); }, [setSelectedSubaccount, formik] ); const onDialogClosed = useCallback(() => { formik.resetForm(); setSelectedSubaccount(null); setSelectedAccountType(null); }, [formik]); const infoIcon = useMemo(() => , []); const subAccountLabel = useMemo(() => { return ( ); }, []); const requiredSpan = useMemo(() => *, []); return ( : } className={{ 'dialog--loading': isFetching, 'dialog--account-form': true, }} autoFocus={true} canEscapeKeyClose={true} onClosed={onDialogClosed} onOpening={onDialogOpening} isOpen={isOpen} isLoading={isFetching} onClose={handleClose} >
} labelInfo={requiredSpan} className={classNames( 'form-group--account-type', 'form-group--select-list', Classes.FILL )} inline={true} helperText={} intent={ errors.account_type_id && touched.account_type_id && Intent.DANGER } > } itemRenderer={accountTypeItem} itemPredicate={filterAccountTypeItems} popoverProps={{ minimal: true }} onItemSelect={onChangeAccountType} selectedItem={formik.values.account_type_id} selectedItemProp={'id'} defaultText={} labelProp={'name'} buttonProps={{ disabled: payload.action === 'edit' }} /> } labelInfo={requiredSpan} className={'form-group--account-name'} intent={errors.name && touched.name && Intent.DANGER} helperText={} inline={true} > } className={'form-group--account-code'} intent={errors.code && touched.code && Intent.DANGER} helperText={} inline={true} labelInfo={infoIcon} > {values.subaccount && ( } className={classNames( 'form-group--parent-account', 'form-group--select-list', Classes.FILL )} inline={true} > )} } className={'form-group--description'} intent={formik.errors.description && Intent.DANGER} helperText={formik.errors.description && formik.errors.credential} inline={true} >