Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 62 additions & 90 deletions src/pages/settings/Payments/PaymentMethodList.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as PaymentMethods from '../../../libs/actions/PaymentMethods';
import Log from '../../../libs/Log';

const MENU_ITEM = 'menuItem';
const BUTTON = 'button';

const propTypes = {
/** What to do when a menu item is pressed */
onPress: PropTypes.func.isRequired,
Expand Down Expand Up @@ -123,7 +120,6 @@ class PaymentMethodList extends Component {

combinedPaymentMethods = _.map(combinedPaymentMethods, paymentMethod => ({
...paymentMethod,
type: MENU_ITEM,
onPress: e => this.props.onPress(e, paymentMethod.accountType, paymentMethod.accountData, paymentMethod.isDefault),
iconFill: this.isPaymentMethodActive(paymentMethod) ? StyleUtils.getIconFillColor(CONST.BUTTON_STATES.PRESSED) : null,
wrapperStyle: this.isPaymentMethodActive(paymentMethod) ? [StyleUtils.getButtonBackgroundColorStyle(CONST.BUTTON_STATES.PRESSED)] : null,
Expand All @@ -132,42 +128,6 @@ class PaymentMethodList extends Component {
return combinedPaymentMethods;
}

/**
* Take all of the different payment methods and create a list that can be easily digested by renderItem
*
* @returns {Array}
*/
createPaymentMethodList() {
const combinedPaymentMethods = this.getFilteredPaymentMethods();

// If we have not added any payment methods, show a default empty state
if (_.isEmpty(combinedPaymentMethods)) {
combinedPaymentMethods.push({
key: 'addFirstPaymentMethodHelpText',
text: this.props.translate('paymentMethodList.addFirstPaymentMethod'),
});
}

if (!this.props.shouldShowAddPaymentMethodButton) {
return combinedPaymentMethods;
}

combinedPaymentMethods.push({
Comment thread
jechandia marked this conversation as resolved.
type: BUTTON,
text: this.props.translate('paymentMethodList.addPaymentMethod'),
icon: Expensicons.CreditCard,
style: [styles.buttonCTA],
iconStyles: [styles.buttonCTAIcon],
onPress: e => this.props.onPress(e),
isDisabled: this.props.isLoadingPayments,
shouldShowRightIcon: true,
success: true,
key: 'addPaymentMethodButton',
});

return combinedPaymentMethods;
}

/**
* Dismisses the error on the payment method
* @param {Object} item
Expand Down Expand Up @@ -207,67 +167,79 @@ class PaymentMethodList extends Component {
* @return {React.Component}
*/
renderItem({item}) {
if (item.type === MENU_ITEM) {
return (
<OfflineWithFeedback
onClose={() => this.dismissError(item)}
pendingAction={item.pendingAction}
errors={item.errors}
errorRowStyles={styles.ph6}
>
<MenuItem
onPress={item.onPress}
title={item.title}
description={item.description}
icon={item.icon}
disabled={item.disabled}
iconFill={item.iconFill}
iconHeight={item.iconSize}
iconWidth={item.iconSize}
badgeText={this.getDefaultBadgeText(item.isDefault)}
wrapperStyle={item.wrapperStyle}
shouldShowSelectedState={this.props.shouldShowSelectedState}
isSelected={this.props.selectedMethodID === item.methodID}
/>
</OfflineWithFeedback>
);
}
if (item.type === BUTTON) {
return (
<FormAlertWrapper>
{isOffline => (
<Button
text={item.text}
icon={item.icon}
onPress={item.onPress}
isDisabled={item.isDisabled || isOffline}
style={item.style}
iconStyles={item.iconStyles}
success={item.success}
shouldShowRightIcon={item.shouldShowRightIcon}
large
/>
)}
</FormAlertWrapper>
);
}
return (
<OfflineWithFeedback
onClose={() => this.dismissError(item)}
pendingAction={item.pendingAction}
errors={item.errors}
errorRowStyles={styles.ph6}
>
<MenuItem
onPress={item.onPress}
title={item.title}
description={item.description}
icon={item.icon}
disabled={item.disabled}
iconFill={item.iconFill}
iconHeight={item.iconSize}
iconWidth={item.iconSize}
badgeText={this.getDefaultBadgeText(item.isDefault)}
wrapperStyle={item.wrapperStyle}
shouldShowSelectedState={this.props.shouldShowSelectedState}
isSelected={this.props.selectedMethodID === item.methodID}
/>
</OfflineWithFeedback>
);
}

/**
* Show add first payment copy when payment methods are
*
* @return {React.Component}
*/
renderListEmptyComponent() {
return (
<Text
style={[styles.popoverMenuItem]}
>
{item.text}
{this.props.translate('paymentMethodList.addFirstPaymentMethod')}
</Text>
);
}

render() {
return (
<FlatList
data={this.createPaymentMethodList()}
renderItem={this.renderItem}
keyExtractor={item => item.key}
/>
<>
<FlatList
data={this.getFilteredPaymentMethods()}
renderItem={this.renderItem}
keyExtractor={item => item.key}
ListEmptyComponent={this.renderListEmptyComponent()}
/>
{
this.props.shouldShowAddPaymentMethodButton
&& (
<FormAlertWrapper>
{
isOffline => (
<Button
text={this.props.translate('paymentMethodList.addPaymentMethod')}
icon={Expensicons.CreditCard}
onPress={e => this.props.onPress(e)}
isDisabled={this.props.isLoadingPayments || isOffline}
style={[styles.mh4, styles.mb4, styles.buttonCTA]}
iconStyles={[styles.buttonCTAIcon]}
key="addPaymentMethodButton"
success
shouldShowRightIcon
large
/>
)
}
</FormAlertWrapper>
)
}
</>
);
}
}
Expand Down
38 changes: 18 additions & 20 deletions src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import {
View, TouchableOpacity, Dimensions, InteractionManager, LayoutAnimation,
View, TouchableOpacity, InteractionManager, LayoutAnimation,
} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
Expand Down Expand Up @@ -49,7 +49,8 @@ class BasePaymentsPage extends React.Component {
title: '',
},
anchorPositionTop: 0,
anchorPositionLeft: 0,
anchorPositionBottom: 0,
anchorPositionRight: 0,
addPaymentMethodButton: null,
};

Expand All @@ -66,24 +67,17 @@ class BasePaymentsPage extends React.Component {

componentDidMount() {
this.fetchData();
if (this.props.shouldListenForResize) {
this.dimensionsSubscription = Dimensions.addEventListener('change', this.setMenuPosition);
}
}

componentDidUpdate(prevProps) {
if (!prevProps.network.isOffline || this.props.network.isOffline) {
return;
if (this.shouldListenForResize) {
this.setMenuPosition();
}

this.fetchData();
}

componentWillUnmount() {
if (!this.props.shouldListenForResize || !this.dimensionsSubscription) {
if (!prevProps.network.isOffline || this.props.network.isOffline) {
return;
}
this.dimensionsSubscription.remove();
this.fetchData();
}

setMenuPosition() {
Expand Down Expand Up @@ -113,10 +107,11 @@ class BasePaymentsPage extends React.Component {
*/
setPositionAddPaymentMenu(position) {
this.setState({
anchorPositionTop: position.bottom,
anchorPositionTop: position.top + position.height,
anchorPositionBottom: this.props.windowHeight - position.top,

// We want the position to be 13px to the right of the left border
anchorPositionLeft: position.left + 13,
anchorPositionRight: (this.props.windowWidth - position.right) + 13,
});
}

Expand All @@ -133,6 +128,8 @@ class BasePaymentsPage extends React.Component {
this.setState({
addPaymentMethodButton: nativeEvent.currentTarget,
});

// The delete/default menu
if (accountType) {
let formattedSelectedPaymentMethod;
if (accountType === CONST.PAYMENT_METHODS.PAYPAL) {
Expand Down Expand Up @@ -170,6 +167,7 @@ class BasePaymentsPage extends React.Component {
this.setState({
shouldShowAddPaymentMenu: true,
});

this.setPositionAddPaymentMenu(position);
}

Expand Down Expand Up @@ -326,8 +324,8 @@ class BasePaymentsPage extends React.Component {
isVisible={this.state.shouldShowAddPaymentMenu}
onClose={this.hideAddPaymentMenu}
anchorPosition={{
top: this.state.anchorPositionTop,
left: this.state.anchorPositionLeft,
bottom: this.state.anchorPositionBottom,
right: this.state.anchorPositionRight - 10,
}}
onItemSelected={method => this.addPaymentMethodTypePressed(method)}
/>
Expand All @@ -336,7 +334,7 @@ class BasePaymentsPage extends React.Component {
onClose={this.hideDefaultDeleteMenu}
anchorPosition={{
top: this.state.anchorPositionTop,
left: this.state.anchorPositionLeft,
right: this.state.anchorPositionRight,
}}
>
<View
Expand Down Expand Up @@ -409,7 +407,7 @@ class BasePaymentsPage extends React.Component {
onClose={this.hidePasswordPrompt}
anchorPosition={{
top: this.state.anchorPositionTop,
left: this.state.anchorPositionLeft,
right: this.state.anchorPositionRight,
}}
onSubmit={(password) => {
this.hidePasswordPrompt();
Expand All @@ -427,7 +425,7 @@ class BasePaymentsPage extends React.Component {
cancelText={this.props.translate('common.cancel')}
anchorPosition={{
top: this.state.anchorPositionTop,
left: this.state.anchorPositionLeft,
right: this.state.anchorPositionRight,
}}
onConfirm={() => {
this.setState({
Expand Down