diff --git a/src/components/KYCWall.js b/src/components/KYCWall/BaseKYCWall.js similarity index 74% rename from src/components/KYCWall.js rename to src/components/KYCWall/BaseKYCWall.js index f0dc66ec99ee..dbcd0c39b062 100644 --- a/src/components/KYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -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 @@ -57,6 +34,9 @@ class KYCWall extends React.Component { } componentWillUnmount() { + if (this.props.shouldListenForResize) { + window.removeEventListener('resize', null); + } PaymentMethods.kycWallRef.current = null; } @@ -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. @@ -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; } diff --git a/src/components/KYCWall/index.js b/src/components/KYCWall/index.js new file mode 100644 index 000000000000..287694560b17 --- /dev/null +++ b/src/components/KYCWall/index.js @@ -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 + +); + +KYCWall.propTypes = propTypes; +KYCWall.defaultProps = defaultProps; +KYCWall.displayName = 'KYCWall'; + +export default KYCWall; diff --git a/src/components/KYCWall/index.native.js b/src/components/KYCWall/index.native.js new file mode 100644 index 000000000000..86a1c54a55ce --- /dev/null +++ b/src/components/KYCWall/index.native.js @@ -0,0 +1,3 @@ +import BaseKYCWall from './BaseKYCWall'; + +export default BaseKYCWall; diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js new file mode 100644 index 000000000000..40403f120f03 --- /dev/null +++ b/src/components/KYCWall/kycWallPropTypes.js @@ -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}; diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js similarity index 84% rename from src/pages/settings/Payments/PaymentsPage.js rename to src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js index 646a3f9b3e11..53a180f3b3a7 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js @@ -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); @@ -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 * @@ -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) { @@ -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); } /** @@ -178,6 +168,9 @@ class PaymentsPage extends React.Component { * Hide the add payment modal */ hideAddPaymentMenu() { + if (this.props.shouldListenForResize) { + window.removeEventListener('resize', null); + } this.setState({shouldShowAddPaymentMenu: false}); } @@ -185,6 +178,9 @@ class PaymentsPage extends React.Component { * Hide the default / delete modal */ hideDefaultDeleteMenu() { + if (this.props.shouldListenForResize) { + window.removeEventListener('resize', null); + } this.setState({shouldShowDefaultDeleteMenu: false}); } @@ -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, @@ -411,4 +407,4 @@ export default compose( initWithStoredValues: false, }, }), -)(PaymentsPage); +)(BasePaymentsPage); diff --git a/src/pages/settings/Payments/PaymentsPage/index.js b/src/pages/settings/Payments/PaymentsPage/index.js new file mode 100644 index 000000000000..8b819cd7edf6 --- /dev/null +++ b/src/pages/settings/Payments/PaymentsPage/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import BasePaymentsPage from './BasePaymentsPage'; + +const PaymentsPage = () => ( + +); + +PaymentsPage.displayName = 'PaymentsPage'; + +export default PaymentsPage; diff --git a/src/pages/settings/Payments/PaymentsPage/index.native.js b/src/pages/settings/Payments/PaymentsPage/index.native.js new file mode 100644 index 000000000000..b0b43a8e6661 --- /dev/null +++ b/src/pages/settings/Payments/PaymentsPage/index.native.js @@ -0,0 +1,3 @@ +import BasePaymentsPage from './BasePaymentsPage'; + +export default BasePaymentsPage; diff --git a/src/pages/settings/Payments/PaymentsPage/paymentsPagePropTypes.js b/src/pages/settings/Payments/PaymentsPage/paymentsPagePropTypes.js new file mode 100644 index 000000000000..3c3d6a2d8d11 --- /dev/null +++ b/src/pages/settings/Payments/PaymentsPage/paymentsPagePropTypes.js @@ -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};