feat(webapp): allow to create a new account item in accounts list component.

This commit is contained in:
a.bouhuolia
2023-05-03 22:41:54 +02:00
parent a7d29a31c8
commit 981b65349d
9 changed files with 83 additions and 54 deletions

View File

@@ -3,8 +3,8 @@ import React, { useMemo } from 'react';
import { MenuItem } from '@blueprintjs/core'; import { MenuItem } from '@blueprintjs/core';
import { FMultiSelect } from '../Forms'; import { FMultiSelect } from '../Forms';
import { accountPredicate } from './_components'; import { accountPredicate } from './_components';
import { filterAccountsByQuery, nestedArrayToflatten } from '@/utils';
import { MenuItemNestedText } from '../Menu'; import { MenuItemNestedText } from '../Menu';
import { usePreprocessingAccounts } from './_hooks';
/** /**
* Default account item renderer of the list. * Default account item renderer of the list.
@@ -45,23 +45,13 @@ export function AccountsMultiSelect({
...rest ...rest
}) { }) {
// Filters accounts based on the given filter props. // Filters accounts based on filter props.
const filteredAccounts = useMemo(() => { const filteredAccounts = usePreprocessingAccounts(accounts, {
const flattenAccounts = nestedArrayToflatten(items);
return filterAccountsByQuery(flattenAccounts, {
filterByRootTypes,
filterByParentTypes, filterByParentTypes,
filterByTypes, filterByTypes,
filterByNormal, filterByNormal,
filterByRootTypes,
}); });
}, [
items,
filterByRootTypes,
filterByParentTypes,
filterByTypes,
filterByNormal,
]);
return ( return (
<FMultiSelect <FMultiSelect

View File

@@ -1,16 +1,12 @@
// @ts-nocheck // @ts-nocheck
import React, { useMemo } from 'react'; import React from 'react';
import * as R from 'ramda'; import * as R from 'ramda';
import intl from 'react-intl-universal'; import intl from 'react-intl-universal';
import { MenuItem } from '@blueprintjs/core'; import { MenuItem } from '@blueprintjs/core';
import { import { MenuItemNestedText, FSelect } from '@/components';
MenuItemNestedText,
FormattedMessage as T,
FSelect,
} from '@/components';
import { filterAccountsByQuery, nestedArrayToflatten } from '@/utils';
import { accountPredicate } from './_components'; import { accountPredicate } from './_components';
import withDialogActions from '@/containers/Dialog/withDialogActions'; import withDialogActions from '@/containers/Dialog/withDialogActions';
import { usePreprocessingAccounts } from './_hooks';
// Create new account renderer. // Create new account renderer.
const createNewItemRenderer = (query, active, handleClick) => { const createNewItemRenderer = (query, active, handleClick) => {
@@ -25,11 +21,7 @@ const createNewItemRenderer = (query, active, handleClick) => {
}; };
// Create new item from the given query string. // Create new item from the given query string.
const createNewItemFromQuery = (name) => { const createNewItemFromQuery = (name) => ({ name });
return {
name,
};
};
/** /**
* Default account item renderer. * Default account item renderer.
@@ -61,6 +53,7 @@ function AccountsSelectRoot({
// #ownProps // #ownProps
items, items,
allowCreate,
filterByParentTypes, filterByParentTypes,
filterByTypes, filterByTypes,
@@ -70,23 +63,17 @@ function AccountsSelectRoot({
...restProps ...restProps
}) { }) {
// Filters accounts based on filter props. // Filters accounts based on filter props.
const filteredAccounts = useMemo(() => { const filteredAccounts = usePreprocessingAccounts(items, {
const flattenAccounts = nestedArrayToflatten(items);
const filteredAccounts = filterAccountsByQuery(flattenAccounts, {
filterByRootTypes,
filterByParentTypes, filterByParentTypes,
filterByTypes, filterByTypes,
filterByNormal, filterByNormal,
filterByRootTypes,
}); });
return filteredAccounts; // Maybe inject new item props to select component.
}, [ const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null;
items, const maybeCreateNewItemFromQuery = allowCreate
filterByRootTypes, ? createNewItemFromQuery
filterByParentTypes, : null;
filterByTypes,
filterByNormal,
]);
return ( return (
<FSelect <FSelect
@@ -97,6 +84,8 @@ function AccountsSelectRoot({
popoverProps={{ minimal: true, usePortal: true, inline: false }} popoverProps={{ minimal: true, usePortal: true, inline: false }}
itemPredicate={accountPredicate} itemPredicate={accountPredicate}
itemRenderer={accountRenderer} itemRenderer={accountRenderer}
createNewItemRenderer={maybeCreateNewItemRenderer}
createNewItemFromQuery={maybeCreateNewItemFromQuery}
{...restProps} {...restProps}
/> />
); );

View File

@@ -1,7 +1,5 @@
// @ts-nocheck
import React from 'react'; import React from 'react';
import { MenuItem } from '@blueprintjs/core';
import { MenuItemNestedText } from '../Menu';
// Filters accounts items. // Filters accounts items.
export const accountPredicate = (query, account, _index, exactMatch) => { export const accountPredicate = (query, account, _index, exactMatch) => {

View File

@@ -0,0 +1,36 @@
import { useMemo } from 'react';
import { filterAccountsByQuery, nestedArrayToflatten } from '@/utils';
interface PreprocessingAccountsOptions {
filterByRootTypes: string[];
filterByParentTypes: string[];
filterByTypes: string[];
filterByNormal: string[];
}
export const usePreprocessingAccounts = (
items: any,
{
filterByRootTypes,
filterByParentTypes,
filterByTypes,
filterByNormal,
}: PreprocessingAccountsOptions,
) => {
return useMemo(() => {
const flattenAccounts = nestedArrayToflatten(items);
const filteredAccounts = filterAccountsByQuery(flattenAccounts, {
filterByRootTypes,
filterByParentTypes,
filterByTypes,
filterByNormal,
});
return filteredAccounts;
}, [
items,
filterByRootTypes,
filterByParentTypes,
filterByTypes,
filterByNormal,
]);
};

View File

@@ -1,15 +1,16 @@
// @ts-nocheck // @ts-nocheck
import React from 'react'; import React from 'react';
import styled from 'styled-components';
import clsx from 'classnames';
import { Button } from '@blueprintjs/core'; import { Button } from '@blueprintjs/core';
import { Select } from '@blueprintjs-formik/select'; import { Select } from '@blueprintjs-formik/select';
import styled from 'styled-components';
import clsx from 'classnames';
export function FSelect({ ...props }) { export function FSelect({ ...props }) {
const input = ({ activeItem, text, label, value }) => { const input = ({ activeItem, text, label, value }) => {
return ( return (
<SelectButton <SelectButton
text={text || props.placeholder || 'Select an item ...'} text={text || props.placeholder || 'Select an item ...'}
disabled={props.disabled || false}
{...props.buttonProps} {...props.buttonProps}
className={clsx({ 'is-selected': !!text }, props.className)} className={clsx({ 'is-selected': !!text }, props.className)}
/> />
@@ -45,7 +46,6 @@ const SelectButton = styled(Button)`
margin-right: 12px; margin-right: 12px;
border-radius: 1px; border-radius: 1px;
} }
&:not([class*='bp3-intent-']) { &:not([class*='bp3-intent-']) {
&, &,
&:hover { &:hover {

View File

@@ -120,6 +120,7 @@ function AccountFormDialogFields({
buttonProps={{ disabled: !values.subaccount }} buttonProps={{ disabled: !values.subaccount }}
fastField={true} fastField={true}
fill={true} fill={true}
allowCreate={true}
/> />
</FFormGroup> </FFormGroup>
)} )}

View File

@@ -101,6 +101,7 @@ function ItemFormBody({ organization: { base_currency } }) {
items={accounts} items={accounts}
sellable={values.sellable} sellable={values.sellable}
shouldUpdate={sellAccountFieldShouldUpdate} shouldUpdate={sellAccountFieldShouldUpdate}
fastField={true}
> >
<AccountsSelect <AccountsSelect
name={'sell_account_id'} name={'sell_account_id'}
@@ -110,6 +111,7 @@ function ItemFormBody({ organization: { base_currency } }) {
filterByParentTypes={[ACCOUNT_PARENT_TYPE.INCOME]} filterByParentTypes={[ACCOUNT_PARENT_TYPE.INCOME]}
fill={true} fill={true}
allowCreate={true} allowCreate={true}
fastField={true}
/> />
</FFormGroup> </FFormGroup>

View File

@@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import intl from 'react-intl-universal'; import intl from 'react-intl-universal';
import { Form, FastField, useFormikContext } from 'formik'; import { Form, FastField, useFormikContext } from 'formik';
import styled from 'styled-components';
import { import {
FormGroup, FormGroup,
RadioGroup, RadioGroup,
@@ -21,7 +22,6 @@ import {
} from '@/components'; } from '@/components';
import { handleStringChange, inputIntent } from '@/utils'; import { handleStringChange, inputIntent } from '@/utils';
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/constants/accountTypes'; import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/constants/accountTypes';
import { useAccountantFormContext } from './AccountantFormProvider'; import { useAccountantFormContext } from './AccountantFormProvider';
/** /**
@@ -118,7 +118,7 @@ export default function AccountantForm() {
</FastField> </FastField>
{/* ----------- Deposit customer account ----------- */} {/* ----------- Deposit customer account ----------- */}
<FFormGroup <AccountantFormGroup
name={'preferred_deposit_account'} name={'preferred_deposit_account'}
label={ label={
<strong> <strong>
@@ -133,6 +133,7 @@ export default function AccountantForm() {
/> />
} }
labelInfo={<FieldRequiredHint />} labelInfo={<FieldRequiredHint />}
fastField={true}
> >
<AccountsSelect <AccountsSelect
name={'preferred_deposit_account'} name={'preferred_deposit_account'}
@@ -143,11 +144,12 @@ export default function AccountantForm() {
ACCOUNT_TYPE.BANK, ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET, ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]} ]}
fastField={true}
/> />
</FFormGroup> </AccountantFormGroup>
{/* ----------- Withdrawal vendor account ----------- */} {/* ----------- Withdrawal vendor account ----------- */}
<FFormGroup <AccountantFormGroup
name={'withdrawal_account'} name={'withdrawal_account'}
label={ label={
<strong> <strong>
@@ -162,6 +164,7 @@ export default function AccountantForm() {
/> />
} }
labelInfo={<FieldRequiredHint />} labelInfo={<FieldRequiredHint />}
fastField={true}
> >
<AccountsSelect <AccountsSelect
name={'withdrawal_account'} name={'withdrawal_account'}
@@ -172,11 +175,12 @@ export default function AccountantForm() {
ACCOUNT_TYPE.BANK, ACCOUNT_TYPE.BANK,
ACCOUNT_TYPE.OTHER_CURRENT_ASSET, ACCOUNT_TYPE.OTHER_CURRENT_ASSET,
]} ]}
fastField={true}
/> />
</FFormGroup> </AccountantFormGroup>
{/* ----------- Withdrawal customer account ----------- */} {/* ----------- Withdrawal customer account ----------- */}
<FFormGroup <AccountantFormGroup
name={'preferred_advance_deposit'} name={'preferred_advance_deposit'}
label={ label={
<strong> <strong>
@@ -191,14 +195,16 @@ export default function AccountantForm() {
/> />
} }
labelInfo={<FieldRequiredHint />} labelInfo={<FieldRequiredHint />}
fastField={true}
> >
<AccountsSelect <AccountsSelect
name={'preferred_advance_deposit'} name={'preferred_advance_deposit'}
items={accounts} items={accounts}
placeholder={<T id={'select_payment_account'} />} placeholder={<T id={'select_payment_account'} />}
filterByParentTypes={[ACCOUNT_PARENT_TYPE.CURRENT_ASSET]} filterByParentTypes={[ACCOUNT_PARENT_TYPE.CURRENT_ASSET]}
fastField={true}
/> />
</FFormGroup> </AccountantFormGroup>
<CardFooterActions> <CardFooterActions>
<Button intent={Intent.PRIMARY} loading={isSubmitting} type="submit"> <Button intent={Intent.PRIMARY} loading={isSubmitting} type="submit">
@@ -211,3 +217,7 @@ export default function AccountantForm() {
</Form> </Form>
); );
} }
const AccountantFormGroup = styled(FFormGroup)`
width: 450px;
`;

View File

@@ -131,6 +131,7 @@ function ReceiptFormHeader({
labelInfo={<FieldRequiredHint />} labelInfo={<FieldRequiredHint />}
name={'deposit_account_id'} name={'deposit_account_id'}
items={accounts} items={accounts}
fastField={true}
shouldUpdate={accountsFieldShouldUpdate} shouldUpdate={accountsFieldShouldUpdate}
> >
<AccountsSelect <AccountsSelect
@@ -144,6 +145,8 @@ function ReceiptFormHeader({
]} ]}
allowCreate={true} allowCreate={true}
fill={true} fill={true}
fastField={true}
shouldUpdate={accountsFieldShouldUpdate}
/> />
</FFormGroup> </FFormGroup>