mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
Merge pull request #590 from bigcapitalhq/filter-uncategorized-bank-transactions
feat(banking): Filter uncategorized bank transactions by date
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
.dateFieldGroup{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
// @ts-nocheck
|
||||
import { Button, FormGroup, Intent, Position } from '@blueprintjs/core';
|
||||
import * as Yup from 'yup';
|
||||
import moment from 'moment';
|
||||
import { Form, Formik, FormikConfig, useFormikContext } from 'formik';
|
||||
import {
|
||||
FDateInput,
|
||||
FFormGroup,
|
||||
FSelect,
|
||||
Group,
|
||||
Icon,
|
||||
Stack,
|
||||
} from '@/components';
|
||||
|
||||
const defaultValues = {
|
||||
period: 'all_dates',
|
||||
fromDate: '',
|
||||
toDate: '',
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
fromDate: Yup.date()
|
||||
.nullable()
|
||||
.required('From Date is required')
|
||||
.max(Yup.ref('toDate'), 'From Date cannot be after To Date'),
|
||||
toDate: Yup.date()
|
||||
.nullable()
|
||||
.required('To Date is required')
|
||||
.min(Yup.ref('fromDate'), 'To Date cannot be before From Date'),
|
||||
});
|
||||
|
||||
interface AccountTransactionsDateFilterFormValues {
|
||||
period: string;
|
||||
fromDate: string;
|
||||
toDate: string;
|
||||
}
|
||||
|
||||
interface UncategorizedTransactionsDateFilterProps {
|
||||
initialValues?: AccountTransactionsDateFilterFormValues;
|
||||
onSubmit?: FormikConfig<AccountTransactionsDateFilterFormValues>['onSubmit'];
|
||||
}
|
||||
|
||||
export function AccountTransactionsDateFilterForm({
|
||||
initialValues = {},
|
||||
onSubmit,
|
||||
}: UncategorizedTransactionsDateFilterProps) {
|
||||
const handleSubmit = (values, bag) => {
|
||||
return onSubmit && onSubmit(values, bag);
|
||||
};
|
||||
|
||||
const formInitialValues = {
|
||||
...defaultValues,
|
||||
...initialValues,
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={formInitialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
>
|
||||
<Form>
|
||||
<Stack spacing={15}>
|
||||
<Group spacing={10}>
|
||||
<AccountTransactionDatePeriodField />
|
||||
|
||||
<FFormGroup
|
||||
name={'fromDate'}
|
||||
label={'From Date'}
|
||||
style={{ marginBottom: 0, flex: '1' }}
|
||||
>
|
||||
<FDateInput
|
||||
name={'fromDate'}
|
||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||
formatDate={(date) => date.toLocaleDateString()}
|
||||
parseDate={(str) => new Date(str)}
|
||||
inputProps={{
|
||||
fill: true,
|
||||
placeholder: 'MM/DD/YYY',
|
||||
leftElement: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</FFormGroup>
|
||||
|
||||
<FormGroup
|
||||
label={'To Date'}
|
||||
name={'toDate'}
|
||||
style={{ marginBottom: 0, flex: '1' }}
|
||||
>
|
||||
<FDateInput
|
||||
name={'toDate'}
|
||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||
formatDate={(date) => date.toLocaleDateString()}
|
||||
parseDate={(str) => new Date(str)}
|
||||
inputProps={{
|
||||
fill: true,
|
||||
placeholder: 'MM/DD/YYY',
|
||||
leftElement: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Group>
|
||||
|
||||
<AccountTransactionsDateFilterFooter />
|
||||
</Stack>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountTransactionsDateFilterFooter() {
|
||||
const { submitForm, setValues } = useFormikContext();
|
||||
|
||||
const handleFilterBtnClick = () => {
|
||||
submitForm();
|
||||
};
|
||||
const handleClearBtnClick = () => {
|
||||
setValues({
|
||||
...defaultValues,
|
||||
});
|
||||
submitForm();
|
||||
};
|
||||
|
||||
return (
|
||||
<Group spacing={10}>
|
||||
<Button
|
||||
small
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleFilterBtnClick}
|
||||
style={{ minWidth: 75 }}
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
intent={Intent.DANGER}
|
||||
small
|
||||
onClick={handleClearBtnClick}
|
||||
minimal
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountTransactionDatePeriodField() {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
const handleItemChange = (item) => {
|
||||
const { fromDate, toDate } = getDateRangePeriod(item.value);
|
||||
|
||||
setFieldValue('fromDate', fromDate);
|
||||
setFieldValue('toDate', toDate);
|
||||
setFieldValue('period', item.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<FFormGroup
|
||||
name={'period'}
|
||||
label={'Date'}
|
||||
style={{ marginBottom: 0, flex: '0 28%' }}
|
||||
>
|
||||
<FSelect
|
||||
name={'period'}
|
||||
items={periodOptions}
|
||||
onItemSelect={handleItemChange}
|
||||
popoverProps={{ captureDismiss: true }}
|
||||
/>
|
||||
</FFormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const periodOptions = [
|
||||
{ text: 'All Dates', value: 'all_dates' },
|
||||
{ text: 'Custom', value: 'custom' },
|
||||
{ text: 'Today', value: 'today' },
|
||||
{ text: 'Yesterday', value: 'yesterday' },
|
||||
{ text: 'This week', value: 'this_week' },
|
||||
{ text: 'This year', value: 'this_year' },
|
||||
{ text: 'This month', value: 'this_month' },
|
||||
{ text: 'last week', value: 'last_week' },
|
||||
{ text: 'Last year', value: 'last_year' },
|
||||
{ text: 'Last month', value: 'last_month' },
|
||||
{ text: 'Last month', value: 'last_month' },
|
||||
];
|
||||
|
||||
const getDateRangePeriod = (period: string) => {
|
||||
switch (period) {
|
||||
case 'today':
|
||||
return {
|
||||
fromDate: moment().startOf('day').toDate(),
|
||||
toDate: moment().endOf('day').toDate(),
|
||||
};
|
||||
case 'yesterday':
|
||||
return {
|
||||
fromDate: moment().subtract(1, 'days').startOf('day').toDate(),
|
||||
toDate: moment().subtract(1, 'days').endOf('day').toDate(),
|
||||
};
|
||||
case 'this_week':
|
||||
return {
|
||||
fromDate: moment().startOf('week').toDate(),
|
||||
toDate: moment().endOf('week').toDate(),
|
||||
};
|
||||
case 'this_month':
|
||||
return {
|
||||
fromDate: moment().startOf('month').toDate(),
|
||||
toDate: moment().endOf('month').toDate(),
|
||||
};
|
||||
case 'this_year':
|
||||
return {
|
||||
fromDate: moment().startOf('year').toDate(),
|
||||
toDate: moment().endOf('year').toDate(),
|
||||
};
|
||||
case 'last_week':
|
||||
return {
|
||||
fromDate: moment().subtract(1, 'weeks').startOf('week').toDate(),
|
||||
toDate: moment().subtract(1, 'weeks').endOf('week').toDate(),
|
||||
};
|
||||
case 'last_month':
|
||||
return {
|
||||
fromDate: moment().subtract(1, 'months').startOf('month').toDate(),
|
||||
toDate: moment().subtract(1, 'months').endOf('month').toDate(),
|
||||
};
|
||||
case 'last_year':
|
||||
return {
|
||||
fromDate: moment().subtract(1, 'years').startOf('year').toDate(),
|
||||
toDate: moment().subtract(1, 'years').endOf('year').toDate(),
|
||||
};
|
||||
case 'all_dates':
|
||||
case 'custom':
|
||||
default:
|
||||
return { fromDate: null, toDate: null };
|
||||
}
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
// @ts-nocheck
|
||||
import * as R from 'ramda';
|
||||
import { useMemo } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { useAppQueryString } from '@/hooks';
|
||||
import { Group } from '@/components';
|
||||
import { Group, Stack, } from '@/components';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import { TagsControl } from '@/components/TagsControl';
|
||||
import { AccountUncategorizedDateFilter } from './UncategorizedTransactions/AccountUncategorizedDateFilter';
|
||||
import { Divider } from '@blueprintjs/core';
|
||||
|
||||
export function AccountTransactionsUncategorizeFilter() {
|
||||
const { bankAccountMetaSummary } = useAccountTransactionsContext();
|
||||
@@ -54,12 +56,17 @@ export function AccountTransactionsUncategorizeFilter() {
|
||||
);
|
||||
|
||||
return (
|
||||
<Group position={'apart'}>
|
||||
<TagsControl
|
||||
options={options}
|
||||
value={locationQuery?.uncategorizedFilter || 'all'}
|
||||
onValueChange={handleTabsChange}
|
||||
/>
|
||||
<Group position={'apart'} style={{ marginBottom: 14 }}>
|
||||
<Group align={'stretch'} spacing={10}>
|
||||
<TagsControl
|
||||
options={options}
|
||||
value={locationQuery?.uncategorizedFilter || 'all'}
|
||||
onValueChange={handleTabsChange}
|
||||
/>
|
||||
<Divider />
|
||||
<AccountUncategorizedDateFilter />
|
||||
</Group>
|
||||
|
||||
<TagsControl
|
||||
options={[{ value: 'excluded', label: 'Excluded' }]}
|
||||
value={locationQuery?.uncategorizedFilter || 'all'}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
import React from 'react';
|
||||
import { flatten, map } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import { IntersectionObserver } from '@/components';
|
||||
import { useAccountUncategorizedTransactionsInfinity } from '@/hooks/query';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import { withBanking } from '../withBanking';
|
||||
|
||||
const AccountUncategorizedTransactionsContext = React.createContext();
|
||||
|
||||
@@ -13,9 +15,15 @@ function flattenInfinityPagesData(data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Account uncategorized transctions provider.
|
||||
* Account un-categorized transactions provider.
|
||||
*/
|
||||
function AccountUncategorizedTransactionsBoot({ children }) {
|
||||
function AccountUncategorizedTransactionsBootRoot({
|
||||
// #withBanking
|
||||
uncategorizedTransactionsFilter,
|
||||
|
||||
// #ownProps
|
||||
children,
|
||||
}) {
|
||||
const { accountId } = useAccountTransactionsContext();
|
||||
|
||||
// Fetches the uncategorized transactions.
|
||||
@@ -29,6 +37,8 @@ function AccountUncategorizedTransactionsBoot({ children }) {
|
||||
hasNextPage: hasUncategorizedTransactionsNextPage,
|
||||
} = useAccountUncategorizedTransactionsInfinity(accountId, {
|
||||
page_size: 50,
|
||||
min_date: uncategorizedTransactionsFilter?.fromDate || null,
|
||||
max_date: uncategorizedTransactionsFilter?.toDate || null,
|
||||
});
|
||||
// Memorized the cashflow account transactions.
|
||||
const uncategorizedTransactions = React.useMemo(
|
||||
@@ -69,6 +79,12 @@ function AccountUncategorizedTransactionsBoot({ children }) {
|
||||
);
|
||||
}
|
||||
|
||||
const AccountUncategorizedTransactionsBoot = R.compose(
|
||||
withBanking(({ uncategorizedTransactionsFilter }) => ({
|
||||
uncategorizedTransactionsFilter,
|
||||
})),
|
||||
)(AccountUncategorizedTransactionsBootRoot);
|
||||
|
||||
const useAccountUncategorizedTransactionsContext = () =>
|
||||
React.useContext(AccountUncategorizedTransactionsContext);
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { flatten, map } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import { IntersectionObserver } from '@/components';
|
||||
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||
import { useExcludedBankTransactionsInfinity } from '@/hooks/query/bank-rules';
|
||||
import { withBanking } from '../../withBanking';
|
||||
|
||||
interface ExcludedBankTransactionsContextValue {
|
||||
isExcludedTransactionsLoading: boolean;
|
||||
@@ -27,7 +29,11 @@ interface ExcludedBankTransactionsTableBootProps {
|
||||
/**
|
||||
* Account uncategorized transctions provider.
|
||||
*/
|
||||
function ExcludedBankTransactionsTableBoot({
|
||||
function ExcludedBankTransactionsTableBootRoot({
|
||||
// #withBanking
|
||||
uncategorizedTransactionsFilter,
|
||||
|
||||
// #ownProps
|
||||
children,
|
||||
}: ExcludedBankTransactionsTableBootProps) {
|
||||
const { accountId } = useAccountTransactionsContext();
|
||||
@@ -44,6 +50,8 @@ function ExcludedBankTransactionsTableBoot({
|
||||
} = useExcludedBankTransactionsInfinity({
|
||||
page_size: 50,
|
||||
account_id: accountId,
|
||||
min_date: uncategorizedTransactionsFilter?.fromDate || null,
|
||||
max_date: uncategorizedTransactionsFilter.toDate || null,
|
||||
});
|
||||
// Memorized the cashflow account transactions.
|
||||
const excludedBankTransactions = React.useMemo(
|
||||
@@ -84,6 +92,12 @@ function ExcludedBankTransactionsTableBoot({
|
||||
);
|
||||
}
|
||||
|
||||
const ExcludedBankTransactionsTableBoot = R.compose(
|
||||
withBanking(({ uncategorizedTransactionsFilter }) => ({
|
||||
uncategorizedTransactionsFilter,
|
||||
})),
|
||||
)(ExcludedBankTransactionsTableBootRoot);
|
||||
|
||||
const useExcludedTransactionsBoot = () =>
|
||||
React.useContext(ExcludedTransactionsContext);
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { flatten, map } from 'lodash';
|
||||
import { IntersectionObserver } from '@/components';
|
||||
import * as R from 'ramda';
|
||||
import { IntersectionObserver, NumericInputCell } from '@/components';
|
||||
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||
import { useRecognizedBankTransactionsInfinity } from '@/hooks/query/bank-rules';
|
||||
import { withBanking } from '../../withBanking';
|
||||
|
||||
interface RecognizedTransactionsContextValue {
|
||||
isRecongizedTransactionsLoading: boolean;
|
||||
@@ -27,7 +29,10 @@ interface RecognizedTransactionsTableBootProps {
|
||||
/**
|
||||
* Account uncategorized transctions provider.
|
||||
*/
|
||||
function RecognizedTransactionsTableBoot({
|
||||
function RecognizedTransactionsTableBootRoot({
|
||||
// #withBanking
|
||||
uncategorizedTransactionsFilter,
|
||||
|
||||
children,
|
||||
}: RecognizedTransactionsTableBootProps) {
|
||||
const { accountId } = useAccountTransactionsContext();
|
||||
@@ -44,6 +49,8 @@ function RecognizedTransactionsTableBoot({
|
||||
} = useRecognizedBankTransactionsInfinity({
|
||||
page_size: 50,
|
||||
account_id: accountId,
|
||||
min_date: uncategorizedTransactionsFilter.fromDate || null,
|
||||
max_date: uncategorizedTransactionsFilter?.toDate || null,
|
||||
});
|
||||
// Memorized the cashflow account transactions.
|
||||
const recognizedTransactions = React.useMemo(
|
||||
@@ -84,6 +91,12 @@ function RecognizedTransactionsTableBoot({
|
||||
);
|
||||
}
|
||||
|
||||
const RecognizedTransactionsTableBoot = R.compose(
|
||||
withBanking(({ uncategorizedTransactionsFilter }) => ({
|
||||
uncategorizedTransactionsFilter,
|
||||
})),
|
||||
)(RecognizedTransactionsTableBootRoot);
|
||||
|
||||
const useRecognizedTransactionsBoot = () =>
|
||||
React.useContext(RecognizedTransactionsContext);
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// @ts-nocheck
|
||||
import { useState } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import moment from 'moment';
|
||||
import { Box, Icon } from '@/components';
|
||||
import { Classes, Popover, Position } from '@blueprintjs/core';
|
||||
import { withBankingActions } from '../../withBankingActions';
|
||||
import { withBanking } from '../../withBanking';
|
||||
import { AccountTransactionsDateFilterForm } from '../AccountTransactionsDateFilter';
|
||||
import { TagButton } from './TagButton';
|
||||
|
||||
function AccountUncategorizedDateFilterRoot({
|
||||
uncategorizedTransactionsFilter,
|
||||
}) {
|
||||
const fromDate = uncategorizedTransactionsFilter?.fromDate;
|
||||
const toDate = uncategorizedTransactionsFilter?.toDate;
|
||||
|
||||
const fromDateFormatted = moment(fromDate).isSame(
|
||||
moment().format('YYYY'),
|
||||
'year',
|
||||
)
|
||||
? moment(fromDate).format('MMM, DD')
|
||||
: moment(fromDate).format('MMM, DD, YYYY');
|
||||
const toDateFormatted = moment(toDate).isSame(moment().format('YYYY'), 'year')
|
||||
? moment(toDate).format('MMM, DD')
|
||||
: moment(toDate).format('MMM, DD, YYYY');
|
||||
|
||||
const buttonText =
|
||||
fromDate && toDate
|
||||
? `Date: ${fromDateFormatted} → ${toDateFormatted}`
|
||||
: 'Date Filter';
|
||||
|
||||
// Popover open state.
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
|
||||
// Handle the filter form submitting.
|
||||
const handleSubmit = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={
|
||||
<Box style={{ padding: 18 }}>
|
||||
<UncategorizedTransactionsDateFilter onSubmit={handleSubmit} />
|
||||
</Box>
|
||||
}
|
||||
position={Position.RIGHT}
|
||||
popoverClassName={Classes.POPOVER_CONTENT}
|
||||
isOpen={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<TagButton
|
||||
outline
|
||||
icon={<Icon icon={'date-range'} />}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{buttonText}
|
||||
</TagButton>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
export const AccountUncategorizedDateFilter = R.compose(
|
||||
withBanking(({ uncategorizedTransactionsFilter }) => ({
|
||||
uncategorizedTransactionsFilter,
|
||||
})),
|
||||
)(AccountUncategorizedDateFilterRoot);
|
||||
|
||||
export const UncategorizedTransactionsDateFilter = R.compose(
|
||||
withBankingActions,
|
||||
withBanking(({ uncategorizedTransactionsFilter }) => ({
|
||||
uncategorizedTransactionsFilter,
|
||||
})),
|
||||
)(
|
||||
({
|
||||
// #withBankingActions
|
||||
setUncategorizedTransactionsFilter,
|
||||
|
||||
// #withBanking
|
||||
uncategorizedTransactionsFilter,
|
||||
|
||||
// #ownProps
|
||||
onSubmit,
|
||||
}) => {
|
||||
const initialValues = {
|
||||
...uncategorizedTransactionsFilter,
|
||||
};
|
||||
|
||||
const handleSubmit = (values) => {
|
||||
setUncategorizedTransactionsFilter({
|
||||
fromDate: values.fromDate,
|
||||
toDate: values.toDate,
|
||||
});
|
||||
onSubmit && onSubmit(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<AccountTransactionsDateFilterForm
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,11 @@
|
||||
.root{
|
||||
min-height: 26px;
|
||||
border-radius: 15px;
|
||||
font-size: 13px;
|
||||
padding: 0 10px;
|
||||
|
||||
&:global(.bp4-button:not([class*=bp4-intent-]):not(.bp4-minimal)) {
|
||||
background: #fff;
|
||||
border: 1px solid #e1e2e8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import { Button } from "@blueprintjs/core"
|
||||
import styles from './TagButton.module.scss';
|
||||
|
||||
|
||||
|
||||
export const TagButton = (props) => {
|
||||
return <Button {...props} className={styles.root} />
|
||||
}
|
||||
@@ -25,6 +25,8 @@ export const withBanking = (mapState) => {
|
||||
|
||||
categorizedTransactionsSelected:
|
||||
state.plaid.categorizedTransactionsSelected,
|
||||
|
||||
uncategorizedTransactionsFilter: state.plaid.uncategorizedFilter
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
removeTransactionsToCategorizeSelected,
|
||||
setCategorizedTransactionsSelected,
|
||||
resetCategorizedTransactionsSelected,
|
||||
setUncategorizedTransactionsFilter,
|
||||
resetUncategorizedTranasctionsFilter,
|
||||
} from '@/store/banking/banking.reducer';
|
||||
|
||||
export interface WithBankingActionsProps {
|
||||
@@ -40,6 +42,9 @@ export interface WithBankingActionsProps {
|
||||
|
||||
setCategorizedTransactionsSelected: (ids: Array<string | number>) => void;
|
||||
resetCategorizedTransactionsSelected: () => void;
|
||||
|
||||
setUncategorizedTransactionsFilter: (filter: any) => void;
|
||||
resetUncategorizedTranasctionsFilter: () => void;
|
||||
}
|
||||
|
||||
const mapDipatchToProps = (dispatch: any): WithBankingActionsProps => ({
|
||||
@@ -138,6 +143,19 @@ const mapDipatchToProps = (dispatch: any): WithBankingActionsProps => ({
|
||||
*/
|
||||
resetCategorizedTransactionsSelected: () =>
|
||||
dispatch(resetCategorizedTransactionsSelected()),
|
||||
|
||||
/**
|
||||
* Sets the uncategorized transactions filter.
|
||||
* @param {any} filter -
|
||||
*/
|
||||
setUncategorizedTransactionsFilter: (filter: any) =>
|
||||
dispatch(setUncategorizedTransactionsFilter({ filter })),
|
||||
|
||||
/**
|
||||
* Resets the uncategorized transactions filter.
|
||||
*/
|
||||
resetUncategorizedTranasctionsFilter: () =>
|
||||
dispatch(resetUncategorizedTranasctionsFilter()),
|
||||
});
|
||||
|
||||
export const withBankingActions = connect<
|
||||
|
||||
Reference in New Issue
Block a user