Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Add payment dynamic #7566

Merged
merged 6 commits into from
Feb 11, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
177 changes: 177 additions & 0 deletions src/components/KYCWall/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
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',
};

// 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
// to render the AddPaymentMethodMenu in the correct location.
class KYCWall extends React.Component {
constructor(props) {
super(props);

this.continue = this.continue.bind(this);

this.state = {
shouldShowAddPaymentMenu: false,
anchorPositionTop: 0,
anchorPositionLeft: 0,
};
}

componentDidMount() {
window.removeEventListener('resize', null);
PaymentMethods.getPaymentMethods();
PaymentMethods.kycWallRef.current = this;
}

componentWillUnmount() {
PaymentMethods.kycWallRef.current = null;
}

/**
* @param {DOMRect} domRect
* @returns {Object}
*/
getAnchorPosition(domRect) {
if (this.props.popoverPlacement === 'bottom') {
return {
anchorPositionTop: domRect.top + (domRect.height - 2),
anchorPositionLeft: domRect.left + 20,
};
}

return {
anchorPositionTop: domRect.top - 150,
anchorPositionLeft: domRect.left,
};
}

/**
* 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.
* If they are already KYC'd we will continue whatever action is gated behind the KYC wall.
*
* @param {Event} event
*/
continue(event) {
// 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');
let clickedElementLocation = getClickedElementLocation(event.nativeEvent);
let position = this.getAnchorPosition(clickedElementLocation);
window.addEventListener('resize', () => {
clickedElementLocation = getClickedElementLocation(event.nativeEvent);
position = this.getAnchorPosition(clickedElementLocation);
this.setPositionAddPaymentMenu(position);
});
this.setState({
shouldShowAddPaymentMenu: true,
});
this.setPositionAddPaymentMenu(position);
return;
}

// Ask the user to upgrade to a gold wallet as this means they have not yet went through our Know Your Customer (KYC) checks
const hasGoldWallet = this.props.userWallet.tierName && this.props.userWallet.tierName === CONST.WALLET.TIER_NAME.GOLD;
if (!hasGoldWallet) {
Log.info('[KYC Wallet] User does not have gold wallet');
Navigation.navigate(this.props.enablePaymentsRoute);
return;
}

Log.info('[KYC Wallet] User has valid payment method and passed KYC checks');
this.props.onSuccessfulKYC();
}

render() {
return (
<>
<AddPaymentMethodMenu
isVisible={this.state.shouldShowAddPaymentMenu}
onClose={() => this.setState({shouldShowAddPaymentMenu: false})}
anchorPosition={{
top: this.state.anchorPositionTop,
left: this.state.anchorPositionLeft,
}}
shouldShowPaypal={false}
onItemSelected={(item) => {
this.setState({shouldShowAddPaymentMenu: false});
if (item === CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
Navigation.navigate(this.props.addBankAccountRoute);
} else if (item === CONST.PAYMENT_METHODS.DEBIT_CARD) {
Navigation.navigate(this.props.addDebitCardRoute);
}
}}
/>
{this.props.isLoadingPaymentMethods
? (<ActivityIndicator color={themeColors.spinner} size="large" />)
: this.props.children(this.continue)}
</>
);
}
}

KYCWall.propTypes = propTypes;
KYCWall.defaultProps = defaultProps;

export default withOnyx({
userWallet: {
key: ONYXKEYS.USER_WALLET,
},
cardList: {
key: ONYXKEYS.CARD_LIST,
},
bankAccountList: {
key: ONYXKEYS.BANK_ACCOUNT_LIST,
},
isLoadingPaymentMethods: {
key: ONYXKEYS.IS_LOADING_PAYMENT_METHODS,
initWithStoredValues: false,
},
})(KYCWall);
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,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';
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 */
Expand Down
Loading