From 6d5dc6f857de8b050a95f57af88dbac1084ff56e Mon Sep 17 00:00:00 2001 From: David Bondy Date: Mon, 2 Sep 2024 11:48:39 -0600 Subject: [PATCH] Revert "Revert "Consolidate options on settlement "Pay" button"" --- .../ButtonWithDropdownMenu/index.tsx | 2 +- .../ButtonWithDropdownMenu/types.ts | 3 +- src/components/KYCWall/BaseKYCWall.tsx | 129 +++--------------- .../MoneyRequestConfirmationList.tsx | 1 - src/components/SettlementButton.tsx | 45 +++--- src/languages/en.ts | 3 + src/languages/es.ts | 5 + src/languages/types.ts | 1 + src/pages/iou/MoneyRequestAmountForm.tsx | 1 - src/types/onyx/OriginalMessage.ts | 2 +- 10 files changed, 55 insertions(+), 137 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu/index.tsx b/src/components/ButtonWithDropdownMenu/index.tsx index 74b38f515a06..bcce5d09c348 100644 --- a/src/components/ButtonWithDropdownMenu/index.tsx +++ b/src/components/ButtonWithDropdownMenu/index.tsx @@ -64,7 +64,7 @@ function ButtonWithDropdownMenu({ if ('measureInWindow' in dropdownAnchor.current) { dropdownAnchor.current.measureInWindow((x, y, w, h) => { setPopoverAnchorPosition({ - horizontal: x + w, + horizontal: x + w + h, vertical: anchorAlignment.vertical === CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP ? y + h + CONST.MODAL.POPOVER_MENU_PADDING // if vertical anchorAlignment is TOP, menu will open below the button and we need to add the height of button and padding diff --git a/src/components/ButtonWithDropdownMenu/types.ts b/src/components/ButtonWithDropdownMenu/types.ts index e4b81da94942..9be13696721c 100644 --- a/src/components/ButtonWithDropdownMenu/types.ts +++ b/src/components/ButtonWithDropdownMenu/types.ts @@ -1,12 +1,13 @@ import type {RefObject} from 'react'; import type {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'; import type {ValueOf} from 'type-fest'; +import type {PaymentMethodType} from '@components/KYCWall/types'; import type 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'; -type PaymentType = DeepValueOf; +type PaymentType = DeepValueOf; type WorkspaceMemberBulkActionType = DeepValueOf; diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index fd681546c470..625973bbbe59 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,16 +1,12 @@ -import React, {useCallback, useEffect, useRef, useState} from 'react'; -import {Dimensions} from 'react-native'; -import type {EmitterSubscription, GestureResponderEvent, View} from 'react-native'; +import React, {useCallback, useRef} from 'react'; +import type {GestureResponderEvent, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; -import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; import * as BankAccounts from '@libs/actions/BankAccounts'; -import getClickedTargetLocation from '@libs/getClickedTargetLocation'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import * as PaymentMethods from '@userActions/PaymentMethods'; import * as Policy from '@userActions/Policy/Policy'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; @@ -19,10 +15,7 @@ import ROUTES from '@src/ROUTES'; import type {BankAccountList, FundList, ReimbursementAccount, UserWallet, WalletTerms} from '@src/types/onyx'; 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; +import type {KYCWallProps, PaymentMethod} from './types'; type BaseKYCWallOnyxProps = { /** The user's wallet */ @@ -49,10 +42,6 @@ type BaseKYCWallProps = KYCWallProps & BaseKYCWallOnyxProps; function KYCWall({ addBankAccountRoute, addDebitCardRoute, - anchorAlignment = { - horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, - vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, - }, bankAccountList = {}, chatReportID = '', children, @@ -63,60 +52,13 @@ function KYCWall({ onSuccessfulKYC, reimbursementAccount, shouldIncludeDebitCard = true, - shouldListenForResize = false, source, userWallet, walletTerms, - shouldShowPersonalBankAccountOption = false, }: BaseKYCWallProps) { const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); - const [shouldShowAddPaymentMenu, setShouldShowAddPaymentMenu] = useState(false); - - const [anchorPosition, setAnchorPosition] = useState({ - anchorPositionVertical: 0, - anchorPositionHorizontal: 0, - }); - - const getAnchorPosition = useCallback( - (domRect: DomRect): AnchorPosition => { - if (anchorAlignment.vertical === CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP) { - return { - anchorPositionVertical: domRect.top + domRect.height + CONST.MODAL.POPOVER_MENU_PADDING, - anchorPositionHorizontal: domRect.left + POPOVER_MENU_ANCHOR_POSITION_HORIZONTAL_OFFSET, - }; - } - - return { - anchorPositionVertical: domRect.top - CONST.MODAL.POPOVER_MENU_PADDING, - anchorPositionHorizontal: domRect.left, - }; - }, - [anchorAlignment.vertical], - ); - - /** - * Set position of the transfer payment menu - */ - const setPositionAddPaymentMenu = ({anchorPositionVertical, anchorPositionHorizontal}: AnchorPosition) => { - setAnchorPosition({ - anchorPositionVertical, - anchorPositionHorizontal, - }); - }; - - const setMenuPosition = useCallback(() => { - if (!transferBalanceButtonRef.current) { - return; - } - - const buttonPosition = getClickedTargetLocation(transferBalanceButtonRef.current as HTMLDivElement); - const position = getAnchorPosition(buttonPosition); - - setPositionAddPaymentMenu(position); - }, [getAnchorPosition]); - const selectPaymentMethod = useCallback( (paymentMethod: PaymentMethod) => { onSelectPaymentMethod(paymentMethod); @@ -159,11 +101,6 @@ function KYCWall({ */ Wallet.setKYCWallSource(source, chatReportID); - if (shouldShowAddPaymentMenu) { - setShouldShowAddPaymentMenu(false); - return; - } - // Use event target as fallback if anchorRef is null for safety const targetElement = anchorRef.current ?? (event?.currentTarget as HTMLDivElement); @@ -184,11 +121,19 @@ function KYCWall({ return; } - const clickedElementLocation = getClickedTargetLocation(targetElement as HTMLDivElement); - const position = getAnchorPosition(clickedElementLocation); - - setPositionAddPaymentMenu(position); - setShouldShowAddPaymentMenu(true); + switch (iouPaymentType) { + case CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT: + selectPaymentMethod(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + break; + case CONST.PAYMENT_METHODS.DEBIT_CARD: + selectPaymentMethod(CONST.PAYMENT_METHODS.DEBIT_CARD); + break; + case CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT: + selectPaymentMethod(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT); + break; + default: + break; + } return; } @@ -214,58 +159,18 @@ function KYCWall({ chatReportID, enablePaymentsRoute, fundList, - getAnchorPosition, iouReport, onSuccessfulKYC, reimbursementAccount?.achData?.state, selectPaymentMethod, shouldIncludeDebitCard, - shouldShowAddPaymentMenu, source, userWallet?.tierName, walletTerms?.source, ], ); - useEffect(() => { - let dimensionsSubscription: EmitterSubscription | null = null; - - PaymentMethods.kycWallRef.current = {continueAction}; - - if (shouldListenForResize) { - dimensionsSubscription = Dimensions.addEventListener('change', setMenuPosition); - } - - return () => { - if (shouldListenForResize && dimensionsSubscription) { - dimensionsSubscription.remove(); - } - - PaymentMethods.kycWallRef.current = null; - }; - }, [chatReportID, setMenuPosition, shouldListenForResize, continueAction]); - - return ( - <> - setShouldShowAddPaymentMenu(false)} - anchorRef={anchorRef} - anchorPosition={{ - vertical: anchorPosition.anchorPositionVertical, - horizontal: anchorPosition.anchorPositionHorizontal, - }} - anchorAlignment={anchorAlignment} - onItemSelected={(item: PaymentMethod) => { - setShouldShowAddPaymentMenu(false); - selectPaymentMethod(item); - }} - shouldShowPersonalBankAccountOption={shouldShowPersonalBankAccountOption} - /> - {children(continueAction, viewRef(anchorRef))} - - ); + return <>{children(continueAction, viewRef(anchorRef))}; } KYCWall.displayName = 'BaseKYCWall'; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index f3089505d15a..cee1450baeb2 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -837,7 +837,6 @@ function MoneyRequestConfirmationList({ onPress={confirm} enablePaymentsRoute={ROUTES.IOU_SEND_ENABLE_PAYMENTS} addBankAccountRoute={bankAccountRoute} - shouldShowPersonalBankAccountOption currency={iouCurrencyCode} policyID={policyID} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index e68d09375d49..fc72f2fe7418 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -105,9 +105,6 @@ type SettlementButtonProps = SettlementButtonOnyxProps & { /** The anchor alignment of the popover menu for KYC wall popover */ kycWallAnchorAlignment?: AnchorAlignment; - /** Whether the personal bank account option should be shown */ - shouldShowPersonalBankAccountOption?: boolean; - /** The priority to assign the enter key event listener to buttons. 0 is the highest priority. */ enterKeyEventListenerPriority?: number; @@ -147,7 +144,6 @@ function SettlementButton({ shouldShowApproveButton = false, shouldDisableApproveButton = false, style, - shouldShowPersonalBankAccountOption = false, enterKeyEventListenerPriority = 0, confirmApproval, policy, @@ -170,25 +166,35 @@ function SettlementButton({ (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport) && policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL); const shouldShowPayElsewhereOption = (!isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) && !isInvoiceReport; const paymentButtonOptions = useMemo(() => { - const buttonOptions = []; const isExpenseReport = ReportUtils.isExpenseReport(iouReport); const paymentMethods = { - [CONST.IOU.PAYMENT_TYPE.EXPENSIFY]: { - text: translate('iou.settleExpensify', {formattedAmount}), - icon: Expensicons.Wallet, - value: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, - }, [CONST.IOU.PAYMENT_TYPE.VBBA]: { text: translate('iou.settleExpensify', {formattedAmount}), icon: Expensicons.Wallet, value: CONST.IOU.PAYMENT_TYPE.VBBA, }, + [CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]: { + text: translate('iou.settlePersonalBank', {formattedAmount}), + icon: Expensicons.Bank, + value: CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, + }, + [CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]: { + text: translate('iou.settleBusinessBank', {formattedAmount}), + icon: Expensicons.Bank, + value: CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT, + }, + [CONST.PAYMENT_METHODS.DEBIT_CARD]: { + text: translate('iou.settleDebitCard', {formattedAmount}), + icon: Expensicons.CreditCard, + value: CONST.PAYMENT_METHODS.DEBIT_CARD, + }, [CONST.IOU.PAYMENT_TYPE.ELSEWHERE]: { text: translate('iou.payElsewhere', {formattedAmount}), icon: Expensicons.Cash, value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; + const buttonOptions = []; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, @@ -206,12 +212,10 @@ function SettlementButton({ // If the user has previously chosen a specific payment option or paid for some expense, // let's use the last payment method or use default. const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? '-1'; - if (canUseWallet) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); - } - if (isExpenseReport && shouldShowPaywithExpensifyOption) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); + if (canUseWallet || (isExpenseReport && shouldShowPaywithExpensifyOption)) { + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); } + if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } @@ -271,7 +275,12 @@ function SettlementButton({ return; } - if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { + if ( + iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || + iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD + ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; @@ -305,7 +314,6 @@ function SettlementButton({ chatReportID={chatReportID} iouReport={iouReport} anchorAlignment={kycWallAnchorAlignment} - shouldShowPersonalBankAccountOption={shouldShowPersonalBankAccountOption} > {(triggerKYCFlow, buttonRef) => ( @@ -313,10 +321,7 @@ function SettlementButton({ onOptionsMenuShow={onPaymentOptionsShow} onOptionsMenuHide={onPaymentOptionsHide} buttonRef={buttonRef} - shouldAlwaysShowDropdownMenu={isInvoiceReport} - customText={isInvoiceReport ? translate('iou.settlePayment', {formattedAmount}) : undefined} menuHeaderText={isInvoiceReport ? translate('workspace.invoices.paymentMethods.chooseInvoiceMethod') : undefined} - isSplitButton={!isInvoiceReport} isDisabled={isDisabled} isLoading={isLoading} onPress={(event, iouPaymentType) => selectPaymentType(event, iouPaymentType, triggerKYCFlow)} diff --git a/src/languages/en.ts b/src/languages/en.ts index 30e2dad391d9..22bfe32bf1eb 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -778,6 +778,9 @@ export default { settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Pay ${formattedAmount}`, settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} as a business` : `Pay as a business`), payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} elsewhere` : `Pay elsewhere`), + settlePersonalBank: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with personal bank account` : `Pay with personal bank account`), + settleBusinessBank: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with business bank account` : `Pay with business bank account`), + settleDebitCard: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with debit card` : `Pay with debit card`), nextStep: 'Next steps', finished: 'Finished', sendInvoice: ({amount}: RequestAmountParams) => `Send ${amount} invoice`, diff --git a/src/languages/es.ts b/src/languages/es.ts index 16b8f6f42ed2..fd73392c7502 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -771,6 +771,11 @@ export default { settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Pagar ${formattedAmount}`, settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} como negocio` : `Pagar como empresa`), payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} de otra forma` : `Pagar de otra forma`), + settlePersonalBank: ({formattedAmount}: SettleExpensifyCardParams) => + formattedAmount ? `Pagar ${formattedAmount} con cuenta bancaria personal` : `Pagar con cuenta bancaria personal`, + settleBusinessBank: ({formattedAmount}: SettleExpensifyCardParams) => + formattedAmount ? `Pagar ${formattedAmount} con cuenta bancaria comercial` : `Pagar con cuenta bancaria comercial`, + settleDebitCard: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} con tarjeta de débito` : `Pagar con tarjeta de débito`), nextStep: 'Pasos siguientes', finished: 'Finalizado', sendInvoice: ({amount}: RequestAmountParams) => `Enviar factura de ${amount}`, diff --git a/src/languages/types.ts b/src/languages/types.ts index c4c6b25b06d0..fb396a3f64ea 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -103,6 +103,7 @@ type RequestCountParams = { type SettleExpensifyCardParams = { formattedAmount: string; + available?: boolean; }; type RequestAmountParams = {amount: string}; diff --git a/src/pages/iou/MoneyRequestAmountForm.tsx b/src/pages/iou/MoneyRequestAmountForm.tsx index ba406c3ddef6..81de69919ed3 100644 --- a/src/pages/iou/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/MoneyRequestAmountForm.tsx @@ -323,7 +323,6 @@ function MoneyRequestAmountForm( horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, }} - shouldShowPersonalBankAccountOption enterKeyEventListenerPriority={1} /> ) : ( diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index c18992923c21..f0cc7c6b4db4 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -8,7 +8,7 @@ import type ReportActionName from './ReportActionName'; type JoinWorkspaceResolution = ValueOf; /** Types of payments methods */ -type PaymentMethodType = DeepValueOf; +type PaymentMethodType = DeepValueOf; /** Types of sources of original message */ type OriginalMessageSource = 'Chronos' | 'email' | 'ios' | 'android' | 'web' | '';