diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx index 9a9d656b1c38c..9ac6c3d710318 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx @@ -1,5 +1,6 @@ import React, {useEffect} from 'react'; import {View} from 'react-native'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import PrevNextButtons from '@components/PrevNextButtons'; import Text from '@components/Text'; import useArchivedReportsIdSet from '@hooks/useArchivedReportsIdSet'; @@ -15,6 +16,20 @@ import {search} from '@userActions/Search'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData'; +import type {Report} from '@src/types/onyx'; +import mapOnyxCollectionItems from '@src/utils/mapOnyxCollectionItems'; + +type ReportPendingFields = Pick; + +const selectReportsPendingFields = (reports: OnyxCollection) => + mapOnyxCollectionItems(reports, (report: OnyxEntry): ReportPendingFields | undefined => + report + ? { + pendingAction: report.pendingAction, + pendingFields: report.pendingFields, + } + : undefined, + ); type MoneyRequestReportNavigationProps = { reportID?: string; @@ -24,6 +39,7 @@ type MoneyRequestReportNavigationProps = { function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) { const [lastSearchQuery] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY, {canBeMissing: true}); const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${lastSearchQuery?.queryJSON?.hash}`, {canBeMissing: true}); + const [liveReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true, selector: selectReportsPendingFields}); const currentUserDetails = useCurrentUserPersonalDetails(); const {localeCompare, formatPhoneNumber, translate} = useLocalize(); const [isActionLoadingSet = new Set()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}`, {canBeMissing: true, selector: isActionLoadingSetSelector}); @@ -59,7 +75,16 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo }); results = getSortedSections(type, status ?? '', searchData, localeCompare, translate, sortBy, sortOrder, groupBy).map((value) => value.reportID); } - const allReports = results; + + const reportKeyPrefix = ONYXKEYS.COLLECTION.REPORT; + const allReports = results.filter((id) => { + if (!id) { + return false; + } + const liveReport = liveReports?.[`${reportKeyPrefix}${id}`]; + const isPendingDelete = liveReport?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || liveReport?.pendingFields?.preview === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + return !isPendingDelete; + }); const currentIndex = allReports.indexOf(reportID); const allReportsCount = lastSearchQuery?.previousLengthOfResults ?? 0; @@ -84,6 +109,14 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo return; } + if (allReports.length !== allReportsCount) { + saveLastSearchParams({ + ...lastSearchQuery, + previousLengthOfResults: allReports.length, + }); + return; + } + if (currentIndex < allReportsCount - 1) { return; } @@ -130,7 +163,7 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo return; } - const prevIndex = (currentIndex - 1) % allReports.length; + const prevIndex = (currentIndex - 1 + allReports.length) % allReports.length; goToReportId(allReports.at(prevIndex)); }; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx index f96ce35ec9f38..b78768a4ac17b 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx @@ -5,6 +5,7 @@ import React, {useCallback, useEffect, useMemo} from 'react'; // eslint-disable-next-line no-restricted-imports import {Animated, InteractionManager, ScrollView, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import MoneyReportHeader from '@components/MoneyReportHeader'; import MoneyRequestHeader from '@components/MoneyRequestHeader'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -193,10 +194,21 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe }; }, [reportID]); + const isReportPendingDelete = report?.pendingFields?.preview === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + if (!!(isLoadingInitialReportActions && reportActions.length === 0 && !isOffline) || shouldWaitForTransactions) { return ; } + if (reportActions.length === 0 && isReportPendingDelete) { + return ( + + ); + } + if (reportActions.length === 0) { return ; } diff --git a/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx b/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx index 5d7dbe67bb814..7d91c64bb4fc1 100644 --- a/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx +++ b/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx @@ -16,6 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {handleActionButtonPress} from '@libs/actions/Search'; import {isOpenExpenseReport, isProcessingReport} from '@libs/ReportUtils'; import variables from '@styles/variables'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {isActionLoadingSelector} from '@src/selectors/ReportMetaData'; import type {Policy, Report} from '@src/types/onyx'; @@ -67,6 +68,8 @@ function ExpenseReportListItem({ return isEmpty ?? reportItem.isDisabled ?? reportItem.isDisabledCheckbox; }, [reportItem.isDisabled, reportItem.isDisabledCheckbox, reportItem.transactions.length]); + const isReportPendingDelete = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + const {isDelegateAccessRestricted, showDelegateNoAccessModal} = useContext(DelegateNoAccessContext); const handleOnButtonPress = useCallback(() => { @@ -112,8 +115,9 @@ function ExpenseReportListItem({ styles.bgTransparent, item.isSelected && styles.activeComponentBG, styles.mh0, + isReportPendingDelete && styles.cursorDisabled, ], - [styles, item.isSelected], + [styles, item.isSelected, isReportPendingDelete], ); const listItemWrapperStyle = useMemo( @@ -180,9 +184,11 @@ function ExpenseReportListItem({ onLongPressRow={onLongPressRow} shouldSyncFocus={shouldSyncFocus} hoverStyle={item.isSelected && styles.activeComponentBG} - pressableWrapperStyle={[styles.mh5, animatedHighlightStyle]} + pressableWrapperStyle={[styles.mh5, animatedHighlightStyle, isReportPendingDelete && styles.cursorDisabled]} shouldShowRightCaret={false} shouldUseDefaultRightHandSideCheckmark={false} + isDisabled={isReportPendingDelete} + shouldDisableHoverStyle={isReportPendingDelete} > {(hovered) => (