Skip to content

Commit

Permalink
Merge pull request #15394 from Expensify/aldo_fix-disconnect-workspac…
Browse files Browse the repository at this point in the history
…e-bankaccount

Handle error in workspace's bank account page
  • Loading branch information
jasperhuangg authored Apr 20, 2023
2 parents 5cd0ab3 + 270dc00 commit e0c4211
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 143 deletions.
9 changes: 9 additions & 0 deletions src/components/AvatarWithIndicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {policyPropTypes} from '../pages/workspace/withPolicy';
import walletTermsPropTypes from '../pages/EnablePayments/walletTermsPropTypes';
import * as PolicyUtils from '../libs/PolicyUtils';
import * as PaymentMethods from '../libs/actions/PaymentMethods';
import * as ReimbursementAccountProps from '../pages/ReimbursementAccount/reimbursementAccountPropTypes';
import * as ReportUtils from '../libs/ReportUtils';
import * as UserUtils from '../libs/UserUtils';
import themeColors from '../styles/themes/default';
Expand Down Expand Up @@ -43,6 +44,9 @@ const propTypes = {
/** The user's wallet (coming from Onyx) */
userWallet: userWalletPropTypes,

/** Bank account attached to free plan */
reimbursementAccount: ReimbursementAccountProps.reimbursementAccountPropTypes,

/** Information about the user accepting the terms for payments */
walletTerms: walletTermsPropTypes,

Expand All @@ -58,6 +62,7 @@ const propTypes = {

const defaultProps = {
tooltipText: '',
reimbursementAccount: {},
policiesMemberList: {},
policies: {},
bankAccountList: {},
Expand All @@ -82,6 +87,7 @@ const AvatarWithIndicator = (props) => {
() => _.some(cleanPolicies, PolicyUtils.hasPolicyError),
() => _.some(cleanPolicies, PolicyUtils.hasCustomUnitsError),
() => _.some(cleanPolicyMembers, PolicyUtils.hasPolicyMemberError),
() => !_.isEmpty(props.reimbursementAccount.errors),
() => UserUtils.hasLoginListError(props.loginList),

// Wallet term errors that are not caused by an IOU (we show the red brick indicator for those in the LHN instead)
Expand Down Expand Up @@ -126,6 +132,9 @@ export default withOnyx({
bankAccountList: {
key: ONYXKEYS.BANK_ACCOUNT_LIST,
},
reimbursementAccount: {
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
},
cardList: {
key: ONYXKEYS.CARD_LIST,
},
Expand Down
3 changes: 1 addition & 2 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import _ from 'underscore';
import React from 'react';
import {createStackNavigator, CardStyleInterpolators} from '@react-navigation/stack';
import styles from '../../../styles/styles';
import CONST from '../../../CONST';

const defaultSubRouteOptions = {
cardStyle: styles.navigationScreenCardStyle,
Expand Down Expand Up @@ -490,7 +489,7 @@ const SettingsModalStackNavigator = createModalStackNavigator([
return ReimbursementAccountPage;
},
name: 'ReimbursementAccount',
initialParams: {stepToOpen: CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT},
initialParams: {stepToOpen: ''},
},
{
getComponent: () => {
Expand Down
1 change: 0 additions & 1 deletion src/libs/actions/BankAccounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ function openReimbursementAccountPage(stepToOpen, subStep, localCurrentStep) {
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {
errors: null,
isLoading: true,
},
},
Expand Down
5 changes: 4 additions & 1 deletion src/libs/actions/ReimbursementAccount/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ function setBankAccountFormValidationErrors(errorFields) {
*/
function resetReimbursementAccount() {
setBankAccountFormValidationErrors({});
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {errors: null});
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {
errors: null,
pendingAction: null,
});
}

/**
Expand Down
25 changes: 12 additions & 13 deletions src/libs/actions/ReimbursementAccount/resetFreePlanBankAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ function resetFreePlanBankAccount(bankAccountID) {
},
{
optimisticData: [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {
shouldShowResetModal: false,
isLoading: true,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
},
},
],
successData: [
{
onyxMethod: CONST.ONYX.METHOD.SET,
key: ONYXKEYS.ONFIDO_TOKEN,
Expand All @@ -44,29 +55,17 @@ function resetFreePlanBankAccount(bankAccountID) {
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: ReimbursementAccountProps.reimbursementAccountDefaultProps,
},
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {isLoading: true},
},
{
onyxMethod: CONST.ONYX.METHOD.SET,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT,
value: {},
},
],
successData: [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {isLoading: false},
},
],
failureData: [
{
onyxMethod: CONST.ONYX.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {isLoading: false},
value: {isLoading: false, pendingAction: null},
},
],
});
Expand Down
113 changes: 62 additions & 51 deletions src/pages/ReimbursementAccount/ContinueBankAccountSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import {ScrollView} from 'react-native';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import * as Expensicons from '../../components/Icon/Expensicons';
import * as Illustrations from '../../components/Icon/Illustrations';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
Expand All @@ -20,6 +21,7 @@ import withPolicy from '../workspace/withPolicy';
import * as ReimbursementAccountProps from './reimbursementAccountPropTypes';
import WorkspaceResetBankAccountModal from '../workspace/WorkspaceResetBankAccountModal';
import * as BankAccounts from '../../libs/actions/BankAccounts';
import OfflineWithFeedback from '../../components/OfflineWithFeedback';

const propTypes = {
/** Bank account currently in setup */
Expand All @@ -28,9 +30,6 @@ const propTypes = {
/** Callback to continue to the next step of the setup */
continue: PropTypes.func.isRequired,

/** Callback to reset the bank account */
startOver: PropTypes.func.isRequired,

/** Policy values needed in the component */
policy: PropTypes.shape({
name: PropTypes.string,
Expand All @@ -44,55 +43,67 @@ const propTypes = {

const defaultProps = {policyName: ''};

const ContinueBankAccountSetup = props => (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
<FullPageNotFoundView shouldShow={_.isEmpty(props.policy)}>
<HeaderWithCloseButton
title={props.translate('workspace.common.bankAccount')}
subtitle={props.policyName}
onCloseButtonPress={Navigation.dismissModal}
onBackButtonPress={Navigation.goBack}
shouldShowGetAssistanceButton
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT}
shouldShowBackButton
/>
<ScrollView style={styles.flex1}>
<Section
title={props.translate('workspace.bankAccount.almostDone')}
icon={Illustrations.BankArrow}
>
<Text>
{props.translate('workspace.bankAccount.youreAlmostDone')}
</Text>
<Button
text={props.translate('workspace.bankAccount.continueWithSetup')}
onPress={props.continue}
icon={Expensicons.Bank}
style={[styles.mv4]}
iconStyles={[styles.buttonCTAIcon]}
shouldShowRightIcon
large
success
/>
<MenuItem
title={props.translate('workspace.bankAccount.startOver')}
icon={Expensicons.RotateLeft}
onPress={() => BankAccounts.requestResetFreePlanBankAccount()}
shouldShowRightIcon
wrapperStyle={[styles.cardMenuItem]}
/>
</Section>
</ScrollView>
</FullPageNotFoundView>
const ContinueBankAccountSetup = (props) => {
const errors = lodashGet(props.reimbursementAccount, 'errors', {});
const pendingAction = lodashGet(props.reimbursementAccount, 'pendingAction', null);
return (
<ScreenWrapper includeSafeAreaPaddingBottom={false}>
<FullPageNotFoundView shouldShow={_.isEmpty(props.policy)}>
<HeaderWithCloseButton
title={props.translate('workspace.common.bankAccount')}
subtitle={props.policyName}
onCloseButtonPress={Navigation.dismissModal}
onBackButtonPress={Navigation.goBack}
shouldShowGetAssistanceButton
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT}
shouldShowBackButton
/>
<ScrollView style={styles.flex1}>
<Section
title={props.translate('workspace.bankAccount.almostDone')}
icon={Illustrations.BankArrow}
>
<OfflineWithFeedback
pendingAction={pendingAction}
errors={errors}
shouldShowErrorMessage
onClose={BankAccounts.resetReimbursementAccount}
>
<Text>
{props.translate('workspace.bankAccount.youreAlmostDone')}
</Text>
<Button
text={props.translate('workspace.bankAccount.continueWithSetup')}
onPress={props.continue}
icon={Expensicons.Bank}
style={[styles.mv4]}
iconStyles={[styles.buttonCTAIcon]}
shouldShowRightIcon
large
success
isDisabled={Boolean(pendingAction) || !_.isEmpty(errors)}
/>
<MenuItem
title={props.translate('workspace.bankAccount.startOver')}
icon={Expensicons.RotateLeft}
onPress={() => BankAccounts.requestResetFreePlanBankAccount()}
shouldShowRightIcon
wrapperStyle={[styles.cardMenuItem]}
disabled={Boolean(pendingAction) || !_.isEmpty(errors)}
/>
</OfflineWithFeedback>
</Section>
</ScrollView>
</FullPageNotFoundView>

{props.reimbursementAccount.shouldShowResetModal && (
<WorkspaceResetBankAccountModal
reimbursementAccount={props.reimbursementAccount}
onConfirm={props.startOver}
/>
)}
</ScreenWrapper>
);
{props.reimbursementAccount.shouldShowResetModal && (
<WorkspaceResetBankAccountModal
reimbursementAccount={props.reimbursementAccount}
/>
)}
</ScreenWrapper>
);
};

ContinueBankAccountSetup.propTypes = propTypes;
ContinueBankAccountSetup.defaultProps = defaultProps;
Expand Down
83 changes: 48 additions & 35 deletions src/pages/ReimbursementAccount/EnableStep.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import _ from 'underscore';
import {ScrollView} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import PropTypes from 'prop-types';
Expand All @@ -14,6 +15,7 @@ import CONST from '../../CONST';
import Button from '../../components/Button';
import * as Expensicons from '../../components/Icon/Expensicons';
import MenuItem from '../../components/MenuItem';
import OfflineWithFeedback from '../../components/OfflineWithFeedback';
import getBankIcon from '../../components/Icon/BankIcons';
import * as ReimbursementAccountProps from './reimbursementAccountPropTypes';
import userPropTypes from '../settings/userPropTypes';
Expand Down Expand Up @@ -54,6 +56,8 @@ const EnableStep = (props) => {
: '';
const bankName = achData.addressName;

const errors = lodashGet(props.reimbursementAccount, 'errors', {});
const pendingAction = lodashGet(props.reimbursementAccount, 'pendingAction', null);
return (
<ScreenWrapper style={[styles.flex1, styles.justifyContentBetween]} includeSafeAreaPaddingBottom={false}>
<HeaderWithCloseButton
Expand All @@ -70,42 +74,51 @@ const EnableStep = (props) => {
title={!isUsingExpensifyCard ? props.translate('workspace.bankAccount.oneMoreThing') : props.translate('workspace.bankAccount.allSet')}
icon={!isUsingExpensifyCard ? Illustrations.ConciergeNew : Illustrations.ThumbsUpStars}
>
<MenuItem
title={bankName}
description={formattedBankAccountNumber}
icon={icon}
iconWidth={iconSize}
iconHeight={iconSize}
disabled
interactive={false}
wrapperStyle={[styles.cardMenuItem, styles.mv3]}
/>
<Text style={[styles.mv3]}>
{!isUsingExpensifyCard
? props.translate('workspace.bankAccount.accountDescriptionNoCards')
: props.translate('workspace.bankAccount.accountDescriptionWithCards')}
</Text>
{!isUsingExpensifyCard && (
<Button
text={props.translate('workspace.bankAccount.addWorkEmail')}
onPress={() => {
Link.openOldDotLink(CONST.ADD_SECONDARY_LOGIN_URL);
User.subscribeToExpensifyCardUpdates();
}}
icon={Expensicons.Mail}
style={[styles.mt4]}
iconStyles={[styles.buttonCTAIcon]}
shouldShowRightIcon
large
success

<OfflineWithFeedback
pendingAction={pendingAction}
errors={errors}
shouldShowErrorMessage
onClose={BankAccounts.resetReimbursementAccount}
>
<MenuItem
title={bankName}
description={formattedBankAccountNumber}
icon={icon}
iconWidth={iconSize}
iconHeight={iconSize}
disabled
interactive={false}
wrapperStyle={[styles.cardMenuItem, styles.mv3]}
/>
<Text style={[styles.mv3]}>
{!isUsingExpensifyCard
? props.translate('workspace.bankAccount.accountDescriptionNoCards')
: props.translate('workspace.bankAccount.accountDescriptionWithCards')}
</Text>
{!isUsingExpensifyCard && (
<Button
text={props.translate('workspace.bankAccount.addWorkEmail')}
onPress={() => {
Link.openOldDotLink(CONST.ADD_SECONDARY_LOGIN_URL);
User.subscribeToExpensifyCardUpdates();
}}
icon={Expensicons.Mail}
style={[styles.mt4]}
iconStyles={[styles.buttonCTAIcon]}
shouldShowRightIcon
large
success
/>
)}
<MenuItem
title={props.translate('workspace.bankAccount.disconnectBankAccount')}
icon={Expensicons.Close}
onPress={BankAccounts.requestResetFreePlanBankAccount}
wrapperStyle={[styles.cardMenuItem, styles.mv3]}
disabled={Boolean(pendingAction) || !_.isEmpty(errors)}
/>
)}
<MenuItem
title={props.translate('workspace.bankAccount.disconnectBankAccount')}
icon={Expensicons.Close}
onPress={BankAccounts.requestResetFreePlanBankAccount}
wrapperStyle={[styles.cardMenuItem, styles.mv3]}
/>
</OfflineWithFeedback>
</Section>
{Boolean(props.user.isCheckingDomain) && (
<Text style={[styles.formError, styles.mh5]}>
Expand Down
Loading

0 comments on commit e0c4211

Please sign in to comment.