From af051141f67ff552ca4b5b1fae6d24f6467d9ecb Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Fri, 13 Oct 2023 16:56:29 +0200
Subject: [PATCH 01/23] feat: add enable wallet button
---
src/languages/en.ts | 2 +
src/languages/es.ts | 2 +
.../settings/Wallet/WalletPage/WalletPage.js | 37 +++++++++++++------
3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 9d376c73ea62..200abc828554 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -845,6 +845,8 @@ export default {
receiveMoney: 'Receive money in your local currency',
expensifyWallet: 'Expensify Wallet',
sendAndReceiveMoney: 'Send and receive money from your Expensify Wallet.',
+ enableWalletToSendAndReceiveMoney: 'Enable your Expensify Wallet to start sending and receiving money with friends!',
+ enableWallet: 'Enable wallet',
bankAccounts: 'Bank accounts',
addBankAccountToSendAndReceive: 'Add a bank account to send and receive payments directly in the app.',
addBankAccount: 'Add bank account',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 316cd1eaed21..7b1f789a3086 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -841,6 +841,8 @@ export default {
receiveMoney: 'Recibe dinero en tu moneda local',
expensifyWallet: 'Billetera Expensify',
sendAndReceiveMoney: 'Envía y recibe dinero desde tu Billetera Expensify.',
+ enableWalletToSendAndReceiveMoney: 'Habilita tu Billetera Expensify para comenzar a enviar y recibir dinero con amigos',
+ enableWallet: 'Habilitar Billetera',
bankAccounts: 'Cuentas bancarias',
addBankAccountToSendAndReceive: 'Añade una cuenta bancaria para enviar y recibir pagos directamente en la aplicación.',
addBankAccount: 'Agregar cuenta bancaria',
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index 4115335bbcd5..c9bb89f5d174 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -62,6 +62,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
const hasBankAccount = !_.isEmpty(bankAccountList) || !_.isEmpty(fundList);
const hasWallet = userWallet.walletLinkedAccountID > 0;
+ const hasSilverWallet = userWallet.tierName === CONST.WALLET.TIER_NAME.SILVER;
const hasAssignedCard = !_.isEmpty(cardList);
const shouldShowEmptyState = !hasBankAccount && !hasWallet && !hasAssignedCard;
@@ -330,7 +331,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
{hasWallet && (
<>
@@ -358,17 +359,29 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
addDebitCardRoute={ROUTES.SETTINGS_ADD_DEBIT_CARD}
popoverPlacement="bottom"
>
- {(triggerKYCFlow, buttonRef) => (
-
- )}
+ {(triggerKYCFlow, buttonRef) =>
+ hasSilverWallet ? (
+
+ ) : (
+
+ )
+ }
>
From b28682a57c6b499754fce1f69e4971aac848984d Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Fri, 13 Oct 2023 17:19:01 +0200
Subject: [PATCH 02/23] fix: disable when offline
---
src/pages/settings/Wallet/WalletPage/WalletPage.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index c9bb89f5d174..24dd0b7e2e52 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -366,7 +366,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
text={translate('walletPage.enableWallet')}
onPress={triggerKYCFlow}
style={styles.mh5}
- disabled={network.isOffline}
+ isDisabled={network.isOffline}
success
large
/>
From 49ac0b5e606e1849d5356903b4290a4a4f0db1ff Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Sun, 15 Oct 2023 10:50:56 +0200
Subject: [PATCH 03/23] feat: continue kyc flow
---
src/components/KYCWall/BaseKYCWall.js | 1 +
src/components/KYCWall/kycWallPropTypes.js | 4 ++++
src/libs/actions/BankAccounts.js | 8 ++++++++
src/libs/actions/PaymentMethods.js | 8 +++++---
src/pages/AddPersonalBankAccountPage.js | 10 ++++++++++
src/pages/settings/Wallet/WalletPage/WalletPage.js | 7 +++++++
6 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js
index 1c1552d55844..315a48184498 100644
--- a/src/components/KYCWall/BaseKYCWall.js
+++ b/src/components/KYCWall/BaseKYCWall.js
@@ -148,6 +148,7 @@ class KYCWall extends React.Component {
anchorAlignment={this.props.anchorAlignment}
onItemSelected={(item) => {
this.setState({shouldShowAddPaymentMenu: false});
+ this.props.onSelectPaymentMethod(item);
if (item === CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
Navigation.navigate(this.props.addBankAccountRoute);
} else if (item === CONST.PAYMENT_METHODS.DEBIT_CARD) {
diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js
index 6c117eb67f5b..5080e5510241 100644
--- a/src/components/KYCWall/kycWallPropTypes.js
+++ b/src/components/KYCWall/kycWallPropTypes.js
@@ -49,6 +49,9 @@ const propTypes = {
horizontal: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL)),
vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)),
}),
+
+ /** Callback for when a payment method has been selected */
+ onSelectPaymentMethod: PropTypes.func,
};
const defaultProps = {
@@ -66,6 +69,7 @@ const defaultProps = {
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM,
},
+ onSelectPaymentMethod: () => {},
};
export {propTypes, defaultProps};
diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js
index 4d3c880b5983..ee44fac20f0e 100644
--- a/src/libs/actions/BankAccounts.js
+++ b/src/libs/actions/BankAccounts.js
@@ -46,6 +46,13 @@ function openPersonalBankAccountSetupView(exitReportID) {
});
}
+/**
+ * @param {Boolean} shouldContinueKYCOnSuccess Whether after adding a bank account we should continue with the KYC flow
+ */
+function setPersonalBankAccountContinueKYCOnSuccess(shouldContinueKYCOnSuccess) {
+ Onyx.merge(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {shouldContinueKYCOnSuccess});
+}
+
function clearPersonalBankAccount() {
clearPlaid();
Onyx.set(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {});
@@ -440,6 +447,7 @@ export {
deletePaymentBankAccount,
handlePlaidError,
openPersonalBankAccountSetupView,
+ setPersonalBankAccountContinueKYCOnSuccess,
clearReimbursementAccount,
openReimbursementAccountPage,
updateBeneficialOwnersForBankAccount,
diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js
index 0ed6f8b036bb..d1cbf0ef893b 100644
--- a/src/libs/actions/PaymentMethods.js
+++ b/src/libs/actions/PaymentMethods.js
@@ -15,15 +15,17 @@ const kycWallRef = createRef();
/**
* When we successfully add a payment method or pass the KYC checks we will continue with our setup action if we have one set.
+ *
+ * @param {String} fallbackRoute
*/
-function continueSetup() {
+function continueSetup(fallbackRoute = ROUTES.HOME) {
if (!kycWallRef.current || !kycWallRef.current.continue) {
- Navigation.goBack(ROUTES.HOME);
+ Navigation.goBack(fallbackRoute);
return;
}
// Close the screen (Add Debit Card, Add Bank Account, or Enable Payments) on success and continue with setup
- Navigation.goBack(ROUTES.HOME);
+ Navigation.goBack(fallbackRoute);
kycWallRef.current.continue();
}
diff --git a/src/pages/AddPersonalBankAccountPage.js b/src/pages/AddPersonalBankAccountPage.js
index 7c04970c3980..ce0e52e607d9 100644
--- a/src/pages/AddPersonalBankAccountPage.js
+++ b/src/pages/AddPersonalBankAccountPage.js
@@ -7,6 +7,7 @@ import HeaderWithBackButton from '../components/HeaderWithBackButton';
import ScreenWrapper from '../components/ScreenWrapper';
import Navigation from '../libs/Navigation/Navigation';
import * as BankAccounts from '../libs/actions/BankAccounts';
+import * as PaymentMethods from '../libs/actions/PaymentMethods';
import withLocalize, {withLocalizePropTypes} from '../components/withLocalize';
import AddPlaidBankAccount from '../components/AddPlaidBankAccount';
import getPlaidOAuthReceivedRedirectURI from '../libs/getPlaidOAuthReceivedRedirectURI';
@@ -35,6 +36,9 @@ const propTypes = {
/** Any reportID we should redirect to at the end of the flow */
exitReportID: PropTypes.string,
+ /** Whether we should continue with KYC at the end of the flow */
+ shouldContinueKYCOnSuccess: PropTypes.bool,
+
/** Whether the form is loading */
isLoading: PropTypes.bool,
@@ -51,6 +55,7 @@ const defaultProps = {
isLoading: false,
plaidAccountID: '',
exitReportID: '',
+ shouldContinueKYCOnSuccess: false,
},
};
@@ -88,8 +93,13 @@ class AddPersonalBankAccountPage extends React.Component {
exitFlow() {
const exitReportID = lodashGet(this.props, 'personalBankAccount.exitReportID');
+ const shouldContinueKYCOnSuccess = lodashGet(this.props, 'personalBankAccount.shouldContinueKYCOnSuccess', false);
+ const shouldShowSuccess = lodashGet(this.props, 'personalBankAccount.shouldShowSuccess', false);
+
if (exitReportID) {
Navigation.dismissModal(exitReportID);
+ } else if (shouldShowSuccess && shouldContinueKYCOnSuccess) {
+ PaymentMethods.continueSetup(ROUTES.SETTINGS_WALLET);
} else {
Navigation.goBack(ROUTES.SETTINGS_WALLET);
}
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index 99526a4962e6..c69fa27294f9 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -354,6 +354,13 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
)}
{
+ if (!hasSilverWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
+ return;
+ }
+ // To allow upgrading to a gold wallet, continue with the KYC flow after adding a bank account
+ BankAccounts.setPersonalBankAccountContinueKYCOnSuccess(true);
+ }}
enablePaymentsRoute={ROUTES.SETTINGS_ENABLE_PAYMENTS}
addBankAccountRoute={ROUTES.SETTINGS_ADD_BANK_ACCOUNT}
addDebitCardRoute={ROUTES.SETTINGS_ADD_DEBIT_CARD}
From a381ece18ebd8dbc034817b6376b9011882ec096 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:08:45 +0200
Subject: [PATCH 04/23] feat: language update
---
src/languages/en.ts | 2 +-
src/languages/es.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 6376e44c98d3..052c7716984a 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1212,7 +1212,7 @@ export default {
},
additionalDetailsStep: {
headerTitle: 'Additional details',
- helpText: 'We need to confirm the following information before we can process this payment.',
+ helpText: 'We need to confirm the following information before you can send and receive money from your Wallet.',
helpTextIdologyQuestions: 'We need to ask you just a few more questions to finish validating your identity.',
helpLink: 'Learn more about why we need this.',
legalFirstNameLabel: 'Legal first name',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 7e78e4b3f56a..493a209247b3 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1231,7 +1231,7 @@ export default {
},
additionalDetailsStep: {
headerTitle: 'Detalles adicionales',
- helpText: 'Necesitamos confirmar la siguiente información antes de que podamos procesar el pago.',
+ helpText: 'Necesitamos confirmar la siguiente información antes de que puedas enviar y recibir dinero desde tu Billetera.',
helpTextIdologyQuestions: 'Tenemos que preguntarte unas preguntas más para terminar de verificar tu identidad',
helpLink: 'Obtén más información sobre por qué necesitamos esto.',
legalFirstNameLabel: 'Primer nombre legal',
From 029b55d4f71e195a6eeecb802fb3e17e491a0ff5 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:21:44 +0200
Subject: [PATCH 05/23] feat: store source initiating kyc flow
---
src/CONST.ts | 6 ++++++
src/components/KYCWall/kycWallPropTypes.js | 3 +++
src/components/SettlementButton.js | 1 +
src/libs/actions/Wallet.js | 9 +++++----
src/pages/EnablePayments/ActivateStep.js | 1 +
5 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/src/CONST.ts b/src/CONST.ts
index 0a86aaf7648a..6c5c340de94e 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1058,6 +1058,12 @@ const CONST = {
},
},
+ KYC_WALL_SOURCE: {
+ REPORT: 'REPORT',
+ ENABLE_WALLET: 'ENABLE_WALLET',
+ TRANSFER_BALANCE: 'TRANSFER_BALANCE',
+ },
+
OS: {
WINDOWS: 'Windows',
MAC_OS: PLATFORM_OS_MACOS,
diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js
index 5080e5510241..7f591a7e019c 100644
--- a/src/components/KYCWall/kycWallPropTypes.js
+++ b/src/components/KYCWall/kycWallPropTypes.js
@@ -26,6 +26,9 @@ const propTypes = {
/** The user's wallet */
userWallet: userWalletPropTypes,
+ /** The source that triggered the KYC wall */
+ source: PropTypes.oneOf(_.values(CONST.KYC_WALL_SOURCE)).isRequired,
+
/** When the button is opened via an IOU, ID for the chatReport that the IOU is linked to */
chatReportID: PropTypes.string,
diff --git a/src/components/SettlementButton.js b/src/components/SettlementButton.js
index 043c27de9a48..8e376a7baedc 100644
--- a/src/components/SettlementButton.js
+++ b/src/components/SettlementButton.js
@@ -204,6 +204,7 @@ function SettlementButton({
addBankAccountRoute={addBankAccountRoute}
addDebitCardRoute={addDebitCardRoute}
isDisabled={isOffline}
+ source={CONST.KYC_WALL_SOURCE.REPORT}
chatReportID={chatReportID}
iouReport={iouReport}
anchorAlignment={anchorAlignment}
diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js
index 38ca49e4836a..183920eccf21 100644
--- a/src/libs/actions/Wallet.js
+++ b/src/libs/actions/Wallet.js
@@ -69,12 +69,13 @@ function setAdditionalDetailsErrorMessage(additionalErrorMessage) {
}
/**
- * Save the ID of the chat whose IOU triggered showing the KYC wall.
+ * Save the source that triggered the KYC wall and optionally the chat report ID associated with the IOU
*
+ * @param {String} source
* @param {String} chatReportID
*/
-function setKYCWallSourceChatReportID(chatReportID) {
- Onyx.merge(ONYXKEYS.WALLET_TERMS, {chatReportID});
+function setKYCWallSource(source, chatReportID = '') {
+ Onyx.merge(ONYXKEYS.WALLET_TERMS, {source, chatReportID});
}
/**
@@ -333,5 +334,5 @@ export {
updatePersonalDetails,
verifyIdentity,
acceptWalletTerms,
- setKYCWallSourceChatReportID,
+ setKYCWallSource,
};
diff --git a/src/pages/EnablePayments/ActivateStep.js b/src/pages/EnablePayments/ActivateStep.js
index 268c2664e01d..3e9f4dc2c989 100644
--- a/src/pages/EnablePayments/ActivateStep.js
+++ b/src/pages/EnablePayments/ActivateStep.js
@@ -24,6 +24,7 @@ const propTypes = {
const defaultProps = {
userWallet: {},
walletTerms: {
+ source: '',
chatReportID: 0,
},
};
From 1493c3200cdbf643bd1af3373fa9e344cc08dcaa Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:22:38 +0200
Subject: [PATCH 06/23] feat: update button text
---
src/pages/EnablePayments/ActivateStep.js | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/pages/EnablePayments/ActivateStep.js b/src/pages/EnablePayments/ActivateStep.js
index 3e9f4dc2c989..21e9e3771e44 100644
--- a/src/pages/EnablePayments/ActivateStep.js
+++ b/src/pages/EnablePayments/ActivateStep.js
@@ -32,7 +32,15 @@ const defaultProps = {
function ActivateStep(props) {
const isGoldWallet = props.userWallet.tierName === CONST.WALLET.TIER_NAME.GOLD;
const animation = isGoldWallet ? LottieAnimations.Fireworks : LottieAnimations.ReviewingBankInfo;
- const continueButtonText = props.walletTerms.chatReportID ? props.translate('activateStep.continueToPayment') : props.translate('activateStep.continueToTransfer');
+ let continueButtonText = '';
+
+ if (props.walletTerms.chatReportID) {
+ continueButtonText = props.translate('activateStep.continueToPayment');
+ } else if (props.walletTerms.source === CONST.KYC_WALL_SOURCE.ENABLE_WALLET) {
+ continueButtonText = props.translate('common.continue');
+ } else {
+ continueButtonText = props.translate('activateStep.continueToTransfer');
+ }
return (
<>
@@ -43,7 +51,7 @@ function ActivateStep(props) {
description={props.translate(`activateStep.${isGoldWallet ? 'activated' : 'checkBackLater'}Message`)}
shouldShowButton={isGoldWallet}
buttonText={continueButtonText}
- onButtonPress={PaymentMethods.continueSetup}
+ onButtonPress={() => PaymentMethods.continueSetup()}
/>
>
);
From d0744c489d2062719086d69ce9dc2ab6ebbaf788 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:26:10 +0200
Subject: [PATCH 07/23] feat: upgrade to gold wallet requires bank account
---
src/components/KYCWall/BaseKYCWall.js | 26 ++++++++++++++-----
src/components/KYCWall/kycWallPropTypes.js | 4 +++
src/libs/PaymentUtils.ts | 4 +--
.../settings/Wallet/WalletPage/WalletPage.js | 1 +
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js
index 315a48184498..d7ae8a336b63 100644
--- a/src/components/KYCWall/BaseKYCWall.js
+++ b/src/components/KYCWall/BaseKYCWall.js
@@ -23,6 +23,7 @@ class KYCWall extends React.Component {
this.continue = this.continue.bind(this);
this.setMenuPosition = this.setMenuPosition.bind(this);
+ this.selectPaymentMethod = this.selectPaymentMethod.bind(this);
this.anchorRef = React.createRef(null);
this.state = {
@@ -87,6 +88,18 @@ class KYCWall extends React.Component {
});
}
+ /**
+ * @param {String} paymentMethod
+ */
+ selectPaymentMethod(paymentMethod) {
+ this.props.onSelectPaymentMethod(paymentMethod);
+ if (paymentMethod === CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
+ Navigation.navigate(this.props.addBankAccountRoute);
+ } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) {
+ Navigation.navigate(this.props.addDebitCardRoute);
+ }
+ }
+
/**
* 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.
@@ -110,9 +123,13 @@ 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 (
(isExpenseReport && lodashGet(this.props.reimbursementAccount, 'achData.state', '') !== CONST.BANK_ACCOUNT.STATE.OPEN) ||
- (!isExpenseReport && !PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, this.props.bankAccountList))
+ (!isExpenseReport && !PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, this.props.bankAccountList, this.props.shouldIncludeDebitCard))
) {
Log.info('[KYC Wallet] User does not have valid payment method');
+ if (!this.props.shouldIncludeDebitCard) {
+ this.selectPaymentMethod(CONST.PAYMENT_METHODS.BANK_ACCOUNT);
+ return;
+ }
const clickedElementLocation = getClickedTargetLocation(targetElement);
const position = this.getAnchorPosition(clickedElementLocation);
this.setPositionAddPaymentMenu(position);
@@ -148,12 +165,7 @@ class KYCWall extends React.Component {
anchorAlignment={this.props.anchorAlignment}
onItemSelected={(item) => {
this.setState({shouldShowAddPaymentMenu: false});
- this.props.onSelectPaymentMethod(item);
- 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.selectPaymentMethod(item);
}}
/>
{this.props.children(this.continue, this.anchorRef)}
diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js
index 7f591a7e019c..ffe694a2dd84 100644
--- a/src/components/KYCWall/kycWallPropTypes.js
+++ b/src/components/KYCWall/kycWallPropTypes.js
@@ -53,6 +53,9 @@ const propTypes = {
vertical: PropTypes.oneOf(_.values(CONST.MODAL.ANCHOR_ORIGIN_VERTICAL)),
}),
+ /** Whether the option to add a debit card should be included */
+ shouldIncludeDebitCard: PropTypes.bool,
+
/** Callback for when a payment method has been selected */
onSelectPaymentMethod: PropTypes.func,
};
@@ -72,6 +75,7 @@ const defaultProps = {
horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT,
vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM,
},
+ shouldIncludeDebitCard: true,
onSelectPaymentMethod: () => {},
};
diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts
index 64260569639e..5c7e96b01d91 100644
--- a/src/libs/PaymentUtils.ts
+++ b/src/libs/PaymentUtils.ts
@@ -17,7 +17,7 @@ type PaymentMethod = (BankAccount | Fund) & {
/**
* Check to see if user has either a debit card or personal bank account added
*/
-function hasExpensifyPaymentMethod(fundList: Record, bankAccountList: Record): boolean {
+function hasExpensifyPaymentMethod(fundList: Record, bankAccountList: Record, shouldIncludeDebitCard = true): boolean {
const validBankAccount = Object.values(bankAccountList).some((bankAccountJSON) => {
const bankAccount = new BankAccountModel(bankAccountJSON);
return bankAccount.isDefaultCredit();
@@ -26,7 +26,7 @@ function hasExpensifyPaymentMethod(fundList: Record, bankAccountLi
// Hide any billing cards that are not P2P debit cards for now because you cannot make them your default method, or delete them
const validDebitCard = Object.values(fundList).some((card) => card?.accountData?.additionalData?.isP2PDebitCard ?? false);
- return validBankAccount || validDebitCard;
+ return validBankAccount || (shouldIncludeDebitCard && validDebitCard);
}
function getPaymentMethodDescription(accountType: AccountType, account: BankAccount['accountData'] | Fund['accountData']): string {
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index c69fa27294f9..f1799294fe55 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -365,6 +365,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
addBankAccountRoute={ROUTES.SETTINGS_ADD_BANK_ACCOUNT}
addDebitCardRoute={ROUTES.SETTINGS_ADD_DEBIT_CARD}
popoverPlacement="bottom"
+ shouldIncludeDebitCard={!hasSilverWallet}
>
{(triggerKYCFlow, buttonRef) =>
hasSilverWallet ? (
From 924f3f588900964c3baaa263d599cb3fac81b61b Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 19:28:39 +0200
Subject: [PATCH 08/23] fix: navigate to wallet upon upgrading
---
src/components/KYCWall/BaseKYCWall.js | 14 ++++++++++++--
src/components/KYCWall/kycWallPropTypes.js | 5 +++++
src/pages/EnablePayments/walletTermsPropTypes.js | 5 +++++
src/pages/settings/Wallet/WalletPage/WalletPage.js | 12 +++++++++---
4 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js
index d7ae8a336b63..19fc65d62cb7 100644
--- a/src/components/KYCWall/BaseKYCWall.js
+++ b/src/components/KYCWall/BaseKYCWall.js
@@ -39,7 +39,6 @@ class KYCWall extends React.Component {
if (this.props.shouldListenForResize) {
this.dimensionsSubscription = Dimensions.addEventListener('change', this.setMenuPosition);
}
- Wallet.setKYCWallSourceChatReportID(this.props.chatReportID);
}
componentWillUnmount() {
@@ -109,6 +108,14 @@ class KYCWall extends React.Component {
* @param {String} iouPaymentType
*/
continue(event, iouPaymentType) {
+ const currentSource = lodashGet(this.props.walletTerms, 'source', this.props.source);
+
+ /**
+ * Set the source, so we can tailor the process according to how we got here.
+ * We do not want to set this on mount, as the source can change upon completing the flow, e.g. when upgrading the wallet to Gold.
+ */
+ Wallet.setKYCWallSource(this.props.source, this.props.chatReportID);
+
if (this.state.shouldShowAddPaymentMenu) {
this.setState({shouldShowAddPaymentMenu: false});
return;
@@ -148,7 +155,7 @@ class KYCWall extends React.Component {
}
}
Log.info('[KYC Wallet] User has valid payment method and passed KYC checks or did not need them');
- this.props.onSuccessfulKYC(iouPaymentType);
+ this.props.onSuccessfulKYC(iouPaymentType, currentSource);
}
render() {
@@ -181,6 +188,9 @@ export default withOnyx({
userWallet: {
key: ONYXKEYS.USER_WALLET,
},
+ walletTerms: {
+ key: ONYXKEYS.WALLET_TERMS,
+ },
fundList: {
key: ONYXKEYS.FUND_LIST,
},
diff --git a/src/components/KYCWall/kycWallPropTypes.js b/src/components/KYCWall/kycWallPropTypes.js
index ffe694a2dd84..7f241f8e1742 100644
--- a/src/components/KYCWall/kycWallPropTypes.js
+++ b/src/components/KYCWall/kycWallPropTypes.js
@@ -5,6 +5,7 @@ import bankAccountPropTypes from '../bankAccountPropTypes';
import cardPropTypes from '../cardPropTypes';
import iouReportPropTypes from '../../pages/iouReportPropTypes';
import reimbursementAccountPropTypes from '../../pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes';
+import walletTermsPropTypes from '../../pages/EnablePayments/walletTermsPropTypes';
import CONST from '../../CONST';
const propTypes = {
@@ -26,6 +27,9 @@ const propTypes = {
/** The user's wallet */
userWallet: userWalletPropTypes,
+ /** Information related to the wallet activation flow */
+ walletTerms: walletTermsPropTypes,
+
/** The source that triggered the KYC wall */
source: PropTypes.oneOf(_.values(CONST.KYC_WALL_SOURCE)).isRequired,
@@ -62,6 +66,7 @@ const propTypes = {
const defaultProps = {
userWallet: {},
+ walletTerms: {},
shouldListenForResize: false,
isDisabled: false,
chatReportID: '',
diff --git a/src/pages/EnablePayments/walletTermsPropTypes.js b/src/pages/EnablePayments/walletTermsPropTypes.js
index c5f19cd3a9f2..c3d1482f946d 100644
--- a/src/pages/EnablePayments/walletTermsPropTypes.js
+++ b/src/pages/EnablePayments/walletTermsPropTypes.js
@@ -1,10 +1,15 @@
import PropTypes from 'prop-types';
+import _ from 'underscore';
+import CONST from '../../CONST';
/** Prop types related to the Terms step of KYC flow */
export default PropTypes.shape({
/** Any error message to show */
errors: PropTypes.objectOf(PropTypes.string),
+ /** The source that triggered the KYC wall */
+ source: PropTypes.oneOf(_.values(CONST.KYC_WALL_SOURCE)).isRequired,
+
/** When the user accepts the Wallet's terms in order to pay an IOU, this is the ID of the chatReport the IOU is linked to */
chatReportID: PropTypes.string,
});
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index f1799294fe55..971f6f1bcf3c 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -242,8 +242,13 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
}
}, [paymentMethod.selectedPaymentMethod.bankAccountID, paymentMethod.selectedPaymentMethod.fundID, paymentMethod.selectedPaymentMethodType]);
- const navigateToTransferBalancePage = () => {
- Navigation.navigate(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE);
+ /**
+ * Navigate to the appropriate page after completing the KYC flow, depending on what initiated it
+ *
+ * @param {String} source
+ */
+ const navigateToWalletOrTransferBalancePage = (source) => {
+ Navigation.navigate(source === CONST.KYC_WALL_SOURCE.ENABLE_WALLET ? ROUTES.SETTINGS_WALLET : ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE);
};
useEffect(() => {
@@ -353,7 +358,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
)}
navigateToWalletOrTransferBalancePage(source)}
onSelectPaymentMethod={(selectedPaymentMethod) => {
if (!hasSilverWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
return;
@@ -365,6 +370,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
addBankAccountRoute={ROUTES.SETTINGS_ADD_BANK_ACCOUNT}
addDebitCardRoute={ROUTES.SETTINGS_ADD_DEBIT_CARD}
popoverPlacement="bottom"
+ source={hasSilverWallet ? CONST.KYC_WALL_SOURCE.ENABLE_WALLET : CONST.KYC_WALL_SOURCE.TRANSFER_BALANCE}
shouldIncludeDebitCard={!hasSilverWallet}
>
{(triggerKYCFlow, buttonRef) =>
From acfef2ad39cdc7b7191eeb95344c17adc3a1cace Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 20:23:08 +0200
Subject: [PATCH 09/23] fix: updated ts type
---
src/libs/actions/BankAccounts.ts | 2 +-
src/types/onyx/PersonalBankAccount.ts | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts
index ab6dfdc304bb..a1c1ea65b2e8 100644
--- a/src/libs/actions/BankAccounts.ts
+++ b/src/libs/actions/BankAccounts.ts
@@ -58,7 +58,7 @@ function openPersonalBankAccountSetupView(exitReportID: string) {
/**
* @param {Boolean} shouldContinueKYCOnSuccess Whether after adding a bank account we should continue with the KYC flow
*/
-function setPersonalBankAccountContinueKYCOnSuccess(shouldContinueKYCOnSuccess) {
+function setPersonalBankAccountContinueKYCOnSuccess(shouldContinueKYCOnSuccess: boolean) {
Onyx.merge(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {shouldContinueKYCOnSuccess});
}
diff --git a/src/types/onyx/PersonalBankAccount.ts b/src/types/onyx/PersonalBankAccount.ts
index ea993d7393e8..23b7fbcd0cd9 100644
--- a/src/types/onyx/PersonalBankAccount.ts
+++ b/src/types/onyx/PersonalBankAccount.ts
@@ -15,6 +15,9 @@ type PersonalBankAccount = {
/** Any reportID we should redirect to at the end of the flow */
exitReportID?: string;
+
+ /** Whether after adding a bank account we should continue with the KYC flow */
+ shouldContinueKYCOnSuccess?: boolean;
};
export default PersonalBankAccount;
From 2617784422fd8728c7ec0e212baf9abf88185075 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Mon, 16 Oct 2023 20:32:33 +0200
Subject: [PATCH 10/23] fix: satisfy linter
---
src/libs/actions/BankAccounts.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts
index a1c1ea65b2e8..6dbf2e09716d 100644
--- a/src/libs/actions/BankAccounts.ts
+++ b/src/libs/actions/BankAccounts.ts
@@ -56,7 +56,7 @@ function openPersonalBankAccountSetupView(exitReportID: string) {
}
/**
- * @param {Boolean} shouldContinueKYCOnSuccess Whether after adding a bank account we should continue with the KYC flow
+ * Whether after adding a bank account we should continue with the KYC flow
*/
function setPersonalBankAccountContinueKYCOnSuccess(shouldContinueKYCOnSuccess: boolean) {
Onyx.merge(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {shouldContinueKYCOnSuccess});
From 25bd8aeb757acf625b089c08a5b509d905b954b4 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Tue, 17 Oct 2023 10:40:20 +0200
Subject: [PATCH 11/23] refactor: consistent wallet activation check
---
.../settings/Wallet/WalletPage/WalletPage.js | 32 +++++++++----------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.js b/src/pages/settings/Wallet/WalletPage/WalletPage.js
index 971f6f1bcf3c..db4a6d56f585 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.js
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.js
@@ -62,7 +62,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
const hasBankAccount = !_.isEmpty(bankAccountList) || !_.isEmpty(fundList);
const hasWallet = userWallet.walletLinkedAccountID > 0;
- const hasSilverWallet = userWallet.tierName === CONST.WALLET.TIER_NAME.SILVER;
+ const hasActivatedWallet = _.contains([CONST.WALLET.TIER_NAME.GOLD, CONST.WALLET.TIER_NAME.PLATINUM], userWallet.tierName);
const hasAssignedCard = !_.isEmpty(cardList);
const shouldShowEmptyState = !hasBankAccount && !hasWallet && !hasAssignedCard;
@@ -336,7 +336,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
{hasWallet && (
<>
@@ -360,7 +360,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
navigateToWalletOrTransferBalancePage(source)}
onSelectPaymentMethod={(selectedPaymentMethod) => {
- if (!hasSilverWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
+ if (hasActivatedWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.BANK_ACCOUNT) {
return;
}
// To allow upgrading to a gold wallet, continue with the KYC flow after adding a bank account
@@ -370,21 +370,11 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
addBankAccountRoute={ROUTES.SETTINGS_ADD_BANK_ACCOUNT}
addDebitCardRoute={ROUTES.SETTINGS_ADD_DEBIT_CARD}
popoverPlacement="bottom"
- source={hasSilverWallet ? CONST.KYC_WALL_SOURCE.ENABLE_WALLET : CONST.KYC_WALL_SOURCE.TRANSFER_BALANCE}
- shouldIncludeDebitCard={!hasSilverWallet}
+ source={hasActivatedWallet ? CONST.KYC_WALL_SOURCE.TRANSFER_BALANCE : CONST.KYC_WALL_SOURCE.ENABLE_WALLET}
+ shouldIncludeDebitCard={hasActivatedWallet}
>
{(triggerKYCFlow, buttonRef) =>
- hasSilverWallet ? (
-
- ) : (
+ hasActivatedWallet ? (
+ ) : (
+
)
}
From 9037c852f2990d0f24c853ae511e4f635b76eef9 Mon Sep 17 00:00:00 2001
From: Sam Hariri <137707942+samh-nl@users.noreply.github.com>
Date: Tue, 17 Oct 2023 15:25:39 +0200
Subject: [PATCH 12/23] fix: rely on continue button press
---
src/pages/AddPersonalBankAccountPage.js | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/pages/AddPersonalBankAccountPage.js b/src/pages/AddPersonalBankAccountPage.js
index ce0e52e607d9..d60bfe170ea2 100644
--- a/src/pages/AddPersonalBankAccountPage.js
+++ b/src/pages/AddPersonalBankAccountPage.js
@@ -91,14 +91,13 @@ class AddPersonalBankAccountPage extends React.Component {
BankAccounts.addPersonalBankAccount(selectedPlaidBankAccount);
}
- exitFlow() {
+ exitFlow(hasPressedContinue = false) {
const exitReportID = lodashGet(this.props, 'personalBankAccount.exitReportID');
const shouldContinueKYCOnSuccess = lodashGet(this.props, 'personalBankAccount.shouldContinueKYCOnSuccess', false);
- const shouldShowSuccess = lodashGet(this.props, 'personalBankAccount.shouldShowSuccess', false);
if (exitReportID) {
Navigation.dismissModal(exitReportID);
- } else if (shouldShowSuccess && shouldContinueKYCOnSuccess) {
+ } else if (hasPressedContinue && shouldContinueKYCOnSuccess) {
PaymentMethods.continueSetup(ROUTES.SETTINGS_WALLET);
} else {
Navigation.goBack(ROUTES.SETTINGS_WALLET);
@@ -125,7 +124,7 @@ class AddPersonalBankAccountPage extends React.Component {
description={this.props.translate('addPersonalBankAccountPage.successMessage')}
shouldShowButton
buttonText={this.props.translate('common.continue')}
- onButtonPress={this.exitFlow}
+ onButtonPress={() => this.exitFlow(true)}
/>
) : (