feat: excluded bank transactions

This commit is contained in:
Ahmed Bouhuolia
2024-06-27 22:14:53 +02:00
parent fab22c9820
commit 978ce6c441
28 changed files with 1301 additions and 27 deletions

View File

@@ -22,6 +22,8 @@ export const TABLES = {
PROJECTS: 'projects',
TIMESHEETS: 'timesheets',
PROJECT_TASKS: 'project_tasks',
UNCATEGORIZED_ACCOUNT_TRANSACTIONS: 'UNCATEGORIZED_ACCOUNT_TRANSACTIONS',
EXCLUDED_BANK_TRANSACTIONS: 'EXCLUDED_BANK_TRANSACTIONS'
};
export const TABLE_SIZE = {

View File

@@ -28,6 +28,7 @@ export function AccountTransactionsUncategorizeFilter() {
<FilterTag round interactive>
All <strong>(2)</strong>
</FilterTag>
<FilterTag round minimal interactive>
Recognized <strong>(0)</strong>
</FilterTag>

View File

@@ -0,0 +1,37 @@
import React from 'react';
interface UncategorizedTransactionsFilterValue {}
const UncategorizedTransactionsFilterContext =
React.createContext<UncategorizedTransactionsFilterValue>(
{} as UncategorizedTransactionsFilterValue,
);
interface UncategorizedTransactionsFilterProviderProps {
children: React.ReactNode;
}
/**
*
*/
function UncategorizedTransactionsFilterProvider({
...props
}: UncategorizedTransactionsFilterProviderProps) {
// Provider payload.
const provider = {};
return (
<UncategorizedTransactionsFilterContext.Provider
value={provider}
{...props}
/>
);
}
const useUncategorizedTransactionsFilter = () =>
React.useContext(UncategorizedTransactionsFilterContext);
export {
UncategorizedTransactionsFilterProvider,
useUncategorizedTransactionsFilter,
};

View File

@@ -4,7 +4,6 @@ import styled from 'styled-components';
import '@/style/pages/CashFlow/AccountTransactions/List.scss';
import AccountTransactionsDataTable from './AccountTransactionsDataTable';
import { AccountTransactionsUncategorizeFilter } from './AccountTransactionsUncategorizeFilter';
import { AccountTransactionsAllProvider } from './AccountTransactionsAllBoot';
const Box = styled.div`
@@ -23,8 +22,6 @@ export default function AccountTransactionsAll() {
return (
<AccountTransactionsAllProvider>
<Box>
<AccountTransactionsUncategorizeFilter />
<CashflowTransactionsTableCard>
<AccountTransactionsDataTable />
</CashflowTransactionsTableCard>

View File

@@ -1,16 +1,22 @@
// @ts-nocheck
import { useEffect } from 'react';
import styled from 'styled-components';
import * as R from 'ramda';
import '@/style/pages/CashFlow/AccountTransactions/List.scss';
import AccountTransactionsUncategorizedTable from './AccountTransactionsUncategorizedTable';
import { AccountUncategorizedTransactionsBoot } from './AllTransactionsUncategorizedBoot';
import { AccountTransactionsUncategorizeFilter } from './AccountTransactionsUncategorizeFilter';
import { UncategorizedTransactionsFilterProvider } from './AccountUncategorizedTransactionsFilterProvider';
import { RecognizedTransactionsTableBoot } from './RecognizedTransactions/RecognizedTransactionsTableBoot';
import { RecognizedTransactionsTable } from './RecognizedTransactions/RecognizedTransactionsTable';
import {
WithBankingActionsProps,
withBankingActions,
} from '../withBankingActions';
import { useEffect } from 'react';
import { AccountUncategorizedTransactionsBoot } from './AllTransactionsUncategorizedBoot';
import AccountTransactionsUncategorizedTable from './AccountTransactionsUncategorizedTable';
import { ExcludedBankTransactionsTableBoot } from './ExcludedTransactions/ExcludedTransactionsTableBoot';
import { ExcludedTransactionsTable } from './ExcludedTransactions/ExcludedTransactionsTable';
const Box = styled.div`
margin: 30px 15px;
@@ -36,14 +42,31 @@ function AllTransactionsUncategorizedRoot({
},
[closeMatchingTransactionAside],
);
return (
<AccountUncategorizedTransactionsBoot>
<UncategorizedTransactionsFilterProvider>
<Box>
<CashflowTransactionsTableCard>
<AccountTransactionsUncategorizedTable />
</CashflowTransactionsTableCard>
<AccountTransactionsUncategorizeFilter />
<ExcludedBankTransactionsTableBoot>
<CashflowTransactionsTableCard>
<ExcludedTransactionsTable />
</CashflowTransactionsTableCard>
</ExcludedBankTransactionsTableBoot>
{/* <RecognizedTransactionsTableBoot>
<CashflowTransactionsTableCard>
<RecognizedTransactionsTable />
</CashflowTransactionsTableCard>
</RecognizedTransactionsTableBoot> */}
{/* <AccountUncategorizedTransactionsBoot>
<CashflowTransactionsTableCard>
<AccountTransactionsUncategorizedTable />
</CashflowTransactionsTableCard>
</AccountUncategorizedTransactionsBoot> */}
</Box>
</AccountUncategorizedTransactionsBoot>
</UncategorizedTransactionsFilterProvider>
);
}

View File

@@ -0,0 +1,137 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import {
DataTable,
TableFastCell,
TableSkeletonRows,
TableSkeletonHeader,
TableVirtualizedListRows,
AppToaster,
} from '@/components';
import { TABLES } from '@/constants/tables';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { useMemorizedColumnsWidths } from '@/hooks';
import { useExcludedTransactionsColumns } from './_utils';
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
import { compose } from '@/utils';
import { ActionsMenu } from './_components';
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
import { Intent } from '@blueprintjs/core';
interface ExcludedTransactionsTableProps {}
/**
* Renders the recognized account transactions datatable.
*/
function ExcludedTransactionsTableRoot({}: ExcludedTransactionsTableProps) {
const { excludedBankTransactions } = useExcludedTransactionsBoot();
const { mutateAsync: unexcludeBankTransaction } =
useUnexcludeUncategorizedTransaction();
// Retrieve table columns.
const columns = useExcludedTransactionsColumns();
// Local storage memorizing columns widths.
const [initialColumnsWidths, , handleColumnResizing] =
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
// Handle cell click.
const handleCellClick = (cell, event) => {};
// Handle restore button click.
const handleRestoreClick = (transaction) => {
unexcludeBankTransaction(transaction.id)
.then(() => {
AppToaster.show({
message: 'The excluded bank transaction has been restored.',
intent: Intent.SUCCESS,
});
})
.catch((error) => {
AppToaster.show({
message: 'Something went wrong.',
intent: Intent.DANGER,
});
});
};
return (
<CashflowTransactionsTable
noInitialFetch={true}
columns={columns}
data={excludedBankTransactions}
sticky={true}
loading={false}
headerLoading={false}
expandColumnSpace={1}
expandToggleColumn={2}
selectionColumnWidth={45}
TableCellRenderer={TableFastCell}
TableLoadingRenderer={TableSkeletonRows}
TableRowsRenderer={TableVirtualizedListRows}
TableHeaderSkeletonRenderer={TableSkeletonHeader}
ContextMenu={ActionsMenu}
onCellClick={handleCellClick}
// #TableVirtualizedListRows props.
vListrowHeight={'small' == 'small' ? 32 : 40}
vListrowHeight={40}
vListOverscanRowCount={0}
initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing}
// noResults={<T id={'cash_flow.account_transactions.no_results'} />}
className="table-constrant"
payload={{
onRestore: handleRestoreClick,
}}
/>
);
}
export const ExcludedTransactionsTable = compose(withDrawerActions)(
ExcludedTransactionsTableRoot,
);
const DashboardConstrantTable = styled(DataTable)`
.table {
.thead {
.th {
background: #fff;
letter-spacing: 1px;
text-transform: uppercase;
font-weight: 500;
font-size: 13px;
}
}
.tbody {
.tr:last-child .td {
border-bottom: 0;
}
}
}
`;
const CashflowTransactionsTable = styled(DashboardConstrantTable)`
.table .tbody {
.tbody-inner .tr.no-results {
.td {
padding: 2rem 0;
font-size: 14px;
color: #888;
font-weight: 400;
border-bottom: 0;
}
}
.tbody-inner {
.tr .td {
border-bottom: 1px solid #e6e6e6;
}
}
}
`;

View File

@@ -0,0 +1,90 @@
// @ts-nocheck
import React from 'react';
import { flatten, map } from 'lodash';
import { IntersectionObserver } from '@/components';
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
import { useExcludedBankTransactionsInfinity } from '@/hooks/query/bank-rules';
interface ExcludedBankTransactionsContextValue {
isExcludedTransactionsLoading: boolean;
isExcludedTransactionsFetching: boolean;
excludedBankTransactions: Array<any>;
}
const ExcludedTransactionsContext =
React.createContext<ExcludedBankTransactionsContextValue>(
{} as ExcludedBankTransactionsContextValue,
);
function flattenInfinityPagesData(data) {
return flatten(map(data.pages, (page) => page.data));
}
interface ExcludedBankTransactionsTableBootProps {
children: React.ReactNode;
}
/**
* Account uncategorized transctions provider.
*/
function ExcludedBankTransactionsTableBoot({
children,
}: ExcludedBankTransactionsTableBootProps) {
const { accountId } = useAccountTransactionsContext();
// Fetches the uncategorized transactions.
const {
data: recognizedTransactionsPage,
isFetching: isExcludedTransactionsFetching,
isLoading: isExcludedTransactionsLoading,
isSuccess: isRecognizedTransactionsSuccess,
isFetchingNextPage: isUncategorizedTransactionFetchNextPage,
fetchNextPage: fetchNextrecognizedTransactionsPage,
hasNextPage: hasUncategorizedTransactionsNextPage,
} = useExcludedBankTransactionsInfinity({
page_size: 50,
account_id: accountId,
});
// Memorized the cashflow account transactions.
const excludedBankTransactions = React.useMemo(
() =>
isRecognizedTransactionsSuccess
? flattenInfinityPagesData(recognizedTransactionsPage)
: [],
[recognizedTransactionsPage, isRecognizedTransactionsSuccess],
);
// Handle the observer ineraction.
const handleObserverInteract = React.useCallback(() => {
if (
!isExcludedTransactionsFetching &&
hasUncategorizedTransactionsNextPage
) {
fetchNextrecognizedTransactionsPage();
}
}, [
isExcludedTransactionsFetching,
hasUncategorizedTransactionsNextPage,
fetchNextrecognizedTransactionsPage,
]);
// Provider payload.
const provider = {
excludedBankTransactions,
isExcludedTransactionsFetching,
isExcludedTransactionsLoading,
};
return (
<ExcludedTransactionsContext.Provider value={provider}>
{children}
<IntersectionObserver
onIntersect={handleObserverInteract}
enabled={!isUncategorizedTransactionFetchNextPage}
/>
</ExcludedTransactionsContext.Provider>
);
}
const useExcludedTransactionsBoot = () =>
React.useContext(ExcludedTransactionsContext);
export { ExcludedBankTransactionsTableBoot, useExcludedTransactionsBoot };

View File

@@ -0,0 +1,11 @@
// @ts-nocheck
import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
import { safeCallback } from '@/utils';
export function ActionsMenu({ payload: { onRestore }, row: { original } }) {
return (
<Menu>
<MenuItem text={'Restore'} onClick={safeCallback(onRestore, original)} />
</Menu>
);
}

View File

@@ -0,0 +1,66 @@
// @ts-nocheck
import React from 'react';
import { getColumnWidth } from '@/utils';
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
const getReportColWidth = (data, accessor, headerText) => {
return getColumnWidth(
data,
accessor,
{ magicSpacing: 10, minWidth: 100 },
headerText,
);
};
const descriptionAccessor = (transaction) => {
return <span style={{ color: '#5F6B7C' }}>{transaction.description}</span>;
};
/**
* Retrieve excluded transactions columns table.
*/
export function useExcludedTransactionsColumns() {
const { excludedBankTransactions: data } = useExcludedTransactionsBoot();
const withdrawalWidth = getReportColWidth(
data,
'formatted_withdrawal_amount',
'Withdrawal',
);
const depositWidth = getReportColWidth(
data,
'formatted_deposit_amount',
'Deposit',
);
return React.useMemo(
() => [
{
Header: 'Date',
accessor: 'formatted_date',
width: 110,
},
{
Header: 'Description',
accessor: descriptionAccessor,
},
{
Header: 'Payee',
accessor: 'payee',
},
{
Header: 'Deposit',
accessor: 'formatted_deposit_amount',
align: 'right',
width: depositWidth,
},
{
Header: 'Withdrawal',
accessor: 'formatted_withdrawal_amount',
align: 'right',
width: withdrawalWidth,
},
],
[],
);
}

View File

@@ -0,0 +1,170 @@
// @ts-nocheck
import React from 'react';
import styled from 'styled-components';
import {
DataTable,
TableFastCell,
TableSkeletonRows,
TableSkeletonHeader,
TableVirtualizedListRows,
FormattedMessage as T,
AppToaster,
} from '@/components';
import { TABLES } from '@/constants/tables';
import withSettings from '@/containers/Settings/withSettings';
import withAlertsActions from '@/containers/Alert/withAlertActions';
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
import { useMemorizedColumnsWidths } from '@/hooks';
import { useUncategorizedTransactionsColumns } from './_utils';
import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot';
import { ActionsMenu } from './_components';
import { compose } from '@/utils';
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
import { Intent } from '@blueprintjs/core';
import {
WithBankingActionsProps,
withBankingActions,
} from '../../withBankingActions';
interface RecognizedTransactionsTableProps extends WithBankingActionsProps {}
/**
* Renders the recognized account transactions datatable.
*/
function RecognizedTransactionsTableRoot({
// #withSettings
cashflowTansactionsTableSize,
// #withAlertsActions
openAlert,
// #withDrawerActions
openDrawer,
// #withBanking
setUncategorizedTransactionIdForMatching,
}: RecognizedTransactionsTableProps) {
const { mutateAsync: excludeBankTransaction } =
useExcludeUncategorizedTransaction();
const { recognizedTransactions } = useRecognizedTransactionsBoot();
// Retrieve table columns.
const columns = useUncategorizedTransactionsColumns();
// Local storage memorizing columns widths.
const [initialColumnsWidths, , handleColumnResizing] =
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
// Handle cell click.
const handleCellClick = (cell, event) => {
setUncategorizedTransactionIdForMatching(
cell.row.original.uncategorized_transaction_id,
);
};
// Handle exclude button click.
const handleExcludeClick = (transaction) => {
excludeBankTransaction(transaction.uncategorized_transaction_id)
.then(() => {
AppToaster.show({
intent: Intent.SUCCESS,
message: 'The bank transaction has been excluded.',
});
})
.catch(() => {
AppToaster.show({
intent: Intent.DANGER,
message: 'Something went wrong.',
});
});
};
//
const handleCategorizeClick = (transaction) => {
setUncategorizedTransactionIdForMatching(
transaction.uncategorized_transaction_id,
);
};
return (
<CashflowTransactionsTable
noInitialFetch={true}
columns={columns}
data={recognizedTransactions}
sticky={true}
loading={false}
headerLoading={false}
expandColumnSpace={1}
expandToggleColumn={2}
selectionColumnWidth={45}
TableCellRenderer={TableFastCell}
TableLoadingRenderer={TableSkeletonRows}
TableRowsRenderer={TableVirtualizedListRows}
TableHeaderSkeletonRenderer={TableSkeletonHeader}
ContextMenu={ActionsMenu}
onCellClick={handleCellClick}
// #TableVirtualizedListRows props.
vListrowHeight={'small' == 'small' ? 32 : 40}
vListrowHeight={40}
vListOverscanRowCount={0}
initialColumnsWidths={initialColumnsWidths}
onColumnResizing={handleColumnResizing}
noResults={<T id={'cash_flow.account_transactions.no_results'} />}
className="table-constrant"
payload={{
onExclude: handleExcludeClick,
onCategorize: handleCategorizeClick,
}}
/>
);
}
export const RecognizedTransactionsTable = compose(
withAlertsActions,
withDrawerActions,
withBankingActions,
)(RecognizedTransactionsTableRoot);
const DashboardConstrantTable = styled(DataTable)`
.table {
.thead {
.th {
background: #fff;
letter-spacing: 1px;
text-transform: uppercase;
font-weight: 500;
font-size: 13px;
}
}
.tbody {
.tr:last-child .td {
border-bottom: 0;
}
}
}
`;
const CashflowTransactionsTable = styled(DashboardConstrantTable)`
.table .tbody {
.tbody-inner .tr.no-results {
.td {
padding: 2rem 0;
font-size: 14px;
color: #888;
font-weight: 400;
border-bottom: 0;
}
}
.tbody-inner {
.tr .td {
border-bottom: 1px solid #e6e6e6;
}
}
}
`;

View File

@@ -0,0 +1,89 @@
// @ts-nocheck
import React from 'react';
import { flatten, map } from 'lodash';
import { IntersectionObserver } from '@/components';
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
import { useRecognizedBankTransactionsInfinity } from '@/hooks/query/bank-rules';
interface RecognizedTransactionsContextValue {
isRecongizedTransactionsLoading: boolean;
isRecognizedTransactionsFetching: boolean;
recognizedTransactions: Array<any>;
}
const RecognizedTransactionsContext =
React.createContext<RecognizedTransactionsContextValue>(
{} as RecognizedTransactionsContextValue,
);
function flattenInfinityPagesData(data) {
return flatten(map(data.pages, (page) => page.data));
}
interface RecognizedTransactionsTableBootProps {
children: React.ReactNode;
}
/**
* Account uncategorized transctions provider.
*/
function RecognizedTransactionsTableBoot({
children,
}: RecognizedTransactionsTableBootProps) {
const { accountId } = useAccountTransactionsContext();
// Fetches the uncategorized transactions.
const {
data: recognizedTransactionsPage,
isFetching: isRecognizedTransactionsFetching,
isLoading: isRecongizedTransactionsLoading,
isSuccess: isRecognizedTransactionsSuccess,
isFetchingNextPage: isUncategorizedTransactionFetchNextPage,
fetchNextPage: fetchNextrecognizedTransactionsPage,
hasNextPage: hasUncategorizedTransactionsNextPage,
} = useRecognizedBankTransactionsInfinity({
page_size: 50,
});
// Memorized the cashflow account transactions.
const recognizedTransactions = React.useMemo(
() =>
isRecognizedTransactionsSuccess
? flattenInfinityPagesData(recognizedTransactionsPage)
: [],
[recognizedTransactionsPage, isRecognizedTransactionsSuccess],
);
// Handle the observer ineraction.
const handleObserverInteract = React.useCallback(() => {
if (
!isRecognizedTransactionsFetching &&
hasUncategorizedTransactionsNextPage
) {
fetchNextrecognizedTransactionsPage();
}
}, [
isRecognizedTransactionsFetching,
hasUncategorizedTransactionsNextPage,
fetchNextrecognizedTransactionsPage,
]);
// Provider payload.
const provider = {
recognizedTransactions,
isRecognizedTransactionsFetching,
isRecongizedTransactionsLoading,
};
return (
<RecognizedTransactionsContext.Provider value={provider}>
{children}
<IntersectionObserver
onIntersect={handleObserverInteract}
enabled={!isUncategorizedTransactionFetchNextPage}
/>
</RecognizedTransactionsContext.Provider>
);
}
const useRecognizedTransactionsBoot = () =>
React.useContext(RecognizedTransactionsContext);
export { RecognizedTransactionsTableBoot, useRecognizedTransactionsBoot };

View File

@@ -0,0 +1,19 @@
// @ts-nocheck
import { Menu, MenuItem, MenuDivider } from '@blueprintjs/core';
import { safeCallback } from '@/utils';
export function ActionsMenu({
payload: { onCategorize, onExclude },
row: { original },
}) {
return (
<Menu>
<MenuItem
text={'Categorize'}
onClick={safeCallback(onCategorize, original)}
/>
<MenuDivider />
<MenuItem text={'Exclude'} onClick={safeCallback(onExclude, original)} />
</Menu>
);
}

View File

@@ -0,0 +1,91 @@
// @ts-nocheck
import { Group, Icon } from '@/components';
import { getColumnWidth } from '@/utils';
import React from 'react';
import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot';
const getReportColWidth = (data, accessor, headerText) => {
return getColumnWidth(
data,
accessor,
{ magicSpacing: 10, minWidth: 100 },
headerText,
);
};
const recognizeAccessor = (transaction) => {
return (
<>
<span>{transaction.assigned_category_formatted}</span>
<Icon
icon={'arrowRight'}
color={'#8F99A8'}
iconSize={12}
style={{ marginLeft: 8, marginRight: 8 }}
/>
<span>{transaction.assigned_account_name}</span>
</>
);
};
const descriptionAccessor = (transaction) => {
return <span style={{ color: '#5F6B7C' }}>{transaction.description}</span>;
};
/**
* Retrieve uncategorized transactions columns table.
*/
export function useUncategorizedTransactionsColumns() {
const { recognizedTransactions: data } = useRecognizedTransactionsBoot();
const withdrawalWidth = getReportColWidth(
data,
'formatted_withdrawal_amount',
'Withdrawal',
);
const depositWidth = getReportColWidth(
data,
'formatted_deposit_amount',
'Deposit',
);
return React.useMemo(
() => [
{
Header: 'Date',
accessor: 'formatted_date',
width: 110,
},
{
Header: 'Description',
accessor: descriptionAccessor,
},
{
Header: 'Payee',
accessor: 'payee',
},
{
Header: 'Recognize',
accessor: recognizeAccessor,
textOverview: true,
},
{
Header: 'Rule',
accessor: 'bank_rule_name',
},
{
Header: 'Deposit',
accessor: 'formatted_deposit_amount',
align: 'right',
width: depositWidth,
},
{
Header: 'Withdrawal',
accessor: 'formatted_withdrawal_amount',
align: 'right',
width: withdrawalWidth,
},
],
[],
);
}

View File

@@ -44,7 +44,7 @@ export function MatchTransaction({
onClick={handleClick}
>
<Stack spacing={3}>
<span>{label}</span>
<span className={styles.label}>{label}</span>
<Text style={{ fontSize: 12, color: '#5C7080' }}>Date: {date}</Text>
</Stack>

View File

@@ -1,5 +1,10 @@
// @ts-nocheck
import { useMutation, useQuery, useQueryClient } from 'react-query';
import {
useInfiniteQuery,
useMutation,
useQuery,
useQueryClient,
} from 'react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase } from '@/utils';
@@ -118,7 +123,7 @@ export function useUnexcludeUncategorizedTransaction(props) {
return useMutation(
(uncategorizedTransactionId: number) =>
apiRequest.post(
apiRequest.put(
`/cashflow/transactions/${uncategorizedTransactionId}/unexclude`,
),
{
@@ -145,3 +150,70 @@ export function useMatchTransaction(props?: any) {
},
);
}
/**
* @returns
*/
export function useRecognizedBankTransactionsInfinity(
query,
infinityProps,
axios,
) {
const apiRequest = useApiRequest();
return useInfiniteQuery(
['RECOGNIZED_BANK_TRANSACTIONS_INFINITY', query],
async ({ pageParam = 1 }) => {
const response = await apiRequest.http({
...axios,
method: 'get',
url: `/api/banking/recognized`,
params: { page: pageParam, ...query },
});
return response.data;
},
{
getPreviousPageParam: (firstPage) => firstPage.pagination.page - 1,
getNextPageParam: (lastPage) => {
const { pagination } = lastPage;
return pagination.total > pagination.page_size * pagination.page
? lastPage.pagination.page + 1
: undefined;
},
...infinityProps,
},
);
}
export function useExcludedBankTransactionsInfinity(
query,
infinityProps,
axios,
) {
const apiRequest = useApiRequest();
return useInfiniteQuery(
['EXCLUDED_BANK_TRANSACTIONS_INFINITY', query],
async ({ pageParam = 1 }) => {
const response = await apiRequest.http({
...axios,
method: 'get',
url: `/api/cashflow/excluded`,
params: { page: pageParam, ...query },
});
return response.data;
},
{
getPreviousPageParam: (firstPage) => firstPage.pagination.page - 1,
getNextPageParam: (lastPage) => {
const { pagination } = lastPage;
return pagination.total > pagination.page_size * pagination.page
? lastPage.pagination.page + 1
: undefined;
},
...infinityProps,
},
);
}

View File

@@ -611,4 +611,10 @@ export default {
],
viewBox: '0 0 16 16',
},
arrowRight: {
path: [
'M14.7,7.29l-5-5C9.52,2.1,9.27,1.99,8.99,1.99c-0.55,0-1,0.45-1,1c0,0.28,0.11,0.53,0.29,0.71l3.29,3.29H1.99c-0.55,0-1,0.45-1,1s0.45,1,1,1h9.59l-3.29,3.29c-0.18,0.18-0.29,0.43-0.29,0.71c0,0.55,0.45,1,1,1c0.28,0,0.53-0.11,0.71-0.29l5-5c0.18-0.18,0.29-0.43,0.29-0.71S14.88,7.47,14.7,7.29z',
],
viewBox: '0 0 16 16',
},
};