diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index a299ae5343b25..73542310819bc 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -8,6 +8,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useDeleteTransactions from '@hooks/useDeleteTransactions'; import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations'; import useGetIOUReportFromReportAction from '@hooks/useGetIOUReportFromReportAction'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLoadingBarVisibility from '@hooks/useLoadingBarVisibility'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -59,7 +60,6 @@ import HeaderWithBackButton from './HeaderWithBackButton'; import HoldOrRejectEducationalModal from './HoldOrRejectEducationalModal'; import HoldSubmitterEducationalModal from './HoldSubmitterEducationalModal'; import Icon from './Icon'; -import * as Expensicons from './Icon/Expensicons'; import LoadingBar from './LoadingBar'; import type {MoneyRequestHeaderStatusBarProps} from './MoneyRequestHeaderStatusBar'; import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar'; @@ -108,6 +108,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre > | null>(null); const [dismissedRejectUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_REJECT_USE_EXPLANATION, {canBeMissing: true}); const [dismissedHoldUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION, {canBeMissing: true}); + const [allSnapshots] = useOnyx(ONYXKEYS.COLLECTION.SNAPSHOT, {canBeMissing: true}); const shouldShowLoadingBar = useLoadingBarVisibility(); const styles = useThemeStyles(); const theme = useTheme(); @@ -154,24 +155,37 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre /> ); + const expensifyIcons = useMemoizedLazyExpensifyIcons([ + 'Stopwatch', + 'Hourglass', + 'Flag', + 'CreditCardHourglass', + 'ReceiptScan', + 'ArrowSplit', + 'ArrowCollapse', + 'Info', + 'Trashcan', + 'ThumbsDown', + ]); + const getStatusBarProps: () => MoneyRequestHeaderStatusBarProps | undefined = () => { if (isOnHold) { - return {icon: getStatusIcon(Expensicons.Stopwatch), description: translate('iou.expenseOnHold')}; + return {icon: getStatusIcon(expensifyIcons.Stopwatch), description: translate('iou.expenseOnHold')}; } if (isMarkAsResolvedAction(parentReport, transactionViolations, policy)) { - return {icon: getStatusIcon(Expensicons.Hourglass), description: translate('iou.reject.rejectedStatus')}; + return {icon: getStatusIcon(expensifyIcons.Hourglass), description: translate('iou.reject.rejectedStatus')}; } if (isDuplicate) { - return {icon: getStatusIcon(Expensicons.Flag), description: translate('iou.expenseDuplicate')}; + return {icon: getStatusIcon(expensifyIcons.Flag), description: translate('iou.expenseDuplicate')}; } if (isExpensifyCardTransaction(transaction) && isPending(transaction)) { - return {icon: getStatusIcon(Expensicons.CreditCardHourglass), description: translate('iou.transactionPendingDescription')}; + return {icon: getStatusIcon(expensifyIcons.CreditCardHourglass), description: translate('iou.transactionPendingDescription')}; } if (shouldShowBrokenConnectionViolation) { return { - icon: getStatusIcon(Expensicons.Hourglass), + icon: getStatusIcon(expensifyIcons.Hourglass), description: ( , DropdownOption>> = { [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.HOLD]: { text: translate('iou.hold'), - icon: Expensicons.Stopwatch, + icon: expensifyIcons.Stopwatch, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.HOLD, onSelected: () => { if (!parentReportAction) { @@ -319,7 +333,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REMOVE_HOLD]: { text: translate('iou.unhold'), - icon: Expensicons.Stopwatch, + icon: expensifyIcons.Stopwatch, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REMOVE_HOLD, onSelected: () => { if (!parentReportAction) { @@ -331,7 +345,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.SPLIT]: { text: isExpenseSplit ? translate('iou.editSplits') : translate('iou.split'), - icon: Expensicons.ArrowSplit, + icon: expensifyIcons.ArrowSplit, value: CONST.REPORT.SECONDARY_ACTIONS.SPLIT, onSelected: () => { initSplitExpense(allTransactions, allReports, transaction); @@ -339,7 +353,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE]: { text: translate('common.merge'), - icon: Expensicons.ArrowCollapse, + icon: expensifyIcons.ArrowCollapse, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.MERGE, onSelected: () => { if (!transaction) { @@ -353,14 +367,14 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.VIEW_DETAILS]: { value: CONST.REPORT.SECONDARY_ACTIONS.VIEW_DETAILS, text: translate('iou.viewDetails'), - icon: Expensicons.Info, + icon: expensifyIcons.Info, onSelected: () => { navigateToDetailsPage(report, Navigation.getActiveRoute()); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.DELETE]: { text: translate('common.delete'), - icon: Expensicons.Trashcan, + icon: expensifyIcons.Trashcan, value: CONST.REPORT.SECONDARY_ACTIONS.DELETE, onSelected: () => { setIsDeleteModalVisible(true); @@ -368,7 +382,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REJECT]: { text: translate('common.reject'), - icon: Expensicons.ThumbsDown, + icon: expensifyIcons.ThumbsDown, value: CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REJECT, onSelected: () => { if (dismissedRejectUseExplanation) { @@ -484,6 +498,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre isSingleTransactionView: true, isChatReportArchived: isParentReportArchived, isChatIOUReportArchived, + allSnapshots, }); } else { deleteTransactions([transaction.transactionID], duplicateTransactions, duplicateTransactionViolations, currentSearchHash, true); diff --git a/src/hooks/useDeleteTransactions.ts b/src/hooks/useDeleteTransactions.ts index f1c7b519a9aed..fe086ec4b1bf5 100644 --- a/src/hooks/useDeleteTransactions.ts +++ b/src/hooks/useDeleteTransactions.ts @@ -27,6 +27,7 @@ type UseDeleteTransactionsParams = { function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransactionsParams) { const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: false}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); + const [allSnapshots] = useOnyx(ONYXKEYS.COLLECTION.SNAPSHOT, {canBeMissing: true}); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(report?.policyID)}`, {canBeMissing: true}); const [allPolicyRecentlyUsedCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES, {canBeMissing: true}); const [allReportNameValuePairs] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS, {canBeMissing: true}); @@ -136,18 +137,19 @@ function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransac const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`]; const chatIOUReportID = chatReport?.reportID; const isChatIOUReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${chatIOUReportID}`); - deleteMoneyRequest( + deleteMoneyRequest({ transactionID, - action, - duplicateTransactions, - duplicateTransactionViolations, + reportAction: action, + transactions: duplicateTransactions, + violations: duplicateTransactionViolations, iouReport, chatReport, isChatIOUReportArchived, + allSnapshots, isSingleTransactionView, - deletedTransactionIDs, - transactionIDs, - ); + transactionIDsPendingDeletion: deletedTransactionIDs, + selectedTransactionIDs: transactionIDs, + }); deletedTransactionIDs.push(transactionID); if (action.childReportID) { deletedTransactionThreadReportIDs.add(action.childReportID); @@ -156,7 +158,19 @@ function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransac return Array.from(deletedTransactionThreadReportIDs); }, - [reportActions, allTransactions, allReports, report, allReportNameValuePairs, allPolicyRecentlyUsedCategories, policyCategories, policy, archivedReportsIdSet, isBetaEnabled], + [ + reportActions, + allTransactions, + allReports, + report, + allReportNameValuePairs, + allPolicyRecentlyUsedCategories, + policyCategories, + policy, + archivedReportsIdSet, + isBetaEnabled, + allSnapshots, + ], ); return { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b4322c58057e1..a445cb5b1dad8 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -75,7 +75,6 @@ import type {NotificationPreference, Participants, Participant as ReportParticip import type {Message, OldDotReportAction, ReportActions} from '@src/types/onyx/ReportAction'; import type {PendingChatMember} from '@src/types/onyx/ReportMetadata'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {Comment, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type {FileObject} from '@src/types/utils/Attachment'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -925,7 +924,7 @@ type GetReportNameParams = { parentReportActionParam?: OnyxInputOrEntry; personalDetails?: Partial; invoiceReceiverPolicy?: OnyxEntry; - transactions?: SearchTransaction[]; + transactions?: Transaction[]; reports?: Report[]; policies?: Policy[]; isReportArchived?: boolean; @@ -2247,7 +2246,7 @@ function findLastAccessedReport(ignoreDomainRooms: boolean, openOnAdminRoom = fa /** * Whether the provided report has expenses */ -function hasExpenses(reportID?: string, transactions?: SearchTransaction[] | Array>): boolean { +function hasExpenses(reportID?: string, transactions?: Transaction[] | Array>): boolean { if (transactions) { return !!transactions?.find((transaction) => transaction?.reportID === reportID); } @@ -2257,7 +2256,7 @@ function hasExpenses(reportID?: string, transactions?: SearchTransaction[] | Arr /** * Whether the provided report is a closed expense report with no expenses */ -function isClosedExpenseReportWithNoExpenses(report: OnyxEntry, transactions?: SearchTransaction[] | Array>): boolean { +function isClosedExpenseReportWithNoExpenses(report: OnyxEntry, transactions?: Transaction[] | Array>): boolean { if (!report?.statusNum || report.statusNum !== CONST.REPORT.STATUS_NUM.CLOSED || !isExpenseReport(report)) { return false; } @@ -4483,7 +4482,7 @@ function canEditMoneyRequest( isChatReportArchived = false, report?: OnyxInputOrEntry, policy?: OnyxEntry, - linkedTransaction?: OnyxEntry | SearchTransaction, + linkedTransaction?: OnyxEntry | Transaction, ): boolean { const isDeleted = isDeletedAction(reportAction); @@ -4625,7 +4624,7 @@ function canEditFieldOfMoneyRequest( isDeleteAction?: boolean, isChatReportArchived = false, outstandingReportsByPolicyID?: OutstandingReportsByPolicyIDDerivedValue, - linkedTransaction?: OnyxEntry | SearchTransaction, + linkedTransaction?: OnyxEntry | Transaction, report?: OnyxInputOrEntry, policy?: OnyxEntry, ): boolean { @@ -4907,7 +4906,7 @@ function areAllRequestsBeingSmartScanned(iouReportID: string | undefined, report * * NOTE: This method is only meant to be used inside this action file. Do not export and use it elsewhere. Use useOnyx instead. */ -function getLinkedTransaction(reportAction: OnyxEntry, transactions?: SearchTransaction[]): OnyxEntry | SearchTransaction { +function getLinkedTransaction(reportAction: OnyxEntry, transactions?: Transaction[]): OnyxEntry | Transaction { let transactionID: string | undefined; if (isMoneyRequestAction(reportAction)) { @@ -4962,7 +4961,7 @@ function getTransactionReportName({ reports, }: { reportAction: OnyxEntry; - transactions?: SearchTransaction[]; + transactions?: Transaction[]; reports?: Report[]; }): string { if (isReversedTransaction(reportAction)) { @@ -5595,7 +5594,7 @@ function getReportName( personalDetails?: Partial, invoiceReceiverPolicy?: OnyxEntry, reportAttributes?: ReportAttributesDerivedValue['reports'], - transactions?: SearchTransaction[], + transactions?: Transaction[], isReportArchived?: boolean, reports?: Report[], policies?: Policy[], @@ -8904,7 +8903,7 @@ function hasViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, - reportTransactions?: SearchTransaction[], + reportTransactions?: Transaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); return transactions.some((transaction) => hasViolation(transaction, transactionViolations, shouldShowInReview)); @@ -8917,7 +8916,7 @@ function hasWarningTypeViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, - reportTransactions?: SearchTransaction[], + reportTransactions?: Transaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); return transactions.some((transaction) => hasWarningTypeViolation(transaction, transactionViolations, shouldShowInReview)); @@ -8950,7 +8949,7 @@ function hasNoticeTypeViolations( reportID: string | undefined, transactionViolations: OnyxCollection, shouldShowInReview?: boolean, - reportTransactions?: SearchTransaction[], + reportTransactions?: Transaction[], ): boolean { const transactions = reportTransactions ?? getReportTransactions(reportID); return transactions.some((transaction) => hasNoticeTypeViolation(transaction, transactionViolations, shouldShowInReview)); @@ -8959,7 +8958,7 @@ function hasNoticeTypeViolations( /** * Checks to see if a report contains any type of violation */ -function hasAnyViolations(reportID: string | undefined, transactionViolations: OnyxCollection, reportTransactions?: SearchTransaction[]) { +function hasAnyViolations(reportID: string | undefined, transactionViolations: OnyxCollection, reportTransactions?: Transaction[]) { return ( hasViolations(reportID, transactionViolations, undefined, reportTransactions) || hasNoticeTypeViolations(reportID, transactionViolations, true, reportTransactions) || @@ -8983,12 +8982,12 @@ function shouldBlockSubmitDueToStrictPolicyRules( reportID: string | undefined, transactionViolations: OnyxCollection, areStrictPolicyRulesEnabled: boolean, - reportTransactions?: Transaction[] | SearchTransaction[], + reportTransactions?: Transaction[], ) { if (!areStrictPolicyRulesEnabled) { return false; } - return hasAnyViolations(reportID, transactionViolations, reportTransactions as SearchTransaction[]); + return hasAnyViolations(reportID, transactionViolations, reportTransactions); } type ReportErrorsAndReportActionThatRequiresAttention = { @@ -10341,7 +10340,7 @@ function getAllHeldTransactions(iouReportID?: string): Transaction[] { /** * Check if Report has any held expenses */ -function hasHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTransaction[]): boolean { +function hasHeldExpenses(iouReportID?: string, allReportTransactions?: Transaction[]): boolean { const iouReportTransactions = getReportTransactions(iouReportID); const transactions = allReportTransactions ?? iouReportTransactions; return transactions.some((transaction) => isOnHoldTransactionUtils(transaction)); @@ -10350,7 +10349,7 @@ function hasHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTra /** * Check if all expenses in the Report are on hold */ -function hasOnlyHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTransaction[]): boolean { +function hasOnlyHeldExpenses(iouReportID?: string, allReportTransactions?: Transaction[]): boolean { const transactionsByIouReportID = getReportTransactions(iouReportID); const reportTransactions = allReportTransactions ?? transactionsByIouReportID; return reportTransactions.length > 0 && !reportTransactions.some((transaction) => !isOnHoldTransactionUtils(transaction)); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index e359bbca79a77..ad27a0ee23120 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2510,6 +2510,16 @@ function getColumnsToShow( return columns; } +type OnyxSnapshotKey = `${typeof ONYXKEYS.COLLECTION.SNAPSHOT}${string}`; + +function getSnapshotKeys(allSnapshots: OnyxCollection) { + if (!allSnapshots) { + return []; + } + + return Object.keys(allSnapshots || {}) as OnyxSnapshotKey[]; +} + export { getSuggestedSearches, getListItem, @@ -2551,5 +2561,6 @@ export { getActionOptions, getColumnsToShow, getHasOptions, + getSnapshotKeys, }; export type {SavedSearchMenuItem, SearchTypeMenuSection, SearchTypeMenuItem, SearchDateModifier, SearchDateModifierLower, SearchKey, ArchivedReportsIDSet}; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index b1e87d3fcc297..2f8652abe41da 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -201,7 +201,7 @@ import { updateReportPreview, } from '@libs/ReportUtils'; import {getCurrentSearchQueryJSON} from '@libs/SearchQueryUtils'; -import {getSuggestedSearches} from '@libs/SearchUIUtils'; +import {getSnapshotKeys, getSuggestedSearches} from '@libs/SearchUIUtils'; import {getSession} from '@libs/SessionUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; @@ -252,7 +252,7 @@ import type RecentlyUsedTags from '@src/types/onyx/RecentlyUsedTags'; import type {InvoiceReceiver, InvoiceReceiverType} from '@src/types/onyx/Report'; import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {SearchTransaction} from '@src/types/onyx/SearchResults'; +import type SearchResults from '@src/types/onyx/SearchResults'; import type {Comment, Receipt, ReceiptSource, Routes, SplitShares, TransactionChanges, TransactionCustomUnit, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import {clearByKey as clearPdfByOnyxKey} from './CachedPDFPaths'; @@ -783,6 +783,21 @@ type DeleteTrackExpenseParams = { isSingleTransactionView: boolean | undefined; isChatReportArchived: boolean | undefined; isChatIOUReportArchived: boolean | undefined; + allSnapshots?: OnyxCollection; +}; + +type DeleteMoneyRequestInputParams = { + transactionID: string | undefined; + reportAction: OnyxTypes.ReportAction; + transactions: OnyxCollection; + violations: OnyxCollection; + iouReport: OnyxEntry; + chatReport: OnyxEntry; + isChatIOUReportArchived: boolean | undefined; + allSnapshots?: OnyxCollection; + isSingleTransactionView?: boolean; + transactionIDsPendingDeletion?: string[]; + selectedTransactionIDs?: string[]; }; let allTransactions: NonNullable> = {}; @@ -8694,18 +8709,21 @@ function cleanUpMoneyRequest( * @param isSingleTransactionView - whether we are in the transaction thread report * @return the url to navigate back once the money request is deleted */ -function deleteMoneyRequest( - transactionID: string | undefined, - reportAction: OnyxTypes.ReportAction, - transactions: OnyxCollection, - violations: OnyxCollection, - iouReport: OnyxEntry, - chatReport: OnyxEntry, - isChatIOUReportArchived: boolean | undefined, - isSingleTransactionView = false, - transactionIDsPendingDeletion?: string[], - selectedTransactionIDs?: string[], -) { +function deleteMoneyRequest(params: DeleteMoneyRequestInputParams): Route | undefined { + const { + transactionID, + reportAction, + transactions, + violations, + iouReport, + chatReport, + isChatIOUReportArchived, + allSnapshots, + isSingleTransactionView = false, + transactionIDsPendingDeletion, + selectedTransactionIDs, + } = params; + if (!transactionID) { return; } @@ -8726,6 +8744,8 @@ function deleteMoneyRequest( const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, iouReport, chatReport, isChatIOUReportArchived, isSingleTransactionView); + const allSnapshotKeys = getSnapshotKeys(allSnapshots); + // STEP 2: Build Onyx data // The logic mostly resembles the cleanUpMoneyRequest function const optimisticData: OnyxUpdate[] = [ @@ -8865,6 +8885,34 @@ function deleteMoneyRequest( }, ]; + if (allSnapshotKeys?.length && allSnapshotKeys.length > 0) { + allSnapshotKeys.forEach((key) => { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }, + } as Partial, + }, + }); + + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + pendingAction: null, + }, + } as Partial, + }, + }); + }); + } + if (reportPreviewAction?.reportActionID) { successData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -9006,6 +9054,7 @@ function deleteTrackExpense({ isSingleTransactionView = false, isChatReportArchived, isChatIOUReportArchived, + allSnapshots, }: DeleteTrackExpenseParams) { if (!chatReportID || !transactionID) { return; @@ -9024,7 +9073,7 @@ function deleteTrackExpense({ // STEP 1: Get all collections we're updating if (!isSelfDM(chatReport)) { - deleteMoneyRequest(transactionID, reportAction, transactions, violations, iouReport, chatIOUReport, isChatIOUReportArchived, isSingleTransactionView); + deleteMoneyRequest({transactionID, reportAction, transactions, violations, iouReport, chatReport: chatIOUReport, isChatIOUReportArchived, allSnapshots, isSingleTransactionView}); return urlToNavigateBack; } @@ -10145,8 +10194,7 @@ function canIOUBePaid( iouReport: OnyxTypes.OnyxInputOrEntry, chatReport: OnyxTypes.OnyxInputOrEntry, policy: OnyxTypes.OnyxInputOrEntry, - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions?: OnyxTypes.Transaction[] | SearchTransaction[], + transactions?: OnyxTypes.Transaction[], onlyShowPayElsewhere = false, chatReportRNVP?: OnyxTypes.ReportNameValuePairs, invoiceReceiverPolicy?: OnyxTypes.Policy, @@ -10219,8 +10267,7 @@ function canCancelPayment(iouReport: OnyxEntry, session: OnyxE function canSubmitReport( report: OnyxEntry, policy: OnyxEntry, - // eslint-disable-next-line @typescript-eslint/no-deprecated - transactions: OnyxTypes.Transaction[] | SearchTransaction[], + transactions: OnyxTypes.Transaction[], allViolations: OnyxCollection | undefined, isReportArchived: boolean, ) { diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 524700e121e0a..a954a55804e50 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -33,7 +33,7 @@ import { isIOUReport as isIOUReportUtil, } from '@libs/ReportUtils'; import type {SearchKey} from '@libs/SearchUIUtils'; -import {isTransactionGroupListItemType} from '@libs/SearchUIUtils'; +import {getSnapshotKeys, isTransactionGroupListItemType} from '@libs/SearchUIUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import CONST from '@src/CONST'; @@ -44,7 +44,7 @@ import type {SearchAdvancedFiltersForm} from '@src/types/form/SearchAdvancedFilt import type {ExportTemplate, LastPaymentMethod, LastPaymentMethodType, Policy, ReportAction, ReportActions, Transaction} from '@src/types/onyx'; import type {PaymentInformation} from '@src/types/onyx/LastPaymentMethod'; import type {ConnectionName} from '@src/types/onyx/Policy'; -import type {SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults'; +import type {SearchReport} from '@src/types/onyx/SearchResults'; import type SearchResults from '@src/types/onyx/SearchResults'; import type Nullable from '@src/types/utils/Nullable'; import SafeString from '@src/utils/SafeString'; @@ -81,7 +81,7 @@ function handleActionButtonPress( // The transactionIDList is needed to handle actions taken on `status:""` where transactions on single expense reports can be approved/paid. // We need the transactionID to display the loading indicator for that list item's action. // eslint-disable-next-line @typescript-eslint/no-deprecated - const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as SearchTransaction[]; + const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as Transaction[]; const hasHeldExpense = hasHeldExpenses('', allReportTransactions); if (hasHeldExpense) { @@ -419,12 +419,12 @@ function search({ */ function updateSearchResultsWithTransactionThreadReportID(hash: number, transactionID: string, reportID: string) { // eslint-disable-next-line @typescript-eslint/no-deprecated - const onyxUpdate: Record>> = { + const onyxUpdate = { data: { [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { transactionThreadReportID: reportID, }, - }, + } as Partial, }; Onyx.merge(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, onyxUpdate); } @@ -698,7 +698,18 @@ function unholdMoneyRequestOnSearch(hash: number, transactionIDList: string[]) { API.write(WRITE_COMMANDS.UNHOLD_MONEY_REQUEST_ON_SEARCH, {hash, transactionIDList}, {optimisticData, finallyData}); } -function deleteMoneyRequestOnSearch(hash: number, transactionIDList: string[], currentSearchResults?: SearchResults) { +function deleteMoneyRequestOnSearch( + hash: number, + transactionIDList: string[], + allSnapshots: OnyxCollection, + transactions: OnyxCollection, + currentSearchResults?: SearchResults, +) { + const allSnapshotKeys = getSnapshotKeys(allSnapshots); + const {optimisticData: loadingOptimisticData, finallyData} = getOnyxLoadingData(hash); + const optimisticData: OnyxUpdate[] = [...loadingOptimisticData]; + const failureData: OnyxUpdate[] = []; + const currentMetadata = currentSearchResults?.search; // Calculate total amount of transactions being deleted @@ -707,40 +718,88 @@ function deleteMoneyRequestOnSearch(hash: number, transactionIDList: string[], c return sum - (transaction?.convertedAmount ?? 0); }, 0); - const {optimisticData: loadingOptimisticData, finallyData} = getOnyxLoadingData(hash); - // @ts-expect-error - will be solved in https://github.com/Expensify/App/issues/73830 - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const optimisticData: OnyxUpdate[] = [ - ...loadingOptimisticData, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data: Object.fromEntries( - transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}]), - // eslint-disable-next-line @typescript-eslint/no-deprecated - ) as Partial, - search: { - ...(currentMetadata ?? {}), - count: Math.max(0, (currentMetadata?.count ?? 0) - transactionIDList.length), - total: (currentMetadata?.total ?? 0) - deletedTotal, - }, + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + search: { + ...(currentMetadata ?? {}), + count: Math.max(0, (currentMetadata?.count ?? 0) - transactionIDList.length), + total: (currentMetadata?.total ?? 0) - deletedTotal, }, }, - ]; - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data: Object.fromEntries( - transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {pendingAction: null}]), - // eslint-disable-next-line @typescript-eslint/no-deprecated - ) as Partial, - search: currentMetadata, - }, + }); + + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + search: currentMetadata, }, - ]; + }); + + if (allSnapshotKeys?.length && allSnapshotKeys.length > 0) { + transactionIDList.forEach((transactionID) => { + allSnapshotKeys.forEach((key) => { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }, + } as Partial, + }, + }); + + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + pendingAction: null, + }, + } as Partial, + }, + }); + }); + + if (transactions) { + const transaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; + + if (transaction) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: {...transaction, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}, + }); + + failureData.push({ + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + value: {...transaction, pendingAction: null}, + }); + + const shouldDeleteIOUReport = getReportTransactions(transaction?.reportID).length === 1; + + if (shouldDeleteIOUReport) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`, + value: { + pendingFields: { + preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + }, + }, + }); + } + } + } + }); + } + API.write(WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH, {hash, transactionIDList}, {optimisticData, failureData, finallyData}); } diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index fdb34dbb73862..ec72b77a82736 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -10,7 +10,6 @@ import ConfirmModal from '@components/ConfirmModal'; import DisplayNames from '@components/DisplayNames'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; -import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -28,6 +27,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useDeleteTransactions from '@hooks/useDeleteTransactions'; import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations'; import useGetIOUReportFromReportAction from '@hooks/useGetIOUReportFromReportAction'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; @@ -159,6 +159,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, {canBeMissing: true}); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`, {canBeMissing: true}); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); + const [allSnapshots] = useOnyx(ONYXKEYS.COLLECTION.SNAPSHOT, {canBeMissing: true}); const parentReportAction = useParentReportAction(report); @@ -303,6 +304,8 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); const isWorkspaceChat = useMemo(() => isWorkspaceChatUtil(report?.chatType ?? ''), [report?.chatType]); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['Users', 'Gear', 'Send', 'Folder', 'UserPlus', 'Pencil', 'Checkmark', 'Building', 'Exit', 'Camera', 'Bug', 'Trashcan']); + useEffect(() => { if (canDeleteRequest) { return; @@ -382,7 +385,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS, translationKey: 'common.members', - icon: Expensicons.Users, + icon: expensifyIcons.Users, subtitle: activeChatMembers.length, isAnonymousAction: false, shouldShowRightIcon: true, @@ -398,7 +401,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.INVITE, translationKey: 'common.invite', - icon: Expensicons.Users, + icon: expensifyIcons.Users, isAnonymousAction: false, shouldShowRightIcon: true, action: () => { @@ -411,7 +414,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS, translationKey: 'common.settings', - icon: Expensicons.Gear, + icon: expensifyIcons.Gear, isAnonymousAction: false, shouldShowRightIcon: true, action: () => { @@ -427,7 +430,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.TRACK.SUBMIT, translationKey: 'actionableMentionTrackExpense.submit', - icon: Expensicons.Send, + icon: expensifyIcons.Send, isAnonymousAction: false, shouldShowRightIcon: true, action: () => { @@ -446,7 +449,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.TRACK.CATEGORIZE, translationKey: 'actionableMentionTrackExpense.categorize', - icon: Expensicons.Folder, + icon: expensifyIcons.Folder, isAnonymousAction: false, shouldShowRightIcon: true, action: () => { @@ -456,7 +459,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.TRACK.SHARE, translationKey: 'actionableMentionTrackExpense.share', - icon: Expensicons.UserPlus, + icon: expensifyIcons.UserPlus, isAnonymousAction: false, shouldShowRightIcon: true, action: () => { @@ -471,7 +474,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.PRIVATE_NOTES, translationKey: 'privateNotes.title', - icon: Expensicons.Pencil, + icon: expensifyIcons.Pencil, isAnonymousAction: false, shouldShowRightIcon: true, action: () => navigateToPrivateNotes(report, currentUserPersonalDetails.accountID, backTo), @@ -484,7 +487,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail if (isCompletedTaskReport(report) && isTaskActionable) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.MARK_AS_INCOMPLETE, - icon: Expensicons.Checkmark, + icon: expensifyIcons.Checkmark, translationKey: 'task.markAsIncomplete', isAnonymousAction: false, action: callFunctionIfActionIsAllowed(() => { @@ -499,7 +502,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.GO_TO_WORKSPACE, translationKey: 'workspace.common.goToWorkspace', - icon: Expensicons.Building, + icon: expensifyIcons.Building, action: () => { if (!report?.policyID) { return; @@ -519,7 +522,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.LEAVE_ROOM, translationKey: 'common.leave', - icon: Expensicons.Exit, + icon: expensifyIcons.Exit, isAnonymousAction: true, action: () => { if (getParticipantsAccountIDsForDisplay(report, false, true).length === 1 && isRootGroupChat) { @@ -536,7 +539,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.DEBUG, translationKey: 'debug.debug', - icon: Expensicons.Bug, + icon: expensifyIcons.Bug, action: () => Navigation.navigate(ROUTES.DEBUG_REPORT.getRoute(report.reportID)), isAnonymousAction: true, shouldShowRightIcon: true, @@ -580,6 +583,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail isRestrictedToPreferredPolicy, preferredPolicyID, introSelected, + expensifyIcons, ]); const displayNamesWithTooltips = useMemo(() => { @@ -639,7 +643,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail updateGroupChatAvatar(report.reportID); }} onImageSelected={(file) => updateGroupChatAvatar(report.reportID, file)} - editIcon={Expensicons.Camera} + editIcon={expensifyIcons.Camera} editIconStyle={styles.smallEditIconAccount} pendingAction={report.pendingFields?.avatar ?? undefined} errors={report.errorFields?.avatar ?? null} @@ -662,6 +666,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail policy, participants, moneyRequestReport?.reportID, + expensifyIcons.Camera, ]); const canJoin = canJoinChat(report, parentReportAction, policy, !!reportNameValuePairs?.private_isArchived); @@ -835,6 +840,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail isSingleTransactionView, isChatReportArchived: isMoneyRequestReportArchived, isChatIOUReportArchived, + allSnapshots, }); } else if (iouTransactionID) { deleteTransactions([iouTransactionID], duplicateTransactions, duplicateTransactionViolations, currentSearchHash, isSingleTransactionView); @@ -859,6 +865,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail deleteTransactions, currentSearchHash, isChatIOUReportArchived, + allSnapshots, ]); // Where to navigate back to after deleting the transaction and its report. @@ -993,7 +1000,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail {shouldShowDeleteButton && ( setIsDeleteModalVisible(true)} /> diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 396a8909f8f4f..4df55d8b9efe3 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -106,6 +106,8 @@ function SearchPage({route}: SearchPageProps) { const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`, {canBeMissing: true}); const personalPolicy = usePersonalPolicy(); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); + const [allSnapshots] = useOnyx(ONYXKEYS.COLLECTION.SNAPSHOT, {canBeMissing: true}); + const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); const [integrationsExportTemplates] = useOnyx(ONYXKEYS.NVP_INTEGRATION_SERVER_EXPORT_TEMPLATES, {canBeMissing: true}); const [csvExportLayouts] = useOnyx(ONYXKEYS.NVP_CSV_EXPORT_LAYOUTS, {canBeMissing: true}); const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); @@ -566,7 +568,7 @@ function SearchPage({route}: SearchPageProps) { }); } - const shouldShowDeleteOption = !isOffline && selectedTransactionsKeys.every((id) => selectedTransactions[id].canDelete); + const shouldShowDeleteOption = selectedTransactionsKeys.every((id) => selectedTransactions[id].canDelete); if (shouldShowDeleteOption) { options.push({ @@ -575,11 +577,6 @@ function SearchPage({route}: SearchPageProps) { value: CONST.SEARCH.BULK_ACTION_TYPES.DELETE, shouldCloseModalOnSelect: true, onSelected: () => { - if (isOffline) { - setIsOfflineModalVisible(true); - return; - } - // Use InteractionManager to ensure this runs after the dropdown modal closes // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { @@ -647,7 +644,7 @@ function SearchPage({route}: SearchPageProps) { // We need to wait for modal to fully disappear before clearing them to avoid translation flicker between singular vs plural // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { - deleteMoneyRequestOnSearch(hash, selectedTransactionsKeys, currentSearchResults); + deleteMoneyRequestOnSearch(hash, selectedTransactionsKeys, allSnapshots, transactions, currentSearchResults); clearSelectedTransactions(); }); }; diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx index 9f6870c360334..c9515e040a684 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -48,6 +48,9 @@ type PopoverReportActionContextMenuProps = { function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuProps) { const {translate} = useLocalize(); + + const [allSnapshots] = useOnyx(ONYXKEYS.COLLECTION.SNAPSHOT, {canBeMissing: true}); + const reportIDRef = useRef(undefined); const typeRef = useRef(undefined); const reportActionRef = useRef> | null>(null); @@ -340,6 +343,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro } ancestorsRef.current = ancestors; }, [originalReport, ancestors]); + const confirmDeleteAndHideModal = useCallback(() => { callbackWhenDeleteModalHide.current = runAndResetCallback(onConfirmDeleteModal.current); const reportAction = reportActionRef.current; @@ -358,6 +362,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro isSingleTransactionView: undefined, isChatReportArchived: isReportArchived, isChatIOUReportArchived, + allSnapshots, }); } else if (originalMessage?.IOUTransactionID) { deleteTransactions([originalMessage.IOUTransactionID], duplicateTransactions, duplicateTransactionViolations, currentSearchHash); @@ -384,6 +389,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro deleteTransactions, currentSearchHash, isOriginalReportArchived, + allSnapshots, ]); const hideDeleteModal = () => { diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 94e691a79c270..11c7285667433 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -4019,7 +4019,15 @@ describe('actions/IOU', () => { if (transaction && createIOUAction) { // When the expense is deleted - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, true, undefined); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: true, + }); } await waitForBatchedUpdates(); @@ -4098,7 +4106,15 @@ describe('actions/IOU', () => { if (transaction && createIOUAction) { // When the IOU expense is deleted - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, true); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: true, + }); } await waitForBatchedUpdates(); @@ -4161,7 +4177,15 @@ describe('actions/IOU', () => { // When we attempt to delete an expense from the IOU report mockFetch?.pause?.(); if (transaction && createIOUAction) { - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4256,7 +4280,15 @@ describe('actions/IOU', () => { if (transaction && createIOUAction) { // When Deleting an expense - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4381,7 +4413,15 @@ describe('actions/IOU', () => { if (transaction && createIOUAction) { // When Deleting an expense - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4455,7 +4495,15 @@ describe('actions/IOU', () => { if (transaction && createIOUAction) { // When deleting expense - deleteMoneyRequest(transaction?.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction?.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4606,7 +4654,15 @@ describe('actions/IOU', () => { mockFetch?.pause?.(); if (transaction && createIOUAction) { // When we delete the expense - deleteMoneyRequest(transaction.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4699,7 +4755,15 @@ describe('actions/IOU', () => { mockFetch?.pause?.(); jest.advanceTimersByTime(10); if (transaction && createIOUAction) { - deleteMoneyRequest(transaction.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + deleteMoneyRequest({ + transactionID: transaction.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } await waitForBatchedUpdates(); @@ -4776,7 +4840,16 @@ describe('actions/IOU', () => { let navigateToAfterDelete; if (transaction && createIOUAction) { - navigateToAfterDelete = deleteMoneyRequest(transaction.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined, true); + navigateToAfterDelete = deleteMoneyRequest({ + transactionID: transaction.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + isSingleTransactionView: true, + }); } let allReports = await new Promise>((resolve) => { @@ -4824,7 +4897,15 @@ describe('actions/IOU', () => { let navigateToAfterDelete; if (transaction && createIOUAction) { // When we delete the expense and we should delete the IOU report - navigateToAfterDelete = deleteMoneyRequest(transaction.transactionID, createIOUAction, {}, {}, iouReport, chatReport, undefined); + navigateToAfterDelete = deleteMoneyRequest({ + transactionID: transaction.transactionID, + reportAction: createIOUAction, + transactions: {}, + violations: {}, + iouReport, + chatReport, + isChatIOUReportArchived: undefined, + }); } // Then we expect to navigate to the chat report expect(chatReport?.reportID).not.toBeUndefined(); @@ -4888,19 +4969,27 @@ describe('actions/IOU', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport); const selectedTransactionIDs = [transaction1.transactionID, transaction2.transactionID]; - deleteMoneyRequest(transaction1.transactionID, moneyRequestAction1, {}, {}, expenseReport, expenseReport, undefined, undefined, [], selectedTransactionIDs); - deleteMoneyRequest( - transaction2.transactionID, - moneyRequestAction2, - {}, - {}, - expenseReport, - expenseReport, - undefined, - undefined, - [transaction1.transactionID], + deleteMoneyRequest({ + transactionID: transaction1.transactionID, + reportAction: moneyRequestAction1, + transactions: {}, + violations: {}, + iouReport: expenseReport, + chatReport: expenseReport, + isChatIOUReportArchived: undefined, selectedTransactionIDs, - ); + }); + deleteMoneyRequest({ + transactionID: transaction2.transactionID, + reportAction: moneyRequestAction2, + transactions: {}, + violations: {}, + iouReport: expenseReport, + chatReport: expenseReport, + isChatIOUReportArchived: undefined, + transactionIDsPendingDeletion: [transaction1.transactionID], + selectedTransactionIDs, + }); await waitForBatchedUpdates();