|
1 | 1 | import React, {useEffect} from 'react'; |
2 | 2 | import {View} from 'react-native'; |
| 3 | +import type {OnyxEntry} from 'react-native-onyx'; |
3 | 4 | import PrevNextButtons from '@components/PrevNextButtons'; |
4 | 5 | import Text from '@components/Text'; |
| 6 | +import useOnyx from '@hooks/useOnyx'; |
5 | 7 | import useSearchSections from '@hooks/useSearchSections'; |
6 | 8 | import useThemeStyles from '@hooks/useThemeStyles'; |
7 | 9 | import Navigation from '@navigation/Navigation'; |
8 | 10 | import {saveLastSearchParams} from '@userActions/ReportNavigation'; |
9 | 11 | import {search} from '@userActions/Search'; |
10 | 12 | import CONST from '@src/CONST'; |
| 13 | +import ONYXKEYS from '@src/ONYXKEYS'; |
| 14 | +import type {SearchResults} from '@src/types/onyx'; |
| 15 | +import type LastSearchParams from '@src/types/onyx/ReportNavigation'; |
11 | 16 |
|
12 | 17 | type MoneyRequestReportNavigationProps = { |
13 | 18 | reportID?: string; |
14 | 19 | shouldDisplayNarrowVersion: boolean; |
15 | 20 | }; |
16 | 21 |
|
17 | | -function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) { |
| 22 | +type SnapshotGuard = { |
| 23 | + hasMultiple: boolean; |
| 24 | + includesReport: boolean; |
| 25 | +}; |
| 26 | + |
| 27 | +const EMPTY_GUARD: SnapshotGuard = {hasMultiple: false, includesReport: false}; |
| 28 | + |
| 29 | +const selectIsExpenseReportSearch = (lastSearchQuery: OnyxEntry<LastSearchParams>): boolean => lastSearchQuery?.queryJSON?.type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT; |
| 30 | + |
| 31 | +const selectQueryHash = (lastSearchQuery: OnyxEntry<LastSearchParams>): number | undefined => lastSearchQuery?.queryJSON?.hash; |
| 32 | + |
| 33 | +const buildSnapshotGuardSelector = |
| 34 | + (reportID: string | undefined) => |
| 35 | + (snapshot: OnyxEntry<SearchResults>): SnapshotGuard => { |
| 36 | + const data = snapshot?.data; |
| 37 | + if (!data || !reportID) { |
| 38 | + return EMPTY_GUARD; |
| 39 | + } |
| 40 | + const prefix = ONYXKEYS.COLLECTION.REPORT; |
| 41 | + let count = 0; |
| 42 | + let includesReport = false; |
| 43 | + for (const key of Object.keys(data)) { |
| 44 | + if (!key.startsWith(prefix)) { |
| 45 | + continue; |
| 46 | + } |
| 47 | + count++; |
| 48 | + if (!includesReport && key.slice(prefix.length) === reportID) { |
| 49 | + includesReport = true; |
| 50 | + } |
| 51 | + if (count > 1 && includesReport) { |
| 52 | + break; |
| 53 | + } |
| 54 | + } |
| 55 | + return {hasMultiple: count > 1, includesReport}; |
| 56 | + }; |
| 57 | + |
| 58 | +function MoneyRequestReportNavigationInner({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) { |
18 | 59 | const {allReports, isSearchLoading, lastSearchQuery} = useSearchSections(); |
| 60 | + const styles = useThemeStyles(); |
19 | 61 |
|
20 | | - const type = lastSearchQuery?.queryJSON?.type; |
21 | 62 | const currentIndex = allReports.indexOf(reportID); |
22 | 63 | const allReportsCount = lastSearchQuery?.previousLengthOfResults ?? 0; |
23 | | - |
24 | 64 | const hideNextButton = !lastSearchQuery?.hasMoreResults && currentIndex === allReports.length - 1; |
25 | 65 | const hidePrevButton = currentIndex === 0; |
26 | | - const styles = useThemeStyles(); |
27 | | - const isExpenseReportSearch = type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT; |
28 | | - const shouldDisplayNavigationArrows = isExpenseReportSearch && allReports && allReports.length > 1 && currentIndex !== -1 && !!lastSearchQuery?.queryJSON; |
| 66 | + const shouldDisplayNavigationArrows = allReports.length > 1 && currentIndex !== -1 && !!lastSearchQuery?.queryJSON; |
29 | 67 |
|
30 | 68 | useEffect(() => { |
31 | 69 | if (!lastSearchQuery?.queryJSON) { |
@@ -100,18 +138,40 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo |
100 | 138 | goToReportId(allReports.at(prevIndex)); |
101 | 139 | }; |
102 | 140 |
|
| 141 | + if (!shouldDisplayNavigationArrows) { |
| 142 | + return null; |
| 143 | + } |
| 144 | + |
| 145 | + return ( |
| 146 | + <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}> |
| 147 | + {!shouldDisplayNarrowVersion && <Text style={styles.mutedTextLabel}>{`${currentIndex + 1} of ${allReportsCount}`}</Text>} |
| 148 | + <PrevNextButtons |
| 149 | + isPrevButtonDisabled={hidePrevButton} |
| 150 | + isNextButtonDisabled={hideNextButton} |
| 151 | + onNext={goToNextReport} |
| 152 | + onPrevious={goToPrevReport} |
| 153 | + /> |
| 154 | + </View> |
| 155 | + ); |
| 156 | +} |
| 157 | + |
| 158 | +function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) { |
| 159 | + const [isExpenseReportSearch] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY, {selector: selectIsExpenseReportSearch}); |
| 160 | + const [hash] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY, {selector: selectQueryHash}); |
| 161 | + const snapshotGuardSelector = buildSnapshotGuardSelector(reportID); |
| 162 | + const [snapshotGuard = EMPTY_GUARD] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, {selector: snapshotGuardSelector}); |
| 163 | + |
| 164 | + const shouldMount = isExpenseReportSearch && snapshotGuard.hasMultiple && snapshotGuard.includesReport; |
| 165 | + |
| 166 | + if (!shouldMount) { |
| 167 | + return null; |
| 168 | + } |
| 169 | + |
103 | 170 | return ( |
104 | | - shouldDisplayNavigationArrows && ( |
105 | | - <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}> |
106 | | - {!shouldDisplayNarrowVersion && <Text style={styles.mutedTextLabel}>{`${currentIndex + 1} of ${allReportsCount}`}</Text>} |
107 | | - <PrevNextButtons |
108 | | - isPrevButtonDisabled={hidePrevButton} |
109 | | - isNextButtonDisabled={hideNextButton} |
110 | | - onNext={goToNextReport} |
111 | | - onPrevious={goToPrevReport} |
112 | | - /> |
113 | | - </View> |
114 | | - ) |
| 171 | + <MoneyRequestReportNavigationInner |
| 172 | + reportID={reportID} |
| 173 | + shouldDisplayNarrowVersion={shouldDisplayNarrowVersion} |
| 174 | + /> |
115 | 175 | ); |
116 | 176 | } |
117 | 177 |
|
|
0 commit comments