Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
58 changes: 58 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,65 @@ const CONST = {
VALIDATION: 'ValidationStep',
ENABLE: 'EnableStep',
},
PAGE_NAMES: {
COUNTRY: 'country',
BANK_ACCOUNT: 'bank-account',
REQUESTOR: 'requestor',
VERIFY_IDENTITY: 'verify-identity',
COMPANY: 'company',
BENEFICIAL_OWNERS: 'beneficial-owners',
ACH_CONTRACT: 'ach-contract',
VALIDATION: 'validation',
ENABLE: 'enable',
},
STEP_NAMES: ['1', '2', '3', '4', '5', '6'],
BANK_INFO_STEP: {
SUB_PAGE_NAMES: {
MANUAL: 'manual',
PLAID: 'plaid',
},
},
PERSONAL_INFO_STEP: {
SUB_PAGE_NAMES: {
FULL_NAME: 'full-name',
DATE_OF_BIRTH: 'date-of-birth',
SSN: 'ssn',
ADDRESS: 'address',
CONFIRMATION: 'confirmation',
},
},
BUSINESS_INFO_STEP: {
SUB_PAGE_NAMES: {
NAME: 'name',
TAX_ID: 'tax-id',
WEBSITE: 'website',
PHONE: 'phone',
ADDRESS: 'address',
TYPE: 'type',
INCORPORATION_DATE: 'incorporation-date',
INCORPORATION_STATE: 'incorporation-state',
INCORPORATION_CODE: 'incorporation-code',
CONFIRMATION: 'confirmation',
},
},
BENEFICIAL_OWNERS_STEP: {
SUB_PAGE_NAMES: {
IS_USER_UBO: 'is-user-ubo',
IS_ANYONE_ELSE_UBO: 'is-anyone-else-ubo',
ARE_THERE_MORE_UBOS: 'are-there-more-ubos',
UBOS_LIST: 'ubos-list',
LEGAL_NAME: 'legal-name',
DATE_OF_BIRTH: 'date-of-birth',
SSN: 'ssn',
ADDRESS: 'address',
CONFIRMATION: 'confirmation',
},
},
COMPLETE_VERIFICATION_STEP: {
SUB_PAGE_NAMES: {
CONFIRM_AGREEMENTS: 'confirm-agreements',
},
},
SUBSTEP: {
MANUAL: 'manual',
PLAID: 'plaid',
Expand Down
38 changes: 19 additions & 19 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {ReplacementReason} from './libs/actions/Card';
import type {IOURequestType} from './libs/actions/IOU';
import Log from './libs/Log';
import type {RootNavigatorParamList} from './libs/Navigation/types';
import type {ReimbursementAccountStepToOpen} from './libs/ReimbursementAccountUtils';
import StringUtils from './libs/StringUtils';
import {getUrlWithParams} from './libs/Url';
import SCREENS from './SCREENS';
Expand Down Expand Up @@ -295,36 +294,24 @@ const ROUTES = {
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: (policyID?: string, backTo?: string) => getUrlWithBackToParam(`bank-account/${VERIFY_ACCOUNT}?policyID=${policyID}`, backTo),
},
BANK_ACCOUNT_NEW: 'bank-account/new',
BANK_ACCOUNT_PERSONAL: 'bank-account/personal',
// TODO: rename the route as no longer accepts step
BANK_ACCOUNT_WITH_STEP_TO_OPEN: {
route: 'bank-account/:stepToOpen?',
getRoute: ({
policyID,
stepToOpen = '',
bankAccountID,
backTo,
subStepToOpen,
}: {
policyID: string | undefined;
stepToOpen?: ReimbursementAccountStepToOpen;
bankAccountID?: number;
backTo?: string;
subStepToOpen?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY;
}) => {
route: 'bank-account/new',
getRoute: ({policyID, bankAccountID, backTo}: {policyID: string | undefined; bankAccountID?: number; backTo?: string}) => {
if (!policyID && !bankAccountID) {
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
return getUrlWithBackToParam(`bank-account/${stepToOpen}`, backTo);
return getUrlWithBackToParam(`bank-account/new`, backTo);
}

if (bankAccountID) {
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
return getUrlWithBackToParam(`bank-account/${stepToOpen}?bankAccountID=${bankAccountID}`, backTo);
return getUrlWithBackToParam(`bank-account/new?bankAccountID=${bankAccountID}`, backTo);
}
// TODO this backTo comes from drilling it through bank account form screens
// should be removed once https://github.com/Expensify/App/pull/72219 is resolved
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}${subStepToOpen ? `&subStep=${subStepToOpen}` : ''}`, backTo);
return getUrlWithBackToParam(`bank-account/new?policyID=${policyID}`, backTo);
},
},
BANK_ACCOUNT_ENTER_SIGNER_INFO: {
Expand Down Expand Up @@ -356,6 +343,19 @@ const ROUTES = {
return getUrlWithBackToParam(`${base}${pagePart}${subPagePart}${actionPart}${queryString}`, backTo);
},
},
BANK_ACCOUNT_USD_SETUP: {
route: 'bank-account/new/us/:page?/:subPage?/:action?',
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: ({policyID, page, subPage, action, backTo}: {policyID?: string; page?: string; subPage?: string; action?: 'edit'; backTo?: string}) => {
const base = 'bank-account/new/us';
const pagePart = page ? `/${page}` : '';
const subPagePart = subPage ? `/${subPage}` : '';
const actionPart = action ? `/${action}` : '';
const queryString = policyID ? `?policyID=${policyID}` : '';
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
return getUrlWithBackToParam(`${base}${pagePart}${subPagePart}${actionPart}${queryString}`, backTo);
},
},
SETTINGS: 'settings',
SETTINGS_PROFILE: {
route: 'settings/profile',
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,7 @@ const SCREENS = {
},
FLAG_COMMENT_ROOT: 'FlagComment_Root',
REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount',
REIMBURSEMENT_ACCOUNT_USD: 'Reimbursement_Account_USD',
REIMBURSEMENT_ACCOUNT_NON_USD: 'Reimbursement_Account_Non_USD',
REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO: 'Reimbursement_Account_Signer_Info',
REFERRAL_DETAILS: 'Referral_Details',
Expand Down
6 changes: 1 addition & 5 deletions src/components/Navigation/DebugTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import {getRouteForCurrentStep as getReimbursementAccountRouteForCurrentStep} from '@libs/ReimbursementAccountUtils';
import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
import {getChatTabBrickRoadReportID} from '@libs/WorkspacesSettingsUtils';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -82,10 +81,7 @@ function getSettingsRoute(status: IndicatorStatus | undefined, reimbursementAcco
case CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS:
return ROUTES.WORKSPACE_INITIAL.getRoute(policyIDWithErrors);
case CONST.INDICATOR_STATUS.HAS_REIMBURSEMENT_ACCOUNT_ERRORS:
return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
policyID: reimbursementAccount?.achData?.policyID,
stepToOpen: getReimbursementAccountRouteForCurrentStep(reimbursementAccount?.achData?.currentStep ?? CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT),
});
return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID: reimbursementAccount?.achData?.policyID});
case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS:
return ROUTES.SETTINGS_SUBSCRIPTION.route;
case CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_INFO:
Expand Down
28 changes: 28 additions & 0 deletions src/hooks/useReimbursementAccountSubmit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {useCallback, useEffect, useRef} from 'react';
import ONYXKEYS from '@src/ONYXKEYS';
import useOnyx from './useOnyx';

/**
* Defers navigation (onSubmit) until the reimbursement account API call completes.
* Instead of navigating to the next step immediately after firing the API call,
* this hook waits for `isLoading` to go back to `false` and checks for errors.
*
* @param onSubmit - callback that navigates to the next step
* @returns markSubmitting - call this right after firing the API action
*/
export default function useReimbursementAccountSubmit(onSubmit?: () => void) {
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
const isSubmittingRef = useRef(false);

useEffect(() => {
if (!isSubmittingRef.current || reimbursementAccount?.isLoading || reimbursementAccount?.errors) {
return;
}
isSubmittingRef.current = false;
onSubmit?.();
}, [reimbursementAccount?.isLoading, reimbursementAccount?.errors, onSubmit]);

return useCallback(() => {
isSubmittingRef.current = true;
}, []);
}
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_ITEMS]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage').default,
[SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require<ReactComponentModule>('@pages/workspace/ConnectExistingBusinessBankAccountPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT_USD]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlowPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountVerifyAccountPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT_ENTER_SIGNER_INFO]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/EnterSignerInfo').default,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,10 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
path: ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.route,
exact: true,
},
[SCREENS.REIMBURSEMENT_ACCOUNT_USD]: {
path: ROUTES.BANK_ACCOUNT_USD_SETUP.route,
exact: true,
},
[SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: {
path: ROUTES.BANK_ACCOUNT_NON_USD_SETUP.route,
exact: true,
Expand Down
8 changes: 8 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2262,6 +2262,14 @@ type ReimbursementAccountNavigatorParamList = {
bankAccountID?: string;
subStep?: typeof CONST.BANK_ACCOUNT.STEP.COUNTRY;
};
[SCREENS.REIMBURSEMENT_ACCOUNT_USD]: {
page?: string;
subPage?: string;
action?: 'edit';
policyID?: string;
// eslint-disable-next-line no-restricted-syntax -- backTo is a temporary param will be removed after https://github.com/Expensify/App/issues/73825 is done
backTo?: Routes;
};
[SCREENS.REIMBURSEMENT_ACCOUNT_NON_USD]: {
page?: string;
subPage?: string;
Expand Down
25 changes: 2 additions & 23 deletions src/libs/ReimbursementAccountUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';
import type {ACHDataReimbursementAccount, ReimbursementAccountStep} from '@src/types/onyx/ReimbursementAccount';
import type {ACHDataReimbursementAccount} from '@src/types/onyx/ReimbursementAccount';

type ReimbursementAccountStepToOpen = ValueOf<typeof REIMBURSEMENT_ACCOUNT_ROUTE_NAMES> | '';

Expand All @@ -14,27 +14,6 @@ const REIMBURSEMENT_ACCOUNT_ROUTE_NAMES = {
NEW: 'new',
} as const;

function getRouteForCurrentStep(currentStep: ReimbursementAccountStep): ReimbursementAccountStepToOpen {
switch (currentStep) {
case CONST.BANK_ACCOUNT.STEP.COMPANY:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.COMPANY;
case CONST.BANK_ACCOUNT.STEP.REQUESTOR:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.PERSONAL_INFORMATION;
case CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.BENEFICIAL_OWNERS;
case CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.CONTRACT;
case CONST.BANK_ACCOUNT.STEP.VALIDATION:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.VALIDATE;
case CONST.BANK_ACCOUNT.STEP.ENABLE:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.ENABLE;
case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT:
case CONST.BANK_ACCOUNT.STEP.COUNTRY:
default:
return REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW;
}
}

/**
* Returns true if a VBBA exists in any state other than OPEN or LOCKED
*/
Expand Down Expand Up @@ -67,5 +46,5 @@ const hasInProgressVBBA = (achData?: ACHDataReimbursementAccount, isNonUSDWorksp
return hasInProgressUSDVBBA(achData);
};

export {getBankAccountIDAsNumber, getRouteForCurrentStep, hasInProgressUSDVBBA, hasInProgressNonUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES};
export {getBankAccountIDAsNumber, hasInProgressUSDVBBA, hasInProgressNonUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES};
export type {ReimbursementAccountStepToOpen};
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ type ConnectedVerifiedBankAccountProps = {
onBackButtonPress: () => void;

/** Method to set the state of shouldShowConnectedVerifiedBankAccount */
setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void;
setShouldShowConnectedVerifiedBankAccount?: (shouldShowConnectedVerifiedBankAccount: boolean) => void;

/** Method to set the state of USD bank account step */
setUSDBankAccountStep: (step: string | null) => void;
setUSDBankAccountStep?: (step: string | null) => void;

/** Whether the workspace currency is set to non USD currency */
isNonUSDWorkspace: boolean;
Expand Down
37 changes: 14 additions & 23 deletions src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types';
import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
import {getRouteForCurrentStep, hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
import {hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
import shouldReopenOnfido from '@libs/shouldReopenOnfido';
import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
import {isFullScreenName} from '@navigation/helpers/isNavigatorName';
Expand Down Expand Up @@ -60,7 +60,6 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
import ConnectedVerifiedBankAccount from './ConnectedVerifiedBankAccount';
import getStartPageForContinueSetup from './NonUSD/utils/getStartPageForContinueSetup';
import USDVerifiedBankAccountFlow from './USD/USDVerifiedBankAccountFlow';
import getFieldsForStep from './USD/utils/getFieldsForStep';
import getStepToOpenFromRouteParams from './USD/utils/getStepToOpenFromRouteParams';
import VerifiedBankAccountFlowEntryPoint from './VerifiedBankAccountFlowEntryPoint';
Expand All @@ -77,7 +76,7 @@ const OFFLINE_ACCESSIBLE_STEPS = [
CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT,
] as const;

function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}: ReimbursementAccountPageProps) {
function ReimbursementAccountPage({route, policy, isLoadingPolicy}: ReimbursementAccountPageProps) {
const {environmentURL} = useEnvironment();
const session = useSession();
const [reimbursementAccount, reimbursementAccountMetadata] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
Expand Down Expand Up @@ -333,10 +332,6 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
// so we don't clear it. We only want to clear the errors if we are moving between steps.
hideBankAccountErrors();
}

// Use the current page navigation object to set the param to the correct route in the stack
const stepToOpen = getRouteForCurrentStep(currentStep);
navigation.setParams({stepToOpen});
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[isOffline, reimbursementAccount?.draftStep, reimbursementAccount?.pendingAction, reimbursementAccount?.isLoading, hasACHDataBeenLoaded, shouldShowContinueSetupButton, currentStep],
Expand All @@ -347,9 +342,19 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
// so we're always showing manual setup with locked numbers he can not change
setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL).then(() => {
setShouldShowContinueSetupButton(false);
setUSDBankAccountStep(currentStep);
const stepToPageName: Record<string, string> = {
[CONST.BANK_ACCOUNT.STEP.COUNTRY]: CONST.BANK_ACCOUNT.PAGE_NAMES.COUNTRY,
[CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT]: CONST.BANK_ACCOUNT.PAGE_NAMES.BANK_ACCOUNT,
[CONST.BANK_ACCOUNT.STEP.REQUESTOR]: CONST.BANK_ACCOUNT.PAGE_NAMES.REQUESTOR,
[CONST.BANK_ACCOUNT.STEP.COMPANY]: CONST.BANK_ACCOUNT.PAGE_NAMES.COMPANY,
[CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS]: CONST.BANK_ACCOUNT.PAGE_NAMES.BENEFICIAL_OWNERS,
[CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT]: CONST.BANK_ACCOUNT.PAGE_NAMES.ACH_CONTRACT,
[CONST.BANK_ACCOUNT.STEP.VALIDATION]: CONST.BANK_ACCOUNT.PAGE_NAMES.VALIDATION,
};
const page = stepToPageName[currentStep] ?? CONST.BANK_ACCOUNT.PAGE_NAMES.COUNTRY;
Navigation.navigate(ROUTES.BANK_ACCOUNT_USD_SETUP.getRoute({policyID: policyIDParam, page, backTo}));
});
}, [currentStep]);
}, [currentStep, policyIDParam, backTo]);

const continueNonUSDVBBASetup = () => {
const {page: startPage, subPage: startSubPage} = getStartPageForContinueSetup(achData, nonUSDCountryDraftValue, policyCurrency, reimbursementAccountDraft);
Expand Down Expand Up @@ -519,20 +524,6 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy, navigation}:
);
}

if (!isNonUSDSetup && USDBankAccountStep !== null) {
return (
<USDVerifiedBankAccountFlow
USDBankAccountStep={USDBankAccountStep}
policyID={policyIDParam}
onBackButtonPress={goBack}
requestorStepRef={requestorStepRef}
onfidoToken={onfidoToken}
setUSDBankAccountStep={setUSDBankAccountStep}
setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
/>
);
}

return (
<VerifiedBankAccountFlowEntryPoint
setShouldShowContinueSetupButton={setShouldShowContinueSetupButton}
Expand Down
Loading
Loading