mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 23:00:34 +00:00
feat: merge the boot provider of categorize and matching forms
This commit is contained in:
@@ -189,7 +189,7 @@ export function useAccountUncategorizedTransactionsColumns() {
|
|||||||
{
|
{
|
||||||
id: 'deposit',
|
id: 'deposit',
|
||||||
Header: intl.get('cash_flow.label.deposit'),
|
Header: intl.get('cash_flow.label.deposit'),
|
||||||
accessor: 'formattet_deposit_amount',
|
accessor: 'formatted_deposit_amount',
|
||||||
width: 40,
|
width: 40,
|
||||||
className: 'deposit',
|
className: 'deposit',
|
||||||
textOverview: true,
|
textOverview: true,
|
||||||
|
|||||||
@@ -2,20 +2,34 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { first } from 'lodash';
|
import { first } from 'lodash';
|
||||||
import { DrawerLoading } from '@/components';
|
import { DrawerLoading } from '@/components';
|
||||||
import {
|
import { useAccounts, useBranches } from '@/hooks/query';
|
||||||
useAccounts,
|
|
||||||
useBranches,
|
|
||||||
useUncategorizedTransaction,
|
|
||||||
} from '@/hooks/query';
|
|
||||||
import { useFeatureCan } from '@/hooks/state';
|
import { useFeatureCan } from '@/hooks/state';
|
||||||
import { Features } from '@/constants';
|
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.
|
* Categorize transcation boot.
|
||||||
*/
|
*/
|
||||||
function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
|
function CategorizeTransactionBoot({
|
||||||
|
...props
|
||||||
|
}: CategorizeTransactionBootProps) {
|
||||||
// Detarmines whether the feature is enabled.
|
// Detarmines whether the feature is enabled.
|
||||||
const { featureCan } = useFeatureCan();
|
const { featureCan } = useFeatureCan();
|
||||||
const isBranchFeatureCan = featureCan(Features.Branches);
|
const isBranchFeatureCan = featureCan(Features.Branches);
|
||||||
@@ -28,12 +42,6 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
|
|||||||
{},
|
{},
|
||||||
{ enabled: isBranchFeatureCan },
|
{ enabled: isBranchFeatureCan },
|
||||||
);
|
);
|
||||||
// Retrieves the uncategorized transaction.
|
|
||||||
const {
|
|
||||||
data: uncategorizedTransaction,
|
|
||||||
isLoading: isUncategorizedTransactionLoading,
|
|
||||||
} = useUncategorizedTransaction(uncategorizedTransactionId);
|
|
||||||
|
|
||||||
// Retrieves the primary branch.
|
// Retrieves the primary branch.
|
||||||
const primaryBranch = useMemo(
|
const primaryBranch = useMemo(
|
||||||
() => branches?.find((b) => b.primary) || first(branches),
|
() => branches?.find((b) => b.primary) || first(branches),
|
||||||
@@ -41,18 +49,17 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const provider = {
|
const provider = {
|
||||||
uncategorizedTransactionId,
|
|
||||||
uncategorizedTransaction,
|
|
||||||
isUncategorizedTransactionLoading,
|
|
||||||
branches,
|
branches,
|
||||||
accounts,
|
accounts,
|
||||||
isBranchesLoading,
|
isBranchesLoading,
|
||||||
isAccountsLoading,
|
isAccountsLoading,
|
||||||
primaryBranch,
|
primaryBranch,
|
||||||
};
|
};
|
||||||
const isLoading =
|
const isLoading = isBranchesLoading || isAccountsLoading;
|
||||||
isBranchesLoading || isUncategorizedTransactionLoading || isAccountsLoading;
|
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
<Spinner size={30} />;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<DrawerLoading loading={isLoading}>
|
<DrawerLoading loading={isLoading}>
|
||||||
<CategorizeTransactionBootContext.Provider value={provider} {...props} />
|
<CategorizeTransactionBootContext.Provider value={provider} {...props} />
|
||||||
@@ -61,6 +68,8 @@ function CategorizeTransactionBoot({ uncategorizedTransactionId, ...props }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const useCategorizeTransactionBoot = () =>
|
const useCategorizeTransactionBoot = () =>
|
||||||
React.useContext(CategorizeTransactionBootContext);
|
React.useContext<CategorizeTransactionBootValue>(
|
||||||
|
CategorizeTransactionBootContext,
|
||||||
|
);
|
||||||
|
|
||||||
export { CategorizeTransactionBoot, useCategorizeTransactionBoot };
|
export { CategorizeTransactionBoot, useCategorizeTransactionBoot };
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ import styled from 'styled-components';
|
|||||||
import { DrawerBody } from '@/components';
|
import { DrawerBody } from '@/components';
|
||||||
import { CategorizeTransactionBoot } from './CategorizeTransactionBoot';
|
import { CategorizeTransactionBoot } from './CategorizeTransactionBoot';
|
||||||
import { CategorizeTransactionForm } from './CategorizeTransactionForm';
|
import { CategorizeTransactionForm } from './CategorizeTransactionForm';
|
||||||
|
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
|
||||||
|
|
||||||
export function CategorizeTransactionContent({}) {
|
export function CategorizeTransactionContent({}) {
|
||||||
const uncategorizedTransactionId = 4;
|
const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CategorizeTransactionBoot
|
<CategorizeTransactionBoot
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { compose } from '@/utils';
|
|||||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||||
import { AppToaster } from '@/components';
|
import { AppToaster } from '@/components';
|
||||||
import { Intent } from '@blueprintjs/core';
|
import { Intent } from '@blueprintjs/core';
|
||||||
|
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categorize cashflow transaction form dialog content.
|
* Categorize cashflow transaction form dialog content.
|
||||||
@@ -24,11 +25,9 @@ function CategorizeTransactionFormRoot({
|
|||||||
// #withDrawerActions
|
// #withDrawerActions
|
||||||
closeDrawer,
|
closeDrawer,
|
||||||
}) {
|
}) {
|
||||||
const {
|
const { uncategorizedTransactionId, uncategorizedTransaction } =
|
||||||
uncategorizedTransactionId,
|
useCategorizeTransactionTabsBoot();
|
||||||
uncategorizedTransaction,
|
const { primaryBranch } = useCategorizeTransactionBoot();
|
||||||
primaryBranch,
|
|
||||||
} = useCategorizeTransactionBoot();
|
|
||||||
const { mutateAsync: categorizeTransaction } = useCategorizeTransaction();
|
const { mutateAsync: categorizeTransaction } = useCategorizeTransaction();
|
||||||
|
|
||||||
// Callbacks handles form submit.
|
// Callbacks handles form submit.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { FormGroup } from '@blueprintjs/core';
|
|||||||
import { FFormGroup, FSelect, } from '@/components';
|
import { FFormGroup, FSelect, } from '@/components';
|
||||||
import { getAddMoneyInOptions, getAddMoneyOutOptions } from '@/constants';
|
import { getAddMoneyInOptions, getAddMoneyOutOptions } from '@/constants';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import { useCategorizeTransactionBoot } from './CategorizeTransactionBoot';
|
import { useCategorizeTransactionTabsBoot } from '@/containers/CashFlow/CategorizeTransactionAside/CategorizeTransactionTabsBoot';
|
||||||
|
|
||||||
// Retrieves the add money in button options.
|
// Retrieves the add money in button options.
|
||||||
const MoneyInOptions = getAddMoneyInOptions();
|
const MoneyInOptions = getAddMoneyInOptions();
|
||||||
@@ -18,7 +18,7 @@ const Title = styled('h3')`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export function CategorizeTransactionFormContent() {
|
export function CategorizeTransactionFormContent() {
|
||||||
const { uncategorizedTransaction } = useCategorizeTransactionBoot();
|
const { uncategorizedTransaction } = useCategorizeTransactionTabsBoot();
|
||||||
|
|
||||||
const transactionTypes = uncategorizedTransaction?.is_deposit_transaction
|
const transactionTypes = uncategorizedTransaction?.is_deposit_transaction
|
||||||
? MoneyInOptions
|
? MoneyInOptions
|
||||||
|
|||||||
@@ -3,18 +3,17 @@ import * as R from 'ramda';
|
|||||||
import { Button, Classes, Intent } from '@blueprintjs/core';
|
import { Button, Classes, Intent } from '@blueprintjs/core';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
|
||||||
import { DRAWERS } from '@/constants/drawers';
|
|
||||||
import { Group } from '@/components';
|
import { Group } from '@/components';
|
||||||
|
import { withBankingActions } from '@/containers/CashFlow/withBankingActions';
|
||||||
|
|
||||||
function CategorizeTransactionFormFooterRoot({
|
function CategorizeTransactionFormFooterRoot({
|
||||||
// #withDrawerActions
|
// #withBankingActions
|
||||||
closeDrawer,
|
closeMatchingTransactionAside,
|
||||||
}) {
|
}) {
|
||||||
const { isSubmitting } = useFormikContext();
|
const { isSubmitting } = useFormikContext();
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
closeDrawer(DRAWERS.CATEGORIZE_TRANSACTION);
|
closeMatchingTransactionAside();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -23,8 +22,8 @@ function CategorizeTransactionFormFooterRoot({
|
|||||||
<Group spacing={10}>
|
<Group spacing={10}>
|
||||||
<Button
|
<Button
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
loading={isSubmitting}
|
|
||||||
style={{ minWidth: '75px' }}
|
style={{ minWidth: '75px' }}
|
||||||
|
loading={isSubmitting}
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
@@ -43,7 +42,7 @@ function CategorizeTransactionFormFooterRoot({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CategorizeTransactionFormFooter = R.compose(withDrawerActions)(
|
export const CategorizeTransactionFormFooter = R.compose(withBankingActions)(
|
||||||
CategorizeTransactionFormFooterRoot,
|
CategorizeTransactionFormFooterRoot,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Aside } from '@/components/Aside/Aside';
|
import { Aside } from '@/components/Aside/Aside';
|
||||||
import { CategorizeTransactionTabs } from './CategorizeTransactionTabs';
|
import { CategorizeTransactionTabs } from './CategorizeTransactionTabs';
|
||||||
@@ -5,24 +6,40 @@ import {
|
|||||||
WithBankingActionsProps,
|
WithBankingActionsProps,
|
||||||
withBankingActions,
|
withBankingActions,
|
||||||
} from '../withBankingActions';
|
} from '../withBankingActions';
|
||||||
|
import { CategorizeTransactionTabsBoot } from './CategorizeTransactionTabsBoot';
|
||||||
|
import { withBanking } from '../withBanking';
|
||||||
|
|
||||||
interface CategorizeTransactionAsideProps extends WithBankingActionsProps {}
|
interface CategorizeTransactionAsideProps extends WithBankingActionsProps {}
|
||||||
|
|
||||||
function CategorizeTransactionAsideRoot({
|
function CategorizeTransactionAsideRoot({
|
||||||
// #withBankingActions
|
// #withBankingActions
|
||||||
closeMatchingTransactionAside,
|
closeMatchingTransactionAside,
|
||||||
|
|
||||||
|
// #withBanking
|
||||||
|
selectedUncategorizedTransactionId,
|
||||||
}: CategorizeTransactionAsideProps) {
|
}: CategorizeTransactionAsideProps) {
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
closeMatchingTransactionAside();
|
closeMatchingTransactionAside();
|
||||||
};
|
};
|
||||||
|
const uncategorizedTransactionId = selectedUncategorizedTransactionId;
|
||||||
|
|
||||||
|
if (!selectedUncategorizedTransactionId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Aside title={'Categorize Bank Transaction'} onClose={handleClose}>
|
<Aside title={'Categorize Bank Transaction'} onClose={handleClose}>
|
||||||
|
<CategorizeTransactionTabsBoot
|
||||||
|
uncategorizedTransactionId={uncategorizedTransactionId}
|
||||||
|
>
|
||||||
<CategorizeTransactionTabs />
|
<CategorizeTransactionTabs />
|
||||||
|
</CategorizeTransactionTabsBoot>
|
||||||
</Aside>
|
</Aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CategorizeTransactionAside = R.compose(withBankingActions)(
|
export const CategorizeTransactionAside = R.compose(
|
||||||
CategorizeTransactionAsideRoot,
|
withBankingActions,
|
||||||
);
|
withBanking(({ selectedUncategorizedTransactionId }) => ({
|
||||||
|
selectedUncategorizedTransactionId,
|
||||||
|
})),
|
||||||
|
)(CategorizeTransactionAsideRoot);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CategorizeTransactionContent } from '../CategorizeTransaction/drawers/C
|
|||||||
|
|
||||||
export function CategorizeTransactionTabs() {
|
export function CategorizeTransactionTabs() {
|
||||||
return (
|
return (
|
||||||
<Tabs large className={styles.tabs}>
|
<Tabs large renderActiveTabPanelOnly className={styles.tabs}>
|
||||||
<Tab
|
<Tab
|
||||||
id="categorize"
|
id="categorize"
|
||||||
title="Categorize Transaction"
|
title="Categorize Transaction"
|
||||||
|
|||||||
@@ -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,
|
||||||
|
);
|
||||||
@@ -13,6 +13,7 @@ import { FastField, FastFieldProps, Form, Formik } from 'formik';
|
|||||||
import { useMatchTransaction } from '@/hooks/query/bank-rules';
|
import { useMatchTransaction } from '@/hooks/query/bank-rules';
|
||||||
import { MatchingTransactionFormValues } from './types';
|
import { MatchingTransactionFormValues } from './types';
|
||||||
import { transformToReq, useGetPendingAmountMatched } from './utils';
|
import { transformToReq, useGetPendingAmountMatched } from './utils';
|
||||||
|
import { useCategorizeTransactionTabsBoot } from './CategorizeTransactionTabsBoot';
|
||||||
import {
|
import {
|
||||||
WithBankingActionsProps,
|
WithBankingActionsProps,
|
||||||
withBankingActions,
|
withBankingActions,
|
||||||
@@ -23,7 +24,7 @@ const initialValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function MatchingBankTransaction() {
|
export function MatchingBankTransaction() {
|
||||||
const uncategorizedTransactionId = 4;
|
const { uncategorizedTransactionId } = useCategorizeTransactionTabsBoot();
|
||||||
const { mutateAsync: matchTransaction } = useMatchTransaction();
|
const { mutateAsync: matchTransaction } = useMatchTransaction();
|
||||||
|
|
||||||
// Handles the form submitting.
|
// Handles the form submitting.
|
||||||
@@ -191,7 +192,6 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
|
|||||||
const handleCancelBtnClick = () => {
|
const handleCancelBtnClick = () => {
|
||||||
closeMatchingTransactionAside();
|
closeMatchingTransactionAside();
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalPending = useGetPendingAmountMatched();
|
const totalPending = useGetPendingAmountMatched();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -202,7 +202,7 @@ const MatchTransactionFooter = R.compose(withBankingActions)(
|
|||||||
Add Reconcile Transaction +
|
Add Reconcile Transaction +
|
||||||
</AnchorButton>
|
</AnchorButton>
|
||||||
|
|
||||||
<Text style={{ fontSize: 13 }} tagName='span'>
|
<Text style={{ fontSize: 13 }} tagName="span">
|
||||||
Pending <FormatNumber value={totalPending} currency={'USD'} />
|
Pending <FormatNumber value={totalPending} currency={'USD'} />
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
Reference in New Issue
Block a user