Skip to content

Commit

Permalink
Merge pull request #3890 from Expensify/stites-finishPaymentsPage
Browse files Browse the repository at this point in the history
Update Payments Page to show wallet balance, empty state, and more!
  • Loading branch information
jasperhuangg authored Jul 21, 2021
2 parents 3ea4b27 + 5655dbc commit 683bcf4
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 24 deletions.
58 changes: 58 additions & 0 deletions src/components/CurrentWalletBalance.js
Original file line number Diff line number Diff line change
@@ -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 (
<ActivityIndicator
color={themeColors.text}
size="large"
style={styles.pv5}
/>
);
}

const formattedBalance = Number(props.userWallet.availableBalance).toFixed(2);

return (
<Text
style={[styles.textXXXLarge, styles.pv5, styles.alignSelfCenter]}
>
{`$${formattedBalance}`}
</Text>
);
};

CurrentWalletBalance.propTypes = propTypes;
CurrentWalletBalance.defaultProps = defaultProps;
CurrentWalletBalance.displayName = 'CurrentWalletBalance';
export default compose(
withLocalize,
withOnyx({
userWallet: {
key: ONYXKEYS.USER_WALLET,
},
}),
)(CurrentWalletBalance);
4 changes: 4 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
6 changes: 4 additions & 2 deletions src/libs/actions/PaymentMethods.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]:
Expand Down
70 changes: 50 additions & 20 deletions src/pages/settings/Payments/PaymentMethodList.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,

Expand Down Expand Up @@ -57,6 +62,7 @@ const defaultProps = {
payPalMeUsername: '',
bankAccountList: [],
cardList: [],
isLoadingPayments: false,
};

class PaymentMethodList extends Component {
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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,
});
}

Expand All @@ -134,14 +156,25 @@ class PaymentMethodList extends Component {
* @return {React.Component}
*/
renderItem({item}) {
if (item.type === MENU_ITEM) {
return (
<MenuItem
onPress={item.onPress}
title={item.title}
description={item.description}
icon={item.icon}
key={item.key}
disabled={item.disabled}
/>
);
}

return (
<MenuItem
onPress={item.onPress}
title={item.title}
description={item.description}
icon={item.icon}
key={item.key}
/>
<Text
style={[styles.popoverMenuItem]}
>
{item.text}
</Text>
);
}

Expand All @@ -168,9 +201,6 @@ export default compose(
cardList: {
key: ONYXKEYS.CARD_LIST,
},
userWallet: {
key: ONYXKEYS.USER_WALLET,
},
payPalMeUsername: {
key: ONYXKEYS.NVP_PAYPAL_ME_ADDRESS,
},
Expand Down
17 changes: 15 additions & 2 deletions src/pages/settings/Payments/PaymentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -39,6 +41,7 @@ class PaymentsPage extends React.Component {
shouldShowAddPaymentMenu: false,
anchorPositionTop: 0,
anchorPositionLeft: 0,
isLoadingPaymentMethods: true,
};

this.paymentMethodPressed = this.paymentMethodPressed.bind(this);
Expand All @@ -47,7 +50,9 @@ class PaymentsPage extends React.Component {
}

componentDidMount() {
getPaymentMethods();
getPaymentMethods().then(() => {
this.setState({isLoadingPaymentMethods: false});
});
}

/**
Expand Down Expand Up @@ -103,9 +108,17 @@ class PaymentsPage extends React.Component {
onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS)}
onCloseButtonPress={() => Navigation.dismissModal(true)}
/>
<View style={[styles.flex1]}>
<View>
<CurrentWalletBalance />
<Text
style={[styles.ph5, styles.textStrong]}
>
{this.props.translate('paymentsPage.paymentMethodsTitle')}
</Text>
<PaymentMethodList
onPress={this.paymentMethodPressed}
style={[styles.flex4]}
isLoadingPayments={this.state.isLoadingPaymentMethods}
/>
</View>
<Popover
Expand Down
7 changes: 7 additions & 0 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ const styles = {
fontSize: variables.fontSizeLarge,
},

textXXXLarge: {
color: themeColors.heading,
fontFamily: fontFamily.GTA_BOLD,
fontSize: variables.fontSizeXXXLarge,
fontWeight: fontWeightBold,
},

textStrong: {
fontFamily: fontFamily.GTA_BOLD,
fontWeight: fontWeightBold,
Expand Down
4 changes: 4 additions & 0 deletions src/styles/utilities/spacing.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ export default {
marginRight: 16,
},

mr5: {
marginRight: 20,
},

ml1: {
marginLeft: 4,
},
Expand Down

0 comments on commit 683bcf4

Please sign in to comment.