From a534dd8b33aca5d182ce8166ceb8b9d3ec12bb3f Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Sat, 24 Feb 2024 12:00:14 -0600 Subject: [PATCH 01/48] consolidated settlement pay button --- src/components/SettlementButton.tsx | 77 +++++++++++++++++++++++------ src/languages/en.ts | 3 ++ src/types/onyx/OriginalMessage.ts | 2 +- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 50bfcd4cc8be..857536a4d1ef 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -9,6 +9,8 @@ import playSound, {SOUNDS} from '@libs/Sound'; import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PaymentMethods from '@userActions/PaymentMethods'; +import * as Policy from '@userActions/Policy'; +import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -147,6 +149,21 @@ function SettlementButton({ 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, @@ -169,12 +186,22 @@ function SettlementButton({ // 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 = nvpLastPaymentMethod?.[policyID] ?? ''; - if (canUseWallet) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); - } - if (isExpenseReport) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); - } + + // no longer want to show these options based on https://github.com/Expensify/App/issues/33967 + // PR issue: https://github.com/Expensify/App/issues/36301 + // what needs to happen to backend to support? + + // if (canUseWallet) { + // buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); + // } + // if (isExpenseReport) { + // buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); + // } + + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); + buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); if (shouldShowApproveButton) { @@ -190,16 +217,34 @@ function SettlementButton({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton]); - 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); - return; - } - - if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { - IOU.approveMoneyRequest(iouReport ?? {}); - return; + const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType , triggerKYCFlow: TriggerKYCFlow) => { + switch (iouPaymentType){ + case CONST.IOU.PAYMENT_TYPE.EXPENSIFY: + case CONST.IOU.PAYMENT_TYPE.VBBA: + // this case i no longer supported as we removed these options per https://github.com/Expensify/App/issues/33967 + // PR issue: https://github.com/Expensify/App/issues/36301 + // is this safe to remove? + triggerKYCFlow(event, iouPaymentType); + BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); + return; + case CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT: + if (iouReport && ReportUtils.isIOUReport(iouReport)) { + const policyID = Policy.createWorkspaceFromIOUPayment(iouReport); + // Navigate to the bank account set up flow for this specific policy + Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', policyID)); + return; + } + Navigation.navigate(addBankAccountRoute); + return; + case CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT: + BankAccounts.openPersonalBankAccountSetupView(); + return; + case CONST.PAYMENT_METHODS.DEBIT_CARD: + Navigation.navigate(addDebitCardRoute); + return; + case CONST.IOU.REPORT_ACTION_TYPE.APPROVE: + IOU.approveMoneyRequest(iouReport ?? {}); + return; } playSound(SOUNDS.DONE); diff --git a/src/languages/en.ts b/src/languages/en.ts index b6a24f33035c..212dcd40de7a 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -611,6 +611,9 @@ export default { settledElsewhere: 'Paid elsewhere', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with Expensify` : `Pay with Expensify`), 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', requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`, diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 06c2d2e6abce..e35605048376 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 = From 08a1fc1f6aa944b5063f13482d391ff87ce46369 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 7 Mar 2024 16:29:51 -0600 Subject: [PATCH 02/48] removal of extra payment window and re-organized to properly use payment_methods --- src/components/ButtonWithDropdownMenu.tsx | 2 +- src/components/KYCWall/BaseKYCWall.tsx | 37 ++++++-------- src/components/SettlementButton.tsx | 61 +++++++---------------- 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu.tsx b/src/components/ButtonWithDropdownMenu.tsx index 9466da601825..b5df176d44a2 100644 --- a/src/components/ButtonWithDropdownMenu.tsx +++ b/src/components/ButtonWithDropdownMenu.tsx @@ -17,7 +17,7 @@ import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import PopoverMenu from './PopoverMenu'; -type PaymentType = DeepValueOf; +type PaymentType = DeepValueOf type DropdownOption = { value: PaymentType; diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 33dfd2b920a9..2818ccf6e20b 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -3,7 +3,6 @@ import {Dimensions} from 'react-native'; import type {EmitterSubscription, GestureResponderEvent} 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'; @@ -156,10 +155,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 HTMLElement); @@ -185,7 +180,20 @@ function KYCWall({ 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: + selectPaymentMethod(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + } return; } @@ -244,22 +252,7 @@ function KYCWall({ 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))} ); diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 857536a4d1ef..3118746a1792 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -9,8 +9,7 @@ import playSound, {SOUNDS} from '@libs/Sound'; import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PaymentMethods from '@userActions/PaymentMethods'; -import * as Policy from '@userActions/Policy'; -import Navigation from '@libs/Navigation/Navigation'; +import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -187,22 +186,13 @@ function SettlementButton({ // let's use the last payment method or use default. const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? ''; - // no longer want to show these options based on https://github.com/Expensify/App/issues/33967 - // PR issue: https://github.com/Expensify/App/issues/36301 - // what needs to happen to backend to support? - - // if (canUseWallet) { - // buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); - // } - // if (isExpenseReport) { - // buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); - // } - - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); + if (canUseWallet) { + buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); + } if (shouldShowApproveButton) { buttonOptions.push(approveButtonOption); @@ -217,34 +207,19 @@ function SettlementButton({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton]); - const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType , triggerKYCFlow: TriggerKYCFlow) => { - switch (iouPaymentType){ - case CONST.IOU.PAYMENT_TYPE.EXPENSIFY: - case CONST.IOU.PAYMENT_TYPE.VBBA: - // this case i no longer supported as we removed these options per https://github.com/Expensify/App/issues/33967 - // PR issue: https://github.com/Expensify/App/issues/36301 - // is this safe to remove? - triggerKYCFlow(event, iouPaymentType); - BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); - return; - case CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT: - if (iouReport && ReportUtils.isIOUReport(iouReport)) { - const policyID = Policy.createWorkspaceFromIOUPayment(iouReport); - // Navigate to the bank account set up flow for this specific policy - Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', policyID)); - return; - } - Navigation.navigate(addBankAccountRoute); - return; - case CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT: - BankAccounts.openPersonalBankAccountSetupView(); - return; - case CONST.PAYMENT_METHODS.DEBIT_CARD: - Navigation.navigate(addDebitCardRoute); - return; - case CONST.IOU.REPORT_ACTION_TYPE.APPROVE: - IOU.approveMoneyRequest(iouReport ?? {}); - return; + const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { + if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || 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; + } + + if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { + IOU.approveMoneyRequest(iouReport ?? {}); + return; } playSound(SOUNDS.DONE); From c825bc08fc1dc67537dc392fe0ed30fefe67fae2 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 8 Mar 2024 10:16:40 -0600 Subject: [PATCH 03/48] Update SettlementButton to match main --- src/components/SettlementButton.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 3118746a1792..1e29c53a15f9 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -9,7 +9,6 @@ import playSound, {SOUNDS} from '@libs/Sound'; import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PaymentMethods from '@userActions/PaymentMethods'; -import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -20,8 +19,10 @@ 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 type {PaymentType} from './ButtonWithDropdownMenu/types'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; +import {useSession} from './OnyxProvider'; type KYCFlowEvent = GestureResponderEvent | KeyboardEvent | undefined; @@ -134,6 +135,14 @@ function SettlementButton({ PaymentMethods.openWalletPage(); }, []); + const policy = ReportUtils.getPolicy(policyID); + const session = useSession(); + const chatReport = ReportUtils.getReport(chatReportID); + const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport as OnyxEntry); + const shouldShowPaywithExpensifyOption = + !isPaidGroupPolicy || + (!shouldHidePaymentOptions && policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && policy?.reimburserEmail === session?.email); + const paymentButtonOptions = useMemo(() => { const buttonOptions = []; const isExpenseReport = ReportUtils.isExpenseReport(iouReport); @@ -245,6 +254,7 @@ function SettlementButton({ > {(triggerKYCFlow, buttonRef) => ( Date: Fri, 8 Mar 2024 10:19:50 -0600 Subject: [PATCH 04/48] Update SettlementButton match main even more --- src/components/SettlementButton.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 1e29c53a15f9..1ca623ff39ff 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -142,7 +142,6 @@ function SettlementButton({ const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && policy?.reimburserEmail === session?.email); - const paymentButtonOptions = useMemo(() => { const buttonOptions = []; const isExpenseReport = ReportUtils.isExpenseReport(iouReport); @@ -215,7 +214,6 @@ function SettlementButton({ // 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: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT @@ -253,7 +251,7 @@ function SettlementButton({ shouldShowPersonalBankAccountOption={shouldShowPersonalBankAccountOption} > {(triggerKYCFlow, buttonRef) => ( - success buttonRef={buttonRef} isDisabled={isDisabled} From d4683762bf13b36e53dfb37f3ff6d5efe401c2f6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 8 Mar 2024 19:33:07 -0600 Subject: [PATCH 05/48] removed default case --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index f130f64f5441..50a448145c6a 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -192,7 +192,7 @@ function KYCWall({ selectPaymentMethod(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT); break; default: - selectPaymentMethod(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + break; } return; From 21bab68c15707116b552a472adeab9c9218b39f6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 4 Apr 2024 13:40:14 -0500 Subject: [PATCH 06/48] Added PaymentMethodType as an option for the dropdown to match old style --- src/components/ButtonWithDropdownMenu/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/ButtonWithDropdownMenu/types.ts b/src/components/ButtonWithDropdownMenu/types.ts index 87db9a29d827..7c68104b7231 100644 --- a/src/components/ButtonWithDropdownMenu/types.ts +++ b/src/components/ButtonWithDropdownMenu/types.ts @@ -5,8 +5,9 @@ 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'; +import type { PaymentMethodType } from '@components/KYCWall/types'; -type PaymentType = DeepValueOf; +type PaymentType = DeepValueOf; type WorkspaceMemberBulkActionType = DeepValueOf; From a3ae2f88b864e711de2b3c64baed76c8ff3db3f5 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 4 Apr 2024 15:08:14 -0500 Subject: [PATCH 07/48] added translations to fix jest tests --- src/languages/es.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/languages/es.ts b/src/languages/es.ts index 53ee6d3fba79..f6b66fcbd810 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -646,6 +646,9 @@ export default { settledElsewhere: 'Pagado de otra forma', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} con Expensify` : `Pagar con Expensify`), 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', requestAmount: ({amount}: RequestAmountParams) => `solicitar ${amount}`, From 6619e114509a57e3f086f49417552a9d40ae80f0 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 4 Apr 2024 17:08:58 -0500 Subject: [PATCH 08/48] Removed unnecessary components --- src/components/KYCWall/BaseKYCWall.tsx | 93 ++------------------------ 1 file changed, 4 insertions(+), 89 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 50a448145c6a..83202eb93db2 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,15 +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 * 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'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; @@ -18,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 */ @@ -48,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, @@ -62,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); @@ -176,11 +119,6 @@ function KYCWall({ return; } - const clickedElementLocation = getClickedTargetLocation(targetElement as HTMLDivElement); - const position = getAnchorPosition(clickedElementLocation); - - setPositionAddPaymentMenu(position); - switch (iouPaymentType) { case CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT: selectPaymentMethod(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); @@ -219,42 +157,19 @@ 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 ( - <> - - {children(continueAction, viewRef(anchorRef))} - + <>{children(continueAction, viewRef(anchorRef))} ); } From 0e3bd691499a8de84683a39fd0772c2fd178bd00 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 4 Apr 2024 17:28:20 -0500 Subject: [PATCH 09/48] Prettier run --- src/components/ButtonWithDropdownMenu/types.ts | 2 +- src/components/KYCWall/BaseKYCWall.tsx | 5 +---- src/components/SettlementButton.tsx | 11 +++++++---- src/languages/en.ts | 2 +- src/languages/es.ts | 8 +++++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu/types.ts b/src/components/ButtonWithDropdownMenu/types.ts index 7c68104b7231..3bc8ccfb8f98 100644 --- a/src/components/ButtonWithDropdownMenu/types.ts +++ b/src/components/ButtonWithDropdownMenu/types.ts @@ -1,11 +1,11 @@ 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'; -import type { PaymentMethodType } from '@components/KYCWall/types'; type PaymentType = DeepValueOf; diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 83202eb93db2..d0b6b3484f4d 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -98,7 +98,6 @@ function KYCWall({ */ Wallet.setKYCWallSource(source, chatReportID); - // Use event target as fallback if anchorRef is null for safety const targetElement = anchorRef.current ?? (event?.currentTarget as HTMLDivElement); @@ -168,9 +167,7 @@ function KYCWall({ ], ); - return ( - <>{children(continueAction, viewRef(anchorRef))} - ); + return <>{children(continueAction, viewRef(anchorRef))}; } KYCWall.displayName = 'BaseKYCWall'; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 58dccf7c1c51..b72b41b74911 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -232,10 +232,13 @@ function SettlementButton({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton, shouldDisableApproveButton]); const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { - if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || 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) { + if ( + iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || + 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; diff --git a/src/languages/en.ts b/src/languages/en.ts index a351f8fe48d8..269f205b4d38 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -652,7 +652,7 @@ export default { 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`), + settleDebitCard: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with debit card` : `Pay with debit card`), nextStep: 'Next Steps', finished: 'Finished', requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`, diff --git a/src/languages/es.ts b/src/languages/es.ts index f6b66fcbd810..677b889f7a42 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -646,9 +646,11 @@ export default { settledElsewhere: 'Pagado de otra forma', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} con Expensify` : `Pagar con Expensify`), 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`), + 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', requestAmount: ({amount}: RequestAmountParams) => `solicitar ${amount}`, From 4e93753421f10eaad20ccacd78a8da033324d37d Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 8 Apr 2024 12:29:08 -0500 Subject: [PATCH 10/48] Removed fragment and updated initial button options --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/components/SettlementButton.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index d0b6b3484f4d..500a6d9342ba 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -167,7 +167,7 @@ function KYCWall({ ], ); - return <>{children(continueAction, viewRef(anchorRef))}; + return children(continueAction, viewRef(anchorRef)); } KYCWall.displayName = 'BaseKYCWall'; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index b72b41b74911..c56e543dcaf1 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -19,7 +19,7 @@ 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 type {PaymentType} from './ButtonWithDropdownMenu/types'; +import type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; import {useSession} from './OnyxProvider'; @@ -153,7 +153,6 @@ function SettlementButton({ const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry)); const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; const paymentButtonOptions = useMemo(() => { - const buttonOptions = []; const isExpenseReport = ReportUtils.isExpenseReport(iouReport); const paymentMethods = { [CONST.IOU.PAYMENT_TYPE.EXPENSIFY]: { @@ -187,6 +186,11 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; + const buttonOptions = [ + paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD], + ] as Array>; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, @@ -205,10 +209,6 @@ function SettlementButton({ // let's use the last payment method or use default. const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? ''; - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); - if (canUseWallet) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); } From c4f7b85c147b44840b6c08f681e9ac77ac29baa5 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 8 Apr 2024 12:38:54 -0500 Subject: [PATCH 11/48] Removed react import --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 500a6d9342ba..ce3bd72e7a79 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useRef} from 'react'; +import {useCallback, useRef} from 'react'; import type {GestureResponderEvent, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; From 55e3e2866e3996cd9d401b80398532f6d6494a3c Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 8 Apr 2024 14:42:49 -0500 Subject: [PATCH 12/48] Update BaseKYCWall.tsx --- src/components/KYCWall/BaseKYCWall.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index ce3bd72e7a79..8e49fbff43dc 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -55,7 +55,7 @@ function KYCWall({ source, userWallet, walletTerms, -}: BaseKYCWallProps) { +}: BaseKYCWallProps): JSX.Element { const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); @@ -167,7 +167,7 @@ function KYCWall({ ], ); - return children(continueAction, viewRef(anchorRef)); + return <>children(continueAction, viewRef(anchorRef)) } KYCWall.displayName = 'BaseKYCWall'; From 114aa85e729a6ba7bc099d97abfc5337542c7c85 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 8 Apr 2024 14:52:14 -0500 Subject: [PATCH 13/48] Update BaseKYCWall.tsx --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 8e49fbff43dc..c46078a809e7 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -167,7 +167,7 @@ function KYCWall({ ], ); - return <>children(continueAction, viewRef(anchorRef)) + return <>{children(continueAction, viewRef(anchorRef))} } KYCWall.displayName = 'BaseKYCWall'; From 4a17c6a0ee274eb0771750b4ddec95a767dc3753 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 8 Apr 2024 15:56:06 -0500 Subject: [PATCH 14/48] Update BaseKYCWall.tsx --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index c46078a809e7..18c922609da7 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -167,7 +167,7 @@ function KYCWall({ ], ); - return <>{children(continueAction, viewRef(anchorRef))} + return <>{children(continueAction, viewRef(anchorRef))}; } KYCWall.displayName = 'BaseKYCWall'; From da3c50eb0335aedfcc16a608c1bafa4bbe2bc6be Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 9 Apr 2024 17:24:48 -0500 Subject: [PATCH 15/48] removed expensify option and fixed breakage --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/components/SettlementButton.tsx | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 18c922609da7..2f63380403d7 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,4 +1,4 @@ -import {useCallback, useRef} from 'react'; +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'; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index a253ea236639..0dd0fc5eecb7 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -197,7 +197,6 @@ function SettlementButton({ value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the request if (shouldHidePaymentOptions && shouldShowApproveButton) { @@ -209,9 +208,6 @@ function SettlementButton({ // let's use the last payment method or use default. const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? ''; - if (canUseWallet) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); - } if (isExpenseReport && shouldShowPaywithExpensifyOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); } From 11f87f2e800bfdd0ad58fa3c59910d62f75d4c5b Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 9 Apr 2024 18:00:40 -0500 Subject: [PATCH 16/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 0dd0fc5eecb7..007cac6960c8 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -186,39 +186,46 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; - const buttonOptions = [ - paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD], - ] as Array>; + + const buttonOptions = []; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - + // Only show the Approve button if the user cannot pay the request if (shouldHidePaymentOptions && shouldShowApproveButton) { return [approveButtonOption]; } - + // 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 = nvpLastPaymentMethod?.[policyID] ?? ''; - + + if ((isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN) || + (!isExpenseReport && bankAccountList !== null && !PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, shouldIncludeDebitCard)) + ) { + buttonOptions.push( + paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD] + ); + } + if (isExpenseReport && shouldShowPaywithExpensifyOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); } if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } - + if (shouldShowApproveButton) { buttonOptions.push(approveButtonOption); } - + // Put the preferred payment method to the front of the array, so it's shown as default if (paymentMethod) { return buttonOptions.sort((method) => (method.value === paymentMethod ? -1 : 0)); From a72034dfe4900877cb6c2846944f0ace99603a70 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 11 Apr 2024 13:47:27 -0500 Subject: [PATCH 17/48] swap changes around --- src/components/KYCWall/BaseKYCWall.tsx | 191 ++++++++++++++++++++++--- src/components/KYCWall/types.ts | 23 ++- src/components/SettlementButton.tsx | 110 +++----------- 3 files changed, 212 insertions(+), 112 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 2f63380403d7..4df7187d1d54 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,13 +1,17 @@ -import React, {useCallback, useRef} from 'react'; -import type {GestureResponderEvent, View} from 'react-native'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; +import {Dimensions} from 'react-native'; +import type {EmitterSubscription, 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 IOU from '@userActions/IOU'; import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import * as Policy from '@userActions/Policy'; +import * as PaymentMethods from '@userActions/PaymentMethods'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -15,7 +19,12 @@ 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 {KYCWallProps, PaymentMethod} from './types'; +import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; +import type { DropdownOption } from '@components/ButtonWithDropdownMenu/types'; +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; type BaseKYCWallOnyxProps = { /** The user's wallet */ @@ -32,6 +41,8 @@ type BaseKYCWallOnyxProps = { /** The reimbursement account linked to the Workspace */ reimbursementAccount: OnyxEntry; + + }; type BaseKYCWallProps = KYCWallProps & BaseKYCWallOnyxProps; @@ -42,6 +53,10 @@ 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, @@ -52,15 +67,77 @@ function KYCWall({ onSuccessfulKYC, reimbursementAccount, shouldIncludeDebitCard = true, + shouldListenForResize = false, source, userWallet, walletTerms, -}: BaseKYCWallProps): JSX.Element { + shouldShowPersonalBankAccountOption = false, + paymentButtonOptions, + buttonConfig, + policyID, +}: BaseKYCWallProps) { const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); + const [shouldShowAddPaymentMenu, setShouldShowAddPaymentMenu] = useState(false); + + const { + size: buttonSize, + isDisabled, + isLoading, + style, + paymentMethodDropdownAnchorAlignment, + enterKeyEventListenerPriority, + pressOnEnter, + confirmApproval + } = buttonConfig; + 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); if (paymentMethod === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { @@ -69,8 +146,6 @@ function KYCWall({ Navigation.navigate(addDebitCardRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { if (iouReport && ReportUtils.isIOUReport(iouReport)) { - const policyID = Policy.createWorkspaceFromIOUPayment(iouReport); - // Navigate to the bank account set up flow for this specific policy Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', policyID)); @@ -78,10 +153,26 @@ function KYCWall({ } Navigation.navigate(addBankAccountRoute); } + + // if (paymentMethod === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { + // if (confirmApproval) { + // confirmApproval(); + // } else { + // IOU.approveMoneyRequest(iouReport ?? {}); + // } + // return; + // } + + // playSound(SOUNDS.DONE); }, - [addBankAccountRoute, addDebitCardRoute, iouReport, onSelectPaymentMethod], + [addBankAccountRoute, addDebitCardRoute, iouReport, onSelectPaymentMethod, policyID], ); + + const savePreferredPaymentMethod = (id: string, value: PaymentMethodType) => { + IOU.savePreferredPaymentMethod(id, value); + }; + /** * Take the position of the button that calls this method and show the Add Payment method menu when the user has no valid payment method. * If they do have a valid payment method they are navigated to the "enable payments" route to complete KYC checks. @@ -98,6 +189,11 @@ 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); @@ -118,19 +214,11 @@ function KYCWall({ return; } - 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; - } + const clickedElementLocation = getClickedTargetLocation(targetElement as HTMLDivElement); + const position = getAnchorPosition(clickedElementLocation); + + setPositionAddPaymentMenu(position); + setShouldShowAddPaymentMenu(true); return; } @@ -156,18 +244,74 @@ function KYCWall({ chatReportID, enablePaymentsRoute, fundList, + getAnchorPosition, iouReport, onSuccessfulKYC, reimbursementAccount?.achData?.state, selectPaymentMethod, shouldIncludeDebitCard, + shouldShowAddPaymentMenu, source, userWallet?.tierName, walletTerms?.source, ], ); - return <>{children(continueAction, viewRef(anchorRef))}; + 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 ? ( + <>{children(continueAction, viewRef(anchorRef))} + ) : ( + + success + isDisabled={isDisabled} + isLoading={isLoading} + onPress={continueAction} + pressOnEnter={pressOnEnter} + options={paymentButtonOptions} + onOptionSelected={(option: DropdownOption) => savePreferredPaymentMethod(policyID, option.value)} + style={style} + buttonSize={buttonSize} + anchorAlignment={paymentMethodDropdownAnchorAlignment} + enterKeyEventListenerPriority={enterKeyEventListenerPriority} + /> + )} + + ); } KYCWall.displayName = 'BaseKYCWall'; @@ -189,4 +333,7 @@ export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, + policy: { + key: ({policyID}: Record) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + }, })(KYCWall); diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 53ed00e04143..756871de0fac 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -1,5 +1,6 @@ import type {RefObject} from 'react'; -import type {GestureResponderEvent, View} from 'react-native'; + +import type {GestureResponderEvent, View, StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; @@ -9,6 +10,9 @@ 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 type {ButtonSizeValue} from '@src/styles/utils/types'; +import type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; + type Source = ValueOf; type DOMRectProperties = 'top' | 'bottom' | 'left' | 'right' | 'height' | 'x' | 'y'; @@ -63,7 +67,22 @@ type KYCWallProps = { onSuccessfulKYC: (iouPaymentType?: PaymentMethodType, currentSource?: Source) => void; /** Children to build the KYC */ - children: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method?: PaymentMethodType) => void, anchorRef: RefObject) => void; + children?: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method?: PaymentMethodType) => void, anchorRef: RefObject) => void; + + paymentButtonOptions: Array>; + + buttonConfig: { + size: ButtonSizeValue; + isDisabled?: boolean; + isLoading?: boolean; + style?: StyleProp; + paymentMethodDropdownAnchorAlignment?: AnchorAlignment; + enterKeyEventListenerPriority?: number; + pressOnEnter?: boolean; + confirmApproval?: () => void | undefined; + }; + /** The policyID of the report we are paying */ + policyID: string; }; export type {AnchorPosition, KYCWallProps, PaymentMethod, DomRect, PaymentMethodType, Source}; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 007cac6960c8..64253c42af22 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -1,13 +1,10 @@ import React, {useEffect, useMemo} from 'react'; -import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import * as ReportUtils from '@libs/ReportUtils'; -import playSound, {SOUNDS} from '@libs/Sound'; -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'; @@ -18,16 +15,10 @@ import type {LastPaymentMethod, Policy, 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 type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; import {useSession} from './OnyxProvider'; -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 = { @@ -153,6 +144,7 @@ function SettlementButton({ const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry)); const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; const paymentButtonOptions = useMemo(() => { + const buttonOptions = []; const isExpenseReport = ReportUtils.isExpenseReport(iouReport); const paymentMethods = { [CONST.IOU.PAYMENT_TYPE.EXPENSIFY]: { @@ -165,67 +157,43 @@ function SettlementButton({ 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, value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - + const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD; + // Only show the Approve button if the user cannot pay the request if (shouldHidePaymentOptions && shouldShowApproveButton) { return [approveButtonOption]; } - + // 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 = nvpLastPaymentMethod?.[policyID] ?? ''; - - if ((isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN) || - (!isExpenseReport && bankAccountList !== null && !PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, shouldIncludeDebitCard)) - ) { - buttonOptions.push( - paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD] - ); + if (canUseWallet) { + buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); } - if (isExpenseReport && shouldShowPaywithExpensifyOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); } if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } - + if (shouldShowApproveButton) { buttonOptions.push(approveButtonOption); } - + // Put the preferred payment method to the front of the array, so it's shown as default if (paymentMethod) { return buttonOptions.sort((method) => (method.value === paymentMethod ? -1 : 0)); @@ -234,35 +202,6 @@ function SettlementButton({ // 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, shouldDisableApproveButton]); - const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { - if ( - iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || - 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; - } - - if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { - if (confirmApproval) { - confirmApproval(); - } else { - IOU.approveMoneyRequest(iouReport ?? {}); - } - return; - } - - playSound(SOUNDS.DONE); - onPress(iouPaymentType); - }; - - const savePreferredPaymentMethod = (id: string, value: PaymentMethodType) => { - IOU.savePreferredPaymentMethod(id, value); - }; return ( - {(triggerKYCFlow, buttonRef) => ( - - success - buttonRef={buttonRef} - isDisabled={isDisabled} - isLoading={isLoading} - onPress={(event, iouPaymentType) => selectPaymentType(event, iouPaymentType, triggerKYCFlow)} - pressOnEnter={pressOnEnter} - options={paymentButtonOptions} - onOptionSelected={(option) => savePreferredPaymentMethod(policyID, option.value)} - style={style} - buttonSize={buttonSize} - anchorAlignment={paymentMethodDropdownAnchorAlignment} - enterKeyEventListenerPriority={enterKeyEventListenerPriority} - /> - )} - + paymentButtonOptions={paymentButtonOptions} + buttonConfig={{ + size: buttonSize, + isDisabled, + isLoading, + style, + paymentMethodDropdownAnchorAlignment, + enterKeyEventListenerPriority, + pressOnEnter, + confirmApproval + }} + policyID={policyID} + /> ); } From b54580b2fdeeb24e4428a365a0d9d52f61b9a2d6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 17 Apr 2024 00:29:29 -0500 Subject: [PATCH 18/48] revert and check if payment added --- src/components/KYCWall/BaseKYCWall.tsx | 193 +++---------------------- src/components/KYCWall/types.ts | 17 +-- src/components/SettlementButton.tsx | 147 +++++++++++++++---- src/languages/en.ts | 21 ++- src/languages/types.ts | 1 + 5 files changed, 161 insertions(+), 218 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 4df7187d1d54..a78db8f35252 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -1,17 +1,13 @@ -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 IOU from '@userActions/IOU'; import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import * as PaymentMethods from '@userActions/PaymentMethods'; +import * as Policy from '@userActions/Policy'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -19,12 +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 ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; -import type { DropdownOption } from '@components/ButtonWithDropdownMenu/types'; -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 */ @@ -41,8 +32,6 @@ type BaseKYCWallOnyxProps = { /** The reimbursement account linked to the Workspace */ reimbursementAccount: OnyxEntry; - - }; type BaseKYCWallProps = KYCWallProps & BaseKYCWallOnyxProps; @@ -53,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, @@ -67,77 +52,15 @@ function KYCWall({ onSuccessfulKYC, reimbursementAccount, shouldIncludeDebitCard = true, - shouldListenForResize = false, source, userWallet, walletTerms, - shouldShowPersonalBankAccountOption = false, - paymentButtonOptions, - buttonConfig, - policyID, -}: BaseKYCWallProps) { +}: BaseKYCWallProps): JSX.Element { const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); - const [shouldShowAddPaymentMenu, setShouldShowAddPaymentMenu] = useState(false); - - const { - size: buttonSize, - isDisabled, - isLoading, - style, - paymentMethodDropdownAnchorAlignment, - enterKeyEventListenerPriority, - pressOnEnter, - confirmApproval - } = buttonConfig; - 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); if (paymentMethod === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { @@ -146,6 +69,8 @@ function KYCWall({ Navigation.navigate(addDebitCardRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { if (iouReport && ReportUtils.isIOUReport(iouReport)) { + const policyID = Policy.createWorkspaceFromIOUPayment(iouReport); + // Navigate to the bank account set up flow for this specific policy Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', policyID)); @@ -153,26 +78,10 @@ function KYCWall({ } Navigation.navigate(addBankAccountRoute); } - - // if (paymentMethod === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { - // if (confirmApproval) { - // confirmApproval(); - // } else { - // IOU.approveMoneyRequest(iouReport ?? {}); - // } - // return; - // } - - // playSound(SOUNDS.DONE); }, - [addBankAccountRoute, addDebitCardRoute, iouReport, onSelectPaymentMethod, policyID], + [addBankAccountRoute, addDebitCardRoute, iouReport, onSelectPaymentMethod], ); - - const savePreferredPaymentMethod = (id: string, value: PaymentMethodType) => { - IOU.savePreferredPaymentMethod(id, value); - }; - /** * Take the position of the button that calls this method and show the Add Payment method menu when the user has no valid payment method. * If they do have a valid payment method they are navigated to the "enable payments" route to complete KYC checks. @@ -189,11 +98,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); @@ -214,11 +118,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; } @@ -244,74 +156,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 ? ( - <>{children(continueAction, viewRef(anchorRef))} - ) : ( - - success - isDisabled={isDisabled} - isLoading={isLoading} - onPress={continueAction} - pressOnEnter={pressOnEnter} - options={paymentButtonOptions} - onOptionSelected={(option: DropdownOption) => savePreferredPaymentMethod(policyID, option.value)} - style={style} - buttonSize={buttonSize} - anchorAlignment={paymentMethodDropdownAnchorAlignment} - enterKeyEventListenerPriority={enterKeyEventListenerPriority} - /> - )} - - ); + return <>{children(continueAction, viewRef(anchorRef))}; } KYCWall.displayName = 'BaseKYCWall'; @@ -333,7 +189,4 @@ export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, - policy: { - key: ({policyID}: Record) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - }, -})(KYCWall); +})(KYCWall); \ No newline at end of file diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 756871de0fac..68d627caa09f 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -67,22 +67,7 @@ type KYCWallProps = { onSuccessfulKYC: (iouPaymentType?: PaymentMethodType, currentSource?: Source) => void; /** Children to build the KYC */ - children?: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method?: PaymentMethodType) => void, anchorRef: RefObject) => void; - - paymentButtonOptions: Array>; - - buttonConfig: { - size: ButtonSizeValue; - isDisabled?: boolean; - isLoading?: boolean; - style?: StyleProp; - paymentMethodDropdownAnchorAlignment?: AnchorAlignment; - enterKeyEventListenerPriority?: number; - pressOnEnter?: boolean; - confirmApproval?: () => void | undefined; - }; - /** The policyID of the report we are paying */ - policyID: string; + children: (continueAction: (event: GestureResponderEvent | KeyboardEvent | undefined, method?: PaymentMethodType) => void, anchorRef: RefObject) => void; }; export type {AnchorPosition, KYCWallProps, PaymentMethod, DomRect, PaymentMethodType, Source}; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 64253c42af22..b39e90483299 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -1,24 +1,34 @@ import React, {useEffect, useMemo} from 'react'; -import type {StyleProp, ViewStyle} from 'react-native'; +import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import playSound, {SOUNDS} from '@libs/Sound'; +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 type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type {ButtonSizeValue} from '@src/styles/utils/types'; -import type {LastPaymentMethod, Policy, Report} from '@src/types/onyx'; +import type {BankAccountList, FundList, LastPaymentMethod, Policy, ReimbursementAccount, 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 type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; import {useSession} from './OnyxProvider'; +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 = { @@ -27,6 +37,15 @@ type SettlementButtonOnyxProps = { /** The policy of the report */ policy: OnyxEntry; + + /** List of user's cards */ + fundList: OnyxEntry; + + /** List of bank accounts */ + bankAccountList: OnyxEntry; + + /** The reimbursement account linked to the Workspace */ + reimbursementAccount: OnyxEntry; }; type SettlementButtonProps = SettlementButtonOnyxProps & { @@ -95,6 +114,15 @@ type SettlementButtonProps = SettlementButtonOnyxProps & { /** Callback to open confirmation modal if any of the transactions is on HOLD */ confirmApproval?: () => void; + + /** List of user's cards */ + fundList: OnyxEntry; + + /** List of bank accounts */ + bankAccountList: OnyxEntry; + + /** The reimbursement account linked to the Workspace */ + reimbursementAccount: OnyxEntry; }; function SettlementButton({ @@ -130,6 +158,9 @@ function SettlementButton({ enterKeyEventListenerPriority = 0, confirmApproval, policy, + fundList, + bankAccountList = {}, + reimbursementAccount, }: SettlementButtonProps) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -143,33 +174,50 @@ function SettlementButton({ const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport); const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry)); const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + const isExpenseReport = ReportUtils.isExpenseReport(iouReport ?? null); + const paymentCardList = fundList ?? {}; + const hasBankAccount = isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN && !isExpenseReport && bankAccountList !== null; + const hasPaymentMethod = bankAccountList !== null && PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, true); + 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, available: hasBankAccount && hasPaymentMethod}), + icon: Expensicons.Bank, + value: CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, + }, + [CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]: { + text: translate('iou.settleBusinessBank', {formattedAmount, available: hasBankAccount && hasPaymentMethod}), + icon: Expensicons.Bank, + value: CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT, + }, + [CONST.PAYMENT_METHODS.DEBIT_CARD]: { + text: translate('iou.settleDebitCard', {formattedAmount, available: hasPaymentMethod}), + 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 = [ + paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], + paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD], + ] as Array>; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the request if (shouldHidePaymentOptions && shouldShowApproveButton) { @@ -180,12 +228,7 @@ function SettlementButton({ // 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 = nvpLastPaymentMethod?.[policyID] ?? ''; - if (canUseWallet) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); - } - if (isExpenseReport && shouldShowPaywithExpensifyOption) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); - } + if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } @@ -202,6 +245,35 @@ function SettlementButton({ // 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, shouldDisableApproveButton]); + const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { + if ( + iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || + 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; + } + + if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { + if (confirmApproval) { + confirmApproval(); + } else { + IOU.approveMoneyRequest(iouReport ?? {}); + } + return; + } + + playSound(SOUNDS.DONE); + onPress(iouPaymentType); + }; + + const savePreferredPaymentMethod = (id: string, value: PaymentMethodType) => { + IOU.savePreferredPaymentMethod(id, value); + }; return ( + > + {(triggerKYCFlow, buttonRef) => ( + + success + buttonRef={buttonRef} + isDisabled={isDisabled} + isLoading={isLoading} + onPress={(event, iouPaymentType) => selectPaymentType(event, iouPaymentType, triggerKYCFlow)} + pressOnEnter={pressOnEnter} + options={paymentButtonOptions} + onOptionSelected={(option) => savePreferredPaymentMethod(policyID, option.value)} + style={style} + buttonSize={buttonSize} + anchorAlignment={paymentMethodDropdownAnchorAlignment} + enterKeyEventListenerPriority={enterKeyEventListenerPriority} + /> + )} + ); } @@ -241,4 +318,16 @@ export default withOnyx({ policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, + fundList: { + key: ONYXKEYS.FUND_LIST, + selector: (fundList) => fundList ?? {}, + }, + bankAccountList: { + key: ONYXKEYS.BANK_ACCOUNT_LIST, + selector: (bankAccountList) => bankAccountList ?? {}, + }, + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + selector: (reimbursementAccount) => reimbursementAccount ?? {}, + }, })(SettlementButton); diff --git a/src/languages/en.ts b/src/languages/en.ts index 3f9cc8db026e..056672ca1d32 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -651,9 +651,24 @@ export default { settledElsewhere: 'Paid elsewhere', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with Expensify` : `Pay with Expensify`), 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`), + settlePersonalBank: ({formattedAmount, available}: SettleExpensifyCardParams) => { + if (!available) { + return `Add personal bank account`; + } + return formattedAmount ? `Pay ${formattedAmount} with personal bank account` : `Pay with personal bank account`; + }, + settleBusinessBank: ({formattedAmount, available}: SettleExpensifyCardParams) => { + if (!available) { + return `Add business bank account`; + } + return formattedAmount ? `Pay ${formattedAmount} with business bank account` : `Pay with business bank account`; + }, + settleDebitCard: ({formattedAmount, available}: SettleExpensifyCardParams) => { + if (!available) { + return `Add debit card`; + } + return formattedAmount ? `Pay ${formattedAmount} with debit card` : `Pay with debit card`; + }, nextStep: 'Next Steps', finished: 'Finished', requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`, diff --git a/src/languages/types.ts b/src/languages/types.ts index c365363f84af..cbb4a804c66c 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -105,6 +105,7 @@ type RequestCountParams = { type SettleExpensifyCardParams = { formattedAmount: string; + available?: boolean; }; type RequestAmountParams = {amount: string}; From 7e8a0cdcb8f964949eebd7bce1e1ed4e8b42e0c9 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 17 Apr 2024 00:55:59 -0500 Subject: [PATCH 19/48] adding back in shouldshowpaywithexpensifyoptions --- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/components/KYCWall/types.ts | 6 ++---- src/components/SettlementButton.tsx | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index a78db8f35252..2f63380403d7 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -189,4 +189,4 @@ export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, -})(KYCWall); \ No newline at end of file +})(KYCWall); diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 68d627caa09f..11a0f74ca66d 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -1,16 +1,14 @@ import type {RefObject} from 'react'; - -import type {GestureResponderEvent, View, StyleProp, ViewStyle} from 'react-native'; +import type {GestureResponderEvent, StyleProp, View, ViewStyle} 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 {ButtonSizeValue} from '@src/styles/utils/types'; 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'; - -import type {ButtonSizeValue} from '@src/styles/utils/types'; import type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; type Source = ValueOf; diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index b39e90483299..8929822ed887 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -177,7 +177,7 @@ function SettlementButton({ const isExpenseReport = ReportUtils.isExpenseReport(iouReport ?? null); const paymentCardList = fundList ?? {}; const hasBankAccount = isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN && !isExpenseReport && bankAccountList !== null; - const hasPaymentMethod = bankAccountList !== null && PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, true); + const hasPaymentMethod = bankAccountList !== null && PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, true) && shouldShowPaywithExpensifyOption; const paymentButtonOptions = useMemo(() => { const paymentMethods = { From 0ced26eb695e7f2f5fe14fbcc6ffb1af4c282850 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 17 Apr 2024 01:04:29 -0500 Subject: [PATCH 20/48] eslint fix --- src/components/KYCWall/types.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 11a0f74ca66d..53ed00e04143 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -1,15 +1,13 @@ import type {RefObject} from 'react'; -import type {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'; +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 {ButtonSizeValue} from '@src/styles/utils/types'; 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'; -import type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; type Source = ValueOf; From 80e64012908eb050e99697049be51b75a6721e05 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 24 Apr 2024 21:31:44 -0500 Subject: [PATCH 21/48] updated per feedback --- src/components/SettlementButton.tsx | 12 ++++-------- src/languages/en.ts | 21 +++------------------ 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 8929822ed887..b4a8c1a87b07 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -187,17 +187,17 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.VBBA, }, [CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]: { - text: translate('iou.settlePersonalBank', {formattedAmount, available: hasBankAccount && hasPaymentMethod}), + 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, available: hasBankAccount && hasPaymentMethod}), + 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, available: hasPaymentMethod}), + text: translate('iou.settleDebitCard', {formattedAmount}), icon: Expensicons.CreditCard, value: CONST.PAYMENT_METHODS.DEBIT_CARD, }, @@ -247,11 +247,7 @@ function SettlementButton({ }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton, shouldDisableApproveButton]); const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if ( - iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || - 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 + !hasBankAccount || !hasPaymentMethod ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); diff --git a/src/languages/en.ts b/src/languages/en.ts index 9b77bb9ccf39..2ed32e286b3a 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -652,24 +652,9 @@ export default { settledElsewhere: 'Paid elsewhere', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with Expensify` : `Pay with Expensify`), payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} elsewhere` : `Pay elsewhere`), - settlePersonalBank: ({formattedAmount, available}: SettleExpensifyCardParams) => { - if (!available) { - return `Add personal bank account`; - } - return formattedAmount ? `Pay ${formattedAmount} with personal bank account` : `Pay with personal bank account`; - }, - settleBusinessBank: ({formattedAmount, available}: SettleExpensifyCardParams) => { - if (!available) { - return `Add business bank account`; - } - return formattedAmount ? `Pay ${formattedAmount} with business bank account` : `Pay with business bank account`; - }, - settleDebitCard: ({formattedAmount, available}: SettleExpensifyCardParams) => { - if (!available) { - return `Add debit card`; - } - return formattedAmount ? `Pay ${formattedAmount} with debit card` : `Pay with debit card`; - }, + 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', requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`, From edb64a764249af9afb1bca9869e468d40a458f29 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 24 Apr 2024 21:32:01 -0500 Subject: [PATCH 22/48] updated per feedback --- src/components/SettlementButton.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index b4a8c1a87b07..f5ba6218469e 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -247,13 +247,20 @@ function SettlementButton({ }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton, shouldDisableApproveButton]); const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if ( - !hasBankAccount || !hasPaymentMethod + (iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || + iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) && !hasBankAccount ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; } + if ((iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD) && !hasPaymentMethod) { + triggerKYCFlow(event, iouPaymentType); + return; + } + if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { if (confirmApproval) { confirmApproval(); From 4c54a1a3ded29ca77b470ecab84f77b0469e3604 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 25 Apr 2024 09:47:22 -0500 Subject: [PATCH 23/48] prettier --- src/components/SettlementButton.tsx | 5 +++-- src/languages/en.ts | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index f5ba6218469e..d7ea089c9f0c 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -248,8 +248,9 @@ function SettlementButton({ const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if ( (iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || - iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || - iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) && !hasBankAccount + iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) && + !hasBankAccount ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); diff --git a/src/languages/en.ts b/src/languages/en.ts index 2ed32e286b3a..2f5f811a63f3 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -652,9 +652,9 @@ export default { settledElsewhere: 'Paid elsewhere', settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pay ${formattedAmount} with Expensify` : `Pay with Expensify`), 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`, + 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', requestAmount: ({amount}: RequestAmountParams) => `request ${amount}`, From 224c4d53fb91f9397517712a9d174b694f2d5c4b Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 7 May 2024 20:50:38 -0500 Subject: [PATCH 24/48] Update BaseKYCWall.tsx --- src/components/KYCWall/BaseKYCWall.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 9708e9af7e43..ea94eb115400 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -55,7 +55,6 @@ function KYCWall({ source, userWallet, walletTerms, - shouldShowPersonalBankAccountOption = false, }: BaseKYCWallProps) { const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); From f5d40fa3bcdb1c09222e795a02c85c54e40c1d81 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 10 May 2024 10:34:39 -0500 Subject: [PATCH 25/48] code review updates --- src/components/SettlementButton.tsx | 59 +++++------------------------ 1 file changed, 10 insertions(+), 49 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index bf6d9d012478..722423279466 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -15,7 +15,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type {ButtonSizeValue} from '@src/styles/utils/types'; -import type {BankAccountList, FundList, LastPaymentMethod, Policy, ReimbursementAccount, Report} from '@src/types/onyx'; +import type {LastPaymentMethod, Policy, 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'; @@ -37,15 +37,6 @@ type SettlementButtonOnyxProps = { /** The policy of the report */ policy: OnyxEntry; - - /** List of user's cards */ - fundList: OnyxEntry; - - /** List of bank accounts */ - bankAccountList: OnyxEntry; - - /** The reimbursement account linked to the Workspace */ - reimbursementAccount: OnyxEntry; }; type SettlementButtonProps = SettlementButtonOnyxProps & { @@ -114,15 +105,6 @@ type SettlementButtonProps = SettlementButtonOnyxProps & { /** Callback to open confirmation modal if any of the transactions is on HOLD */ confirmApproval?: () => void; - - /** List of user's cards */ - fundList: OnyxEntry; - - /** List of bank accounts */ - bankAccountList: OnyxEntry; - - /** The reimbursement account linked to the Workspace */ - reimbursementAccount: OnyxEntry; }; function SettlementButton({ @@ -158,9 +140,6 @@ function SettlementButton({ enterKeyEventListenerPriority = 0, confirmApproval, policy, - fundList, - bankAccountList = {}, - reimbursementAccount, }: SettlementButtonProps) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -174,10 +153,6 @@ function SettlementButton({ const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport); const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry)); const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; - const isExpenseReport = ReportUtils.isExpenseReport(iouReport ?? null); - const paymentCardList = fundList ?? {}; - const hasBankAccount = isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN && !isExpenseReport && bankAccountList !== null; - const hasPaymentMethod = bankAccountList !== null && PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, true) && shouldShowPaywithExpensifyOption; const paymentButtonOptions = useMemo(() => { const paymentMethods = { @@ -207,11 +182,7 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; - const buttonOptions = [ - paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT], - paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD], - ] as Array>; + const buttonOptions = [paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]] as Array>; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, @@ -229,6 +200,10 @@ function SettlementButton({ // let's use the last payment method or use default. const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? ''; + if (shouldShowPersonalBankAccountOption) { + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); + } + if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } @@ -247,17 +222,16 @@ function SettlementButton({ }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton, shouldDisableApproveButton]); const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { if ( - (iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || - iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || - iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) && - !hasBankAccount + iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || + iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; } - if ((iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD) && !hasPaymentMethod) { + if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD) { triggerKYCFlow(event, iouPaymentType); return; } @@ -290,7 +264,6 @@ function SettlementButton({ chatReportID={chatReportID} iouReport={iouReport} anchorAlignment={kycWallAnchorAlignment} - shouldShowPersonalBankAccountOption={shouldShowPersonalBankAccountOption} > {(triggerKYCFlow, buttonRef) => ( @@ -322,16 +295,4 @@ export default withOnyx({ policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - fundList: { - key: ONYXKEYS.FUND_LIST, - selector: (fundList) => fundList ?? {}, - }, - bankAccountList: { - key: ONYXKEYS.BANK_ACCOUNT_LIST, - selector: (bankAccountList) => bankAccountList ?? {}, - }, - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - selector: (reimbursementAccount) => reimbursementAccount ?? {}, - }, })(SettlementButton); From cf08526a400cb5a07fb1c3dcbe656006e46baaca Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 10 May 2024 12:31:11 -0500 Subject: [PATCH 26/48] fixed linter issues --- src/components/SettlementButton.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 722423279466..e2411ca2bc9a 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as BankAccounts from '@userActions/BankAccounts'; @@ -155,6 +154,7 @@ function SettlementButton({ const shouldShowPayElsewhereOption = !isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; const paymentButtonOptions = useMemo(() => { + const isExpenseReport = ReportUtils.isExpenseReport(iouReport); const paymentMethods = { [CONST.IOU.PAYMENT_TYPE.VBBA]: { text: translate('iou.settleExpensify', {formattedAmount}), @@ -199,8 +199,9 @@ 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] ?? ''; + const canUsePersonalBankAccount = isExpenseReport && shouldShowPaywithExpensifyOption; - if (shouldShowPersonalBankAccountOption) { + if (shouldShowPersonalBankAccountOption && canUsePersonalBankAccount) { buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); } From 78b851eb60a2bdcd60fe2fbf8fff444806d4b270 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 13 May 2024 10:58:07 -0500 Subject: [PATCH 27/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index e2411ca2bc9a..a7278c7e248e 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -225,14 +225,10 @@ function SettlementButton({ 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.PERSONAL_BANK_ACCOUNT || + iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD ) { - triggerKYCFlow(event, iouPaymentType); - BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); - return; - } - - if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD) { + if (iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); triggerKYCFlow(event, iouPaymentType); return; } From 77b2ad5e460b0a621c7c794e4730937fe5d330f6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 13 May 2024 11:00:13 -0500 Subject: [PATCH 28/48] order matters --- src/components/SettlementButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index a7278c7e248e..dfa5331b9848 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -228,8 +228,8 @@ function SettlementButton({ iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT || iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD ) { - if (iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); triggerKYCFlow(event, iouPaymentType); + if (iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; } From 9c6379933106987231578d2af7b0497dd9d48b9a Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 13 May 2024 11:16:48 -0500 Subject: [PATCH 29/48] add in elsewhere --- src/components/SettlementButton.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index dfa5331b9848..3a8d427c09de 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -226,10 +226,11 @@ function SettlementButton({ 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 + iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD || + iouPaymentType === CONST.IOU.PAYMENT_TYPE.ELSEWHERE ) { triggerKYCFlow(event, iouPaymentType); - if (iouPaymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); + BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; } From 482a1dfbaa44a6915797888d09c5c32bbbaea0f8 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 13 May 2024 11:34:18 -0500 Subject: [PATCH 30/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 3a8d427c09de..2110dfb9aa88 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -226,7 +226,7 @@ function SettlementButton({ 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 || + iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD || iouPaymentType === CONST.IOU.PAYMENT_TYPE.ELSEWHERE ) { triggerKYCFlow(event, iouPaymentType); From 79e7410988fe73551748299dbbe337a56352bc1d Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Sat, 1 Jun 2024 11:17:44 -0500 Subject: [PATCH 31/48] Update BaseKYCWall.tsx --- src/components/KYCWall/BaseKYCWall.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index dfd15b257560..71ea156fdaf6 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -7,7 +7,6 @@ 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'; From df01e1cb92719490666c800428c9c329c7c43838 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Sun, 2 Jun 2024 11:30:45 -0500 Subject: [PATCH 32/48] Altered elsewhere needing KYC --- src/components/SettlementButton.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 2110dfb9aa88..61368551f89d 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -226,8 +226,7 @@ function SettlementButton({ 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 || - iouPaymentType === CONST.IOU.PAYMENT_TYPE.ELSEWHERE + iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD ) { triggerKYCFlow(event, iouPaymentType); BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); From a6be9716993f11d41f773e52f44b7d920da6e6a6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 4 Jun 2024 10:14:59 -0500 Subject: [PATCH 33/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 07372999ddca..3dcd29669980 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -190,7 +190,6 @@ function SettlementButton({ value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - const canUseWallet = !isExpenseReport && !isInvoiceReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the expense if (shouldHidePaymentOptions && shouldShowApproveButton) { From 17a8654e3d446034725f2c4bb9ee8ab4e2c4eff3 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 7 Jun 2024 09:18:31 -0500 Subject: [PATCH 34/48] Revert settlementbutton changes to match prod and pass --- src/components/SettlementButton.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 3dcd29669980..f71111f5e5a0 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -20,7 +20,7 @@ import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; -import type {DropdownOption, PaymentType} from './ButtonWithDropdownMenu/types'; +import type {PaymentType} from './ButtonWithDropdownMenu/types'; import * as Expensicons from './Icon/Expensicons'; import KYCWall from './KYCWall'; import {useSession} from './OnyxProvider'; @@ -183,13 +183,15 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; - const buttonOptions = [paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT], paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]] as Array>; + + const buttonOptions = []; const approveButtonOption = { text: translate('iou.approve'), icon: Expensicons.ThumbsUp, value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; + const canUseWallet = !isExpenseReport && !isInvoiceReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the expense if (shouldHidePaymentOptions && shouldShowApproveButton) { @@ -200,6 +202,11 @@ 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] ?? ''; + if (canUseWallet) { + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); + } + const canUsePersonalBankAccount = isExpenseReport && shouldShowPaywithExpensifyOption; if (shouldShowPersonalBankAccountOption && canUsePersonalBankAccount) { From 3031ef883450f99c6482d1ed11b8632f7a3dc505 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Fri, 7 Jun 2024 09:33:14 -0500 Subject: [PATCH 35/48] Removed newlines --- src/components/SettlementButton.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index f71111f5e5a0..91cea8f442aa 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -183,7 +183,6 @@ function SettlementButton({ value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, }, }; - const buttonOptions = []; const approveButtonOption = { text: translate('iou.approve'), @@ -212,7 +211,6 @@ function SettlementButton({ if (shouldShowPersonalBankAccountOption && canUsePersonalBankAccount) { buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); } - if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } From cbe89b400f3277bb81271786a2b711d7d13242be Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 25 Jun 2024 01:24:40 -0500 Subject: [PATCH 36/48] match staging --- src/components/SettlementButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 7b4e4bead185..aff9f2374730 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -186,7 +186,7 @@ function SettlementButton({ value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - const canUseWallet = !isExpenseReport && !isInvoiceReport && currency === CONST.CURRENCY.USD; + const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the expense if (shouldHidePaymentOptions && shouldShowApproveButton) { From 5e90b4a816739a05d8d35c8662bf213f47f17bcc Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 2 Jul 2024 20:30:59 -0500 Subject: [PATCH 37/48] Fixed missing option showing --- src/components/SettlementButton.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 46fa7c52f476..31220a11d535 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -203,9 +203,8 @@ function SettlementButton({ buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); } - const canUsePersonalBankAccount = isExpenseReport && shouldShowPaywithExpensifyOption; - - if (shouldShowPersonalBankAccountOption && canUsePersonalBankAccount) { + if (isExpenseReport && shouldShowPaywithExpensifyOption) { + buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); } if (shouldShowPayElsewhereOption) { From ae8a1987ce073a0635005f5696bb98d77a5c70f3 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 3 Jul 2024 09:09:13 -0500 Subject: [PATCH 38/48] prettier --- src/components/SettlementButton.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 31220a11d535..4853fee76487 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -242,11 +242,11 @@ function SettlementButton({ }, [currency, formattedAmount, iouReport, policyID, translate, shouldHidePaymentOptions, shouldShowApproveButton, shouldDisableApproveButton]); const selectPaymentType = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => { - if (policy && SubscriptionUtils.shouldRestrictUserBillableActions(policy.id)) { + if (policy && SubscriptionUtils.shouldRestrictUserBillableActions(policy.id)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(policy.id)); return; } - + if ( iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA || iouPaymentType === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT || @@ -255,7 +255,7 @@ function SettlementButton({ ) { triggerKYCFlow(event, iouPaymentType); return; - }; + } if (iouPaymentType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { if (confirmApproval) { From 59f3bab9bba38b16ca18dcda7e6715a23667101e Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 3 Jul 2024 23:45:27 -0500 Subject: [PATCH 39/48] prettier --- .github/libs/sanitizeStringForJSONParse.ts | 2 +- src/components/SettlementButton.tsx | 4 - src/hooks/useStepFormSubmit.ts | 11 ++- src/languages/types.ts | 20 ++--- src/libs/Localize/index.ts | 11 ++- src/libs/actions/Policy/Policy.ts | 28 ++++--- src/libs/migrations/RenameCardIsVirtual.ts | 27 ++++--- src/libs/migrations/RenameReceiptFilename.ts | 23 +++--- .../EnablePayments/utils/getSubstepValues.ts | 11 ++- .../BeneficialOwnersStep.tsx | 11 ++- .../report/ReportActionsListItemRenderer.tsx | 2 +- src/styles/index.ts | 76 +++++++++---------- src/types/onyx/SearchResults.ts | 8 +- .../ReportActionCompose.perf-test.tsx | 2 +- tests/unit/DateUtilsTest.ts | 4 +- tests/utils/ReportTestUtils.ts | 2 +- tests/utils/TestHelper.ts | 11 ++- 17 files changed, 138 insertions(+), 115 deletions(-) diff --git a/.github/libs/sanitizeStringForJSONParse.ts b/.github/libs/sanitizeStringForJSONParse.ts index ddb7549b0186..d646a566c517 100644 --- a/.github/libs/sanitizeStringForJSONParse.ts +++ b/.github/libs/sanitizeStringForJSONParse.ts @@ -8,7 +8,7 @@ const replacer = (str: string): string => '\r': '\\r', '\f': '\\f', '"': '\\"', - }[str] ?? ''); + })[str] ?? ''; /** * Replace any characters in the string that will break JSON.parse for our Git Log output diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 30e36ecc5e4a..409d9187c166 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -9,7 +9,6 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as SubscriptionUtils from '@libs/SubscriptionUtils'; -import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PolicyActions from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; @@ -99,9 +98,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; diff --git a/src/hooks/useStepFormSubmit.ts b/src/hooks/useStepFormSubmit.ts index 883fe980a338..cd422071c725 100644 --- a/src/hooks/useStepFormSubmit.ts +++ b/src/hooks/useStepFormSubmit.ts @@ -24,10 +24,13 @@ export default function useStepFormSubmit return useCallback( (values: FormOnyxValues) => { if (shouldSaveDraft) { - const stepValues = fieldIds.reduce((acc, key) => { - acc[key] = values[key]; - return acc; - }, {} as Record, OnyxValues[T][Exclude]>); + const stepValues = fieldIds.reduce( + (acc, key) => { + acc[key] = values[key]; + return acc; + }, + {} as Record, OnyxValues[T][Exclude]>, + ); FormActions.setDraftValues(formId, stepValues); } diff --git a/src/languages/types.ts b/src/languages/types.ts index 10ec73bb0846..de7f7b11ce67 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -262,22 +262,22 @@ type FlattenObject = { [TKey in keyof TObject]: TObject[TKey] extends (...args: any[]) => any ? `${TPrefix}${TKey & string}` : // eslint-disable-next-line @typescript-eslint/no-explicit-any - TObject[TKey] extends any[] - ? `${TPrefix}${TKey & string}` - : // eslint-disable-next-line @typescript-eslint/ban-types - TObject[TKey] extends object - ? FlattenObject - : `${TPrefix}${TKey & string}`; + TObject[TKey] extends any[] + ? `${TPrefix}${TKey & string}` + : // eslint-disable-next-line @typescript-eslint/ban-types + TObject[TKey] extends object + ? FlattenObject + : `${TPrefix}${TKey & string}`; }[keyof TObject]; // Retrieves a type for a given key path (calculated from the type above) type TranslateType = TPath extends keyof TObject ? TObject[TPath] : TPath extends `${infer TKey}.${infer TRest}` - ? TKey extends keyof TObject - ? TranslateType - : never - : never; + ? TKey extends keyof TObject + ? TranslateType + : never + : never; type EnglishTranslation = typeof en; diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index c9eef3170245..dd34175e6ad1 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -64,10 +64,13 @@ type Phrase = TranslationFlatObject[TKey] extends * in our cache. */ const translationCache = new Map, Map>( - Object.values(CONST.LOCALES).reduce((cache, locale) => { - cache.push([locale, new Map()]); - return cache; - }, [] as Array<[ValueOf, Map]>), + Object.values(CONST.LOCALES).reduce( + (cache, locale) => { + cache.push([locale, new Map()]); + return cache; + }, + [] as Array<[ValueOf, Map]>, + ), ); /** diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index d075f8653d79..5ff19365bf39 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -2589,13 +2589,16 @@ function enablePolicyTaxes(policyID: string, enabled: boolean) { taxRates: { ...defaultTaxRates, taxes: { - ...Object.keys(defaultTaxRates.taxes).reduce((acc, taxKey) => { - acc[taxKey] = { - ...defaultTaxRates.taxes[taxKey], - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }; - return acc; - }, {} as Record), + ...Object.keys(defaultTaxRates.taxes).reduce( + (acc, taxKey) => { + acc[taxKey] = { + ...defaultTaxRates.taxes[taxKey], + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; + return acc; + }, + {} as Record, + ), }, }, }, @@ -2608,10 +2611,13 @@ function enablePolicyTaxes(policyID: string, enabled: boolean) { value: { taxRates: { taxes: { - ...Object.keys(defaultTaxRates.taxes).reduce((acc, taxKey) => { - acc[taxKey] = {pendingAction: null}; - return acc; - }, {} as Record), + ...Object.keys(defaultTaxRates.taxes).reduce( + (acc, taxKey) => { + acc[taxKey] = {pendingAction: null}; + return acc; + }, + {} as Record, + ), }, }, }, diff --git a/src/libs/migrations/RenameCardIsVirtual.ts b/src/libs/migrations/RenameCardIsVirtual.ts index 751c11d70eac..acd99e5bdf1c 100644 --- a/src/libs/migrations/RenameCardIsVirtual.ts +++ b/src/libs/migrations/RenameCardIsVirtual.ts @@ -26,20 +26,23 @@ export default function () { } Log.info('[Migrate Onyx] Running RenameCardIsVirtual migration'); - const dataToSave = cardsWithIsVirtualProp.reduce((acc, card) => { - if (!card) { - return acc; - } + const dataToSave = cardsWithIsVirtualProp.reduce( + (acc, card) => { + if (!card) { + return acc; + } - acc[card.cardID] = { - nameValuePairs: { - isVirtual: card?.nameValuePairs?.isVirtual, - }, - isVirtual: undefined, - }; + acc[card.cardID] = { + nameValuePairs: { + isVirtual: card?.nameValuePairs?.isVirtual, + }, + isVirtual: undefined, + }; - return acc; - }, {} as Record>); + return acc; + }, + {} as Record>, + ); // eslint-disable-next-line rulesdir/prefer-actions-set-data Onyx.merge(ONYXKEYS.CARD_LIST, dataToSave).then(() => { diff --git a/src/libs/migrations/RenameReceiptFilename.ts b/src/libs/migrations/RenameReceiptFilename.ts index f01676595dd7..2e27802e72d4 100644 --- a/src/libs/migrations/RenameReceiptFilename.ts +++ b/src/libs/migrations/RenameReceiptFilename.ts @@ -30,17 +30,20 @@ export default function () { return resolve(); } Log.info('[Migrate Onyx] Running RenameReceiptFilename migration'); - const dataToSave = transactionsWithReceipt?.reduce((acc, transaction) => { - if (!transaction) { + const dataToSave = transactionsWithReceipt?.reduce( + (acc, transaction) => { + if (!transaction) { + return acc; + } + Log.info(`[Migrate Onyx] Renaming receiptFilename ${transaction.receiptFilename} to filename`); + acc[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = { + filename: transaction.receiptFilename, + receiptFilename: null, + }; return acc; - } - Log.info(`[Migrate Onyx] Renaming receiptFilename ${transaction.receiptFilename} to filename`); - acc[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = { - filename: transaction.receiptFilename, - receiptFilename: null, - }; - return acc; - }, {} as Record>); + }, + {} as Record>, + ); // eslint-disable-next-line rulesdir/prefer-actions-set-data Onyx.mergeCollection(ONYXKEYS.COLLECTION.TRANSACTION, dataToSave).then(() => { diff --git a/src/pages/EnablePayments/utils/getSubstepValues.ts b/src/pages/EnablePayments/utils/getSubstepValues.ts index 2eb80ed1b2ee..4e444b1b53b1 100644 --- a/src/pages/EnablePayments/utils/getSubstepValues.ts +++ b/src/pages/EnablePayments/utils/getSubstepValues.ts @@ -8,10 +8,13 @@ function getSubstepValues( walletAdditionalDetailsDraft: OnyxEntry, walletAdditionalDetails: OnyxEntry, ): {[K in T]: WalletAdditionalDetailsForm[K] | string} { - return Object.entries(inputKeys).reduce((acc, [, value]) => { - acc[value] = walletAdditionalDetailsDraft?.[value] ?? walletAdditionalDetails?.[value as keyof PersonalInfoStepProps] ?? ''; - return acc; - }, {} as {[K in T]: WalletAdditionalDetailsForm[K] | string}); + return Object.entries(inputKeys).reduce( + (acc, [, value]) => { + acc[value] = walletAdditionalDetailsDraft?.[value] ?? walletAdditionalDetails?.[value as keyof PersonalInfoStepProps] ?? ''; + return acc; + }, + {} as {[K in T]: WalletAdditionalDetailsForm[K] | string}, + ); } export default getSubstepValues; diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx index ae0fded74347..c745431290fb 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx @@ -68,10 +68,13 @@ function BeneficialOwnersStep({reimbursementAccount, reimbursementAccountDraft, const submit = () => { const beneficialOwnerFields = ['firstName', 'lastName', 'dob', 'ssnLast4', 'street', 'city', 'state', 'zipCode']; const beneficialOwners = beneficialOwnerKeys.map((ownerKey) => - beneficialOwnerFields.reduce((acc, fieldName) => { - acc[fieldName] = reimbursementAccountDraft ? reimbursementAccountDraft[`beneficialOwner_${ownerKey}_${fieldName}`] : undefined; - return acc; - }, {} as Record), + beneficialOwnerFields.reduce( + (acc, fieldName) => { + acc[fieldName] = reimbursementAccountDraft ? reimbursementAccountDraft[`beneficialOwner_${ownerKey}_${fieldName}`] : undefined; + return acc; + }, + {} as Record, + ), ); BankAccounts.updateBeneficialOwnersForBankAccount( diff --git a/src/pages/home/report/ReportActionsListItemRenderer.tsx b/src/pages/home/report/ReportActionsListItemRenderer.tsx index 1ef689ab1da4..912ad02a19aa 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.tsx +++ b/src/pages/home/report/ReportActionsListItemRenderer.tsx @@ -111,7 +111,7 @@ function ReportActionsListItemRenderer({ childManagerAccountID: reportAction.childManagerAccountID, childMoneyRequestCount: reportAction.childMoneyRequestCount, childOwnerAccountID: reportAction.childOwnerAccountID, - } as ReportAction), + }) as ReportAction, [ reportAction.reportActionID, reportAction.message, diff --git a/src/styles/index.ts b/src/styles/index.ts index 7fabf386813a..c847e4d4c87a 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -108,14 +108,14 @@ const picker = (theme: ThemeColors) => height: variables.inputHeight, borderWidth: 0, textAlign: 'left', - } satisfies TextStyle); + }) satisfies TextStyle; const link = (theme: ThemeColors) => ({ color: theme.link, textDecorationColor: theme.link, fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, - } satisfies ViewStyle & MixedStyleDeclaration); + }) satisfies ViewStyle & MixedStyleDeclaration; const baseCodeTagStyles = (theme: ThemeColors) => ({ @@ -123,7 +123,7 @@ const baseCodeTagStyles = (theme: ThemeColors) => borderRadius: 5, borderColor: theme.border, backgroundColor: theme.textBackground, - } satisfies ViewStyle & MixedStyleDeclaration); + }) satisfies ViewStyle & MixedStyleDeclaration; const headlineFont = { fontFamily: FontUtils.fontFamily.platform.EXP_NEW_KANSAS_MEDIUM, @@ -135,7 +135,7 @@ const modalNavigatorContainer = (isSmallScreenWidth: boolean) => position: 'absolute', width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, height: '100%', - } satisfies ViewStyle); + }) satisfies ViewStyle; const webViewStyles = (theme: ThemeColors) => ({ @@ -237,7 +237,7 @@ const webViewStyles = (theme: ThemeColors) => lineHeight: variables.fontSizeNormalHeight, ...writingDirection.ltr, }, - } satisfies WebViewStyle); + }) satisfies WebViewStyle; const styles = (theme: ThemeColors) => ({ @@ -859,7 +859,7 @@ const styles = (theme: ThemeColors) => pointerEvents: 'none', opacity: 0, }, - } satisfies CustomPickerStyle), + }) satisfies CustomPickerStyle, badge: { backgroundColor: theme.border, @@ -995,7 +995,7 @@ const styles = (theme: ThemeColors) => paddingVertical: 40, gap: 4, flex: 1, - } satisfies ViewStyle), + }) satisfies ViewStyle, receiptViewTextContainer: { paddingHorizontal: 40, @@ -1136,14 +1136,14 @@ const styles = (theme: ThemeColors) => ({ height: lodashClamp(textInputHeight, minHeight, maxHeight), minHeight, - } satisfies ViewStyle), + }) satisfies ViewStyle, autoGrowHeightHiddenInput: (maxWidth: number, maxHeight?: number) => ({ maxWidth, maxHeight: maxHeight && maxHeight + 1, overflow: 'hidden', - } satisfies TextStyle), + }) satisfies TextStyle, textInputContainer: { flex: 1, @@ -1185,7 +1185,7 @@ const styles = (theme: ThemeColors) => textInputLabelTransformation: (translateY: AnimatableNumericValue, translateX: AnimatableNumericValue, scale: AnimatableNumericValue) => ({ transform: [{translateY}, {translateX}, {scale}], - } satisfies TextStyle), + }) satisfies TextStyle, baseTextInput: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, @@ -1324,7 +1324,7 @@ const styles = (theme: ThemeColors) => inputAndroid: { ...picker(theme), }, - } satisfies CustomPickerStyle), + }) satisfies CustomPickerStyle, disabledText: { color: theme.icon, @@ -1569,7 +1569,7 @@ const styles = (theme: ThemeColors) => height: 12, width: 12, zIndex: 10, - } satisfies ViewStyle), + }) satisfies ViewStyle, bottomTabStatusIndicator: (backgroundColor = theme.danger) => ({ borderColor: theme.sidebar, @@ -1649,13 +1649,13 @@ const styles = (theme: ThemeColors) => ({ ...modalNavigatorContainer(isSmallScreenWidth), left: 0, - } satisfies ViewStyle), + }) satisfies ViewStyle, RHPNavigatorContainer: (isSmallScreenWidth: boolean) => ({ ...modalNavigatorContainer(isSmallScreenWidth), right: 0, - } satisfies ViewStyle), + }) satisfies ViewStyle, onboardingNavigatorOuterView: { flex: 1, @@ -1670,7 +1670,7 @@ const styles = (theme: ThemeColors) => maxHeight: '100%', borderRadius: shouldUseNarrowLayout ? 16 : 0, overflow: 'hidden', - } satisfies ViewStyle), + }) satisfies ViewStyle, welcomeVideoNarrowLayout: { width: variables.onboardingModalWidth, @@ -1691,20 +1691,20 @@ const styles = (theme: ThemeColors) => // Menu should be displayed 12px above the floating action button. // To achieve that sidebar must be moved by: distance from the bottom of the sidebar to the fab (variables.fabBottom) + fab height (variables.componentSizeLarge) + distance above the fab (12px) vertical: windowHeight - (variables.fabBottom + variables.componentSizeLarge + 12), - } satisfies AnchorPosition), + }) satisfies AnchorPosition, createAccountMenuPositionProfile: () => ({ horizontal: 18, ...getPopOverVerticalOffset(202 + 40), - } satisfies AnchorPosition), + }) satisfies AnchorPosition, createMenuPositionReportActionCompose: (shouldUseNarrowLayout: boolean, windowHeight: number, windowWidth: number) => ({ // On a narrow layout the menu is displayed in ReportScreen in RHP, so it must be moved from the right side of the screen horizontal: (shouldUseNarrowLayout ? windowWidth - variables.sideBarWidth : variables.sideBarWidth) + 18, vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM, - } satisfies AnchorPosition), + }) satisfies AnchorPosition, createMenuPositionRightSidepane: { right: 18, @@ -1914,7 +1914,7 @@ const styles = (theme: ThemeColors) => outputRange: [0, variables.overlayOpacity], extrapolate: 'clamp', }), - } satisfies ViewStyle), + }) satisfies ViewStyle, nativeOverlayStyles: (current: OverlayStylesParams) => ({ @@ -1927,7 +1927,7 @@ const styles = (theme: ThemeColors) => outputRange: [0, variables.overlayOpacity], extrapolate: 'clamp', }), - } satisfies ViewStyle), + }) satisfies ViewStyle, appContent: { backgroundColor: theme.appBG, @@ -2514,13 +2514,13 @@ const styles = (theme: ThemeColors) => flexBasis: isSmallScreenWidth ? '100%' : 350, flexGrow: 0, alignSelf: 'flex-start', - } satisfies ViewStyle), + }) satisfies ViewStyle, centeredModalStyles: (isSmallScreenWidth: boolean, isFullScreenWhenSmall: boolean) => ({ borderWidth: isSmallScreenWidth && !isFullScreenWhenSmall ? 1 : 0, marginHorizontal: isSmallScreenWidth ? 0 : 20, - } satisfies ViewStyle), + }) satisfies ViewStyle, imageModalImageCenterContainer: { alignItems: 'center', @@ -2684,7 +2684,7 @@ const styles = (theme: ThemeColors) => backgroundColor: theme.cardBG, borderRadius: variables.componentBorderRadiusLarge, overflow: 'hidden', - } satisfies ViewStyle & TextStyle), + }) satisfies ViewStyle & TextStyle, anonymousRoomFooterWordmarkAndLogoContainer: (isSmallSizeLayout: boolean) => ({ flexDirection: 'row', @@ -2693,7 +2693,7 @@ const styles = (theme: ThemeColors) => justifyContent: 'space-between', marginTop: 16, }), - } satisfies ViewStyle), + }) satisfies ViewStyle, anonymousRoomFooterLogo: { width: 88, marginLeft: 0, @@ -2735,8 +2735,8 @@ const styles = (theme: ThemeColors) => borderRadius: 88, }, - rootNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle), - RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle), + rootNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}) satisfies ViewStyle, + RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}) satisfies ViewStyle, avatarInnerTextChat: { color: theme.text, @@ -3026,7 +3026,7 @@ const styles = (theme: ThemeColors) => switchThumbTransformation: (translateX: AnimatableNumericValue) => ({ transform: [{translateX}], - } satisfies ViewStyle), + }) satisfies ViewStyle, radioButtonContainer: { backgroundColor: theme.componentBG, @@ -3253,7 +3253,7 @@ const styles = (theme: ThemeColors) => growlNotificationTranslateY: (translateY: AnimatableNumericValue) => ({ transform: [{translateY}], - } satisfies ViewStyle), + }) satisfies ViewStyle, makeSlideInTranslation: (translationType: Translation, fromValue: number) => ({ @@ -3263,7 +3263,7 @@ const styles = (theme: ThemeColors) => to: { [translationType]: 0, }, - } satisfies CustomAnimation), + }) satisfies CustomAnimation, growlNotificationBox: { backgroundColor: theme.inverse, @@ -3567,25 +3567,25 @@ const styles = (theme: ThemeColors) => ({ ...getPopOverVerticalOffset(60), horizontal: windowWidth - 60, - } satisfies AnchorPosition), + }) satisfies AnchorPosition, threeDotsPopoverOffsetNoCloseButton: (windowWidth: number) => ({ ...getPopOverVerticalOffset(60), horizontal: windowWidth - 10, - } satisfies AnchorPosition), + }) satisfies AnchorPosition, threeDotsPopoverOffsetAttachmentModal: (windowWidth: number) => ({ ...getPopOverVerticalOffset(80), horizontal: windowWidth - 140, - } satisfies AnchorPosition), + }) satisfies AnchorPosition, popoverMenuOffset: (windowWidth: number) => ({ ...getPopOverVerticalOffset(180), horizontal: windowWidth - 355, - } satisfies AnchorPosition), + }) satisfies AnchorPosition, iPhoneXSafeArea: { backgroundColor: theme.inverse, @@ -3689,7 +3689,7 @@ const styles = (theme: ThemeColors) => ({ position: 'absolute', top: receiptImageTopPosition, - } satisfies ViewStyle), + }) satisfies ViewStyle, cardSectionContainer: { backgroundColor: theme.cardBG, @@ -3816,7 +3816,7 @@ const styles = (theme: ThemeColors) => position: 'absolute', width: isSmallScreenWidth ? windowWidth - 32 : CONST.EMOJI_PICKER_SIZE.WIDTH - 32, ...spacing.mh4, - } satisfies ViewStyle), + }) satisfies ViewStyle, reactionCounterText: { fontSize: 13, @@ -4218,7 +4218,7 @@ const styles = (theme: ThemeColors) => color: isSelected ? theme.text : theme.textSupporting, lineHeight: variables.lineHeightNormal, fontSize: variables.fontSizeNormal, - } satisfies TextStyle), + }) satisfies TextStyle, tabBackground: (hovered: boolean, isFocused: boolean, background: string | Animated.AnimatedInterpolation) => ({ backgroundColor: hovered && !isFocused ? theme.highlightBG : background, @@ -4242,7 +4242,7 @@ const styles = (theme: ThemeColors) => top: -height, left: 0, right: 0, - } satisfies ViewStyle), + }) satisfies ViewStyle, dualColorOverscrollSpacer: { position: 'absolute', @@ -5055,7 +5055,7 @@ const styles = (theme: ThemeColors) => fontSize: variables.fontSizeNormal, fontWeight: FontUtils.fontWeight.bold, }, - } satisfies Styles); + }) satisfies Styles; type ThemeStyles = ReturnType; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 89d1b6c72566..1ff4c2c8b2eb 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -12,15 +12,15 @@ type SearchDataTypes = ValueOf; type ListItemType = T extends typeof CONST.SEARCH.DATA_TYPES.TRANSACTION ? typeof TransactionListItem : T extends typeof CONST.SEARCH.DATA_TYPES.REPORT - ? typeof ReportListItem - : never; + ? typeof ReportListItem + : never; /** Model of search result section */ type SectionsType = T extends typeof CONST.SEARCH.DATA_TYPES.TRANSACTION ? TransactionListItemType[] : T extends typeof CONST.SEARCH.DATA_TYPES.REPORT - ? ReportListItemType[] - : never; + ? ReportListItemType[] + : never; /** Mapping of search results to list item */ type SearchTypeToItemMap = { diff --git a/tests/perf-test/ReportActionCompose.perf-test.tsx b/tests/perf-test/ReportActionCompose.perf-test.tsx index 9c6cfdae5a5c..1387ddf1366a 100644 --- a/tests/perf-test/ReportActionCompose.perf-test.tsx +++ b/tests/perf-test/ReportActionCompose.perf-test.tsx @@ -27,7 +27,7 @@ jest.mock( ({ ...jest.requireActual('react-native-reanimated/mock'), useAnimatedRef: jest.fn(), - } as typeof Animated), + }) as typeof Animated, ); jest.mock('@react-navigation/native', () => { diff --git a/tests/unit/DateUtilsTest.ts b/tests/unit/DateUtilsTest.ts index f3abed2e3372..d4ed8650eedc 100644 --- a/tests/unit/DateUtilsTest.ts +++ b/tests/unit/DateUtilsTest.ts @@ -94,7 +94,7 @@ describe('DateUtils', () => { () => ({ resolvedOptions: () => ({timeZone: 'America/Chicago'}), - } as Intl.DateTimeFormat), + }) as Intl.DateTimeFormat, ); Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => { const result = DateUtils.getCurrentTimezone(); @@ -110,7 +110,7 @@ describe('DateUtils', () => { () => ({ resolvedOptions: () => ({timeZone: UTC}), - } as Intl.DateTimeFormat), + }) as Intl.DateTimeFormat, ); Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => { const result = DateUtils.getCurrentTimezone(); diff --git a/tests/utils/ReportTestUtils.ts b/tests/utils/ReportTestUtils.ts index 61c778ab5576..d9262cea249f 100644 --- a/tests/utils/ReportTestUtils.ts +++ b/tests/utils/ReportTestUtils.ts @@ -45,7 +45,7 @@ const getFakeReportAction = (index: number, actionName?: ReportActionName): Repo previousReportActionID: (index === 0 ? 0 : index - 1).toString(), sequenceNumber: 0, shouldShow: true, - } as ReportAction); + }) as ReportAction; const getMockedSortedReportActions = (length = 100): ReportAction[] => Array.from({length}, (element, index): ReportAction => { diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index 9ca0969abc6a..8d71a88157ee 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -215,10 +215,13 @@ function buildTestReportComment(created: string, actorAccountID: number, actionI function assertFormDataMatchesObject(formData: FormData, obj: Report) { expect( - Array.from(formData.entries()).reduce((acc, [key, val]) => { - acc[key] = val; - return acc; - }, {} as Record), + Array.from(formData.entries()).reduce( + (acc, [key, val]) => { + acc[key] = val; + return acc; + }, + {} as Record, + ), ).toEqual(expect.objectContaining(obj)); } From 4925d1d0ff7a2bc4385ea571fd1380512d3477d1 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Wed, 17 Jul 2024 12:19:13 -0500 Subject: [PATCH 40/48] removing should should option --- src/components/MoneyRequestConfirmationList.tsx | 1 - src/components/SettlementButton.tsx | 1 - src/pages/iou/MoneyRequestAmountForm.tsx | 1 - 3 files changed, 3 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 7e6682492eb2..caca720cc097 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -729,7 +729,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 cfb8cc049e29..9d4e3a0e7c31 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -132,7 +132,6 @@ function SettlementButton({ shouldShowApproveButton = false, shouldDisableApproveButton = false, style, - shouldShowPersonalBankAccountOption = false, enterKeyEventListenerPriority = 0, confirmApproval, policy, diff --git a/src/pages/iou/MoneyRequestAmountForm.tsx b/src/pages/iou/MoneyRequestAmountForm.tsx index ff061e7382c6..18f5dfcf784e 100644 --- a/src/pages/iou/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/MoneyRequestAmountForm.tsx @@ -320,7 +320,6 @@ function MoneyRequestAmountForm( horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, }} - shouldShowPersonalBankAccountOption enterKeyEventListenerPriority={1} /> ) : ( From 68caa235e8737704a74955ef4cb9618ee48e58b0 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 18 Jul 2024 00:18:05 -0500 Subject: [PATCH 41/48] Update sanitizeStringForJSONParse.ts --- .github/libs/sanitizeStringForJSONParse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/libs/sanitizeStringForJSONParse.ts b/.github/libs/sanitizeStringForJSONParse.ts index d646a566c517..ddb7549b0186 100644 --- a/.github/libs/sanitizeStringForJSONParse.ts +++ b/.github/libs/sanitizeStringForJSONParse.ts @@ -8,7 +8,7 @@ const replacer = (str: string): string => '\r': '\\r', '\f': '\\f', '"': '\\"', - })[str] ?? ''; + }[str] ?? ''); /** * Replace any characters in the string that will break JSON.parse for our Git Log output From 3b374ad7c387ade878ea9ba69acb00a46cd7eaca Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 18 Jul 2024 00:19:36 -0500 Subject: [PATCH 42/48] Update DateUtilsTest.ts --- tests/unit/DateUtilsTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/DateUtilsTest.ts b/tests/unit/DateUtilsTest.ts index d4ed8650eedc..f3abed2e3372 100644 --- a/tests/unit/DateUtilsTest.ts +++ b/tests/unit/DateUtilsTest.ts @@ -94,7 +94,7 @@ describe('DateUtils', () => { () => ({ resolvedOptions: () => ({timeZone: 'America/Chicago'}), - }) as Intl.DateTimeFormat, + } as Intl.DateTimeFormat), ); Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => { const result = DateUtils.getCurrentTimezone(); @@ -110,7 +110,7 @@ describe('DateUtils', () => { () => ({ resolvedOptions: () => ({timeZone: UTC}), - }) as Intl.DateTimeFormat, + } as Intl.DateTimeFormat), ); Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => { const result = DateUtils.getCurrentTimezone(); From 8b4aa91fed907a7ae13a10febec96d2028fe3f93 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 18 Jul 2024 00:25:05 -0500 Subject: [PATCH 43/48] prettier --- src/hooks/useStepFormSubmit.ts | 11 +-- src/languages/types.ts | 20 ++--- src/libs/Localize/index.ts | 11 +-- src/libs/actions/Policy/Policy.ts | 28 +++---- src/libs/migrations/RenameCardIsVirtual.ts | 27 +++---- src/libs/migrations/RenameReceiptFilename.ts | 23 +++--- .../EnablePayments/utils/getSubstepValues.ts | 11 +-- .../BeneficialOwnersStep.tsx | 11 +-- .../report/ReportActionsListItemRenderer.tsx | 2 +- src/styles/index.ts | 76 +++++++++---------- src/types/onyx/SearchResults.ts | 8 +- tests/utils/ReportTestUtils.ts | 2 +- tests/utils/TestHelper.ts | 11 +-- 13 files changed, 107 insertions(+), 134 deletions(-) diff --git a/src/hooks/useStepFormSubmit.ts b/src/hooks/useStepFormSubmit.ts index cd422071c725..883fe980a338 100644 --- a/src/hooks/useStepFormSubmit.ts +++ b/src/hooks/useStepFormSubmit.ts @@ -24,13 +24,10 @@ export default function useStepFormSubmit return useCallback( (values: FormOnyxValues) => { if (shouldSaveDraft) { - const stepValues = fieldIds.reduce( - (acc, key) => { - acc[key] = values[key]; - return acc; - }, - {} as Record, OnyxValues[T][Exclude]>, - ); + const stepValues = fieldIds.reduce((acc, key) => { + acc[key] = values[key]; + return acc; + }, {} as Record, OnyxValues[T][Exclude]>); FormActions.setDraftValues(formId, stepValues); } diff --git a/src/languages/types.ts b/src/languages/types.ts index 649ec519a1f1..a50dccbfc63e 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -265,22 +265,22 @@ type FlattenObject = { [TKey in keyof TObject]: TObject[TKey] extends (...args: any[]) => any ? `${TPrefix}${TKey & string}` : // eslint-disable-next-line @typescript-eslint/no-explicit-any - TObject[TKey] extends any[] - ? `${TPrefix}${TKey & string}` - : // eslint-disable-next-line @typescript-eslint/ban-types - TObject[TKey] extends object - ? FlattenObject - : `${TPrefix}${TKey & string}`; + TObject[TKey] extends any[] + ? `${TPrefix}${TKey & string}` + : // eslint-disable-next-line @typescript-eslint/ban-types + TObject[TKey] extends object + ? FlattenObject + : `${TPrefix}${TKey & string}`; }[keyof TObject]; // Retrieves a type for a given key path (calculated from the type above) type TranslateType = TPath extends keyof TObject ? TObject[TPath] : TPath extends `${infer TKey}.${infer TRest}` - ? TKey extends keyof TObject - ? TranslateType - : never - : never; + ? TKey extends keyof TObject + ? TranslateType + : never + : never; type EnglishTranslation = typeof en; diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index dd34175e6ad1..c9eef3170245 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -64,13 +64,10 @@ type Phrase = TranslationFlatObject[TKey] extends * in our cache. */ const translationCache = new Map, Map>( - Object.values(CONST.LOCALES).reduce( - (cache, locale) => { - cache.push([locale, new Map()]); - return cache; - }, - [] as Array<[ValueOf, Map]>, - ), + Object.values(CONST.LOCALES).reduce((cache, locale) => { + cache.push([locale, new Map()]); + return cache; + }, [] as Array<[ValueOf, Map]>), ); /** diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 20407860d73a..e6d2e35dd8c1 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -2647,16 +2647,13 @@ function enablePolicyTaxes(policyID: string, enabled: boolean) { taxRates: { ...defaultTaxRates, taxes: { - ...Object.keys(defaultTaxRates.taxes).reduce( - (acc, taxKey) => { - acc[taxKey] = { - ...defaultTaxRates.taxes[taxKey], - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }; - return acc; - }, - {} as Record, - ), + ...Object.keys(defaultTaxRates.taxes).reduce((acc, taxKey) => { + acc[taxKey] = { + ...defaultTaxRates.taxes[taxKey], + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; + return acc; + }, {} as Record), }, }, }, @@ -2669,13 +2666,10 @@ function enablePolicyTaxes(policyID: string, enabled: boolean) { value: { taxRates: { taxes: { - ...Object.keys(defaultTaxRates.taxes).reduce( - (acc, taxKey) => { - acc[taxKey] = {pendingAction: null}; - return acc; - }, - {} as Record, - ), + ...Object.keys(defaultTaxRates.taxes).reduce((acc, taxKey) => { + acc[taxKey] = {pendingAction: null}; + return acc; + }, {} as Record), }, }, }, diff --git a/src/libs/migrations/RenameCardIsVirtual.ts b/src/libs/migrations/RenameCardIsVirtual.ts index acd99e5bdf1c..751c11d70eac 100644 --- a/src/libs/migrations/RenameCardIsVirtual.ts +++ b/src/libs/migrations/RenameCardIsVirtual.ts @@ -26,23 +26,20 @@ export default function () { } Log.info('[Migrate Onyx] Running RenameCardIsVirtual migration'); - const dataToSave = cardsWithIsVirtualProp.reduce( - (acc, card) => { - if (!card) { - return acc; - } + const dataToSave = cardsWithIsVirtualProp.reduce((acc, card) => { + if (!card) { + return acc; + } - acc[card.cardID] = { - nameValuePairs: { - isVirtual: card?.nameValuePairs?.isVirtual, - }, - isVirtual: undefined, - }; + acc[card.cardID] = { + nameValuePairs: { + isVirtual: card?.nameValuePairs?.isVirtual, + }, + isVirtual: undefined, + }; - return acc; - }, - {} as Record>, - ); + return acc; + }, {} as Record>); // eslint-disable-next-line rulesdir/prefer-actions-set-data Onyx.merge(ONYXKEYS.CARD_LIST, dataToSave).then(() => { diff --git a/src/libs/migrations/RenameReceiptFilename.ts b/src/libs/migrations/RenameReceiptFilename.ts index 2e27802e72d4..f01676595dd7 100644 --- a/src/libs/migrations/RenameReceiptFilename.ts +++ b/src/libs/migrations/RenameReceiptFilename.ts @@ -30,20 +30,17 @@ export default function () { return resolve(); } Log.info('[Migrate Onyx] Running RenameReceiptFilename migration'); - const dataToSave = transactionsWithReceipt?.reduce( - (acc, transaction) => { - if (!transaction) { - return acc; - } - Log.info(`[Migrate Onyx] Renaming receiptFilename ${transaction.receiptFilename} to filename`); - acc[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = { - filename: transaction.receiptFilename, - receiptFilename: null, - }; + const dataToSave = transactionsWithReceipt?.reduce((acc, transaction) => { + if (!transaction) { return acc; - }, - {} as Record>, - ); + } + Log.info(`[Migrate Onyx] Renaming receiptFilename ${transaction.receiptFilename} to filename`); + acc[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = { + filename: transaction.receiptFilename, + receiptFilename: null, + }; + return acc; + }, {} as Record>); // eslint-disable-next-line rulesdir/prefer-actions-set-data Onyx.mergeCollection(ONYXKEYS.COLLECTION.TRANSACTION, dataToSave).then(() => { diff --git a/src/pages/EnablePayments/utils/getSubstepValues.ts b/src/pages/EnablePayments/utils/getSubstepValues.ts index 4e444b1b53b1..2eb80ed1b2ee 100644 --- a/src/pages/EnablePayments/utils/getSubstepValues.ts +++ b/src/pages/EnablePayments/utils/getSubstepValues.ts @@ -8,13 +8,10 @@ function getSubstepValues( walletAdditionalDetailsDraft: OnyxEntry, walletAdditionalDetails: OnyxEntry, ): {[K in T]: WalletAdditionalDetailsForm[K] | string} { - return Object.entries(inputKeys).reduce( - (acc, [, value]) => { - acc[value] = walletAdditionalDetailsDraft?.[value] ?? walletAdditionalDetails?.[value as keyof PersonalInfoStepProps] ?? ''; - return acc; - }, - {} as {[K in T]: WalletAdditionalDetailsForm[K] | string}, - ); + return Object.entries(inputKeys).reduce((acc, [, value]) => { + acc[value] = walletAdditionalDetailsDraft?.[value] ?? walletAdditionalDetails?.[value as keyof PersonalInfoStepProps] ?? ''; + return acc; + }, {} as {[K in T]: WalletAdditionalDetailsForm[K] | string}); } export default getSubstepValues; diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx index c745431290fb..ae0fded74347 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx @@ -68,13 +68,10 @@ function BeneficialOwnersStep({reimbursementAccount, reimbursementAccountDraft, const submit = () => { const beneficialOwnerFields = ['firstName', 'lastName', 'dob', 'ssnLast4', 'street', 'city', 'state', 'zipCode']; const beneficialOwners = beneficialOwnerKeys.map((ownerKey) => - beneficialOwnerFields.reduce( - (acc, fieldName) => { - acc[fieldName] = reimbursementAccountDraft ? reimbursementAccountDraft[`beneficialOwner_${ownerKey}_${fieldName}`] : undefined; - return acc; - }, - {} as Record, - ), + beneficialOwnerFields.reduce((acc, fieldName) => { + acc[fieldName] = reimbursementAccountDraft ? reimbursementAccountDraft[`beneficialOwner_${ownerKey}_${fieldName}`] : undefined; + return acc; + }, {} as Record), ); BankAccounts.updateBeneficialOwnersForBankAccount( diff --git a/src/pages/home/report/ReportActionsListItemRenderer.tsx b/src/pages/home/report/ReportActionsListItemRenderer.tsx index 912ad02a19aa..1ef689ab1da4 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.tsx +++ b/src/pages/home/report/ReportActionsListItemRenderer.tsx @@ -111,7 +111,7 @@ function ReportActionsListItemRenderer({ childManagerAccountID: reportAction.childManagerAccountID, childMoneyRequestCount: reportAction.childMoneyRequestCount, childOwnerAccountID: reportAction.childOwnerAccountID, - }) as ReportAction, + } as ReportAction), [ reportAction.reportActionID, reportAction.message, diff --git a/src/styles/index.ts b/src/styles/index.ts index 5e0bbe883753..697b5c0dba65 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -109,14 +109,14 @@ const picker = (theme: ThemeColors) => height: variables.inputHeight, borderWidth: 0, textAlign: 'left', - }) satisfies TextStyle; + } satisfies TextStyle); const link = (theme: ThemeColors) => ({ color: theme.link, textDecorationColor: theme.link, fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, - }) satisfies ViewStyle & MixedStyleDeclaration; + } satisfies ViewStyle & MixedStyleDeclaration); const baseCodeTagStyles = (theme: ThemeColors) => ({ @@ -124,7 +124,7 @@ const baseCodeTagStyles = (theme: ThemeColors) => borderRadius: 5, borderColor: theme.border, backgroundColor: theme.textBackground, - }) satisfies ViewStyle & MixedStyleDeclaration; + } satisfies ViewStyle & MixedStyleDeclaration); const headlineFont = { fontFamily: FontUtils.fontFamily.platform.EXP_NEW_KANSAS_MEDIUM, @@ -136,7 +136,7 @@ const modalNavigatorContainer = (isSmallScreenWidth: boolean) => position: 'absolute', width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, height: '100%', - }) satisfies ViewStyle; + } satisfies ViewStyle); const webViewStyles = (theme: ThemeColors) => ({ @@ -238,7 +238,7 @@ const webViewStyles = (theme: ThemeColors) => lineHeight: variables.fontSizeNormalHeight, ...writingDirection.ltr, }, - }) satisfies WebViewStyle; + } satisfies WebViewStyle); const styles = (theme: ThemeColors) => ({ @@ -867,7 +867,7 @@ const styles = (theme: ThemeColors) => pointerEvents: 'none', opacity: 0, }, - }) satisfies CustomPickerStyle, + } satisfies CustomPickerStyle), badge: { backgroundColor: theme.border, @@ -1018,7 +1018,7 @@ const styles = (theme: ThemeColors) => paddingVertical: 40, gap: 4, flex: 1, - }) satisfies ViewStyle, + } satisfies ViewStyle), receiptViewTextContainer: { paddingHorizontal: 40, @@ -1159,14 +1159,14 @@ const styles = (theme: ThemeColors) => ({ height: lodashClamp(textInputHeight, minHeight, maxHeight), minHeight, - }) satisfies ViewStyle, + } satisfies ViewStyle), autoGrowHeightHiddenInput: (maxWidth: number, maxHeight?: number) => ({ maxWidth, maxHeight: maxHeight && maxHeight + 1, overflow: 'hidden', - }) satisfies TextStyle, + } satisfies TextStyle), textInputContainer: { flex: 1, @@ -1208,7 +1208,7 @@ const styles = (theme: ThemeColors) => textInputLabelTransformation: (translateY: AnimatableNumericValue, translateX: AnimatableNumericValue, scale: AnimatableNumericValue) => ({ transform: [{translateY}, {translateX}, {scale}], - }) satisfies TextStyle, + } satisfies TextStyle), baseTextInput: { fontFamily: FontUtils.fontFamily.platform.EXP_NEUE, @@ -1347,7 +1347,7 @@ const styles = (theme: ThemeColors) => inputAndroid: { ...picker(theme), }, - }) satisfies CustomPickerStyle, + } satisfies CustomPickerStyle), disabledText: { color: theme.icon, @@ -1597,7 +1597,7 @@ const styles = (theme: ThemeColors) => height: 12, width: 12, zIndex: 10, - }) satisfies ViewStyle, + } satisfies ViewStyle), bottomTabStatusIndicator: (backgroundColor: string = theme.danger) => ({ borderColor: theme.sidebar, @@ -1677,13 +1677,13 @@ const styles = (theme: ThemeColors) => ({ ...modalNavigatorContainer(isSmallScreenWidth), left: 0, - }) satisfies ViewStyle, + } satisfies ViewStyle), RHPNavigatorContainer: (isSmallScreenWidth: boolean) => ({ ...modalNavigatorContainer(isSmallScreenWidth), right: 0, - }) satisfies ViewStyle, + } satisfies ViewStyle), onboardingNavigatorOuterView: { flex: 1, @@ -1698,7 +1698,7 @@ const styles = (theme: ThemeColors) => maxHeight: '100%', borderRadius: shouldUseNarrowLayout ? 16 : 0, overflow: 'hidden', - }) satisfies ViewStyle, + } satisfies ViewStyle), welcomeVideoNarrowLayout: { width: variables.onboardingModalWidth, @@ -1719,20 +1719,20 @@ const styles = (theme: ThemeColors) => // Menu should be displayed 12px above the floating action button. // To achieve that sidebar must be moved by: distance from the bottom of the sidebar to the fab (variables.fabBottom) + fab height (variables.componentSizeLarge) + distance above the fab (12px) vertical: windowHeight - (variables.fabBottom + variables.componentSizeLarge + 12), - }) satisfies AnchorPosition, + } satisfies AnchorPosition), createAccountMenuPositionProfile: () => ({ horizontal: 18, ...getPopOverVerticalOffset(202 + 40), - }) satisfies AnchorPosition, + } satisfies AnchorPosition), createMenuPositionReportActionCompose: (shouldUseNarrowLayout: boolean, windowHeight: number, windowWidth: number) => ({ // On a narrow layout the menu is displayed in ReportScreen in RHP, so it must be moved from the right side of the screen horizontal: (shouldUseNarrowLayout ? windowWidth - variables.sideBarWidth : variables.sideBarWidth) + 18, vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM, - }) satisfies AnchorPosition, + } satisfies AnchorPosition), createMenuPositionRightSidepane: { right: 18, @@ -1942,7 +1942,7 @@ const styles = (theme: ThemeColors) => outputRange: [0, variables.overlayOpacity], extrapolate: 'clamp', }), - }) satisfies ViewStyle, + } satisfies ViewStyle), nativeOverlayStyles: (current: OverlayStylesParams) => ({ @@ -1955,7 +1955,7 @@ const styles = (theme: ThemeColors) => outputRange: [0, variables.overlayOpacity], extrapolate: 'clamp', }), - }) satisfies ViewStyle, + } satisfies ViewStyle), appContent: { backgroundColor: theme.appBG, @@ -2542,13 +2542,13 @@ const styles = (theme: ThemeColors) => flexBasis: isSmallScreenWidth ? '100%' : 350, flexGrow: 0, alignSelf: 'flex-start', - }) satisfies ViewStyle, + } satisfies ViewStyle), centeredModalStyles: (isSmallScreenWidth: boolean, isFullScreenWhenSmall: boolean) => ({ borderWidth: isSmallScreenWidth && !isFullScreenWhenSmall ? 1 : 0, marginHorizontal: isSmallScreenWidth ? 0 : 20, - }) satisfies ViewStyle, + } satisfies ViewStyle), imageModalImageCenterContainer: { alignItems: 'center', @@ -2712,7 +2712,7 @@ const styles = (theme: ThemeColors) => backgroundColor: theme.cardBG, borderRadius: variables.componentBorderRadiusLarge, overflow: 'hidden', - }) satisfies ViewStyle & TextStyle, + } satisfies ViewStyle & TextStyle), anonymousRoomFooterWordmarkAndLogoContainer: (isSmallSizeLayout: boolean) => ({ flexDirection: 'row', @@ -2721,7 +2721,7 @@ const styles = (theme: ThemeColors) => justifyContent: 'space-between', marginTop: 16, }), - }) satisfies ViewStyle, + } satisfies ViewStyle), anonymousRoomFooterLogo: { width: 88, marginLeft: 0, @@ -2785,8 +2785,8 @@ const styles = (theme: ThemeColors) => borderRadius: 88, }, - rootNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}) satisfies ViewStyle, - RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1}) satisfies ViewStyle, + rootNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle), + RHPNavigatorContainerNavigatorContainerStyles: (isSmallScreenWidth: boolean) => ({marginLeft: isSmallScreenWidth ? 0 : variables.sideBarWidth, flex: 1} satisfies ViewStyle), avatarInnerTextChat: { color: theme.text, @@ -3076,7 +3076,7 @@ const styles = (theme: ThemeColors) => switchThumbTransformation: (translateX: AnimatableNumericValue) => ({ transform: [{translateX}], - }) satisfies ViewStyle, + } satisfies ViewStyle), radioButtonContainer: { backgroundColor: theme.componentBG, @@ -3303,7 +3303,7 @@ const styles = (theme: ThemeColors) => growlNotificationTranslateY: (translateY: AnimatableNumericValue) => ({ transform: [{translateY}], - }) satisfies ViewStyle, + } satisfies ViewStyle), makeSlideInTranslation: (translationType: Translation, fromValue: number) => ({ @@ -3313,7 +3313,7 @@ const styles = (theme: ThemeColors) => to: { [translationType]: 0, }, - }) satisfies CustomAnimation, + } satisfies CustomAnimation), growlNotificationBox: { backgroundColor: theme.inverse, @@ -3617,25 +3617,25 @@ const styles = (theme: ThemeColors) => ({ ...getPopOverVerticalOffset(60), horizontal: windowWidth - 60, - }) satisfies AnchorPosition, + } satisfies AnchorPosition), threeDotsPopoverOffsetNoCloseButton: (windowWidth: number) => ({ ...getPopOverVerticalOffset(60), horizontal: windowWidth - 10, - }) satisfies AnchorPosition, + } satisfies AnchorPosition), threeDotsPopoverOffsetAttachmentModal: (windowWidth: number) => ({ ...getPopOverVerticalOffset(80), horizontal: windowWidth - 140, - }) satisfies AnchorPosition, + } satisfies AnchorPosition), popoverMenuOffset: (windowWidth: number) => ({ ...getPopOverVerticalOffset(180), horizontal: windowWidth - 355, - }) satisfies AnchorPosition, + } satisfies AnchorPosition), iPhoneXSafeArea: { backgroundColor: theme.inverse, @@ -3739,7 +3739,7 @@ const styles = (theme: ThemeColors) => ({ position: 'absolute', top: receiptImageTopPosition, - }) satisfies ViewStyle, + } satisfies ViewStyle), cardSectionContainer: { backgroundColor: theme.cardBG, @@ -3866,7 +3866,7 @@ const styles = (theme: ThemeColors) => position: 'absolute', width: isSmallScreenWidth ? windowWidth - 32 : CONST.EMOJI_PICKER_SIZE.WIDTH - 32, ...spacing.mh4, - }) satisfies ViewStyle, + } satisfies ViewStyle), reactionCounterText: { fontSize: 13, @@ -4269,7 +4269,7 @@ const styles = (theme: ThemeColors) => color: isSelected ? theme.text : theme.textSupporting, lineHeight: variables.lineHeightNormal, fontSize: variables.fontSizeNormal, - }) satisfies TextStyle, + } satisfies TextStyle), tabBackground: (hovered: boolean, isFocused: boolean, background: string | Animated.AnimatedInterpolation) => ({ backgroundColor: hovered && !isFocused ? theme.highlightBG : background, @@ -4293,7 +4293,7 @@ const styles = (theme: ThemeColors) => top: -height, left: 0, right: 0, - }) satisfies ViewStyle, + } satisfies ViewStyle), dualColorOverscrollSpacer: { position: 'absolute', @@ -5158,7 +5158,7 @@ const styles = (theme: ThemeColors) => width: 184, height: 112, }, - }) satisfies Styles; + } satisfies Styles); type ThemeStyles = ReturnType; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 695a78285495..97a8b459ff0f 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -12,15 +12,15 @@ type SearchDataTypes = ValueOf; type ListItemType = T extends typeof CONST.SEARCH.DATA_TYPES.TRANSACTION ? typeof TransactionListItem : T extends typeof CONST.SEARCH.DATA_TYPES.REPORT - ? typeof ReportListItem - : never; + ? typeof ReportListItem + : never; /** Model of search result section */ type SectionsType = T extends typeof CONST.SEARCH.DATA_TYPES.TRANSACTION ? TransactionListItemType[] : T extends typeof CONST.SEARCH.DATA_TYPES.REPORT - ? ReportListItemType[] - : never; + ? ReportListItemType[] + : never; /** Mapping of search results to list item */ type SearchTypeToItemMap = { diff --git a/tests/utils/ReportTestUtils.ts b/tests/utils/ReportTestUtils.ts index d5fb8ba01f92..bd62aca882b2 100644 --- a/tests/utils/ReportTestUtils.ts +++ b/tests/utils/ReportTestUtils.ts @@ -44,7 +44,7 @@ const getFakeReportAction = (index: number, actionName?: ReportActionName): Repo reportActionID: index.toString(), sequenceNumber: 0, shouldShow: true, - }) as ReportAction; + } as ReportAction); const getMockedSortedReportActions = (length = 100): ReportAction[] => Array.from({length}, (element, index): ReportAction => { diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index 1fcbff36b8ba..84ea2b2aafbe 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -298,13 +298,10 @@ function buildTestReportComment(created: string, actorAccountID: number, actionI function assertFormDataMatchesObject(formData: FormData, obj: Report) { expect( - Array.from(formData.entries()).reduce( - (acc, [key, val]) => { - acc[key] = val; - return acc; - }, - {} as Record, - ), + Array.from(formData.entries()).reduce((acc, [key, val]) => { + acc[key] = val; + return acc; + }, {} as Record), ).toEqual(expect.objectContaining(obj)); } From 9bc4ae1743c153174196f9c06d773e4b7c26f4b7 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Sun, 28 Jul 2024 20:44:51 -0500 Subject: [PATCH 44/48] updated settlement button --- src/components/ButtonWithDropdownMenu/index.tsx | 2 +- src/components/SettlementButton.tsx | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu/index.tsx b/src/components/ButtonWithDropdownMenu/index.tsx index 094c26a2b387..a9739e87335e 100644 --- a/src/components/ButtonWithDropdownMenu/index.tsx +++ b/src/components/ButtonWithDropdownMenu/index.tsx @@ -56,7 +56,7 @@ function ButtonWithDropdownMenu({ if ('measureInWindow' in caretButton.current) { caretButton.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/SettlementButton.tsx b/src/components/SettlementButton.tsx index e44b94bc8b76..8eecef9048d8 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -285,10 +285,7 @@ function SettlementButton({ success 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)} From 4a4519bbf16351dc32aff833e0a1ce3b137bd51d Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 20 Aug 2024 20:47:07 -0500 Subject: [PATCH 45/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 35c7f667c085..71539cef7b21 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -199,7 +199,7 @@ function SettlementButton({ value: CONST.IOU.REPORT_ACTION_TYPE.APPROVE, disabled: !!shouldDisableApproveButton, }; - const canUseWallet = !isExpenseReport && currency === CONST.CURRENCY.USD; + const canUseWallet = !isExpenseReport && !isInvoiceReport && currency === CONST.CURRENCY.USD; // Only show the Approve button if the user cannot pay the expense if (shouldHidePaymentOptions && shouldShowApproveButton) { From 77a6688d2db74f25433a0e4a2418b5afd2da966c Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Tue, 20 Aug 2024 21:02:31 -0500 Subject: [PATCH 46/48] Update SettlementButton.tsx --- src/components/SettlementButton.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 71539cef7b21..2e29d36a8fd3 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -210,15 +210,11 @@ 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) { + if (canUseWallet || (isExpenseReport && shouldShowPaywithExpensifyOption)) { buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); } - if (isExpenseReport && shouldShowPaywithExpensifyOption) { - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT]); - } if (shouldShowPayElsewhereOption) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); } From d3cf95e583687dd0546074b30d2ab0cdb4ed8713 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Thu, 22 Aug 2024 22:20:11 -0500 Subject: [PATCH 47/48] final fix --- src/components/SettlementButton.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 2e29d36a8fd3..b6730070a22b 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -212,7 +212,6 @@ function SettlementButton({ const paymentMethod = nvpLastPaymentMethod?.[policyID] ?? '-1'; if (canUseWallet || (isExpenseReport && shouldShowPaywithExpensifyOption)) { buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); - buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.DEBIT_CARD]); } if (shouldShowPayElsewhereOption) { From 2f9c1d600a652316c9fdc8106b92886e40446bf6 Mon Sep 17 00:00:00 2001 From: Brandon Henry Date: Mon, 26 Aug 2024 00:27:03 -0500 Subject: [PATCH 48/48] Added back in personalbankaccount set --- src/components/SettlementButton.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index b6730070a22b..bd2d7ad76b67 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -9,6 +9,7 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as SubscriptionUtils from '@libs/SubscriptionUtils'; +import * as BankAccounts from '@userActions/BankAccounts'; import * as IOU from '@userActions/IOU'; import * as PolicyActions from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; @@ -280,6 +281,7 @@ function SettlementButton({ iouPaymentType === CONST.PAYMENT_METHODS.DEBIT_CARD ) { triggerKYCFlow(event, iouPaymentType); + BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(ROUTES.ENABLE_PAYMENTS); return; }