feat(webapp): bank rule form

This commit is contained in:
Ahmed Bouhuolia
2024-06-25 17:31:32 +02:00
parent dad8aeaff1
commit f1f52ce972
7 changed files with 239 additions and 61 deletions

View File

@@ -1,5 +1,7 @@
import React, { createContext } from 'react';
import { DialogContent } from '@/components';
import { useBankRule } from '@/hooks/query/bank-rules';
import { useAccounts } from '@/hooks/query';
interface RuleFormBootValues {
bankRule?: null;
@@ -17,10 +19,25 @@ interface RuleFormBootProps {
}
function RuleFormBoot({ bankRuleId, ...props }: RuleFormBootProps) {
const provider = {} as RuleFormBootValues;
const { data: bankRule, isLoading: isBankRuleLoading } = useBankRule(
bankRuleId as number,
{
enabled: !!bankRuleId,
},
);
const { data: accounts, isLoading: isAccountsLoading } = useAccounts({}, {});
const provider = {
bankRule,
accounts,
isBankRuleLoading,
isAccountsLoading,
} as RuleFormBootValues;
const isLoading = isBankRuleLoading || isAccountsLoading;
return (
<DialogContent isLoading={false}>
<DialogContent isLoading={isLoading}>
<RuleFormBootContext.Provider value={provider} {...props} />
</DialogContent>
);

View File

@@ -11,10 +11,8 @@ export default function RuleFormContent({
bankRuleId,
}: RuleFormContentProps) {
return (
<div>
<RuleFormBoot bankRuleId={bankRuleId}>
<RuleFormContentForm />
</RuleFormBoot>
</div>
<RuleFormBoot bankRuleId={bankRuleId}>
<RuleFormContentForm />
</RuleFormBoot>
);
}

View File

@@ -1,7 +1,11 @@
import { Form, Formik, useFormikContext } from 'formik';
// @ts-nocheck
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import { Button, Classes, Intent, Radio } from '@blueprintjs/core';
import * as R from 'ramda';
import { CreateRuleFormSchema } from './RuleFormContentForm.schema';
import {
AccountsSelect,
AppToaster,
Box,
FFormGroup,
FInputGroup,
@@ -9,42 +13,57 @@ import {
FSelect,
Group,
} from '@/components';
import { useCreateBankRule } from '@/hooks/query/bank-rules';
import {
AssignTransactionTypeOptions,
FieldCondition,
Fields,
RuleFormValues,
TransactionTypeOptions,
initialValues,
} from './_utils';
import { useRuleFormDialogBoot } from './RuleFormBoot';
import { transfromToSnakeCase } from '@/utils';
import withDialogActions from '@/containers/Dialog/withDialogActions';
import { DialogsName } from '@/constants/dialogs';
const initialValues = {
name: '',
order: 0,
applyIfAccountId: '',
applyIfTransactionType: '',
conditionsType: '',
conditions: [
{
field: 'description',
comparator: 'contains',
value: 'payment',
},
],
assignCategory: '',
assignAccountId: '',
};
function RuleFormContentFormRoot({
// #withDialogActions
openDialog,
closeDialog,
}) {
const { accounts } = useRuleFormDialogBoot();
const { mutateAsync: createBankRule } = useCreateBankRule();
interface RuleFormValues {
name: string;
order: number;
applyIfAccountId: string;
applyIfTransactionType: string;
conditionsType: string;
conditions: Array<{
field: string;
comparator: string;
value: string;
}>;
assignCategory: string;
assignAccountId: string;
}
export function RuleFormContentForm() {
const validationSchema = CreateRuleFormSchema;
const handleSubmit = () => {};
// Handles the form submitting.
const handleSubmit = (
values: RuleFormValues,
{ setSubmitting }: FormikHelpers<RuleFormValues>,
) => {
const _value = transfromToSnakeCase(values);
setSubmitting(true);
createBankRule(_value)
.then(() => {
setSubmitting(false);
closeDialog(DialogsName.BankRuleForm);
AppToaster.show({
intent: Intent.SUCCESS,
message: 'The bank rule has been created successfully.',
});
})
.catch((error) => {
setSubmitting(false);
AppToaster.show({
intent: Intent.DANGER,
message: 'Something went wrong!',
});
});
};
return (
<Formik<RuleFormValues>
@@ -57,8 +76,21 @@ export function RuleFormContentForm() {
<FInputGroup name={'name'} />
</FFormGroup>
<FFormGroup name={'conditionsType'} label={'Apply to transactions are'}>
<FSelect name={'conditionsType'} items={[]} />
<FFormGroup
name={'applyIfAccountId'}
label={'Apply the rule to account'}
>
<AccountsSelect name={'applyIfAccountId'} items={accounts} />
</FFormGroup>
<FFormGroup
name={'applyIfTransactionType'}
label={'Apply to transactions are'}
>
<FSelect
name={'applyIfTransactionType'}
items={TransactionTypeOptions}
/>
</FFormGroup>
<FFormGroup
@@ -78,11 +110,14 @@ export function RuleFormContentForm() {
<h3>Then Assign</h3>
<FFormGroup name={'assignCategory'} label={'Transaction type'}>
<FSelect name={'assignCategory'} items={[]} />
<FSelect
name={'assignCategory'}
items={AssignTransactionTypeOptions}
/>
</FFormGroup>
<FFormGroup name={'assignAccountId'} label={'Account category'}>
<FSelect name={'assignAccountId'} items={[]} />
<AccountsSelect name={'assignAccountId'} items={accounts} />
</FFormGroup>
<FFormGroup name={'assignRef'} label={'Reference'}>
@@ -95,15 +130,19 @@ export function RuleFormContentForm() {
);
}
export const RuleFormContentForm = R.compose(withDialogActions)(
RuleFormContentFormRoot,
);
function RuleFormConditions() {
const { values } = useFormikContext<RuleFormValues>();
const { values, setFieldValue } = useFormikContext<RuleFormValues>();
const handleAddConditionBtnClick = () => {
values.conditions.push({
field: '',
comparator: '',
value: '',
});
const _conditions = [
...values.conditions,
{ field: '', comparator: '', value: '' },
];
setFieldValue('conditions', _conditions);
};
return (
@@ -111,20 +150,20 @@ function RuleFormConditions() {
{values?.conditions?.map((condition, index) => (
<Group>
<FFormGroup name={`conditions[${index}].field`} label={'Field'}>
<FSelect name={`conditions[${index}].field`} items={[]} />
<FSelect name={`conditions[${index}].field`} items={Fields} />
</FFormGroup>
<FFormGroup
name={`conditions[${index}].comparator`}
label={'Condition'}
>
<FSelect name={`conditions[${index}].comparator`} items={[]} />
<FSelect
name={`conditions[${index}].comparator`}
items={FieldCondition}
/>
</FFormGroup>
<FFormGroup
name={`conditions[${index}].condition`}
label={'Condition'}
>
<FFormGroup name={`conditions[${index}].value`} label={'Condition'}>
<FInputGroup name={`conditions[${index}].value`} />
</FFormGroup>
</Group>

View File

@@ -0,0 +1,49 @@
export const initialValues = {
name: '',
order: 0,
applyIfAccountId: '',
applyIfTransactionType: '',
conditionsType: '',
conditions: [
{
field: 'description',
comparator: 'contains',
value: 'payment',
},
],
assignCategory: '',
assignAccountId: '',
};
export interface RuleFormValues {
name: string;
order: number;
applyIfAccountId: string;
applyIfTransactionType: string;
conditionsType: string;
conditions: Array<{
field: string;
comparator: string;
value: string;
}>;
assignCategory: string;
assignAccountId: string;
}
export const TransactionTypeOptions = [
{ value: 'deposit', text: 'Deposit' },
{ value: 'withdrawal', text: 'Withdrawal' },
];
export const Fields = [
{ value: 'description', text: 'Description' },
{ value: 'amount', text: 'Amount' },
{ value: 'payee', text: 'Payee' },
];
export const FieldCondition = [
{ value: 'contains', text: 'Contains' },
{ value: 'equals', text: 'equals' },
{ value: 'not_contains', text: 'Not Contains' },
];
export const AssignTransactionTypeOptions = [
{ value: 'expense', text: 'Expense' },
];

View File

@@ -13,7 +13,9 @@ export function RulesList() {
<RulesListActionsBar />
<DashboardPageContent>
<BankRulesTable />
<RulesListBoot>
<BankRulesTable />
</RulesListBoot>
</DashboardPageContent>
</RulesListBoot>
);

View File

@@ -1,9 +1,9 @@
import React, { createContext } from 'react';
import { DialogContent } from '@/components';
import { useBankRules } from '@/hooks/query/bank-rules';
interface RulesListBootValues {
rules: any;
isRulesLoading: boolean;
bankRules: any;
}
const RulesListBootContext = createContext<RulesListBootValues>(
@@ -15,7 +15,9 @@ interface RulesListBootProps {
}
function RulesListBoot({ ...props }: RulesListBootProps) {
const provider = {} as RulesListBootValues;
const { data: bankRules, isLoading: isBankRulesLoading } = useBankRules();
const provider = { bankRules, isBankRulesLoading } as RulesListBootValues;
return (
<DialogContent isLoading={false}>