diff --git a/src/languages/en.js b/src/languages/en.js index 1520446a1498..b35ecd89c328 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -381,8 +381,8 @@ export default { }, paymentMethodList: { addPaymentMethod: 'Add payment method', - addDebitCard: 'Add debit card', - addBankAccount: 'Add bank account', + addNewDebitCard: 'Add new debit card', + addNewBankAccount: 'Add new bank account', accountLastFour: 'Account ending in', cardLastFour: 'Card ending in', addFirstPaymentMethod: 'Add a payment method to send and receive payments directly in the app.', diff --git a/src/languages/es.js b/src/languages/es.js index 627dd67ccda3..a9be390740ed 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -381,8 +381,8 @@ export default { }, paymentMethodList: { addPaymentMethod: 'Agrega método de pago', - addDebitCard: 'Agregar tarjeta de débito', - addBankAccount: 'Agregar cuenta de banco', + addNewDebitCard: 'Agregar nueva tarjeta de débito', + addNewBankAccount: 'Agregar nueva cuenta de banco', accountLastFour: 'Cuenta con terminación', cardLastFour: 'Tarjeta con terminacíon', addFirstPaymentMethod: 'Añade un método de pago para enviar y recibir pagos directamente desde la aplicación.', diff --git a/src/libs/PaymentUtils.js b/src/libs/PaymentUtils.js index eb55234ece6f..674bffc9b8c5 100644 --- a/src/libs/PaymentUtils.js +++ b/src/libs/PaymentUtils.js @@ -65,7 +65,7 @@ function formatPaymentMethods(bankAccountList, cardList, payPalMeUsername = '', combinedPaymentMethods.push({ title: card.addressName, description: formattedCardNumber, - methodID: card.cardNumber, + methodID: card.fundID, icon, iconSize, key: `card-${card.cardNumber}`, diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 4cfcc941ee8a..94a1b6cedb6f 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -184,10 +184,10 @@ function clearDebitCardFormErrorAndSubmit() { * Call the API to transfer wallet balance. * @param {Object} paymentMethod * @param {*} paymentMethod.methodID - * @param {String} paymentMethod.type + * @param {String} paymentMethod.accountType */ function transferWalletBalance(paymentMethod) { - const paymentMethodIDKey = paymentMethod.type === CONST.PAYMENT_METHODS.BANK_ACCOUNT + const paymentMethodIDKey = paymentMethod.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? CONST.PAYMENT_METHOD_ID_KEYS.BANK_ACCOUNT : CONST.PAYMENT_METHOD_ID_KEYS.DEBIT_CARD; const parameters = { @@ -209,13 +209,10 @@ function transferWalletBalance(paymentMethod) { }); } -/** - * Set the transfer account and reset the transfer data for Wallet balance transfer - * @param {String} selectedAccountID - */ -function saveWalletTransferAccountAndResetData(selectedAccountID) { +function resetWalletTransferData() { Onyx.merge(ONYXKEYS.WALLET_TRANSFER, { - selectedAccountID, + selectedAccountType: '', + selectedAccountID: null, filterPaymentMethodType: null, loading: false, shouldShowConfirmModal: false, @@ -229,6 +226,22 @@ function saveWalletTransferAmount(transferAmount) { Onyx.merge(ONYXKEYS.WALLET_TRANSFER, {transferAmount}); } +/** + * @param {String} selectedAccountType + * @param {String} selectedAccountID + */ +function saveWalletTransferAccountTypeAndID(selectedAccountType, selectedAccountID) { + Onyx.merge(ONYXKEYS.WALLET_TRANSFER, {selectedAccountType, selectedAccountID}); +} + +/** + * Toggles the user's selected type of payment method (bank account or debit card) on the wallet transfer balance screen. + * @param {String} filterPaymentMethodType + */ +function saveWalletTransferMethodType(filterPaymentMethodType) { + Onyx.merge(ONYXKEYS.WALLET_TRANSFER, {filterPaymentMethodType}); +} + function dismissWalletConfirmModal() { Onyx.merge(ONYXKEYS.WALLET_TRANSFER, {shouldShowConfirmModal: false}); } @@ -243,7 +256,9 @@ export { continueSetup, clearDebitCardFormErrorAndSubmit, transferWalletBalance, - saveWalletTransferAccountAndResetData, + resetWalletTransferData, saveWalletTransferAmount, + saveWalletTransferAccountTypeAndID, + saveWalletTransferMethodType, dismissWalletConfirmModal, }; diff --git a/src/pages/settings/Payments/ChooseTransferAccountPage.js b/src/pages/settings/Payments/ChooseTransferAccountPage.js index eb3fec894eca..b1d878340048 100644 --- a/src/pages/settings/Payments/ChooseTransferAccountPage.js +++ b/src/pages/settings/Payments/ChooseTransferAccountPage.js @@ -1,27 +1,100 @@ import React from 'react'; +import {withOnyx} from 'react-native-onyx'; +import {View} from 'react-native'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; import ScreenWrapper from '../../../components/ScreenWrapper'; import Navigation from '../../../libs/Navigation/Navigation'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView'; +import CONST from '../../../CONST'; +import PaymentMethodList from './PaymentMethodList'; +import * as PaymentMethods from '../../../libs/actions/PaymentMethods'; +import ROUTES from '../../../ROUTES'; +import MenuItem from '../../../components/MenuItem'; +import * as Expensicons from '../../../components/Icon/Expensicons'; +import compose from '../../../libs/compose'; +import ONYXKEYS from '../../../ONYXKEYS'; +import walletTransferPropTypes from './walletTransferPropTypes'; +import styles from '../../../styles/styles'; const propTypes = { + /** Wallet transfer propTypes */ + walletTransfer: walletTransferPropTypes, + ...withLocalizePropTypes, }; -const ChooseTransferAccountPage = props => ( - - - Navigation.goBack()} - onCloseButtonPress={() => Navigation.dismissModal()} - /> - - -); +const defaultProps = { + walletTransfer: {}, +}; + +const ChooseTransferAccountPage = (props) => { + /** + * Go back to transfer balance screen with the selected bank account set + * @param {Object} event Click event object + * @param {String} accountType of the selected account type + * @param {Object} account of the selected account data + */ + const selectAccountAndNavigateBack = (event, accountType, account) => { + PaymentMethods.saveWalletTransferAccountTypeAndID( + accountType, + accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT + ? account.bankAccountID + : account.fundID, + ); + Navigation.navigate(ROUTES.SETTINGS_PAYMENTS_TRANSFER_BALANCE); + }; + + /** + * @param {String} paymentType + */ + const navigateToAddPaymentMethodPage = () => { + if (props.walletTransfer.filterPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { + Navigation.navigate(ROUTES.SETTINGS_ADD_DEBIT_CARD); + return; + } + Navigation.navigate(ROUTES.SETTINGS_ADD_BANK_ACCOUNT); + }; + + return ( + + + Navigation.goBack()} + onCloseButtonPress={() => Navigation.dismissModal()} + /> + + + + + + + ); +}; ChooseTransferAccountPage.propTypes = propTypes; +ChooseTransferAccountPage.defaultProps = defaultProps; +ChooseTransferAccountPage.displayName = 'ChooseTransferAccountPage'; -export default withLocalize(ChooseTransferAccountPage); +export default compose( + withLocalize, + withOnyx({ + walletTransfer: { + key: ONYXKEYS.WALLET_TRANSFER, + }, + }), +)(ChooseTransferAccountPage); diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index fac11964eab7..4d08e0d177c8 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -45,6 +45,13 @@ const propTypes = { cardID: PropTypes.number, })), + /** Whether the add Payment button be shown on the list */ + shouldShowAddPaymentMethodButton: PropTypes.bool, + + /** Type to filter the payment Method list */ + filterType: PropTypes.oneOf([CONST.PAYMENT_METHODS.DEBIT_CARD, CONST.PAYMENT_METHODS.BANK_ACCOUNT, '']), + + /** User wallet props */ userWallet: PropTypes.shape({ /** The ID of the linked account */ walletLinkedAccountID: PropTypes.number, @@ -66,6 +73,8 @@ const defaultProps = { }, isLoadingPayments: false, isAddPaymentMenuActive: false, + shouldShowAddPaymentMethodButton: true, + filterType: '', }; class PaymentMethodList extends Component { @@ -82,6 +91,11 @@ class PaymentMethodList extends Component { */ createPaymentMethodList() { let combinedPaymentMethods = PaymentUtils.formatPaymentMethods(this.props.bankAccountList, this.props.cardList, this.props.payPalMeUsername, this.props.userWallet); + + if (!_.isEmpty(this.props.filterType)) { + combinedPaymentMethods = _.filter(combinedPaymentMethods, paymentMethod => paymentMethod.accountType === this.props.filterType); + } + combinedPaymentMethods = _.map(combinedPaymentMethods, paymentMethod => ({ ...paymentMethod, type: MENU_ITEM, @@ -96,6 +110,10 @@ class PaymentMethodList extends Component { }); } + if (!this.props.shouldShowAddPaymentMethodButton) { + return combinedPaymentMethods; + } + combinedPaymentMethods.push({ type: MENU_ITEM, title: this.props.translate('paymentMethodList.addPaymentMethod'), @@ -132,6 +150,8 @@ class PaymentMethodList extends Component { iconWidth={item.iconSize} badgeText={item.isDefault ? this.props.translate('paymentMethodList.defaultPaymentMethod') : null} wrapperStyle={item.wrapperStyle} + shouldShowSelectedState={this.props.shouldShowSelectedState} + isSelected={this.props.selectedMethodID === item.methodID} /> ); } diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index eaddb559cdac..4956648a34ce 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -238,7 +238,7 @@ class PaymentsPage extends React.Component { )} {this.props.translate('paymentsPage.paymentMethodsTitle')} diff --git a/src/pages/settings/Payments/TransferBalancePage.js b/src/pages/settings/Payments/TransferBalancePage.js index c54e3cb9617b..52a2dfef84de 100644 --- a/src/pages/settings/Payments/TransferBalancePage.js +++ b/src/pages/settings/Payments/TransferBalancePage.js @@ -3,7 +3,6 @@ import React from 'react'; import {View, ScrollView} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import ONYXKEYS from '../../../ONYXKEYS'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; import ScreenWrapper from '../../../components/ScreenWrapper'; @@ -24,6 +23,7 @@ import walletTransferPropTypes from './walletTransferPropTypes'; import * as PaymentMethods from '../../../libs/actions/PaymentMethods'; import * as PaymentUtils from '../../../libs/PaymentUtils'; import userWalletPropTypes from '../../EnablePayments/userWalletPropTypes'; +import ROUTES from '../../../ROUTES'; const propTypes = { /** User's wallet information */ @@ -96,11 +96,19 @@ class TransferBalancePage extends React.Component { }, ]; - this.saveTransferAmountAndBalance = this.saveTransferAmountAndBalance.bind(this); - this.getSelectedPaymentMethodAccount = this.getSelectedPaymentMethodAccount.bind(this); - + PaymentMethods.resetWalletTransferData(); const selectedAccount = this.getSelectedPaymentMethodAccount(); - PaymentMethods.saveWalletTransferAccountAndResetData(selectedAccount ? selectedAccount.id : ''); + + // Select the default payment account when page is opened, + // so that user can see that preselected on choose transfer account page + if (!selectedAccount || !selectedAccount.isDefault) { + return; + } + + PaymentMethods.saveWalletTransferAccountTypeAndID( + selectedAccount.accountType, + selectedAccount.methodID, + ); } /** @@ -108,23 +116,42 @@ class TransferBalancePage extends React.Component { * @returns {Object|undefined} */ getSelectedPaymentMethodAccount() { - const paymentMethods = PaymentUtils.formatPaymentMethods(this.props.bankAccountList, this.props.cardList, '', this.props.userWallet); - const accountID = this.props.walletTransfer.selectedAccountID || lodashGet(this.props, 'userWallet.walletLinkedAccountID', ''); - return _.find(paymentMethods, method => method.methodID === accountID); + const paymentMethods = PaymentUtils.formatPaymentMethods( + this.props.bankAccountList, + this.props.cardList, + '', + this.props.userWallet, + ); + + const defaultAccount = _.find(paymentMethods, method => method.isDefault); + const selectedAccount = _.find( + paymentMethods, + method => method.accountType === this.props.walletTransfer.selectedAccountType + && method.methodID === this.props.walletTransfer.selectedAccountID, + ); + return selectedAccount || defaultAccount; } /** * @param {Number} transferAmount * @param {Object} selectedAccount */ - saveTransferAmountAndBalance(transferAmount, selectedAccount) { + saveTransferAmountAndStartTransfer(transferAmount, selectedAccount) { PaymentMethods.saveWalletTransferAmount(transferAmount); PaymentMethods.transferWalletBalance(selectedAccount); } + /** + * @param {String} filterPaymentMethodType + */ + navigateToChooseTransferAccount(filterPaymentMethodType) { + PaymentMethods.saveWalletTransferMethodType(filterPaymentMethodType); + Navigation.navigate(ROUTES.SETTINGS_PAYMENTS_CHOOSE_TRANSFER_ACCOUNT); + } + render() { const selectedAccount = this.getSelectedPaymentMethodAccount(); - const selectedPaymentType = selectedAccount && selectedAccount.type === CONST.PAYMENT_METHODS.BANK_ACCOUNT + const selectedPaymentType = selectedAccount && selectedAccount.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? CONST.WALLET.TRANSFER_METHOD_TYPE.ACH : CONST.WALLET.TRANSFER_METHOD_TYPE.INSTANT; @@ -162,6 +189,7 @@ class TransferBalancePage extends React.Component { ...(selectedPaymentType === paymentType.key && styles.transferBalanceSelectedPayment), }} + onPress={() => this.navigateToChooseTransferAccount(paymentType.type)} /> ))} this.navigateToChooseTransferAccount(selectedAccount.accountType)} /> )} this.saveTransferAmountAndBalance(transferAmount, selectedAccount)} + onPress={() => this.saveTransferAmountAndStartTransfer(transferAmount, selectedAccount)} text={this.props.translate( 'transferAmountPage.transfer', {