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

Refactor Terms step of Wallet_Activate into AcceptWalletTerms #10443

Merged
merged 12 commits into from
Aug 23, 2022

Conversation

francoisl
Copy link
Contributor

@francoisl francoisl commented Aug 18, 2022

cc @MariaHCD

Hold until https://github.com/Expensify/Web-Expensify/pull/34588 is at least on staging.

Details

  1. Use the new API command AcceptWalletTerms when the user accepts the terms of the Expensify Wallet, instead of using the deprecated Wallet_Activate command
  2. Revamp the ActivateStep component to be prettier when the user finishes setting up a Gold wallet.

This PR does not implement the Red Brick Road for KYC errors. This will come in follow-up PRs.

Fixed Issues

Part of https://github.com/Expensify/Expensify/issues/218502

Tests

Pre-requisites:

  1. Have an account with a pending wallet (all new accounts have a pending wallet created automatically)
  2. Find the wallet's bankAccountID of that account in auth, and then run (replace the bankAccountID at the end):
UPDATE bankAccounts SET additionalData = JSON_SET(COALESCE(NULLIF(additionalData, ''), '{}'), '$.currentStep', 'TermsStep') WHERE bankAccountID = XXX;

Tests

  1. Navigate to /enable-payments
  2. You'll see the "Terms and fees" page.

image

3. Scroll down to the bottom, and make sure you can't click the "Enable Payments" button without checking both buttons

image

  1. Check both checkboxes, click the Enable Payments button

  2. Since the wallet technically doesn't pass all identity checks at that point, it will be a Silver wallet, and you should see a "We're still reviewing your information. Please check back later." message

imageimage

  1. Run the flow again but for a Gold wallet. Start by resetting and configuring the wallet as follows:

    1. Run the validator:wallet CLI Tool on the account
    2. In auth, run: UPDATE bankAccounts SET additionalData = JSON_SET(COALESCE(NULLIF(additionalData, ''), '{}'), '$.currentStep', 'TermsStep') WHERE bankAccountID = <walletID>;
    3. In NewDot, run the following in the console: Onyx.merge('userWallet', {shouldShowWalletActivationSuccess:null})
  2. Navigate to /enable-payments again. Check both boxes at the bottom, and click the button

  3. Make sure you see the following Tada page

Screen Shot 2022-08-22 at 1 00 54 PM

  • Verify that no errors appear in the JS console

PR Review Checklist

Contributor (PR Author) Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

PR Reviewer Checklist

The Contributor+ will copy/paste it into a new comment and complete it after the author checklist is completed

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by tagging the marketing team on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • Any functional components have the displayName property
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

QA Steps

  • Verify that no errors appear in the JS console

Screenshots

Web

Mobile Web

Desktop

iOS

Android

@francoisl francoisl requested a review from MariaHCD August 18, 2022 04:14
@francoisl francoisl self-assigned this Aug 18, 2022
@francoisl francoisl requested a review from a team as a code owner August 18, 2022 04:14
@francoisl francoisl changed the title Refactor Terms step of Wallet_Activate into AcceptWalletTerms [HOLD Web-E #34588] Refactor Terms step of Wallet_Activate into AcceptWalletTerms Aug 18, 2022
@melvin-bot melvin-bot bot requested review from Justicea83 and removed request for a team August 18, 2022 04:14
Comment on lines 40 to 61
<View style={[styles.pageWrapper, styles.flex1, styles.flexColumn, styles.alignItemsCenter, styles.justifyContentCenter]}>
<Icon
src={Illustrations.TadaBlue}
height={100}
width={100}
fill={defaultTheme.iconSuccessFill}
/>
<View style={[styles.ph5]}>
<Text style={[styles.mt5, styles.h1, styles.textAlignCenter]}>
{this.props.translate('activateStep.activated')}
</Text>
</View>
</View>
<FixedFooter>
<Button
text={this.props.translate('common.continue')}
onPress={PaymentMethods.continueSetup}
style={[styles.mt4]}
iconStyles={[styles.mr5]}
success
/>
</FixedFooter>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +77 to +79
{this.props.userWallet.tierName === CONST.WALLET.TIER_NAME.SILVER && (
<Text>{this.props.translate('activateStep.checkBackLater')}</Text>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue for a mockup for the Check back later screen here: https://github.com/Expensify/Expensify/issues/223443

Doesn't have to be part of this PR, can be a follow up improvement.

onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.USER_WALLET,
value: {
shouldShowWalletActivationSuccess: null,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to null instead of false so it gets removed, I figured it's no longer needed at that point.

Comment on lines 697 to 698
activatedTitle: 'Billetera Expensify lista!',
activatedMessage: 'Enhorabuena, tu billetera Expensify está lista para usar.',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting confirmation for these here.

Copy link
Contributor

@MariaHCD MariaHCD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I think we just need those translations and then we should be good to go!

src/libs/actions/Wallet.js Show resolved Hide resolved
@francoisl francoisl changed the title [HOLD Web-E #34588] Refactor Terms step of Wallet_Activate into AcceptWalletTerms Refactor Terms step of Wallet_Activate into AcceptWalletTerms Aug 19, 2022
@francoisl
Copy link
Contributor Author

Updated and removed the hold.

One thing I'm not sure about is that I get an error in the JS console that seems to point to something unrelated, but it's also happening on main.

Warning: Failed prop type: Invalid prop `userWallet.availableBalance` of type `number` supplied to `AvatarWithIndicator`, expected `object`.
    at AvatarWithIndicator (webpack-internal:///./src/components/AvatarWithIndicator.js:69:23)

it points to the availableBalance prop in userWalletPropTypes, which is already defined as a number and is not required..? We can probably ignore for this PR but just checking.

@francoisl francoisl changed the title Refactor Terms step of Wallet_Activate into AcceptWalletTerms [HOLD] Refactor Terms step of Wallet_Activate into AcceptWalletTerms Aug 19, 2022
@francoisl
Copy link
Contributor Author

Fixed the conflicts with your other PR we just merged, and also I'm putting this back on hold until https://github.com/Expensify/Web-Expensify/pull/34588 is on staging.

@@ -19,4 +19,7 @@ export default PropTypes.shape({

/** Status of wallet - e.g. SILVER or GOLD */
tierName: PropTypes.string,

/** Whether we should show the ActivateStep view success view after the user finished the KYC flow */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Whether we should show the ActivateStep view success view after the user finished the KYC flow */
/** Whether we should show the ActivateStep success view after the user finished the KYC flow */

<Text style={[styles.formError, styles.mb2]}>
{_.last(_.values(errors))}
</Text>
)}
<Button
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's replace the Button component with the FormAlertWithSubmitButton. It's more consistent with all other forms and we can get rid of these lines

const bool isButtonDisabled = !this.state.hasAcceptedDisclosure || !this.state.hasAcceptedPrivacyPolicyAndWalletAgreement;
...
<FormAlertWithSubmitButton
    buttonText={this.props.translate('termsStep.enablePayments')}
    onSubmit={() => {
        if (!this.state.hasAcceptedDisclosure
            || !this.state.hasAcceptedPrivacyPolicyAndWalletAgreement) {
            this.setState({error: true});
            return;
        }

        this.setState({error: false});
        BankAccounts.acceptWalletTerms({
            hasAcceptedTerms: this.state.hasAcceptedDisclosure
                && this.state.hasAcceptedPrivacyPolicyAndWalletAgreement,
        });
    }}
    isDisabled={isButtonDisabled || this.props.network.isOffline}
     message={this.state.error ? this.props.translate('common.error.acceptedTerms') : !_.isEmpty(errors) ? _.last(_.values(errors)) : ''}
    isAlertVisible={this.state.error || !_.isEmpty(errors)}
/>

Screen Shot 2022-08-22 at 1 46 47 PM

<FixedFooter>
<Button
text={this.props.translate('common.continue')}
onPress={PaymentMethods.continueSetup}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested but just wanted to confirm if clicking this will lead the user back to the action they were previously taking i.e. paying via the wallet or transferring their wallet balance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a huge pain to test on dev for some reason, but yes. It calls this function, which at the bottom ends up calling the onSuccessfulKYC() prop method.

Screen.Recording.2022-08-22.at.3.38.56.PM.mov

</View>
<FixedFooter>
<Button
text={this.props.translate('common.continue')}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal but we can probably adjust this now or in a follow up PR.

The green success button will either state “Continue to payment” or “Continue to transfer” based on the action that we will be returning the user to.

https://docs.google.com/document/d/1PYqKcBpjPxewL5OneCmqbMJNH8G3CNkqbJWqzHSaXhU/edit#bookmark=id.8y4wjrbvjh9z

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah at the moment I don't see how we would do that so I don't mind if we do this in a follow-up PR.

@MariaHCD
Copy link
Contributor

One thing I'm not sure about is that I get an error in the JS console that seems to point to something unrelated, but it's also happening on main.

Yeah, I see this is happening for the EnablePaymentsPage and AvatarWithIndicator but I have no idea why 🤔 I think it was probably introduced here when I updated userWalletPropTypes and is unrelated to this PR so I think its okay if we ignore it for now. I will try to investigate a bit more.

react.development.js?72d0:209 Warning: Failed prop type: Invalid prop `userWallet.availableBalance` of type `number` supplied to `EnablePaymentsPage`, expected `object`.
Warning: Failed prop type: Invalid prop `userWallet.availableBalance` of type `number` supplied to `AvatarWithIndicator`, expected `object`.

Copy link
Contributor

@MariaHCD MariaHCD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor change but otherwise looks good to me!

src/pages/EnablePayments/ActivateStep.js Outdated Show resolved Hide resolved
Co-authored-by: Maria D'Costa <maria@expensify.com>
@francoisl
Copy link
Contributor Author

Updated, thanks for the reviews!

Copy link
Contributor

@MariaHCD MariaHCD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@francoisl francoisl changed the title [HOLD] Refactor Terms step of Wallet_Activate into AcceptWalletTerms Refactor Terms step of Wallet_Activate into AcceptWalletTerms Aug 23, 2022
@francoisl
Copy link
Contributor Author

Removed the Hold on this. I don't know if @Justicea83 you want to review? Otherwise Maria feel free to merge!

Copy link
Contributor

@Justicea83 Justicea83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM!

@Justicea83 Justicea83 merged commit e7503a0 into main Aug 23, 2022
@Justicea83 Justicea83 deleted the francois-refactorAcceptWalletTerms branch August 23, 2022 13:52
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by @Justicea83 in version: 1.1.89-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants