diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormBoot.tsx b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormBoot.tsx index de9d01679..8d3e72094 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormBoot.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormBoot.tsx @@ -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 ( - + ); diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx index 6f8e6d9b1..ff0893a1e 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContent.tsx @@ -11,10 +11,8 @@ export default function RuleFormContent({ bankRuleId, }: RuleFormContentProps) { return ( -
- - - -
+ + + ); } diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx index 230f0ed74..b371e2a32 100644 --- a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/RuleFormContentForm.tsx @@ -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, + ) => { + 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 ( @@ -57,8 +76,21 @@ export function RuleFormContentForm() { - - + + + + + + Then Assign - + - + @@ -95,15 +130,19 @@ export function RuleFormContentForm() { ); } +export const RuleFormContentForm = R.compose(withDialogActions)( + RuleFormContentFormRoot, +); + function RuleFormConditions() { - const { values } = useFormikContext(); + const { values, setFieldValue } = useFormikContext(); 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) => ( - + - + - + diff --git a/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts new file mode 100644 index 000000000..d88136c9b --- /dev/null +++ b/packages/webapp/src/containers/Banking/Rules/RuleFormDialog/_utils.ts @@ -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' }, +]; diff --git a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx index 8c35a99ae..e241f2923 100644 --- a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesList.tsx @@ -13,7 +13,9 @@ export function RulesList() { - + + + ); diff --git a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesListBoot.tsx b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesListBoot.tsx index 71035fd60..f8c2cbd69 100644 --- a/packages/webapp/src/containers/Banking/Rules/RulesList/RulesListBoot.tsx +++ b/packages/webapp/src/containers/Banking/Rules/RulesList/RulesListBoot.tsx @@ -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( @@ -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 ( diff --git a/packages/webapp/src/hooks/query/bank-rules.ts b/packages/webapp/src/hooks/query/bank-rules.ts new file mode 100644 index 000000000..d9fa54d2d --- /dev/null +++ b/packages/webapp/src/hooks/query/bank-rules.ts @@ -0,0 +1,71 @@ +// @ts-nocheck +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import useApiRequest from '../useRequest'; + +/** + * + */ +export function useCreateBankRule(props) { + const queryClient = useQueryClient(); + const apiRequest = useApiRequest(); + + return useMutation((values) => apiRequest.post(`/banking/rules`, values), { + onSuccess: (res, id) => { + // Invalidate queries. + }, + ...props, + }); +} + +export function useEditBankRule(props) { + const queryClient = useQueryClient(); + const apiRequest = useApiRequest(); + + return useMutation((id: number) => apiRequest.post(`/bank-rules/${id}`), { + onSuccess: (res, id) => { + // Invalidate queries. + }, + ...props, + }); +} + +export function useDeleteBankRule(props) { + const queryClient = useQueryClient(); + const apiRequest = useApiRequest(); + + return useMutation((id: number) => apiRequest.delete(`/bank-rules/${id}`), { + onSuccess: (res, id) => { + // Invalidate queries. + }, + ...props, + }); +} + +/** + * + * @returns + */ +export function useBankRules() { + const apiRequest = useApiRequest(); + + return useQuery(['BANK_RULEs'], () => + apiRequest.get('/banking/rules').then((res) => res.data.bank_rules), + ); +} + +/** + * + * @returns + */ +export function useBankRule(bankRuleId: number, props) { + const apiRequest = useApiRequest(); + + return useQuery( + ['BANK_RULEs', bankRuleId], + () => + apiRequest + .get(`/banking/rules/${bankRuleId}`) + .then((res) => res.data.bank_rule), + props, + ); +}