Skip to content

Commit

Permalink
Merge pull request #7566 from phivh/fix/add-payment-dynamic
Browse files Browse the repository at this point in the history
Fix: Add payment dynamic
  • Loading branch information
deetergp authored Feb 11, 2022
2 parents e75be3f + 62f1a74 commit 1898d81
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 105 deletions.
72 changes: 35 additions & 37 deletions src/components/KYCWall.js → src/components/KYCWall/BaseKYCWall.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import {ActivityIndicator} from 'react-native';
import themeColors from '../styles/themes/default';
import CONST from '../CONST';
import Navigation from '../libs/Navigation/Navigation';
import AddPaymentMethodMenu from './AddPaymentMethodMenu';
import getClickedElementLocation from '../libs/getClickedElementLocation';
import * as PaymentUtils from '../libs/PaymentUtils';
import * as PaymentMethods from '../libs/actions/PaymentMethods';
import ONYXKEYS from '../ONYXKEYS';
import userWalletPropTypes from '../pages/EnablePayments/userWalletPropTypes';
import Log from '../libs/Log';

const propTypes = {
/** Route for the Add Bank Account screen for a given navigation stack */
addBankAccountRoute: PropTypes.string.isRequired,

/** Route for the Add Debit Card screen for a given navigation stack */
addDebitCardRoute: PropTypes.string.isRequired,

/** Route for the KYC enable payments screen for a given navigation stack */
enablePaymentsRoute: PropTypes.string.isRequired,

/** Where to place the popover */
popoverPlacement: PropTypes.string,

...userWalletPropTypes,
};

const defaultProps = {
// eslint-disable-next-line react/default-props-match-prop-types
userWallet: {},
popoverPlacement: 'top',
};
import themeColors from '../../styles/themes/default';
import CONST from '../../CONST';
import Navigation from '../../libs/Navigation/Navigation';
import AddPaymentMethodMenu from '../AddPaymentMethodMenu';
import getClickedElementLocation from '../../libs/getClickedElementLocation';
import * as PaymentUtils from '../../libs/PaymentUtils';
import * as PaymentMethods from '../../libs/actions/PaymentMethods';
import ONYXKEYS from '../../ONYXKEYS';
import Log from '../../libs/Log';
import {propTypes, defaultProps} from './kycWallPropTypes';

// This component allows us to block various actions by forcing the user to first add a default payment method and successfully make it through our Know Your Customer flow
// before continuing to take whatever action they originally intended to take. It requires a button as a child and a native event so we can get the coordinates and use it
Expand All @@ -57,6 +34,9 @@ class KYCWall extends React.Component {
}

componentWillUnmount() {
if (this.props.shouldListenForResize) {
window.removeEventListener('resize', null);
}
PaymentMethods.kycWallRef.current = null;
}

Expand All @@ -78,6 +58,18 @@ class KYCWall extends React.Component {
};
}

/**
* Set position of the transfer payment menu
*
* @param {Object} position
*/
setPositionAddPaymentMenu(position) {
this.setState({
anchorPositionTop: position.anchorPositionTop,
anchorPositionLeft: position.anchorPositionLeft,
});
}

/**
* 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.
Expand All @@ -89,13 +81,19 @@ class KYCWall extends React.Component {
// Check to see if user has a valid payment method on file and display the add payment popover if they don't
if (!PaymentUtils.hasExpensifyPaymentMethod(this.props.cardList, this.props.bankAccountList)) {
Log.info('[KYC Wallet] User does not have valid payment method');
const clickedElementLocation = getClickedElementLocation(event.nativeEvent);
const {anchorPositionTop, anchorPositionLeft} = this.getAnchorPosition(clickedElementLocation);
let clickedElementLocation = getClickedElementLocation(event.nativeEvent);
let position = this.getAnchorPosition(clickedElementLocation);
if (this.props.shouldListenForResize) {
window.addEventListener('resize', () => {
clickedElementLocation = getClickedElementLocation(event.nativeEvent);
position = this.getAnchorPosition(clickedElementLocation);
this.setPositionAddPaymentMenu(position);
});
}
this.setState({
shouldShowAddPaymentMenu: true,
anchorPositionTop,
anchorPositionLeft,
});
this.setPositionAddPaymentMenu(position);
return;
}

Expand Down
14 changes: 14 additions & 0 deletions src/components/KYCWall/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import {propTypes, defaultProps} from './kycWallPropTypes';
import BaseKYCWall from './BaseKYCWall';

const KYCWall = props => (
// eslint-disable-next-line react/jsx-props-no-spreading
<BaseKYCWall {...props} shouldListenForResize />
);

KYCWall.propTypes = propTypes;
KYCWall.defaultProps = defaultProps;
KYCWall.displayName = 'KYCWall';

export default KYCWall;
3 changes: 3 additions & 0 deletions src/components/KYCWall/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import BaseKYCWall from './BaseKYCWall';

export default BaseKYCWall;
30 changes: 30 additions & 0 deletions src/components/KYCWall/kycWallPropTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import PropTypes from 'prop-types';
import userWalletPropTypes from '../../pages/EnablePayments/userWalletPropTypes';

const propTypes = {
/** Route for the Add Bank Account screen for a given navigation stack */
addBankAccountRoute: PropTypes.string.isRequired,

/** Route for the Add Debit Card screen for a given navigation stack */
addDebitCardRoute: PropTypes.string.isRequired,

/** Route for the KYC enable payments screen for a given navigation stack */
enablePaymentsRoute: PropTypes.string.isRequired,

/** Where to place the popover */
popoverPlacement: PropTypes.string,

/** Listen for window resize event on web and desktop */
shouldListenForResize: PropTypes.bool,

...userWalletPropTypes,
};

const defaultProps = {
// eslint-disable-next-line react/default-props-match-prop-types
userWallet: {},
popoverPlacement: 'top',
shouldListenForResize: false,
};

export {propTypes, defaultProps};
Original file line number Diff line number Diff line change
@@ -1,59 +1,35 @@
import React from 'react';
import {View, TouchableOpacity} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
import PaymentMethodList from './PaymentMethodList';
import ROUTES from '../../../ROUTES';
import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton';
import PasswordPopover from '../../../components/PasswordPopover';
import ScreenWrapper from '../../../components/ScreenWrapper';
import Navigation from '../../../libs/Navigation/Navigation';
import styles from '../../../styles/styles';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import compose from '../../../libs/compose';
import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index';
import * as BankAccounts from '../../../libs/actions/BankAccounts';
import Popover from '../../../components/Popover';
import MenuItem from '../../../components/MenuItem';
import Text from '../../../components/Text';
import * as PaymentMethods from '../../../libs/actions/PaymentMethods';
import getClickedElementLocation from '../../../libs/getClickedElementLocation';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import CurrentWalletBalance from '../../../components/CurrentWalletBalance';
import ONYXKEYS from '../../../ONYXKEYS';
import Permissions from '../../../libs/Permissions';
import ConfirmPopover from '../../../components/ConfirmPopover';
import AddPaymentMethodMenu from '../../../components/AddPaymentMethodMenu';
import CONST from '../../../CONST';
import * as Expensicons from '../../../components/Icon/Expensicons';
import walletTransferPropTypes from './walletTransferPropTypes';
import ConfirmModal from '../../../components/ConfirmModal';
import KYCWall from '../../../components/KYCWall';
import PaymentMethodList from '../PaymentMethodList';
import ROUTES from '../../../../ROUTES';
import HeaderWithCloseButton from '../../../../components/HeaderWithCloseButton';
import PasswordPopover from '../../../../components/PasswordPopover';
import ScreenWrapper from '../../../../components/ScreenWrapper';
import Navigation from '../../../../libs/Navigation/Navigation';
import styles from '../../../../styles/styles';
import withLocalize from '../../../../components/withLocalize';
import compose from '../../../../libs/compose';
import KeyboardAvoidingView from '../../../../components/KeyboardAvoidingView/index';
import * as BankAccounts from '../../../../libs/actions/BankAccounts';
import Popover from '../../../../components/Popover';
import MenuItem from '../../../../components/MenuItem';
import Text from '../../../../components/Text';
import * as PaymentMethods from '../../../../libs/actions/PaymentMethods';
import getClickedElementLocation from '../../../../libs/getClickedElementLocation';
import withWindowDimensions from '../../../../components/withWindowDimensions';
import CurrentWalletBalance from '../../../../components/CurrentWalletBalance';
import ONYXKEYS from '../../../../ONYXKEYS';
import Permissions from '../../../../libs/Permissions';
import ConfirmPopover from '../../../../components/ConfirmPopover';
import AddPaymentMethodMenu from '../../../../components/AddPaymentMethodMenu';
import CONST from '../../../../CONST';
import * as Expensicons from '../../../../components/Icon/Expensicons';
import ConfirmModal from '../../../../components/ConfirmModal';
import KYCWall from '../../../../components/KYCWall';
import {propTypes, defaultProps} from './paymentsPagePropTypes';

const propTypes = {
/** Wallet balance transfer props */
walletTransfer: walletTransferPropTypes,

/** List of betas available to current user */
betas: PropTypes.arrayOf(PropTypes.string),

/** Are we loading payment methods? */
isLoadingPaymentMethods: PropTypes.bool,

...withLocalizePropTypes,

...windowDimensionsPropTypes,
};

const defaultProps = {
walletTransfer: {
shouldShowConfirmModal: false,
},
betas: [],
isLoadingPaymentMethods: true,
};

class PaymentsPage extends React.Component {
class BasePaymentsPage extends React.Component {
constructor(props) {
super(props);

Expand Down Expand Up @@ -94,6 +70,20 @@ class PaymentsPage extends React.Component {
}
}

/**
* Set position of the payment menu
*
* @param {Object} position
*/
setPositionAddPaymentMenu(position) {
this.setState({
anchorPositionTop: position.bottom,

// We want the position to be 13px to the right of the left border
anchorPositionLeft: position.left + 13,
});
}

/**
* Display the delete/default menu, or the add payment method menu
*
Expand All @@ -102,7 +92,13 @@ class PaymentsPage extends React.Component {
* @param {String} account
*/
paymentMethodPressed(nativeEvent, accountType, account) {
const position = getClickedElementLocation(nativeEvent);
let position = getClickedElementLocation(nativeEvent);
if (this.props.shouldListenForResize) {
window.addEventListener('resize', () => {
position = getClickedElementLocation(nativeEvent);
this.setPositionAddPaymentMenu(position);
});
}
if (accountType) {
let formattedSelectedPaymentMethod;
if (accountType === CONST.PAYMENT_METHODS.PAYPAL) {
Expand Down Expand Up @@ -131,21 +127,15 @@ class PaymentsPage extends React.Component {
shouldShowDefaultDeleteMenu: true,
selectedPaymentMethod: account,
selectedPaymentMethodType: accountType,
anchorPositionTop: position.bottom,

// We want the position to be 13px to the right of the left border
anchorPositionLeft: position.left + 13,
formattedSelectedPaymentMethod,
});
} else {
this.setState({
shouldShowAddPaymentMenu: true,
anchorPositionTop: position.bottom,

// We want the position to be 13px to the right of the left border
anchorPositionLeft: position.left + 13,
});
this.setPositionAddPaymentMenu(position);
return;
}
this.setState({
shouldShowAddPaymentMenu: true,
});
this.setPositionAddPaymentMenu(position);
}

/**
Expand Down Expand Up @@ -178,13 +168,19 @@ class PaymentsPage extends React.Component {
* Hide the add payment modal
*/
hideAddPaymentMenu() {
if (this.props.shouldListenForResize) {
window.removeEventListener('resize', null);
}
this.setState({shouldShowAddPaymentMenu: false});
}

/**
* Hide the default / delete modal
*/
hideDefaultDeleteMenu() {
if (this.props.shouldListenForResize) {
window.removeEventListener('resize', null);
}
this.setState({shouldShowDefaultDeleteMenu: false});
}

Expand Down Expand Up @@ -393,8 +389,8 @@ class PaymentsPage extends React.Component {
}
}

PaymentsPage.propTypes = propTypes;
PaymentsPage.defaultProps = defaultProps;
BasePaymentsPage.propTypes = propTypes;
BasePaymentsPage.defaultProps = defaultProps;

export default compose(
withWindowDimensions,
Expand All @@ -411,4 +407,4 @@ export default compose(
initWithStoredValues: false,
},
}),
)(PaymentsPage);
)(BasePaymentsPage);
10 changes: 10 additions & 0 deletions src/pages/settings/Payments/PaymentsPage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import BasePaymentsPage from './BasePaymentsPage';

const PaymentsPage = () => (
<BasePaymentsPage shouldListenForResize />
);

PaymentsPage.displayName = 'PaymentsPage';

export default PaymentsPage;
3 changes: 3 additions & 0 deletions src/pages/settings/Payments/PaymentsPage/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import BasePaymentsPage from './BasePaymentsPage';

export default BasePaymentsPage;
33 changes: 33 additions & 0 deletions src/pages/settings/Payments/PaymentsPage/paymentsPagePropTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import PropTypes from 'prop-types';
import walletTransferPropTypes from '../walletTransferPropTypes';
import {withLocalizePropTypes} from '../../../../components/withLocalize';
import {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions';

const propTypes = {
/** Wallet balance transfer props */
walletTransfer: walletTransferPropTypes,

/** List of betas available to current user */
betas: PropTypes.arrayOf(PropTypes.string),

/** Are we loading payment methods? */
isLoadingPaymentMethods: PropTypes.bool,

/** Listen for window resize event on web and desktop. */
shouldListenForResize: PropTypes.bool,

...withLocalizePropTypes,

...windowDimensionsPropTypes,
};

const defaultProps = {
walletTransfer: {
shouldShowConfirmModal: false,
},
betas: [],
isLoadingPaymentMethods: true,
shouldListenForResize: false,
};

export {propTypes, defaultProps};

0 comments on commit 1898d81

Please sign in to comment.