diff --git a/src/components/CurrentWalletBalance.js b/src/components/CurrentWalletBalance.js new file mode 100644 index 000000000000..b58fe6108dd1 --- /dev/null +++ b/src/components/CurrentWalletBalance.js @@ -0,0 +1,58 @@ +import React from 'react'; +import {ActivityIndicator, Text} from 'react-native'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {withOnyx} from 'react-native-onyx'; +import styles from '../styles/styles'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import compose from '../libs/compose'; +import themeColors from '../styles/themes/default'; +import ONYXKEYS from '../ONYXKEYS'; + +const propTypes = { + /** The user's wallet account */ + userWallet: PropTypes.shape({ + /** The user's current wallet balance */ + availableBalance: PropTypes.number, + }), + + ...withLocalizePropTypes, +}; + +const defaultProps = { + userWallet: {}, +}; + +const CurrentWalletBalance = (props) => { + if (_.isEmpty(props.userWallet)) { + return ( + + ); + } + + const formattedBalance = Number(props.userWallet.availableBalance).toFixed(2); + + return ( + + {`$${formattedBalance}`} + + ); +}; + +CurrentWalletBalance.propTypes = propTypes; +CurrentWalletBalance.defaultProps = defaultProps; +CurrentWalletBalance.displayName = 'CurrentWalletBalance'; +export default compose( + withLocalize, + withOnyx({ + userWallet: { + key: ONYXKEYS.USER_WALLET, + }, + }), +)(CurrentWalletBalance); diff --git a/src/languages/en.js b/src/languages/en.js index 2c13b708c404..702f67edff68 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -239,10 +239,14 @@ export default { addPayPalAccount: 'Add PayPal Account', growlMessageOnSave: 'Your PayPal username was successfully added', }, + paymentsPage: { + paymentMethodsTitle: 'Payment Methods', + }, paymentMethodList: { addPaymentMethod: 'Add Payment Method', accountLastFour: 'Account ending in', cardLastFour: 'Card ending in', + addFirstPaymentMethod: 'Add a payment method to send and receive payments directly in the app', }, preferencesPage: { mostRecent: 'Most Recent', diff --git a/src/languages/es.js b/src/languages/es.js index de5b415a1fdf..fc9a4b2f1ee5 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -231,10 +231,14 @@ export default { yourPayPalUsername: 'Tu usuario de PayPal', addPayPalAccount: 'Agregar Cuenta de Paypal', }, + paymentsPage: { + paymentMethodsTitle: 'Métodos de pago', + }, paymentMethodList: { addPaymentMethod: 'Agrega método de pago', 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', }, preferencesPage: { mostRecent: 'Más Recientes', diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index ab21cf9e42c7..f6474b581cd9 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -6,15 +6,17 @@ import CONST from '../../CONST'; /** * Calls the API to get the user's bankAccountList, cardList, wallet, and payPalMe + * + * @returns {Promise} */ function getPaymentMethods() { - API.Get({ + return API.Get({ returnValueList: 'bankAccountList, cardList, userWallet, nameValuePairs', name: 'paypalMeAddress', }) .then((response) => { Onyx.multiSet({ - [ONYXKEYS.USER_WALLET]: lodashGet(response, 'userWallet', null), + [ONYXKEYS.USER_WALLET]: lodashGet(response, 'userWallet', {}), [ONYXKEYS.BANK_ACCOUNT_LIST]: lodashGet(response, 'bankAccountList', []), [ONYXKEYS.CARD_LIST]: lodashGet(response, 'cardList', []), [ONYXKEYS.NVP_PAYPAL_ME_ADDRESS]: diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index 0994ca80a31e..c76ac9024f4e 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -1,8 +1,9 @@ import _ from 'underscore'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {FlatList} from 'react-native'; +import {FlatList, Text} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import styles from '../../../styles/styles'; import MenuItem from '../../../components/MenuItem'; import compose from '../../../libs/compose'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; @@ -13,13 +14,17 @@ import { CreditCard, PayPal, Plus, - Wallet, } from '../../../components/Icon/Expensicons'; +const MENU_ITEM = 'menuItem'; + const propTypes = { /** What to do when a menu item is pressed */ onPress: PropTypes.func.isRequired, + /** Are we loading payments from the server? */ + isLoadingPayments: PropTypes.bool, + /** User's paypal.me username if they have one */ payPalMeUsername: PropTypes.string, @@ -57,6 +62,7 @@ const defaultProps = { payPalMeUsername: '', bankAccountList: [], cardList: [], + isLoadingPayments: false, }; class PaymentMethodList extends Component { @@ -75,20 +81,26 @@ class PaymentMethodList extends Component { const combinedPaymentMethods = []; _.each(this.props.bankAccountList, (bankAccount) => { - combinedPaymentMethods.push({ - title: bankAccount.addressName, + // Add all bank accounts besides the wallet + if (bankAccount.type !== CONST.BANK_ACCOUNT_TYPES.WALLET) { + combinedPaymentMethods.push({ + type: MENU_ITEM, + title: bankAccount.addressName, - // eslint-disable-next-line - description: `${this.props.translate('paymentMethodList.accountLastFour')} ${bankAccount.accountNumber.slice(-4)}`, - icon: bankAccount.type === CONST.BANK_ACCOUNT_TYPES.WALLET ? Wallet : Bank, - onPress: e => this.props.onPress(e, bankAccount.bankAccountID), - key: `bankAccount-${bankAccount.bankAccountID}`, - }); + // eslint-disable-next-line + description: `${this.props.translate('paymentMethodList.accountLastFour')} ${bankAccount.accountNumber.slice(-4)}`, + icon: Bank, + onPress: e => this.props.onPress(e, bankAccount.bankAccountID), + key: `bankAccount-${bankAccount.bankAccountID}`, + }); + } }); _.each(this.props.cardList, (card) => { + // Add all cards besides the "cash" card if (card.cardName !== CONST.CARD_TYPES.DEFAULT_CASH) { combinedPaymentMethods.push({ + type: MENU_ITEM, title: card.cardName, // eslint-disable-next-line @@ -102,6 +114,7 @@ class PaymentMethodList extends Component { if (this.props.payPalMeUsername) { combinedPaymentMethods.push({ + type: MENU_ITEM, title: 'PayPal.me', description: this.props.payPalMeUsername, icon: PayPal, @@ -110,15 +123,24 @@ class PaymentMethodList extends Component { }); } + // If we have not added any payment methods, show a default empty state + if (_.isEmpty(combinedPaymentMethods)) { + combinedPaymentMethods.push({ + text: this.props.translate('paymentMethodList.addFirstPaymentMethod'), + }); + } + // Don't show Add Payment Method button if user provided details for all possible payment methods. // Right now only available method is Paypal.me // When there is a new payment method, it needs to be added to following if condition. if (!this.props.payPalMeUsername) { combinedPaymentMethods.push({ + type: MENU_ITEM, title: this.props.translate('paymentMethodList.addPaymentMethod'), icon: Plus, onPress: e => this.props.onPress(e), key: 'addPaymentMethodButton', + disabled: this.props.isLoadingPayments, }); } @@ -134,14 +156,25 @@ class PaymentMethodList extends Component { * @return {React.Component} */ renderItem({item}) { + if (item.type === MENU_ITEM) { + return ( + + ); + } + return ( - + + {item.text} + ); } @@ -168,9 +201,6 @@ export default compose( cardList: { key: ONYXKEYS.CARD_LIST, }, - userWallet: { - key: ONYXKEYS.USER_WALLET, - }, payPalMeUsername: { key: ONYXKEYS.NVP_PAYPAL_ME_ADDRESS, }, diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 7f2dc9deb8ad..3d266d1cfa48 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -12,11 +12,13 @@ import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; +import Text from '../../../components/Text'; import getPaymentMethods from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; import {PayPal} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; import getClickedElementLocation from '../../../libs/getClickedElementLocation'; +import CurrentWalletBalance from '../../../components/CurrentWalletBalance'; const PAYPAL = 'payPalMe'; @@ -39,6 +41,7 @@ class PaymentsPage extends React.Component { shouldShowAddPaymentMenu: false, anchorPositionTop: 0, anchorPositionLeft: 0, + isLoadingPaymentMethods: true, }; this.paymentMethodPressed = this.paymentMethodPressed.bind(this); @@ -47,7 +50,9 @@ class PaymentsPage extends React.Component { } componentDidMount() { - getPaymentMethods(); + getPaymentMethods().then(() => { + this.setState({isLoadingPaymentMethods: false}); + }); } /** @@ -103,9 +108,17 @@ class PaymentsPage extends React.Component { onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS)} onCloseButtonPress={() => Navigation.dismissModal(true)} /> - + + + + {this.props.translate('paymentsPage.paymentMethodsTitle')} +