|
| 1 | +import React, {useEffect, useRef} from 'react'; |
| 2 | +import {View} from 'react-native'; |
| 3 | +import type {ValueOf} from 'type-fest'; |
| 4 | +import type {ButtonWithDropdownMenuRef} from '@components/ButtonWithDropdownMenu/types'; |
| 5 | +import MoneyReportHeaderPrimaryAction from '@components/MoneyReportHeaderPrimaryAction'; |
| 6 | +import {useSearchActionsContext, useSearchStateContext} from '@components/Search/SearchContext'; |
| 7 | +import useExportAgainModal from '@hooks/useExportAgainModal'; |
| 8 | +import useOnyx from '@hooks/useOnyx'; |
| 9 | +import useResponsiveLayout from '@hooks/useResponsiveLayout'; |
| 10 | +import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP'; |
| 11 | +import useThemeStyles from '@hooks/useThemeStyles'; |
| 12 | +import useTransactionThreadReport from '@hooks/useTransactionThreadReport'; |
| 13 | +import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; |
| 14 | +import CONST from '@src/CONST'; |
| 15 | +import ONYXKEYS from '@src/ONYXKEYS'; |
| 16 | +import MoneyReportHeaderSecondaryActions from './MoneyReportHeaderSecondaryActions'; |
| 17 | +import MoneyReportHeaderSelectionDropdown from './MoneyReportHeaderSelectionDropdown'; |
| 18 | +import type {MoneyReportHeaderActionsProps} from './types'; |
| 19 | + |
| 20 | +/** |
| 21 | + * Narrow the wide primaryAction union to what report-level secondary actions accept. |
| 22 | + * TRANSACTION_PRIMARY_ACTIONS values (e.g. "keepThisOne") are irrelevant here. |
| 23 | + */ |
| 24 | +function narrowPrimaryAction(primaryAction: MoneyReportHeaderActionsProps['primaryAction']): ValueOf<typeof CONST.REPORT.PRIMARY_ACTIONS> | '' { |
| 25 | + if ((Object.values(CONST.REPORT.PRIMARY_ACTIONS) as string[]).includes(primaryAction)) { |
| 26 | + return primaryAction as ValueOf<typeof CONST.REPORT.PRIMARY_ACTIONS>; |
| 27 | + } |
| 28 | + return ''; |
| 29 | +} |
| 30 | + |
| 31 | +function MoneyReportHeaderActions({reportID, primaryAction, isReportInSearch, backTo}: MoneyReportHeaderActionsProps) { |
| 32 | + const styles = useThemeStyles(); |
| 33 | + const dropdownMenuRef = useRef<ButtonWithDropdownMenuRef>(null) as React.RefObject<ButtonWithDropdownMenuRef>; |
| 34 | + |
| 35 | + // We need isSmallScreenWidth for the hold expense modal layout https://github.com/Expensify/App/pull/47990#issuecomment-2362382026 |
| 36 | + // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth |
| 37 | + const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); |
| 38 | + const shouldDisplayNarrowVersion = shouldUseNarrowLayout || isMediumScreenWidth; |
| 39 | + const {isWideRHPDisplayedOnWideLayout, isSuperWideRHPDisplayedOnWideLayout} = useResponsiveLayoutOnWideRHP(); |
| 40 | + const shouldDisplayNarrowMoreButton = !shouldDisplayNarrowVersion || isWideRHPDisplayedOnWideLayout || isSuperWideRHPDisplayedOnWideLayout; |
| 41 | + |
| 42 | + const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); |
| 43 | + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(moneyRequestReport?.chatReportID)}`); |
| 44 | + |
| 45 | + const {transactionThreadReportID} = useTransactionThreadReport(reportID); |
| 46 | + |
| 47 | + const {triggerExportOrConfirm} = useExportAgainModal(moneyRequestReport?.reportID, moneyRequestReport?.policyID); |
| 48 | + |
| 49 | + const {selectedTransactionIDs} = useSearchStateContext(); |
| 50 | + const {clearSelectedTransactions} = useSearchActionsContext(); |
| 51 | + const hasSelectedTransactions = !!selectedTransactionIDs.length; |
| 52 | + const isTransactionThread = !!transactionThreadReportID; |
| 53 | + |
| 54 | + useEffect(() => { |
| 55 | + if (!transactionThreadReportID) { |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + clearSelectedTransactions(true); |
| 60 | + }, [transactionThreadReportID]); // eslint-disable-line react-hooks/exhaustive-deps |
| 61 | + |
| 62 | + const narrowedPrimaryAction = narrowPrimaryAction(primaryAction); |
| 63 | + |
| 64 | + if (hasSelectedTransactions && !isTransactionThread) { |
| 65 | + return ( |
| 66 | + <View style={shouldDisplayNarrowMoreButton ? undefined : [styles.dFlex, styles.w100, styles.ph5, styles.pb3]}> |
| 67 | + <MoneyReportHeaderSelectionDropdown |
| 68 | + reportID={reportID} |
| 69 | + primaryAction={narrowedPrimaryAction} |
| 70 | + isReportInSearch={isReportInSearch} |
| 71 | + wrapperStyle={shouldDisplayNarrowMoreButton ? undefined : styles.w100} |
| 72 | + /> |
| 73 | + </View> |
| 74 | + ); |
| 75 | + } |
| 76 | + |
| 77 | + return ( |
| 78 | + <View style={[styles.flexRow, styles.gap2, ...(!shouldDisplayNarrowMoreButton ? [styles.pb3, styles.ph5, styles.w100, styles.alignItemsCenter, styles.justifyContentCenter] : [])]}> |
| 79 | + {!!primaryAction && ( |
| 80 | + <View style={!shouldDisplayNarrowMoreButton ? [styles.flex1] : undefined}> |
| 81 | + <MoneyReportHeaderPrimaryAction |
| 82 | + reportID={reportID} |
| 83 | + chatReportID={chatReport?.reportID} |
| 84 | + primaryAction={primaryAction} |
| 85 | + onExportModalOpen={() => triggerExportOrConfirm(CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION)} |
| 86 | + /> |
| 87 | + </View> |
| 88 | + )} |
| 89 | + <MoneyReportHeaderSecondaryActions |
| 90 | + reportID={reportID} |
| 91 | + primaryAction={narrowedPrimaryAction} |
| 92 | + isReportInSearch={isReportInSearch} |
| 93 | + backTo={backTo} |
| 94 | + dropdownMenuRef={dropdownMenuRef} |
| 95 | + /> |
| 96 | + </View> |
| 97 | + ); |
| 98 | +} |
| 99 | + |
| 100 | +export default MoneyReportHeaderActions; |
| 101 | +export type {MoneyReportHeaderActionsProps}; |
0 commit comments