import { castArray, uniq } from 'lodash'; import { PayloadAction, createSlice } from '@reduxjs/toolkit'; interface StorePlaidState { plaidToken: string; openMatchingTransactionAside: boolean; uncategorizedTransactionIdForMatching: number | null; openReconcileMatchingTransaction: { isOpen: boolean; pending: number }; uncategorizedTransactionsSelected: Array; excludedTransactionsSelected: Array; transactionsToCategorizeSelected: Array; enableMultipleCategorization: boolean; categorizedTransactionsSelected: Array; uncategorizedFilter: { fromDate?: string; toDate?: string }; } export const PlaidSlice = createSlice({ name: 'plaid', initialState: { plaidToken: '', openMatchingTransactionAside: false, uncategorizedTransactionIdForMatching: null, openReconcileMatchingTransaction: { isOpen: false, pending: 0, }, uncategorizedTransactionsSelected: [], excludedTransactionsSelected: [], transactionsToCategorizeSelected: [], enableMultipleCategorization: false, categorizedTransactionsSelected: [], // Filter uncategorizedFilter: {}, } as StorePlaidState, reducers: { setPlaidId: (state: StorePlaidState, action: PayloadAction) => { state.plaidToken = action.payload; }, resetPlaidId: (state: StorePlaidState) => { state.plaidToken = ''; }, setUncategorizedTransactionIdForMatching: ( state: StorePlaidState, action: PayloadAction, ) => { state.openMatchingTransactionAside = true; state.uncategorizedTransactionIdForMatching = action.payload; }, closeMatchingTransactionAside: (state: StorePlaidState) => { state.openMatchingTransactionAside = false; state.uncategorizedTransactionIdForMatching = null; }, openReconcileMatchingTransaction: ( state: StorePlaidState, action: PayloadAction<{ pending: number }>, ) => { state.openReconcileMatchingTransaction.isOpen = true; state.openReconcileMatchingTransaction.pending = action.payload.pending; }, closeReconcileMatchingTransaction: (state: StorePlaidState) => { state.openReconcileMatchingTransaction.isOpen = false; state.openReconcileMatchingTransaction.pending = 0; }, /** * Sets the selected uncategorized transactions. * @param {StorePlaidState} state * @param {PayloadAction<{ transactionIds: Array }>} action */ setUncategorizedTransactionsSelected: ( state: StorePlaidState, action: PayloadAction<{ transactionIds: Array }>, ) => { state.uncategorizedTransactionsSelected = action.payload.transactionIds; }, /** * Resets the selected uncategorized transactions. * @param {StorePlaidState} state */ resetUncategorizedTransactionsSelected: (state: StorePlaidState) => { state.uncategorizedTransactionsSelected = []; }, /** * Sets excluded selected transactions. * @param {StorePlaidState} state * @param {PayloadAction<{ ids: Array }>} action */ setExcludedTransactionsSelected: ( state: StorePlaidState, action: PayloadAction<{ ids: Array }>, ) => { state.excludedTransactionsSelected = action.payload.ids; }, /** * Resets the excluded selected transactions * @param {StorePlaidState} state */ resetExcludedTransactionsSelected: (state: StorePlaidState) => { state.excludedTransactionsSelected = []; }, /** * Sets the selected transactions to categorize or match. * @param {StorePlaidState} state * @param {PayloadAction<{ ids: Array }>} action */ setTransactionsToCategorizeSelected: ( state: StorePlaidState, action: PayloadAction<{ ids: Array }>, ) => { const ids = castArray(action.payload.ids); state.transactionsToCategorizeSelected = ids; state.openMatchingTransactionAside = true; }, /** * Adds a transaction to selected transactions to categorize or match. * @param {StorePlaidState} state * @param {PayloadAction<{ id: string | number }>} action */ addTransactionsToCategorizeSelected: ( state: StorePlaidState, action: PayloadAction<{ id: string | number }>, ) => { state.transactionsToCategorizeSelected = uniq([ ...state.transactionsToCategorizeSelected, action.payload.id, ]); state.openMatchingTransactionAside = true; }, /** * Removes a transaction from the selected transactions to categorize or match. * @param {StorePlaidState} state * @param {PayloadAction<{ id: string | number }>} action */ removeTransactionsToCategorizeSelected: ( state: StorePlaidState, action: PayloadAction<{ id: string | number }>, ) => { state.transactionsToCategorizeSelected = state.transactionsToCategorizeSelected.filter( (t) => t !== action.payload.id, ); if (state.transactionsToCategorizeSelected.length === 0) { state.openMatchingTransactionAside = false; } else { state.openMatchingTransactionAside = true; } }, /** * Resets the selected transactions to categorize or match. * @param {StorePlaidState} state */ resetTransactionsToCategorizeSelected: (state: StorePlaidState) => { state.transactionsToCategorizeSelected = []; state.openMatchingTransactionAside = false; }, /** * Enables/Disables the multiple selection to categorize or match. * @param {StorePlaidState} state * @param {PayloadAction<{ enable: boolean }>} action */ enableMultipleCategorization: ( state: StorePlaidState, action: PayloadAction<{ enable: boolean }>, ) => { state.enableMultipleCategorization = action.payload.enable; }, /** * Sets the selected ids of the categorized transactions. * @param {StorePlaidState} * @param {PayloadAction<{ ids: Array }>} */ setCategorizedTransactionsSelected: ( state: StorePlaidState, action: PayloadAction<{ ids: Array }>, ) => { state.categorizedTransactionsSelected = action.payload.ids; }, /** * Resets the selected categorized transcations. * @param {StorePlaidState} */ resetCategorizedTransactionsSelected: (state: StorePlaidState) => { state.categorizedTransactionsSelected = []; }, /** * Sets the uncategorized transactions filter. * @param {StorePlaidState} state * @param {PayloadAction<{ filter: any }>} action */ setUncategorizedTransactionsFilter: ( state: StorePlaidState, action: PayloadAction<{ filter: any }>, ) => { state.uncategorizedFilter = action.payload.filter; }, /** * Resets the uncategorized transactions filter. * @param {StorePlaidState} state */ resetUncategorizedTranasctionsFilter: (state: StorePlaidState) => { state.uncategorizedFilter = {}; }, }, }); export const { setPlaidId, resetPlaidId, setUncategorizedTransactionIdForMatching, closeMatchingTransactionAside, openReconcileMatchingTransaction, closeReconcileMatchingTransaction, setUncategorizedTransactionsSelected, resetUncategorizedTransactionsSelected, setExcludedTransactionsSelected, resetExcludedTransactionsSelected, setTransactionsToCategorizeSelected, addTransactionsToCategorizeSelected, removeTransactionsToCategorizeSelected, resetTransactionsToCategorizeSelected, enableMultipleCategorization, setCategorizedTransactionsSelected, resetCategorizedTransactionsSelected, // Uncategorized transactions filter. setUncategorizedTransactionsFilter, resetUncategorizedTranasctionsFilter, } = PlaidSlice.actions; export const getPlaidToken = (state: any) => state.plaid.plaidToken; export const getTransactionsToCategorizeSelected = (state: any) => state.plaid.transactionsToCategorizeSelected; export const getOpenMatchingTransactionAside = (state: any) => state.plaid.openMatchingTransactionAside; export const isMultipleCategorization = (state: any) => state.plaid.enableMultipleCategorization; export const getTransactionsToCategorizeIdsSelected = (state: any) => state.plaid.transactionsToCategorizeSelected; export const getUncategorizedTransactionsFilter = (state: any) => state.uncategorizedFilter;