feat: merge the boot provider of categorize and matching forms

This commit is contained in:
Ahmed Bouhuolia
2024-06-29 17:00:36 +02:00
parent 5d5d4a1972
commit 3cd66ba4d6
10 changed files with 129 additions and 43 deletions

View File

@@ -189,7 +189,7 @@ export function useAccountUncategorizedTransactionsColumns() {
{
id: 'deposit',
Header: intl.get('cash_flow.label.deposit'),
accessor: 'formattet_deposit_amount',
accessor: 'formatted_deposit_amount',
width: 40,
className: 'deposit',
textOverview: true,

View File

@@ -2,20 +2,34 @@
import React, { useMemo } from 'react';
import { first } from 'lodash';
import { DrawerLoading } from '@/components';
import {
useAccounts,
useBranches,
useUncategorizedTransaction,
} from '@/hooks/query';
import { useAccounts, useBranches } from '@/hooks/query';
import { useFeatureCan } from '@/hooks/state';
import { Features } from '@/constants';
import { Spinner } from '@blueprintjs/core';
const CategorizeTransactionBootContext = React.createContext();
interface CategorizeTransactionBootProps {
children: React.ReactNode;
}
interface CategorizeTransactionBootValue {
branches: any;
accounts: any;
isBranchesLoading: boolean;
isAccountsLoading: boolean;
primaryBranch: any;
}
const CategorizeTransactionBootContext =
React.createContext<CategorizeTransactionBootValue>(
{} as CategorizeTransactionBootValue,
);
/**
* Categorize transcation boot.
*/
function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
function CategorizeTransactionBoot({
...props
}: CategorizeTransactionBootProps) {
// Detarmines whether the feature is enabled.
const { featureCan } = useFeatureCan();
const isBranchFeatureCan = featureCan(Features.Branches);
@@ -28,12 +42,6 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
{},
{ enabled: isBranchFeatureCan },
);
// Retrieves the uncategorized transaction.
const {
data: uncategorizedTransaction,
isLoading: isUncategorizedTransactionLoading,
} = useUncategorizedTransaction(uncategorizedTransactionId);
// Retrieves the primary branch.
const primaryBranch = useMemo(
() => branches?.find((b) => b.primary) || first(branches),
@@ -41,18 +49,17 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
);
const provider = {
uncategorizedTransactionId,
uncategorizedTransaction,
isUncategorizedTransactionLoading,
branches,
accounts,
isBranchesLoading,
isAccountsLoading,
primaryBranch,
};
const isLoading =
isBranchesLoading || isUncategorizedTransactionLoading || isAccountsLoading;
const isLoading = isBranchesLoading || isAccountsLoading;
if (isLoading) {
<Spinner size={30} />;
}
return (
<DrawerLoading loading={isLoading}>
<CategorizeTransactionBootContext.Provider value={provider} {...props} />
@@ -61,6 +68,8 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
}
const useCategorizeTransactionBoot = () =>
React.useContext(CategorizeTransactionBootContext);
React.useContext<CategorizeTransactionBootValue>(
CategorizeTransactionBootContext,
);
export { CategorizeTransactionBoot, useCategorizeTransactionBoot };

View File

@@ -3,9 +3,10 @@ import styled from 'styled-components';
import { DrawerBody } from '@/components';
import { CategorizeTransactionBoot } from './CategorizeTransactionBoot';
import { CategorizeTransactionForm } from './CategorizeTransactionForm';
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
export function CategorizeTransactionContent({}) {
const uncategorizedTransactionId = 4;
const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot();
return (
<CategorizeTransactionBoot

View File

@@ -16,6 +16,7 @@ import { compose } from '@/utils';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { AppToaster } from '@/components';
import { Intent } from '@blueprintjs/core';
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
/**
* Categorize cashflow transaction form dialog content.
@@ -24,11 +25,9 @@ function CategorizeTransactionFormRoot({
// #withDrawerActions
closeDrawer,
}) {
const {
uncategorizedTransactionId,
uncategorizedTransaction,
primaryBranch,
} = useCategorizeTransactionBoot();
const { uncategorizedTransactionId, uncategorizedTransaction } =
useCategorizeTransactionTabsBoot();
const { primaryBranch } = useCategorizeTransactionBoot();
const { mutateAsync: categorizeTransaction } = useCategorizeTransaction();
// Callbacks handles form submit.

View File

@@ -5,7 +5,7 @@ import { FormGroup } from '@blueprintjs/core';
import { FFormGroup, FSelect, } from '@/components';
import { getAddMoneyInOptions, getAddMoneyOutOptions } from '@/constants';
import { useFormikContext } from 'formik';
import { useCategorizeTransactionBoot } from './CategorizeTransactionBoot';
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
// Retrieves the add money in button options.
const MoneyInOptions = getAddMoneyInOptions();
@@ -18,7 +18,7 @@ const Title = styled('h3')`
`;
export function CategorizeTransactionFormContent() {
const { uncategorizedTransaction } = useCategorizeTransactionBoot();
const { uncategorizedTransaction } = useCategorizeTransactionTabsBoot();
const transactionTypes = uncategorizedTransaction?.is_deposit_transaction
? MoneyInOptions

View File

@@ -3,18 +3,17 @@ import * as R from 'ramda';
import { Button, Classes, Intent } from '@blueprintjs/core';
import { useFormikContext } from 'formik';
import styled from 'styled-components';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { DRAWERS } from '@/constants/drawers';
import { Group } from '@/components';
import { withBankingActions } from '@/containers/CashFlow/withBankingActions';
function CategorizeTransactionFormFooterRoot({
// #withDrawerActions
closeDrawer,
// #withBankingActions
closeMatchingTransactionAside,
}) {
const { isSubmitting } = useFormikContext();
const handleClose = () => {
closeDrawer(DRAWERS.CATEGORIZE_TRANSACTION);
closeMatchingTransactionAside();
};
return (
@@ -23,8 +22,8 @@ function CategorizeTransactionFormFooterRoot({
<Group spacing={10}>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
style={{ minWidth: '75px' }}
loading={isSubmitting}
type="submit"
>
Save
@@ -43,7 +42,7 @@ function CategorizeTransactionFormFooterRoot({
);
}
export const CategorizeTransactionFormFooter = R.compose(withDrawerActions)(
export const CategorizeTransactionFormFooter = R.compose(withBankingActions)(
CategorizeTransactionFormFooterRoot,
);

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
import * as R from 'ramda';
import { Aside } from '@/components/Aside/Aside';
import { CategorizeTransactionTabs } from './CategorizeTransactionTabs';
@@ -5,24 +6,40 @@ import {
WithBankingActionsProps,
withBankingActions,
} from '../withBankingActions';
import { CategorizeTransactionTabsBoot } from './CategorizeTransactionTabsBoot';
import { withBanking } from '../withBanking';
interface CategorizeTransactionAsideProps extends WithBankingActionsProps {}
function CategorizeTransactionAsideRoot({
// #withBankingActions
closeMatchingTransactionAside,
// #withBanking
selectedUncategorizedTransactionId,
}: CategorizeTransactionAsideProps) {
const handleClose = () => {
closeMatchingTransactionAside();
};
const uncategorizedTransactionId = selectedUncategorizedTransactionId;
if (!selectedUncategorizedTransactionId) {
return null;
}
return (
<Aside title={'Categorize Bank Transaction'} onClose={handleClose}>
<CategorizeTransactionTabs />
<CategorizeTransactionTabsBoot
uncategorizedTransactionId={uncategorizedTransactionId}
>
<CategorizeTransactionTabs />
</CategorizeTransactionTabsBoot>
</Aside>
);
}
export const CategorizeTransactionAside = R.compose(withBankingActions)(
CategorizeTransactionAsideRoot,
);
export const CategorizeTransactionAside = R.compose(
withBankingActions,
withBanking(({ selectedUncategorizedTransactionId }) => ({
selectedUncategorizedTransactionId,
})),
)(CategorizeTransactionAsideRoot);

View File

@@ -5,7 +5,7 @@ import { CategorizeTransactionContent } from '../CategorizeTransaction/drawers/C
export function CategorizeTransactionTabs() {
return (
<Tabs large className={styles.tabs}>
<Tabs large renderActiveTabPanelOnly className={styles.tabs}>
<Tab
id="categorize"
title="Categorize Transaction"

View File

@@ -0,0 +1,61 @@
// @ts-nocheck
import React from 'react';
import { Spinner } from '@blueprintjs/core';
import { useUncategorizedTransaction } from '@/hooks/query';
interface CategorizeTransactionTabsValue {
uncategorizedTransactionId: number;
isUncategorizedTransactionLoading: boolean;
uncategorizedTransaction: any;
}
interface CategorizeTransactionTabsBootProps {
uncategorizedTransactionId: number;
children: React.ReactNode;
}
const CategorizeTransactionTabsBootContext =
React.createContext<CategorizeTransactionTabsValue>(
{} as CategorizeTransactionTabsValue,
);
/**
* Categorize transcation tabs boot.
*/
export function CategorizeTransactionTabsBoot({
uncategorizedTransactionId,
children,
}: CategorizeTransactionTabsBootProps) {
const {
data: uncategorizedTransaction,
isLoading: isUncategorizedTransactionLoading,
} = useUncategorizedTransaction(uncategorizedTransactionId);
const provider = {
uncategorizedTransactionId,
uncategorizedTransaction,
isUncategorizedTransactionLoading,
};
const isLoading = isUncategorizedTransactionLoading;
// Use a key prop to force re-render of children when uncategorizedTransactionId changes
const childrenPerKey = React.useMemo(() => {
return React.Children.map(children, (child) =>
React.cloneElement(child, { key: uncategorizedTransactionId }),
);
}, [children, uncategorizedTransactionId]);
if (isLoading) {
return <Spinner size={30} />;
}
return (
<CategorizeTransactionTabsBootContext.Provider value={provider}>
{childrenPerKey}
</CategorizeTransactionTabsBootContext.Provider>
);
}
export const useCategorizeTransactionTabsBoot = () =>
React.useContext<CategorizeTransactionTabsValue>(
CategorizeTransactionTabsBootContext,
);

View File

@@ -13,6 +13,7 @@ import { FastField, FastFieldProps, Form, Formik } from 'formik';
import { useMatchTransaction } from '@/hooks/query/bank-rules';
import { MatchingTransactionFormValues } from './types';
import { transformToReq, useGetPendingAmountMatched } from './utils';
import { useCategorizeTransactionTabsBoot } from './CategorizeTransactionTabsBoot';
import {
WithBankingActionsProps,
withBankingActions,
@@ -23,7 +24,7 @@ const initialValues = {
};
export function MatchingBankTransaction() {
const uncategorizedTransactionId = 4;
const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot();
const { mutateAsync: matchTransaction } = useMatchTransaction();
// Handles the form submitting.
@@ -191,7 +192,6 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
const handleCancelBtnClick = () => {
closeMatchingTransactionAside();
};
const totalPending = useGetPendingAmountMatched();
return (
@@ -202,7 +202,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
Add Reconcile Transaction +
</AnchorButton>
<Text style={{ fontSize: 13 }} tagName='span'>
<Text style={{ fontSize: 13 }} tagName="span">
Pending <FormatNumber value={totalPending} currency={'USD'} />
</Text>
</Group>