diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 83b6d1b31e4a..34267688e1cd 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -408,7 +408,7 @@ type OnyxValues = { [ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string; [ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean; [ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean; - [ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: Record; + [ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: OnyxTypes.LastPaymentMethod; [ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[]; [ONYXKEYS.NVP_HAS_DISMISSED_IDLE_PANEL]: boolean; [ONYXKEYS.NVP_INTRO_SELECTED]: OnyxTypes.IntroSelected; diff --git a/src/components/ButtonWithDropdownMenu.tsx b/src/components/ButtonWithDropdownMenu.tsx index 18e30079094f..9466da601825 100644 --- a/src/components/ButtonWithDropdownMenu.tsx +++ b/src/components/ButtonWithDropdownMenu.tsx @@ -9,15 +9,18 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import type {AnchorPosition} from '@styles/index'; import CONST from '@src/CONST'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; import type IconAsset from '@src/types/utils/IconAsset'; import Button from './Button'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; -import type {AnchorAlignment} from './Popover/types'; import PopoverMenu from './PopoverMenu'; +type PaymentType = DeepValueOf; + type DropdownOption = { - value: string; + value: PaymentType; text: string; icon: IconAsset; iconWidth?: number; @@ -30,7 +33,7 @@ type ButtonWithDropdownMenuProps = { menuHeaderText?: string; /** Callback to execute when the main button is pressed */ - onPress: (event: GestureResponderEvent | KeyboardEvent | undefined, value: string) => void; + onPress: (event: GestureResponderEvent | KeyboardEvent | undefined, value: PaymentType) => void; /** Callback to execute when a dropdown option is selected */ onOptionSelected?: (option: DropdownOption) => void; diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 89cceadc0fb0..ab2d217deb0e 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -17,7 +17,9 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {BankAccountList, FundList, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx'; -import type {AnchorPosition, DomRect, KYCWallProps, PaymentMethod, TransferMethod} from './types'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import viewRef from '@src/types/utils/viewRef'; +import type {AnchorPosition, DomRect, KYCWallProps, PaymentMethod} from './types'; // This sets the Horizontal anchor position offset for POPOVER MENU. const POPOVER_MENU_ANCHOR_POSITION_HORIZONTAL_OFFSET = 20; @@ -67,7 +69,7 @@ function KYCWall({ walletTerms, shouldShowPersonalBankAccountOption = false, }: BaseKYCWallProps) { - const anchorRef = useRef(null); + const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); const [shouldShowAddPaymentMenu, setShouldShowAddPaymentMenu] = useState(false); @@ -145,7 +147,7 @@ function KYCWall({ * */ const continueAction = useCallback( - (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: TransferMethod) => { + (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: PaymentMethodType) => { const currentSource = walletTerms?.source ?? source; /** @@ -259,7 +261,7 @@ function KYCWall({ }} shouldShowPersonalBankAccountOption={shouldShowPersonalBankAccountOption} /> - {children(continueAction, anchorRef)} + {children(continueAction, viewRef(anchorRef))} ); } diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 1fe16d4a17c3..1ee8010574c3 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -1,24 +1,20 @@ -import type {ForwardedRef} from 'react'; -import type {GestureResponderEvent} from 'react-native'; +import type {RefObject} from 'react'; +import type {GestureResponderEvent, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type {Route} from '@src/ROUTES'; import type {Report} from '@src/types/onyx'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; type Source = ValueOf; -type TransferMethod = ValueOf; - type DOMRectProperties = 'top' | 'bottom' | 'left' | 'right' | 'height' | 'x' | 'y'; type DomRect = Pick; -type AnchorAlignment = { - horizontal: ValueOf; - vertical: ValueOf; -}; - type AnchorPosition = { anchorPositionVertical: number; anchorPositionHorizontal: number; @@ -49,7 +45,7 @@ type KYCWallProps = { chatReportID?: string; /** The IOU/Expense report we are paying */ - iouReport?: OnyxEntry; + iouReport?: OnyxEntry | EmptyObject; /** Where the popover should be positioned relative to the anchor points. */ anchorAlignment?: AnchorAlignment; @@ -64,10 +60,10 @@ type KYCWallProps = { shouldShowPersonalBankAccountOption?: boolean; /** Callback for the end of the onContinue trigger on option selection */ - onSuccessfulKYC: (iouPaymentType?: TransferMethod, currentSource?: Source) => void; + onSuccessfulKYC: (iouPaymentType?: PaymentMethodType, currentSource?: Source) => void; /** Children to build the KYC */ - children: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method: TransferMethod) => void, anchorRef: ForwardedRef) => void; + children: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method: PaymentMethodType) => void, anchorRef: RefObject) => void; }; -export type {AnchorPosition, KYCWallProps, PaymentMethod, TransferMethod, DomRect}; +export type {AnchorPosition, KYCWallProps, PaymentMethod, DomRect}; diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 0c478e125def..3f5a3c50f6cc 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -128,7 +128,6 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money {shouldShowSettlementButton && !isSmallScreenWidth && ( ; - - /** The vertical anchor alignment of the popover */ - vertical: ValueOf; -}; - type PopoverDimensions = { width: number; height: number; @@ -49,4 +40,4 @@ type PopoverProps = BaseModalProps & type PopoverWithWindowDimensionsProps = PopoverProps & WindowDimensionsProps; -export type {PopoverProps, PopoverWithWindowDimensionsProps, AnchorAlignment}; +export type {PopoverProps, PopoverWithWindowDimensionsProps}; diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index ff7d0fdfb8e5..34391933da32 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -9,9 +9,9 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import CONST from '@src/CONST'; import type {AnchorPosition} from '@src/styles'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; import MenuItem from './MenuItem'; -import type {AnchorAlignment} from './Popover/types'; import PopoverWithMeasuredContent from './PopoverWithMeasuredContent'; import Text from './Text'; diff --git a/src/components/ProcessMoneyRequestHoldMenu.tsx b/src/components/ProcessMoneyRequestHoldMenu.tsx index 5f32240aca9b..e3f6190d2a1b 100644 --- a/src/components/ProcessMoneyRequestHoldMenu.tsx +++ b/src/components/ProcessMoneyRequestHoldMenu.tsx @@ -3,11 +3,11 @@ import React from 'react'; import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import Button from './Button'; import HoldMenuSectionList from './HoldMenuSectionList'; import type {PopoverAnchorPosition} from './Modal/types'; import Popover from './Popover'; -import type {AnchorAlignment} from './Popover/types'; import Text from './Text'; import TextPill from './TextPill'; diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 13c9d547ea57..c572e9d5f896 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -290,12 +290,11 @@ function ReportPreview({ )} {shouldShowSettlementButton && ( chatReport && iouReport && IOU.payMoneyRequest(paymentType, chatReport, iouReport)} + onPress={(paymentType?: PaymentMethodType) => chatReport && iouReport && paymentType && IOU.payMoneyRequest(paymentType, chatReport, iouReport)} enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS} addBankAccountRoute={bankAccountRoute} shouldHidePaymentOptions={!shouldShowPayButton} diff --git a/src/components/SettlementButton.js b/src/components/SettlementButton.tsx similarity index 67% rename from src/components/SettlementButton.js rename to src/components/SettlementButton.tsx index ddbe88e9275c..8ed25853fcf3 100644 --- a/src/components/SettlementButton.js +++ b/src/components/SettlementButton.tsx @@ -1,148 +1,130 @@ -import PropTypes from 'prop-types'; import React, {useEffect, useMemo} from 'react'; +import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import compose from '@libs/compose'; import * as ReportUtils from '@libs/ReportUtils'; -import iouReportPropTypes from '@pages/iouReportPropTypes'; import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {Route} from '@src/ROUTES'; +import type {ButtonSizeValue} from '@src/styles/utils/types'; +import type {LastPaymentMethod, Report} from '@src/types/onyx'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; -import withNavigation from './withNavigation'; -const propTypes = { +type KYCFlowEvent = GestureResponderEvent | KeyboardEvent | undefined; + +type TriggerKYCFlow = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType) => void; + +type EnablePaymentsRoute = typeof ROUTES.ENABLE_PAYMENTS | typeof ROUTES.IOU_SEND_ENABLE_PAYMENTS | typeof ROUTES.SETTINGS_ENABLE_PAYMENTS; + +type SettlementButtonOnyxProps = { + /** The last payment method used per policy */ + nvpLastPaymentMethod?: OnyxEntry; +}; + +type SettlementButtonProps = SettlementButtonOnyxProps & { /** Callback to execute when this button is pressed. Receives a single payment type argument. */ - onPress: PropTypes.func.isRequired, + onPress: (paymentType?: PaymentMethodType) => void; + + /** The route to redirect if user does not have a payment method setup */ + enablePaymentsRoute: EnablePaymentsRoute; /** Call the onPress function on main button when Enter key is pressed */ - pressOnEnter: PropTypes.bool, + pressOnEnter?: boolean; /** Settlement currency type */ - currency: PropTypes.string, + currency?: string; /** When the button is opened via an IOU, ID for the chatReport that the IOU is linked to */ - chatReportID: PropTypes.string, + chatReportID?: string; /** The IOU/Expense report we are paying */ - iouReport: iouReportPropTypes, - - /** The route to redirect if user does not have a payment method setup */ - enablePaymentsRoute: PropTypes.string.isRequired, - - /** Should we show the approve button? */ - shouldHidePaymentOptions: PropTypes.bool, + iouReport?: OnyxEntry | EmptyObject; /** Should we show the payment options? */ - shouldShowApproveButton: PropTypes.bool, + shouldHidePaymentOptions?: boolean; - /** The last payment method used per policy */ - nvp_lastPaymentMethod: PropTypes.objectOf(PropTypes.string), + /** Should we show the payment options? */ + shouldShowApproveButton?: boolean; /** The policyID of the report we are paying */ - policyID: PropTypes.string, + policyID?: string; /** Additional styles to add to the component */ - style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + style?: StyleProp; /** Total money amount in form */ - formattedAmount: PropTypes.string, + formattedAmount?: string; /** The size of button size */ - buttonSize: PropTypes.oneOf(_.values(CONST.DROPDOWN_BUTTON_SIZE)), + buttonSize?: ButtonSizeValue; /** Route for the Add Bank Account screen for a given navigation stack */ - addBankAccountRoute: PropTypes.string, + addBankAccountRoute?: Route; /** Route for the Add Debit Card screen for a given navigation stack */ - addDebitCardRoute: PropTypes.string, + addDebitCardRoute?: Route; /** Whether the button should be disabled */ - isDisabled: PropTypes.bool, + isDisabled?: boolean; /** Whether we should show a loading state for the main button */ - isLoading: PropTypes.bool, + isLoading?: boolean; /** The anchor alignment of the popover menu for payment method dropdown */ - paymentMethodDropdownAnchorAlignment: PropTypes.shape({ - horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)), - vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)), - }), + paymentMethodDropdownAnchorAlignment?: AnchorAlignment; /** The anchor alignment of the popover menu for KYC wall popover */ - kycWallAnchorAlignment: PropTypes.shape({ - horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)), - vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)), - }), + kycWallAnchorAlignment?: AnchorAlignment; /** Whether the personal bank account option should be shown */ - shouldShowPersonalBankAccountOption: PropTypes.bool, + shouldShowPersonalBankAccountOption?: boolean; /** The priority to assign the enter key event listener to buttons. 0 is the highest priority. */ - enterKeyEventListenerPriority: PropTypes.number, + enterKeyEventListenerPriority?: number; }; -const defaultProps = { - isLoading: false, - isDisabled: false, - pressOnEnter: false, - addBankAccountRoute: '', - addDebitCardRoute: '', - currency: CONST.CURRENCY.USD, - chatReportID: '', - - // The "iouReport" and "nvp_lastPaymentMethod" objects needs to be stable to prevent the "useMemo" - // hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT - iouReport: CONST.EMPTY_OBJECT, - nvp_lastPaymentMethod: CONST.EMPTY_OBJECT, - shouldHidePaymentOptions: false, - shouldShowApproveButton: false, - style: [], - policyID: '', - formattedAmount: '', - buttonSize: CONST.DROPDOWN_BUTTON_SIZE.MEDIUM, - kycWallAnchorAlignment: { +function SettlementButton({ + addDebitCardRoute = '', + addBankAccountRoute = '', + kycWallAnchorAlignment = { horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, // button is at left, so horizontal anchor is at LEFT vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, // we assume that popover menu opens below the button, anchor is at TOP }, - paymentMethodDropdownAnchorAlignment: { + paymentMethodDropdownAnchorAlignment = { horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, // caret for dropdown is at right, so horizontal anchor is at RIGHT vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP, // we assume that popover menu opens below the button, anchor is at TOP }, - shouldShowPersonalBankAccountOption: false, - enterKeyEventListenerPriority: 0, -}; - -function SettlementButton({ - addDebitCardRoute, - addBankAccountRoute, - kycWallAnchorAlignment, - paymentMethodDropdownAnchorAlignment, - buttonSize, - chatReportID, - currency, + buttonSize = CONST.DROPDOWN_BUTTON_SIZE.MEDIUM, + chatReportID = '', + currency = CONST.CURRENCY.USD, enablePaymentsRoute, - iouReport, - isDisabled, - isLoading, - formattedAmount, - nvp_lastPaymentMethod, + // The "iouReport" and "nvpLastPaymentMethod" objects needs to be stable to prevent the "useMemo" + // hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT + iouReport = CONST.EMPTY_OBJECT, + nvpLastPaymentMethod = CONST.EMPTY_OBJECT, + isDisabled = false, + isLoading = false, + formattedAmount = '', onPress, - pressOnEnter, - policyID, - shouldHidePaymentOptions, - shouldShowApproveButton, + pressOnEnter = false, + policyID = '', + shouldHidePaymentOptions = false, + shouldShowApproveButton = false, style, - shouldShowPersonalBankAccountOption, - enterKeyEventListenerPriority, -}) { + shouldShowPersonalBankAccountOption = false, + enterKeyEventListenerPriority = 0, +}: SettlementButtonProps) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -185,7 +167,7 @@ function SettlementButton({ // To achieve the one tap pay experience we need to choose the correct payment type as default. // If the user has previously chosen a specific payment option or paid for some request or expense, // let's use the last payment method or use default. - const paymentMethod = nvp_lastPaymentMethod[policyID] || ''; + const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? ''; if (canUseWallet) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); } @@ -200,14 +182,14 @@ function SettlementButton({ // Put the preferred payment method to the front of the array, so it's shown as default if (paymentMethod) { - return _.sortBy(buttonOptions, (method) => (method.value === paymentMethod ? 0 : 1)); + return buttonOptions.sort((method) => (method.value === paymentMethod ? 0 : 1)); } return buttonOptions; // We don't want to reorder the options when the preferred payment method changes while the button is still visible // eslint-disable-next-line react-hooks/exhaustive-deps }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton]); - const selectPaymentType = (event, iouPaymentType, triggerKYCFlow) => { + const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); @@ -222,6 +204,10 @@ function SettlementButton({ onPress(iouPaymentType); }; + const savePreferredPaymentMethod = (id: string, value: PaymentMethodType) => { + IOU.savePreferredPaymentMethod(id, value); + }; + return ( selectPaymentType(event, iouPaymentType, triggerKYCFlow)} pressOnEnter={pressOnEnter} options={paymentButtonOptions} - onOptionSelected={(option) => IOU.savePreferredPaymentMethod(policyID, option.value)} + onOptionSelected={(option) => savePreferredPaymentMethod(policyID, option.value)} style={style} buttonSize={buttonSize} anchorAlignment={paymentMethodDropdownAnchorAlignment} @@ -254,15 +240,11 @@ function SettlementButton({ ); } -SettlementButton.propTypes = propTypes; -SettlementButton.defaultProps = defaultProps; SettlementButton.displayName = 'SettlementButton'; -export default compose( - withNavigation, - withOnyx({ - nvp_lastPaymentMethod: { - key: ONYXKEYS.NVP_LAST_PAYMENT_METHOD, - }, - }), -)(SettlementButton); +export default withOnyx({ + nvpLastPaymentMethod: { + key: ONYXKEYS.NVP_LAST_PAYMENT_METHOD, + selector: (paymentMethod) => paymentMethod ?? {}, + }, +})(SettlementButton); diff --git a/src/components/ThreeDotsMenu/index.tsx b/src/components/ThreeDotsMenu/index.tsx index 7384874a2746..5de074afff75 100644 --- a/src/components/ThreeDotsMenu/index.tsx +++ b/src/components/ThreeDotsMenu/index.tsx @@ -3,7 +3,6 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; -import type {AnchorAlignment} from '@components/Popover/types'; import type {PopoverMenuItem} from '@components/PopoverMenu'; import PopoverMenu from '@components/PopoverMenu'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; @@ -15,6 +14,7 @@ import * as Browser from '@libs/Browser'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import type {AnchorPosition} from '@src/styles'; +import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; type ThreeDotsMenuProps = { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index c3de0f9f749f..d9b504a959da 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -13,6 +13,7 @@ import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvata import CONST from '@src/CONST'; import type {ParentNavigationSummaryParams, TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type { Beta, @@ -614,13 +615,19 @@ function isExpenseReport(report: OnyxEntry | EmptyObject): boolean { } /** - * Checks if a report is an IOU report. + * Checks if a report is an IOU report using report or reportID */ function isIOUReport(reportOrID: OnyxEntry | string | EmptyObject): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; return report?.type === CONST.REPORT.TYPE.IOU; } +/** + * Checks if a report is an IOU report using report + */ +function isIOUReportUsingReport(report: OnyxEntry | EmptyObject): report is Report { + return report?.type === CONST.REPORT.TYPE.IOU; +} /** * Checks if a report is a task report. */ @@ -856,7 +863,7 @@ function isPublicAnnounceRoom(report: OnyxEntry): boolean { * If the report is a policy expense, the route should be for adding bank account for that policy * else since the report is a personal IOU, the route should be for personal bank account. */ -function getBankAccountRoute(report: OnyxEntry): string { +function getBankAccountRoute(report: OnyxEntry): Route { return isPolicyExpenseChat(report) ? ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', report?.policyID) : ROUTES.SETTINGS_ADD_BANK_ACCOUNT; } @@ -4961,6 +4968,7 @@ export { isReportParticipant, isValidReport, isReportFieldOfTypeTitle, + isIOUReportUsingReport, hasUpdatedTotal, isReportFieldDisabled, getAvailableReportFields, diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index cbc5778187a1..2199c5768612 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -3,7 +3,6 @@ import type {MutableRefObject} from 'react'; import type {GestureResponderEvent} from 'react-native'; import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {TransferMethod} from '@components/KYCWall/types'; import * as API from '@libs/API'; import type {AddPaymentCardParams, DeletePaymentCardParams, MakeDefaultPaymentMethodParams, PaymentCardParams, TransferWalletBalanceParams} from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; @@ -14,11 +13,12 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Route} from '@src/ROUTES'; import type {BankAccountList, FundList} from '@src/types/onyx'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type PaymentMethod from '@src/types/onyx/PaymentMethod'; import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer'; type KYCWallRef = { - continueAction?: (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: TransferMethod) => void; + continueAction?: (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: PaymentMethodType) => void; }; /** diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index dc09f81af60b..4bc5063629e9 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -38,6 +38,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Policy, PolicyMember, PolicyTags, RecentlyUsedCategories, RecentlyUsedTags, ReimbursementAccount, Report, ReportAction, Transaction} from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {CustomUnit} from '@src/types/onyx/Policy'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type AnnounceRoomMembersOnyxData = { @@ -1551,9 +1552,9 @@ function buildOptimisticPolicyRecentlyUsedTags(policyID: string, tag: string): R * * @returns policyID of the workspace we have created */ -function createWorkspaceFromIOUPayment(iouReport: Report): string | undefined { +function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string | undefined { // This flow only works for IOU reports - if (!ReportUtils.isIOUReport(iouReport)) { + if (!ReportUtils.isIOUReportUsingReport(iouReport)) { return; } diff --git a/src/types/onyx/LastPaymentMethod.ts b/src/types/onyx/LastPaymentMethod.ts new file mode 100644 index 000000000000..677a23fa9586 --- /dev/null +++ b/src/types/onyx/LastPaymentMethod.ts @@ -0,0 +1,3 @@ +type LastPaymentMethod = Record; + +export default LastPaymentMethod; diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 2ca9e67dfe53..459ff5524034 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -2,7 +2,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -type PaymentMethodType = DeepValueOf; +type PaymentMethodType = DeepValueOf; type ActionName = DeepValueOf; type OriginalMessageActionName = diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index ef37e40026a4..4728c8872e75 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -28,6 +28,7 @@ import type {FundList} from './Fund'; import type Fund from './Fund'; import type IntroSelected from './IntroSelected'; import type IOU from './IOU'; +import type LastPaymentMethod from './LastPaymentMethod'; import type Locale from './Locale'; import type {LoginList} from './Login'; import type Login from './Login'; @@ -161,6 +162,7 @@ export type { PolicyReportField, PolicyReportFields, RecentlyUsedReportFields, + LastPaymentMethod, NewRoomForm, IKnowATeacherForm, IntroSchoolPrincipalForm, diff --git a/src/types/utils/AnchorAlignment.ts b/src/types/utils/AnchorAlignment.ts new file mode 100644 index 000000000000..899e3d9e277b --- /dev/null +++ b/src/types/utils/AnchorAlignment.ts @@ -0,0 +1,12 @@ +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; + +type AnchorAlignment = { + /** The horizontal anchor alignment of the popover */ + horizontal: ValueOf; + + /** The vertical anchor alignment of the popover */ + vertical: ValueOf; +}; + +export default AnchorAlignment;