diff --git a/src/CONST.ts b/src/CONST.ts index dcef6d01f36c..f7f7e40d5043 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -5188,12 +5188,16 @@ const CONST = { REPORT: 'report', }, ACTION_TYPES: { - DONE: 'done', - PAID: 'paid', VIEW: 'view', REVIEW: 'review', + DONE: 'done', + PAID: 'paid', + }, + BULK_ACTION_TYPES: { + EXPORT: 'export', HOLD: 'hold', UNHOLD: 'unhold', + DELETE: 'delete', }, TRANSACTION_TYPE: { CASH: 'cash', @@ -5224,15 +5228,6 @@ const CONST = { ACTION: 'action', TAX_AMOUNT: 'taxAmount', }, - BULK_ACTION_TYPES: { - DELETE: 'delete', - HOLD: 'hold', - UNHOLD: 'unhold', - SUBMIT: 'submit', - APPROVE: 'approve', - PAY: 'pay', - EXPORT: 'export', - }, SYNTAX_OPERATORS: { AND: 'and', OR: 'or', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 0ccb210c9d7a..d8bba1a3615b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -61,8 +61,8 @@ const ROUTES = { }, TRANSACTION_HOLD_REASON_RHP: { - route: 'search/:query/hold/:transactionID', - getRoute: (query: string, transactionID: string) => `search/${query}/hold/${transactionID}` as const, + route: 'search/:query/hold', + getRoute: (query: string) => `search/${query}/hold` as const, }, // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated diff --git a/src/components/Search/SearchContext.tsx b/src/components/Search/SearchContext.tsx index 3911780d3965..367a03e081cd 100644 --- a/src/components/Search/SearchContext.tsx +++ b/src/components/Search/SearchContext.tsx @@ -6,7 +6,7 @@ const defaultSearchContext = { currentSearchHash: -1, selectedTransactionIDs: [], setCurrentSearchHash: () => {}, - setSelectedTransactionIds: () => {}, + setSelectedTransactionIDs: () => {}, }; const Context = React.createContext(defaultSearchContext); @@ -27,7 +27,7 @@ function SearchContextProvider({children}: ChildrenProps) { [searchContextData], ); - const setSelectedTransactionIds = useCallback( + const setSelectedTransactionIDs = useCallback( (selectedTransactionIDs: string[]) => { setSearchContextData({ ...searchContextData, @@ -41,9 +41,9 @@ function SearchContextProvider({children}: ChildrenProps) { () => ({ ...searchContextData, setCurrentSearchHash, - setSelectedTransactionIds, + setSelectedTransactionIDs, }), - [searchContextData, setCurrentSearchHash, setSelectedTransactionIds], + [searchContextData, setCurrentSearchHash, setSelectedTransactionIDs], ); return {children}; diff --git a/src/components/Search/SearchListWithHeader.tsx b/src/components/Search/SearchListWithHeader.tsx index 87a39fdd504b..bd4b843bbd60 100644 --- a/src/components/Search/SearchListWithHeader.tsx +++ b/src/components/Search/SearchListWithHeader.tsx @@ -26,7 +26,7 @@ type SearchListWithHeaderProps = Omit selectedTransactions[id].canDelete); + const shouldShowHoldOption = !isOffline && selectedTransactionsKeys.every((id) => selectedTransactions[id].canHold); - if (itemsToDelete.length > 0) { + if (shouldShowHoldOption) { options.push({ - icon: Expensicons.Trashcan, - text: translate('search.bulkActions.delete'), - value: CONST.SEARCH.BULK_ACTION_TYPES.DELETE, + icon: Expensicons.Stopwatch, + text: translate('search.bulkActions.hold'), + value: CONST.SEARCH.BULK_ACTION_TYPES.HOLD, shouldCloseModalOnSelect: true, onSelected: () => { if (isOffline) { @@ -99,18 +104,23 @@ function SearchPageHeader({ return; } - onSelectDeleteOption?.(itemsToDelete); + clearSelectedItems?.(); + if (isMobileSelectionModeActive) { + setIsMobileSelectionModeActive?.(false); + } + setSelectedTransactionIDs(selectedTransactionsKeys); + Navigation.navigate(ROUTES.TRANSACTION_HOLD_REASON_RHP.getRoute(query)); }, }); } - const itemsToHold = selectedTransactionsKeys.filter((id) => selectedTransactions[id].action === CONST.SEARCH.BULK_ACTION_TYPES.HOLD); + const shouldShowUnholdOption = !isOffline && selectedTransactionsKeys.every((id) => selectedTransactions[id].canUnhold); - if (itemsToHold.length > 0) { + if (shouldShowUnholdOption) { options.push({ icon: Expensicons.Stopwatch, - text: translate('search.bulkActions.hold'), - value: CONST.SEARCH.BULK_ACTION_TYPES.HOLD, + text: translate('search.bulkActions.unhold'), + value: CONST.SEARCH.BULK_ACTION_TYPES.UNHOLD, shouldCloseModalOnSelect: true, onSelected: () => { if (isOffline) { @@ -122,18 +132,18 @@ function SearchPageHeader({ if (isMobileSelectionModeActive) { setIsMobileSelectionModeActive?.(false); } - SearchActions.holdMoneyRequestOnSearch(hash, itemsToHold, ''); + SearchActions.unholdMoneyRequestOnSearch(hash, selectedTransactionsKeys); }, }); } - const itemsToUnhold = selectedTransactionsKeys.filter((id) => selectedTransactions[id].action === CONST.SEARCH.BULK_ACTION_TYPES.UNHOLD); + const shouldShowDeleteOption = !isOffline && selectedTransactionsKeys.every((id) => selectedTransactions[id].canDelete); - if (itemsToUnhold.length > 0) { + if (shouldShowDeleteOption) { options.push({ - icon: Expensicons.Stopwatch, - text: translate('search.bulkActions.unhold'), - value: CONST.SEARCH.BULK_ACTION_TYPES.UNHOLD, + icon: Expensicons.Trashcan, + text: translate('search.bulkActions.delete'), + value: CONST.SEARCH.BULK_ACTION_TYPES.DELETE, shouldCloseModalOnSelect: true, onSelected: () => { if (isOffline) { @@ -141,11 +151,7 @@ function SearchPageHeader({ return; } - clearSelectedItems?.(); - if (isMobileSelectionModeActive) { - setIsMobileSelectionModeActive?.(false); - } - SearchActions.unholdMoneyRequestOnSearch(hash, itemsToUnhold); + onSelectDeleteOption?.(selectedTransactionsKeys); }, }); } @@ -188,6 +194,7 @@ function SearchPageHeader({ activeWorkspaceID, selectedReports, styles.textWrap, + setSelectedTransactionIDs, ]); if (isSmallScreenWidth) { diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 2238b0f49855..232ae841d4ff 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -9,6 +9,12 @@ type SelectedTransactionInfo = { /** If the transaction can be deleted */ canDelete: boolean; + /** If the transaction can be put on hold */ + canHold: boolean; + + /** If the transaction can be removed from hold */ + canUnhold: boolean; + /** The action that can be performed for the transaction */ action: string; }; @@ -23,7 +29,7 @@ type SearchContext = { currentSearchHash: number; selectedTransactionIDs: string[]; setCurrentSearchHash: (hash: number) => void; - setSelectedTransactionIds: (selectedTransactionIds: string[]) => void; + setSelectedTransactionIDs: (selectedTransactionIds: string[]) => void; }; type ASTNode = { diff --git a/src/components/SelectionList/Search/ActionCell.tsx b/src/components/SelectionList/Search/ActionCell.tsx index 7888a8b26114..f535c0342e55 100644 --- a/src/components/SelectionList/Search/ActionCell.tsx +++ b/src/components/SelectionList/Search/ActionCell.tsx @@ -1,19 +1,15 @@ -import React, {useCallback} from 'react'; +import React from 'react'; import {View} from 'react-native'; import Badge from '@components/Badge'; import Button from '@components/Button'; import * as Expensicons from '@components/Icon/Expensicons'; -import {useSearchContext} from '@components/Search/SearchContext'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import Navigation from '@navigation/Navigation'; import variables from '@styles/variables'; -import * as SearchActions from '@userActions/Search'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -import ROUTES from '@src/ROUTES'; import type {SearchTransactionAction} from '@src/types/onyx/SearchResults'; const actionTranslationsMap: Record = { @@ -21,13 +17,10 @@ const actionTranslationsMap: Record = review: 'common.review', done: 'common.done', paid: 'iou.settledExpensify', - hold: 'iou.hold', - unhold: 'iou.unhold', }; type ActionCellProps = { action?: SearchTransactionAction; - transactionID?: string; isLargeScreenWidth?: boolean; isSelected?: boolean; goToItem: () => void; @@ -35,34 +28,12 @@ type ActionCellProps = { parentAction?: string; }; -function ActionCell({ - action = CONST.SEARCH.ACTION_TYPES.VIEW, - transactionID, - isLargeScreenWidth = true, - isSelected = false, - goToItem, - isChildListItem = false, - parentAction = '', -}: ActionCellProps) { +function ActionCell({action = CONST.SEARCH.ACTION_TYPES.VIEW, isLargeScreenWidth = true, isSelected = false, goToItem, isChildListItem = false, parentAction = ''}: ActionCellProps) { const {translate} = useLocalize(); const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const {currentSearchHash} = useSearchContext(); - - const onButtonPress = useCallback(() => { - if (!transactionID) { - return; - } - - if (action === CONST.SEARCH.ACTION_TYPES.HOLD) { - Navigation.navigate(ROUTES.TRANSACTION_HOLD_REASON_RHP.getRoute(CONST.SEARCH.TAB.ALL, transactionID)); - } else if (action === CONST.SEARCH.ACTION_TYPES.UNHOLD) { - SearchActions.unholdMoneyRequestOnSearch(currentSearchHash, [transactionID]); - } - }, [action, currentSearchHash, transactionID]); - const text = translate(actionTranslationsMap[action]); const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || (parentAction === CONST.SEARCH.ACTION_TYPES.PAID && action === CONST.SEARCH.ACTION_TYPES.PAID); @@ -119,16 +90,6 @@ function ActionCell({ /> ); } - return ( -