diff --git a/src/CONST.ts b/src/CONST.ts index 622db1610ccd..8439ad4f8c58 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -680,6 +680,14 @@ const CONST = { AGREEMENTS: 'AgreementsStep', FINISH: 'FinishStep', }, + BANK_INFO_STEP_ACH_DATA_INPUT_IDS: { + ACCOUNT_HOLDER_NAME: 'addressName', + ACCOUNT_HOLDER_REGION: 'addressState', + ACCOUNT_HOLDER_CITY: 'addressCity', + ACCOUNT_HOLDER_ADDRESS: 'addressStreet', + ACCOUNT_HOLDER_POSTAL_CODE: 'addressZipCode', + ROUTING_CODE: 'routingNumber', + }, BUSINESS_INFO_STEP: { PICKLIST: { ANNUAL_VOLUME_RANGE: 'AnnualVolumeRange', diff --git a/src/components/Form/types.ts b/src/components/Form/types.ts index 02cc4e899b32..34161c53ba8c 100644 --- a/src/components/Form/types.ts +++ b/src/components/Form/types.ts @@ -27,7 +27,7 @@ import type TimeModalPicker from '@components/TimeModalPicker'; import type UploadFile from '@components/UploadFile'; import type ValuePicker from '@components/ValuePicker'; import type ConstantSelector from '@pages/Debug/ConstantSelector'; -import type BusinessTypePicker from '@pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker'; +import type BusinessTypePicker from '@pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker'; import type DimensionTypeSelector from '@pages/workspace/accounting/intacct/import/DimensionTypeSelector'; import type NetSuiteCustomFieldMappingPicker from '@pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomFieldMappingPicker'; import type NetSuiteCustomListPicker from '@pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListPicker'; diff --git a/src/components/SubStepForms/AddressStep.tsx b/src/components/SubStepForms/AddressStep.tsx index 86e6e328d226..5dd5a164f25c 100644 --- a/src/components/SubStepForms/AddressStep.tsx +++ b/src/components/SubStepForms/AddressStep.tsx @@ -6,9 +6,9 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors, isValidAddress, isValidZipCode, isValidZipCodeInternational} from '@libs/ValidationUtils'; import AddressFormFields from '@pages/ReimbursementAccount/AddressFormFields'; -import HelpLinks from '@pages/ReimbursementAccount/PersonalInfo/HelpLinks'; +import HelpLinks from '@pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks'; import type {OnyxFormValuesMapping} from '@src/ONYXKEYS'; type AddressValues = { @@ -95,16 +95,16 @@ function AddressStep({ const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, stepFields); + const errors = getFieldRequiredErrors(values, stepFields); const street = values[inputFieldsIDs.street as keyof typeof values]; - if (street && !ValidationUtils.isValidAddress(street as FormValue)) { + if (street && !isValidAddress(street as FormValue)) { // @ts-expect-error type mismatch to be fixed errors[inputFieldsIDs.street] = translate('bankAccount.error.addressStreet'); } const zipCode = values[inputFieldsIDs.zipCode as keyof typeof values]; - if (zipCode && (shouldDisplayCountrySelector ? !ValidationUtils.isValidZipCodeInternational(zipCode as string) : !ValidationUtils.isValidZipCode(zipCode as string))) { + if (zipCode && (shouldDisplayCountrySelector ? !isValidZipCodeInternational(zipCode as string) : !isValidZipCode(zipCode as string))) { // @ts-expect-error type mismatch to be fixed errors[inputFieldsIDs.zipCode] = translate('bankAccount.error.zipCode'); } diff --git a/src/components/SubStepForms/FullNameStep.tsx b/src/components/SubStepForms/FullNameStep.tsx index 6c53da67e411..6d7404ab81c9 100644 --- a/src/components/SubStepForms/FullNameStep.tsx +++ b/src/components/SubStepForms/FullNameStep.tsx @@ -9,7 +9,7 @@ import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import {getFieldRequiredErrors, isRequiredFulfilled, isValidLegalName} from '@libs/ValidationUtils'; -import HelpLinks from '@pages/ReimbursementAccount/PersonalInfo/HelpLinks'; +import HelpLinks from '@pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks'; import CONST from '@src/CONST'; import type {OnyxFormValuesMapping} from '@src/ONYXKEYS'; diff --git a/src/components/SubStepForms/SingleFieldStep.tsx b/src/components/SubStepForms/SingleFieldStep.tsx index c74bedeed3c6..f45cfa521282 100644 --- a/src/components/SubStepForms/SingleFieldStep.tsx +++ b/src/components/SubStepForms/SingleFieldStep.tsx @@ -9,7 +9,7 @@ import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import HelpLinks from '@pages/ReimbursementAccount/PersonalInfo/HelpLinks'; +import HelpLinks from '@pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks'; import CONST from '@src/CONST'; import type {OnyxFormValuesMapping} from '@src/ONYXKEYS'; diff --git a/src/libs/API/parameters/RestartBankAccountSetupParams.ts b/src/libs/API/parameters/RestartBankAccountSetupParams.ts index 5cb4fa132d10..e41a87056c4d 100644 --- a/src/libs/API/parameters/RestartBankAccountSetupParams.ts +++ b/src/libs/API/parameters/RestartBankAccountSetupParams.ts @@ -1,7 +1,7 @@ type RestartBankAccountSetupParams = { bankAccountID: number; ownerEmail: string; - policyID: string; + policyID: string | undefined; }; export default RestartBankAccountSetupParams; diff --git a/src/libs/actions/ReimbursementAccount/resetFreePlanBankAccount.ts b/src/libs/actions/ReimbursementAccount/resetFreePlanBankAccount.ts index 5bb51f22d64a..2c36ae7e5d6a 100644 --- a/src/libs/actions/ReimbursementAccount/resetFreePlanBankAccount.ts +++ b/src/libs/actions/ReimbursementAccount/resetFreePlanBankAccount.ts @@ -17,7 +17,7 @@ Onyx.connect({ /** * Reset user's reimbursement account. This will delete the bank account. */ -function resetFreePlanBankAccount(bankAccountID: number | undefined, session: OnyxEntry, policyID: string) { +function resetFreePlanBankAccount(bankAccountID: number | undefined, session: OnyxEntry, policyID: string | undefined) { if (!bankAccountID) { throw new Error('Missing bankAccountID when attempting to reset free plan bank account'); } diff --git a/src/pages/ReimbursementAccount/ACHContractStep.tsx b/src/pages/ReimbursementAccount/ACHContractStep.tsx deleted file mode 100644 index d4ba013e27d9..000000000000 --- a/src/pages/ReimbursementAccount/ACHContractStep.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import CompleteVerification from './CompleteVerification/CompleteVerification'; - -type ACHContractStepProps = { - /** Goes to the previous step */ - onBackButtonPress: () => void; -}; - -function ACHContractStep({onBackButtonPress}: ACHContractStepProps) { - return ; -} - -ACHContractStep.displayName = 'ACHContractStep'; - -export default ACHContractStep; diff --git a/src/pages/ReimbursementAccount/AddressFormFields.tsx b/src/pages/ReimbursementAccount/AddressFormFields.tsx index c095e439cbd8..95cd11a478ab 100644 --- a/src/pages/ReimbursementAccount/AddressFormFields.tsx +++ b/src/pages/ReimbursementAccount/AddressFormFields.tsx @@ -167,6 +167,7 @@ function AddressFormFields({ modalHeaderTitle={translate('countryStep.selectCountry')} searchInputTitle={translate('countryStep.findCountry')} value={values?.country} + defaultValue={defaultValues?.country} onValueChange={handleCountryChange} stateInputIDToReset={inputKeys.state ?? 'stateInput'} /> diff --git a/src/pages/ReimbursementAccount/BankAccountStep.tsx b/src/pages/ReimbursementAccount/BankAccountStep.tsx deleted file mode 100644 index 2e094d425d16..000000000000 --- a/src/pages/ReimbursementAccount/BankAccountStep.tsx +++ /dev/null @@ -1,251 +0,0 @@ -import React, {useEffect, useMemo, useRef} from 'react'; -import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx} from 'react-native-onyx'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; -import LottieAnimations from '@components/LottieAnimations'; -import MenuItem from '@components/MenuItem'; -import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Section from '@components/Section'; -import Text from '@components/Text'; -import TextLink from '@components/TextLink'; -import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; -import useLocalize from '@hooks/useLocalize'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {getEarliestErrorField, getLatestErrorField} from '@libs/ErrorUtils'; -import getPlaidDesktopMessage from '@libs/getPlaidDesktopMessage'; -import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils'; -import {openPlaidView, setBankAccountSubStep} from '@userActions/BankAccounts'; -import {openExternalLink, openExternalLinkWithToken} from '@userActions/Link'; -import {updateReimbursementAccountDraft} from '@userActions/ReimbursementAccount'; -import {clearContactMethodErrors, requestValidateCodeAction, validateSecondaryLogin} from '@userActions/User'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {ReimbursementAccountForm} from '@src/types/form/ReimbursementAccountForm'; -import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type * as OnyxTypes from '@src/types/onyx'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import BankInfo from './BankInfo/BankInfo'; - -type BankAccountStepProps = { - /** The OAuth URI + stateID needed to re-initialize the PlaidLink after the user logs into their bank */ - receivedRedirectURI?: string | null; - - /** During the OAuth flow we need to use the plaidLink token that we initially connected with */ - plaidLinkOAuthToken?: OnyxEntry; - - /* The workspace name */ - policyName?: string; - - /* The workspace ID */ - policyID?: string; - - /** The bank account currently in setup */ - reimbursementAccount: OnyxEntry; - - /** Goes to the previous step */ - onBackButtonPress: () => void; - - /** Should ValidateCodeActionModal be displayed or not */ - isValidateCodeActionModalVisible?: boolean; - - /** Toggle ValidateCodeActionModal */ - toggleValidateCodeActionModal?: (isVisible: boolean) => void; -}; - -const bankInfoStepKeys = INPUT_IDS.BANK_INFO_STEP; - -function BankAccountStep({ - plaidLinkOAuthToken = '', - policyID = '', - policyName = '', - receivedRedirectURI, - reimbursementAccount, - onBackButtonPress, - isValidateCodeActionModalVisible, - toggleValidateCodeActionModal, -}: BankAccountStepProps) { - const theme = useTheme(); - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const [account] = useOnyx(ONYXKEYS.ACCOUNT); - const [isPlaidDisabled] = useOnyx(ONYXKEYS.IS_PLAID_DISABLED); - const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); - const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const contactMethod = account?.primaryLogin ?? ''; - const selectedSubStep = useRef(''); - - const loginData = useMemo(() => loginList?.[contactMethod], [loginList, contactMethod]); - const validateLoginError = getEarliestErrorField(loginData, 'validateLogin'); - const hasMagicCodeBeenSent = !!loginData?.validateCodeSent; - - let subStep = reimbursementAccount?.achData?.subStep ?? ''; - const shouldReinitializePlaidLink = plaidLinkOAuthToken && receivedRedirectURI && subStep !== CONST.BANK_ACCOUNT.SUBSTEP.MANUAL; - if (shouldReinitializePlaidLink) { - subStep = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; - } - const plaidDesktopMessage = getPlaidDesktopMessage(); - const bankAccountRoute = `${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policyID, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW, ROUTES.WORKSPACE_INITIAL.getRoute(policyID))}`; - const personalBankAccounts = bankAccountList ? Object.keys(bankAccountList).filter((key) => bankAccountList[key].accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) : []; - - useEffect(() => { - if (!account?.validated) { - return; - } - - if (selectedSubStep.current === CONST.BANK_ACCOUNT.SUBSTEP.MANUAL) { - setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL); - } else if (selectedSubStep.current === CONST.BANK_ACCOUNT.SUBSTEP.PLAID) { - openPlaidView(); - } - }, [account?.validated]); - - const removeExistingBankAccountDetails = () => { - const bankAccountData: Partial = { - [bankInfoStepKeys.ROUTING_NUMBER]: '', - [bankInfoStepKeys.ACCOUNT_NUMBER]: '', - [bankInfoStepKeys.PLAID_MASK]: '', - [bankInfoStepKeys.IS_SAVINGS]: undefined, - [bankInfoStepKeys.BANK_NAME]: '', - [bankInfoStepKeys.PLAID_ACCOUNT_ID]: '', - [bankInfoStepKeys.PLAID_ACCESS_TOKEN]: '', - }; - updateReimbursementAccountDraft(bankAccountData); - }; - - if (subStep === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID || subStep === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) { - return ( - - ); - } - - return ( - - - - -
- {!!plaidDesktopMessage && ( - - openExternalLinkWithToken(bankAccountRoute)}>{translate(plaidDesktopMessage)} - - )} - {!!personalBankAccounts.length && ( - - - - {translate('workspace.bankAccount.connectBankAccountNote')} - - - )} - - { - if (isPlaidDisabled) { - return; - } - if (!account?.validated) { - selectedSubStep.current = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; - toggleValidateCodeActionModal?.(true); - return; - } - removeExistingBankAccountDetails(); - openPlaidView(); - }} - shouldShowRightIcon - wrapperStyle={[styles.sectionMenuItemTopDescription]} - /> - - - { - if (!account?.validated) { - selectedSubStep.current = CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL; - toggleValidateCodeActionModal?.(true); - return; - } - removeExistingBankAccountDetails(); - setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL); - }} - shouldShowRightIcon - wrapperStyle={[styles.sectionMenuItemTopDescription]} - /> - -
- - {translate('common.privacy')} - openExternalLink(CONST.ENCRYPTION_AND_SECURITY_HELP_URL)} - style={[styles.flexRow, styles.alignItemsCenter]} - accessibilityLabel={translate('bankAccount.yourDataIsSecure')} - > - {translate('bankAccount.yourDataIsSecure')} - - - - - -
- requestValidateCodeAction()} - handleSubmitForm={(validateCode) => validateSecondaryLogin(loginList, contactMethod, validateCode)} - validateError={!isEmptyObject(validateLoginError) ? validateLoginError : getLatestErrorField(loginData, 'validateCodeSent')} - clearError={() => clearContactMethodErrors(contactMethod, !isEmptyObject(validateLoginError) ? 'validateLogin' : 'validateCodeSent')} - onClose={() => toggleValidateCodeActionModal?.(false)} - /> -
-
- ); -} - -BankAccountStep.displayName = 'BankAccountStep'; - -export default BankAccountStep; diff --git a/src/pages/ReimbursementAccount/CompanyStep.tsx b/src/pages/ReimbursementAccount/CompanyStep.tsx deleted file mode 100644 index 740fc7329d30..000000000000 --- a/src/pages/ReimbursementAccount/CompanyStep.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import BusinessInfo from './BusinessInfo/BusinessInfo'; - -type CompanyStepProps = { - /** Goes to the previous step */ - onBackButtonPress: () => void; -}; - -function CompanyStep({onBackButtonPress}: CompanyStepProps) { - return ; -} - -CompanyStep.displayName = 'CompanyStep'; - -export default CompanyStep; diff --git a/src/pages/ReimbursementAccount/EnableBankAccount/EnableBankAccount.tsx b/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx similarity index 64% rename from src/pages/ReimbursementAccount/EnableBankAccount/EnableBankAccount.tsx rename to src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx index 1d8ce04d7f71..40e06dcb180d 100644 --- a/src/pages/ReimbursementAccount/EnableBankAccount/EnableBankAccount.tsx +++ b/src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx @@ -2,8 +2,8 @@ import React from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import getBankIcon from '@components/Icon/BankIcons'; -import * as Expensicons from '@components/Icon/Expensicons'; -import * as Illustrations from '@components/Icon/Illustrations'; +import {Close} from '@components/Icon/Expensicons'; +import {ThumbsUpStars} from '@components/Icon/Illustrations'; import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -13,35 +13,42 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import WorkspaceResetBankAccountModal from '@pages/workspace/WorkspaceResetBankAccountModal'; -import * as BankAccounts from '@userActions/ReimbursementAccount'; +import {requestResetFreePlanBankAccount, resetReimbursementAccount} from '@userActions/ReimbursementAccount'; import CONST from '@src/CONST'; import type {ReimbursementAccount} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -type EnableBankAccountProps = { +type ConnectedVerifiedBankAccountProps = { /** Bank account currently in setup */ reimbursementAccount: OnyxEntry; /** Method to trigger when pressing back button of the header */ onBackButtonPress: () => void; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setUSDBankAccountStep: (step: string | null) => void; }; -function EnableBankAccount({reimbursementAccount, onBackButtonPress}: EnableBankAccountProps) { +function ConnectedVerifiedBankAccount({reimbursementAccount, onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep}: ConnectedVerifiedBankAccountProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const achData = reimbursementAccount?.achData ?? {}; - const {icon, iconSize, iconStyles} = getBankIcon({bankName: achData.bankName, styles}); + const {icon, iconSize, iconStyles} = getBankIcon({bankName: reimbursementAccount?.achData?.bankName, styles}); - const formattedBankAccountNumber = achData.accountNumber ? `${translate('bankAccount.accountEnding')} ${achData.accountNumber.slice(-4)}` : ''; - const bankAccountOwnerName = achData.addressName; + const formattedBankAccountNumber = reimbursementAccount?.achData?.accountNumber + ? `${translate('bankAccount.accountEnding')} ${reimbursementAccount?.achData?.accountNumber.slice(-4)}` + : ''; + const bankAccountOwnerName = reimbursementAccount?.achData?.addressName; const errors = reimbursementAccount?.errors ?? {}; const pendingAction = reimbursementAccount?.pendingAction; const shouldShowResetModal = reimbursementAccount?.shouldShowResetModal ?? false; return (
{translate('workspace.bankAccount.accountDescriptionWithCards')}
- {shouldShowResetModal && } + {shouldShowResetModal && ( + + )}
); } -EnableBankAccount.displayName = 'EnableStep'; +ConnectedVerifiedBankAccount.displayName = 'ConnectedVerifiedBankAccount'; -export default EnableBankAccount; +export default ConnectedVerifiedBankAccount; diff --git a/src/pages/ReimbursementAccount/ContinueBankAccountSetup.tsx b/src/pages/ReimbursementAccount/ContinueBankAccountSetup.tsx deleted file mode 100644 index 9e1897348dab..000000000000 --- a/src/pages/ReimbursementAccount/ContinueBankAccountSetup.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import Button from '@components/Button'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import * as Expensicons from '@components/Icon/Expensicons'; -import * as Illustrations from '@components/Icon/Illustrations'; -import MenuItem from '@components/MenuItem'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Section from '@components/Section'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import WorkspaceResetBankAccountModal from '@pages/workspace/WorkspaceResetBankAccountModal'; -import * as BankAccounts from '@userActions/BankAccounts'; -import CONST from '@src/CONST'; -import type * as OnyxTypes from '@src/types/onyx'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; - -type ContinueBankAccountStepProps = { - /** Bank account currently in setup */ - reimbursementAccount: OnyxEntry; - - /** Callback to continue to the next step of the setup */ - onContinuePress: () => void; - - /* The workspace name */ - policyName?: string; - - /** Goes to the previous step */ - onBackButtonPress: () => void; -}; - -function ContinueBankAccountSetup({policyName = '', onBackButtonPress, reimbursementAccount, onContinuePress}: ContinueBankAccountStepProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const errors = reimbursementAccount?.errors ?? {}; - const pendingAction = reimbursementAccount?.pendingAction ?? null; - - return ( - - - -
- - {translate('workspace.bankAccount.youreAlmostDone')} -
-
- - {!!reimbursementAccount?.shouldShowResetModal && } -
- ); -} - -ContinueBankAccountSetup.displayName = 'ContinueBankAccountSetup'; - -export default ContinueBankAccountSetup; diff --git a/src/pages/ReimbursementAccount/NonUSD/Agreements/index.tsx b/src/pages/ReimbursementAccount/NonUSD/Agreements/index.tsx index 605157e2fe33..5cabb20771c8 100644 --- a/src/pages/ReimbursementAccount/NonUSD/Agreements/index.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/Agreements/index.tsx @@ -5,7 +5,7 @@ import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; import CONST from '@src/CONST'; -import Confirmation from './substeps/Confirmation'; +import Confirmation from './subSteps/Confirmation'; type AgreementsProps = { /** Handles back button press */ diff --git a/src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/Agreements/subSteps/Confirmation.tsx similarity index 81% rename from src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx rename to src/pages/ReimbursementAccount/NonUSD/Agreements/subSteps/Confirmation.tsx index 945b17c530ae..1e181d42a00f 100644 --- a/src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/Agreements/subSteps/Confirmation.tsx @@ -9,7 +9,7 @@ import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors, isRequiredFulfilled} from '@libs/ValidationUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -45,26 +45,24 @@ function Confirmation({onNext}: SubStepProps) { const defaultValues = { [AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT]: - !!reimbursementAccount?.achData?.additionalData?.corpay?.[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT] ?? reimbursementAccountDraft?.[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT] ?? '', - [PROVIDE_TRUTHFUL_INFORMATION]: - !!reimbursementAccount?.achData?.additionalData?.corpay?.[PROVIDE_TRUTHFUL_INFORMATION] ?? reimbursementAccountDraft?.[PROVIDE_TRUTHFUL_INFORMATION] ?? '', - [AGREE_TO_TERMS_AND_CONDITIONS]: - !!reimbursementAccount?.achData?.additionalData?.corpay?.[AGREE_TO_TERMS_AND_CONDITIONS] ?? reimbursementAccountDraft?.[AGREE_TO_TERMS_AND_CONDITIONS] ?? '', + !!reimbursementAccount?.achData?.corpay?.[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT] ?? reimbursementAccountDraft?.[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT] ?? '', + [PROVIDE_TRUTHFUL_INFORMATION]: !!reimbursementAccount?.achData?.corpay?.[PROVIDE_TRUTHFUL_INFORMATION] ?? reimbursementAccountDraft?.[PROVIDE_TRUTHFUL_INFORMATION] ?? '', + [AGREE_TO_TERMS_AND_CONDITIONS]: !!reimbursementAccount?.achData?.corpay?.[AGREE_TO_TERMS_AND_CONDITIONS] ?? reimbursementAccountDraft?.[AGREE_TO_TERMS_AND_CONDITIONS] ?? '', }; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + const errors = getFieldRequiredErrors(values, STEP_FIELDS); - if (!ValidationUtils.isRequiredFulfilled(values[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT])) { + if (!isRequiredFulfilled(values[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT])) { errors[AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT] = translate('agreementsStep.error.authorized'); } - if (!ValidationUtils.isRequiredFulfilled(values[PROVIDE_TRUTHFUL_INFORMATION])) { + if (!isRequiredFulfilled(values[PROVIDE_TRUTHFUL_INFORMATION])) { errors[PROVIDE_TRUTHFUL_INFORMATION] = translate('agreementsStep.error.certify'); } - if (!ValidationUtils.isRequiredFulfilled(values[AGREE_TO_TERMS_AND_CONDITIONS])) { + if (!isRequiredFulfilled(values[AGREE_TO_TERMS_AND_CONDITIONS])) { errors[AGREE_TO_TERMS_AND_CONDITIONS] = translate('common.error.acceptTerms'); } diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/BankInfo.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/BankInfo.tsx index 91771521c089..fae42c0207a8 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/BankInfo.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/BankInfo.tsx @@ -1,19 +1,21 @@ +import React, {useEffect, useMemo} from 'react'; import type {ComponentType} from 'react'; -import React, {useEffect} from 'react'; import {useOnyx} from 'react-native-onyx'; import InteractiveStepWrapper from '@components/InteractiveStepWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; +import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; +import getInitialSubStepForBankInfoStep from '@pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBankInfoStep'; +import getInputKeysForBankInfoStep from '@pages/ReimbursementAccount/NonUSD/utils/getInputKeysForBankInfoStep'; import {clearReimbursementAccountBankCreation, createCorpayBankAccount, getCorpayBankAccountFields} from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; import type {ReimbursementAccountForm} from '@src/types/form/ReimbursementAccountForm'; -import AccountHolderDetails from './substeps/AccountHolderDetails'; -import BankAccountDetails from './substeps/BankAccountDetails'; -import Confirmation from './substeps/Confirmation'; -import UploadStatement from './substeps/UploadStatement'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import AccountHolderDetails from './subSteps/AccountHolderDetails'; +import BankAccountDetails from './subSteps/BankAccountDetails'; +import Confirmation from './subSteps/Confirmation'; import type {BankInfoSubStepProps} from './types'; const {COUNTRY} = INPUT_IDS.ADDITIONAL_DATA; @@ -35,12 +37,15 @@ function BankInfo({onBackButtonPress, onSubmit}: BankInfoProps) { const policyID = reimbursementAccount?.achData?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); const currency = policy?.outputCurrency ?? ''; - const country = reimbursementAccountDraft?.[COUNTRY] ?? reimbursementAccountDraft?.[COUNTRY] ?? ''; + const country = reimbursementAccount?.achData?.[COUNTRY] ?? reimbursementAccountDraft?.[COUNTRY] ?? ''; + const inputKeys = getInputKeysForBankInfoStep(corpayFields); + const values = useMemo(() => getBankInfoStepValues(inputKeys, reimbursementAccountDraft, reimbursementAccount), [inputKeys, reimbursementAccount, reimbursementAccountDraft]); + const startFrom = getInitialSubStepForBankInfoStep(values, corpayFields); const submit = () => { const {formFields, isLoading, isSuccess, ...corpayData} = corpayFields ?? {}; - createCorpayBankAccount({...reimbursementAccountDraft, ...corpayData} as ReimbursementAccountForm, policyID); + createCorpayBankAccount({...values, ...corpayData} as ReimbursementAccountForm, policyID); }; useEffect(() => { @@ -61,8 +66,7 @@ function BankInfo({onBackButtonPress, onSubmit}: BankInfoProps) { getCorpayBankAccountFields(country, currency); }, [country, currency]); - const bodyContent: Array> = - currency !== CONST.CURRENCY.AUD ? [BankAccountDetails, AccountHolderDetails, Confirmation] : [BankAccountDetails, AccountHolderDetails, UploadStatement, Confirmation]; + const bodyContent: Array> = [BankAccountDetails, AccountHolderDetails, Confirmation]; const { componentToRender: SubStep, @@ -72,7 +76,7 @@ function BankInfo({onBackButtonPress, onSubmit}: BankInfoProps) { prevScreen, moveTo, goToTheLastStep, - } = useSubStep({bodyContent, startFrom: 0, onFinished: submit}); + } = useSubStep({bodyContent, startFrom, onFinished: submit}); const handleBackButtonPress = () => { if (isEditing) { diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/AccountHolderDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx similarity index 94% rename from src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/AccountHolderDetails.tsx rename to src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx index 268356dee063..9ce9e9862e81 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/AccountHolderDetails.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx @@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import useThemeStyles from '@hooks/useThemeStyles'; import type {BankInfoSubStepProps} from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {ReimbursementAccountForm} from '@src/types/form/ReimbursementAccountForm'; @@ -35,7 +35,10 @@ function AccountHolderDetails({onNext, isEditing, corpayFields}: BankInfoSubStep const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValues = useMemo(() => getSubstepValues(subStepKeys ?? {}, reimbursementAccountDraft, reimbursementAccount), [subStepKeys, reimbursementAccount, reimbursementAccountDraft]); + const defaultValues = useMemo( + () => getBankInfoStepValues(subStepKeys ?? {}, reimbursementAccountDraft, reimbursementAccount), + [subStepKeys, reimbursementAccount, reimbursementAccountDraft], + ); const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: fieldIds as Array>, diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/BankAccountDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx similarity index 78% rename from src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/BankAccountDetails.tsx rename to src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx index 052f8560c5ca..000e18bb37d0 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/BankAccountDetails.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import {ActivityIndicator, View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxKeys, FormOnyxValues} from '@components/Form/types'; @@ -10,18 +11,29 @@ import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccoun import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import type {BankInfoSubStepProps} from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; +import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {ReimbursementAccountForm} from '@src/types/form'; function BankAccountDetails({onNext, isEditing, corpayFields}: BankInfoSubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const theme = useTheme(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const bankAccountDetailsFields = useMemo(() => { return corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX)); }, [corpayFields]); + const subStepKeys = bankAccountDetailsFields?.reduce((acc, field) => { + acc[field.id as keyof ReimbursementAccountForm] = field.id as keyof ReimbursementAccountForm; + return acc; + }, {} as Record); + + const defaultValues = getBankInfoStepValues(subStepKeys ?? {}, reimbursementAccountDraft, reimbursementAccount); + const fieldIds = bankAccountDetailsFields?.map((field) => field.id); const validate = useCallback( @@ -73,11 +85,12 @@ function BankAccountDetails({onNext, isEditing, corpayFields}: BankInfoSubStepPr aria-label={field.label} role={CONST.ROLE.PRESENTATION} shouldSaveDraft={!isEditing} + defaultValue={String(defaultValues[field.id as keyof typeof defaultValues]) ?? ''} /> ); }); - }, [bankAccountDetailsFields, styles.mb6, isEditing]); + }, [bankAccountDetailsFields, styles.mb6, isEditing, defaultValues]); return ( <> {translate('bankInfoStep.whatAreYour')} - {inputs} - {!inputs && ( - + {corpayFields?.isLoading ? ( + + ) : ( + inputs )} diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx new file mode 100644 index 000000000000..037f54ca8fea --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx @@ -0,0 +1,83 @@ +import React, {useMemo} from 'react'; +import {ActivityIndicator, View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import type {BankInfoSubStepProps} from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; +import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; +import getInputKeysForBankInfoStep from '@pages/ReimbursementAccount/NonUSD/utils/getInputKeysForBankInfoStep'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; + +const {ACCOUNT_HOLDER_COUNTRY} = INPUT_IDS.ADDITIONAL_DATA.CORPAY; +function Confirmation({onNext, onMove, corpayFields}: BankInfoSubStepProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const theme = useTheme(); + + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); + const inputKeys = getInputKeysForBankInfoStep(corpayFields); + const values = useMemo(() => getBankInfoStepValues(inputKeys, reimbursementAccountDraft, reimbursementAccount), [inputKeys, reimbursementAccount, reimbursementAccountDraft]); + + const items = useMemo( + () => + corpayFields?.formFields?.map((field) => { + let title = values[field.id as keyof typeof values] ? String(values[field.id as keyof typeof values]) : ''; + + if (field.id === ACCOUNT_HOLDER_COUNTRY) { + title = CONST.ALL_COUNTRIES[title as keyof typeof CONST.ALL_COUNTRIES]; + } + + return ( + { + if (!field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX)) { + onMove(0); + } else { + onMove(1); + } + }} + key={field.id} + /> + ); + }), + [corpayFields, onMove, values], + ); + + return ( + + + {translate('bankInfoStep.letsDoubleCheck')} + {translate('bankInfoStep.thisBankAccount')} + {corpayFields?.isLoading ? ( + + ) : ( + items + )} + + + ); +} + +Confirmation.displayName = 'Confirmation'; + +export default Confirmation; diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/Confirmation.tsx deleted file mode 100644 index ac31fd54e45b..000000000000 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/Confirmation.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, {useMemo} from 'react'; -import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; -import FormProvider from '@components/Form/FormProvider'; -import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import type {BankInfoSubStepProps} from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReimbursementAccountForm} from '@src/types/form/ReimbursementAccountForm'; -import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; - -const {ACCOUNT_HOLDER_COUNTRY} = INPUT_IDS.ADDITIONAL_DATA.CORPAY; -function Confirmation({onNext, onMove, corpayFields}: BankInfoSubStepProps) { - const {translate} = useLocalize(); - const styles = useThemeStyles(); - - const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const inputKeys = useMemo(() => { - const keys: Record = {}; - corpayFields?.formFields?.forEach((field) => { - keys[field.id] = field.id as keyof ReimbursementAccountForm; - }); - return keys; - }, [corpayFields]); - const values = useMemo(() => getSubstepValues(inputKeys, reimbursementAccountDraft, reimbursementAccount), [inputKeys, reimbursementAccount, reimbursementAccountDraft]); - - const items = useMemo( - () => ( - <> - {corpayFields?.formFields?.map((field) => { - let title = values[field.id as keyof typeof values] ? String(values[field.id as keyof typeof values]) : ''; - - if (field.id === ACCOUNT_HOLDER_COUNTRY) { - title = CONST.ALL_COUNTRIES[title as keyof typeof CONST.ALL_COUNTRIES]; - } - - return ( - { - if (!field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX)) { - onMove(0); - } else { - onMove(1); - } - }} - key={field.id} - /> - ); - })} - {!!reimbursementAccountDraft?.[INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_STATEMENT] && ( - file.name).join(', ')} - shouldShowRightIcon - onPress={() => onMove(2)} - /> - )} - - ), - [corpayFields, onMove, reimbursementAccountDraft, translate, values], - ); - - return ( - - - {translate('bankInfoStep.letsDoubleCheck')} - {translate('bankInfoStep.thisBankAccount')} - {items} - - - ); -} - -Confirmation.displayName = 'Confirmation'; - -export default Confirmation; diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/UploadStatement.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/UploadStatement.tsx deleted file mode 100644 index 2815f9b85413..000000000000 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/UploadStatement.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import React, {useCallback, useState} from 'react'; -import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; -import type {FileObject} from '@components/AttachmentModal'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; -import Text from '@components/Text'; -import UploadFile from '@components/UploadFile'; -import useLocalize from '@hooks/useLocalize'; -import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; -import type {SubStepProps} from '@hooks/useSubStep/types'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {getLastFourDigits} from '@libs/BankAccountUtils'; -import {getFieldRequiredErrors} from '@libs/ValidationUtils'; -import WhyLink from '@pages/ReimbursementAccount/NonUSD/WhyLink'; -import {clearErrorFields, setDraftValues, setErrorFields} from '@userActions/FormActions'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; - -type UploadStatementProps = SubStepProps; - -const {BANK_STATEMENT} = INPUT_IDS.ADDITIONAL_DATA.CORPAY; -const STEP_FIELDS = [BANK_STATEMENT]; - -function UploadStatement({onNext, isEditing}: UploadStatementProps) { - const {translate} = useLocalize(); - const styles = useThemeStyles(); - - const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - - const defaultValues = { - [BANK_STATEMENT]: reimbursementAccount?.achData?.additionalData?.corpay?.[BANK_STATEMENT] ?? reimbursementAccountDraft?.[BANK_STATEMENT] ?? [], - }; - - const [uploadedIDs, setUploadedID] = useState(defaultValues[BANK_STATEMENT]); - - const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - const baseError = getFieldRequiredErrors(values, STEP_FIELDS); - - if (baseError) { - return baseError; - } - - return {}; - }, []); - - const handleSubmit = useReimbursementAccountStepFormSubmit({ - fieldIds: STEP_FIELDS, - onNext, - shouldSaveDraft: isEditing, - }); - - const handleSelectIDFile = (files: FileObject[]) => { - setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[BANK_STATEMENT]: [...uploadedIDs, ...files]}); - setUploadedID((prev) => [...prev, ...files]); - }; - - const handleRemoveIDFile = (fileName: string) => { - const newUploadedIDs = uploadedIDs.filter((file) => file.name !== fileName); - setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[BANK_STATEMENT]: newUploadedIDs}); - setUploadedID(newUploadedIDs); - }; - - const setUploadError = (error: string) => { - if (!error) { - clearErrorFields(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM); - return; - } - - setErrorFields(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[BANK_STATEMENT]: {onUpload: error}}); - }; - - return ( - - - {translate('bankInfoStep.uploadYourLatest')} - - {translate('bankInfoStep.pleaseUpload', {lastFourDigits: getLastFourDigits(reimbursementAccountDraft?.accountNumber ?? '')})} - - {translate('bankInfoStep.bankStatement')} - - - - - ); -} - -UploadStatement.displayName = 'UploadStatement'; - -export default UploadStatement; diff --git a/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerInfo.tsx b/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerInfo.tsx index 6c68afb01604..918d749f9cf8 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerInfo.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerInfo.tsx @@ -58,7 +58,7 @@ function BeneficialOwnerInfo({onBackButtonPress, onSubmit}: BeneficialOwnerInfoP const [isAnyoneElseOwner, setIsAnyoneElseOwner] = useState(false); const [currentSubStep, setCurrentSubStep] = useState(SUBSTEP.IS_USER_BENEFICIAL_OWNER); const [totalOwnedPercentage, setTotalOwnedPercentage] = useState>({}); - const companyName = reimbursementAccount?.achData?.additionalData?.corpay?.[COMPANY_NAME] ?? reimbursementAccountDraft?.[COMPANY_NAME] ?? ''; + const companyName = reimbursementAccount?.achData?.corpay?.[COMPANY_NAME] ?? reimbursementAccountDraft?.[COMPANY_NAME] ?? ''; const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? CONST.DEFAULT_NUMBER_ID; const totalOwnedPercentageSum = Object.values(totalOwnedPercentage).reduce((acc, value) => acc + value, 0); diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/BusinessInfo.tsx index c9a8beb685d5..6675305cccd3 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/BusinessInfo.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/BusinessInfo.tsx @@ -5,22 +5,22 @@ import InteractiveStepWrapper from '@components/InteractiveStepWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import type {SaveCorpayOnboardingCompanyDetails} from '@libs/API/parameters/SaveCorpayOnboardingCompanyDetailsParams'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getInitialSubStepForBusinessInfoStep from '@pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBusinessInfoStep'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import {clearReimbursementAccountSaveCorpayOnboardingCompanyDetails, getCorpayOnboardingFields, saveCorpayOnboardingCompanyDetails} from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import Address from './substeps/Address'; -import AverageReimbursement from './substeps/AverageReimbursement'; -import BusinessType from './substeps/BusinessType'; -import Confirmation from './substeps/Confirmation'; -import ContactInformation from './substeps/ContactInformation'; -import IncorporationLocation from './substeps/IncorporationLocation'; -import Name from './substeps/Name'; -import PaymentVolume from './substeps/PaymentVolume'; -import RegistrationNumber from './substeps/RegistrationNumber'; -import TaxIDEINNumber from './substeps/TaxIDEINNumber'; +import Address from './subSteps/Address'; +import AverageReimbursement from './subSteps/AverageReimbursement'; +import BusinessType from './subSteps/BusinessType'; +import Confirmation from './subSteps/Confirmation'; +import ContactInformation from './subSteps/ContactInformation'; +import IncorporationLocation from './subSteps/IncorporationLocation'; +import Name from './subSteps/Name'; +import PaymentVolume from './subSteps/PaymentVolume'; +import RegistrationNumber from './subSteps/RegistrationNumber'; +import TaxIDEINNumber from './subSteps/TaxIDEINNumber'; type BusinessInfoProps = { /** Handles back button press */ @@ -30,8 +30,6 @@ type BusinessInfoProps = { onSubmit: () => void; }; -type BusinessInfoParamsPartial = Omit; - const bodyContent: Array> = [ Name, Address, @@ -72,24 +70,21 @@ function BusinessInfo({onBackButtonPress, onSubmit}: BusinessInfoProps) { const policyID = reimbursementAccount?.achData?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); const currency = policy?.outputCurrency ?? ''; - const businessInfoStepValues = useMemo(() => getSubstepValues(INPUT_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const businessInfoStepValues = useMemo(() => getSubStepValues(INPUT_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? CONST.DEFAULT_NUMBER_ID; - const country = reimbursementAccount?.achData?.additionalData?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? reimbursementAccountDraft?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? ''; + const startFrom = useMemo(() => getInitialSubStepForBusinessInfoStep(businessInfoStepValues), [businessInfoStepValues]); + + const country = reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? reimbursementAccountDraft?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? ''; useEffect(() => { getCorpayOnboardingFields(country); }, [country]); const submit = useCallback(() => { - const params = {} as BusinessInfoParamsPartial; - Object.values(INPUT_KEYS).forEach((currentKey) => { - params[currentKey] = businessInfoStepValues[currentKey]; - }); - saveCorpayOnboardingCompanyDetails( { - ...params, + ...businessInfoStepValues, fundSourceCountries: country, fundDestinationCountries: country, currencyNeeded: currency, @@ -115,7 +110,7 @@ function BusinessInfo({onBackButtonPress, onSubmit}: BusinessInfoProps) { }; }, [reimbursementAccount, onSubmit]); - const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo, goToTheLastStep} = useSubStep({bodyContent, startFrom: 0, onFinished: submit}); + const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo, goToTheLastStep} = useSubStep({bodyContent, startFrom, onFinished: submit}); const handleBackButtonPress = () => { if (isEditing) { diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Address.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Address.tsx similarity index 91% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Address.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Address.tsx index 997c14644eb8..07ece7fcf0a9 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Address.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Address.tsx @@ -4,7 +4,7 @@ import AddressStep from '@components/SubStepForms/AddressStep'; import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -29,10 +29,10 @@ function Address({onNext, onMove, isEditing}: AddressProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const onyxValues = useMemo(() => getSubstepValues(INPUT_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const onyxValues = useMemo(() => getSubStepValues(INPUT_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); - const businessStepCountryDraftValue = onyxValues[COMPANY_COUNTRY_CODE]; - const countryStepCountryDraftValue = reimbursementAccountDraft?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? ''; + const businessStepCountryDraftValue = onyxValues[COMPANY_COUNTRY_CODE] ?? ''; + const countryStepCountryDraftValue = reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? ''; const countryInitialValue = businessStepCountryDraftValue !== '' && businessStepCountryDraftValue !== countryStepCountryDraftValue ? businessStepCountryDraftValue : countryStepCountryDraftValue; @@ -41,7 +41,7 @@ function Address({onNext, onMove, isEditing}: AddressProps) { city: onyxValues[COMPANY_CITY] ?? '', state: onyxValues[COMPANY_STATE] ?? '', zipCode: onyxValues[COMPANY_POSTAL_CODE] ?? '', - country: businessStepCountryDraftValue ?? countryInitialValue, + country: onyxValues[COMPANY_COUNTRY_CODE] ?? countryInitialValue, }; // Has to be stored in state and updated on country change due to the fact that we can't relay on onyxValues when user is editing the form (draft values are not being saved in that case) diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/AverageReimbursement.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx similarity index 94% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/AverageReimbursement.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx index 323946761428..ddf7bcfc9241 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/AverageReimbursement.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx @@ -22,7 +22,6 @@ function AverageReimbursement({onNext, isEditing}: AverageReimbursementProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const [corpayOnboardingFields] = useOnyx(ONYXKEYS.CORPAY_ONBOARDING_FIELDS); const policyID = reimbursementAccount?.achData?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); @@ -39,7 +38,7 @@ function AverageReimbursement({onNext, isEditing}: AverageReimbursementProps) { }, {} as Record); }, [corpayOnboardingFields]); - const tradeVolumeDefaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[TRADE_VOLUME] ?? reimbursementAccountDraft?.[TRADE_VOLUME] ?? ''; + const tradeVolumeDefaultValue = reimbursementAccount?.achData?.corpay?.[TRADE_VOLUME] ?? ''; const validate = useCallback((values: FormOnyxValues): FormInputErrors => { return getFieldRequiredErrors(values, STEP_FIELDS); diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/BusinessType.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/BusinessType.tsx similarity index 93% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/BusinessType.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/BusinessType.tsx index 88d577443206..793748b37b15 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/BusinessType.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/BusinessType.tsx @@ -23,7 +23,6 @@ function BusinessType({onNext, isEditing}: BusinessTypeProps) { const styles = useThemeStyles(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const [corpayOnboardingFields] = useOnyx(ONYXKEYS.CORPAY_ONBOARDING_FIELDS); const incorporationTypeListOptions = useMemo(() => { @@ -48,8 +47,8 @@ function BusinessType({onNext, isEditing}: BusinessTypeProps) { }, {} as Record); }, [corpayOnboardingFields]); - const incorporationTypeDefaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[APPLICANT_TYPE_ID] ?? reimbursementAccountDraft?.[APPLICANT_TYPE_ID] ?? ''; - const businessCategoryDefaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[BUSINESS_CATEGORY] ?? reimbursementAccountDraft?.[BUSINESS_CATEGORY] ?? ''; + const incorporationTypeDefaultValue = reimbursementAccount?.achData?.corpay?.[APPLICANT_TYPE_ID] ?? ''; + const businessCategoryDefaultValue = reimbursementAccount?.achData?.corpay?.[BUSINESS_CATEGORY] ?? ''; const validate = useCallback((values: FormOnyxValues): FormInputErrors => { return getFieldRequiredErrors(values, STEP_FIELDS); diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Confirmation.tsx similarity index 98% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Confirmation.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Confirmation.tsx index bb3f0450b9df..7a54d5ffca2b 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Confirmation.tsx @@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import {getLatestErrorMessage} from '@libs/ErrorUtils'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -52,7 +52,7 @@ function Confirmation({onNext, onMove}: SubStepProps) { const [corpayOnboardingFields] = useOnyx(ONYXKEYS.CORPAY_ONBOARDING_FIELDS); const error = getLatestErrorMessage(reimbursementAccount); - const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const paymentVolume = useMemo( () => displayStringValue(corpayOnboardingFields?.picklists.AnnualVolumeRange ?? [], values[ANNUAL_VOLUME]), diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/ContactInformation.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/ContactInformation.tsx similarity index 90% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/ContactInformation.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/ContactInformation.tsx index a077ace5111f..a41d5056fb55 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/ContactInformation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/ContactInformation.tsx @@ -24,11 +24,9 @@ function ContactInformation({onNext, isEditing}: ContactInformationProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const phoneNumberDefaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[BUSINESS_CONTACT_NUMBER] ?? reimbursementAccountDraft?.[BUSINESS_CONTACT_NUMBER] ?? ''; - const confirmationEmailDefaultValue = - reimbursementAccount?.achData?.additionalData?.corpay?.[BUSINESS_CONFIRMATION_EMAIL] ?? reimbursementAccountDraft?.[BUSINESS_CONFIRMATION_EMAIL] ?? ''; + const phoneNumberDefaultValue = reimbursementAccount?.achData?.corpay?.[BUSINESS_CONTACT_NUMBER] ?? ''; + const confirmationEmailDefaultValue = reimbursementAccount?.achData?.corpay?.[BUSINESS_CONFIRMATION_EMAIL] ?? ''; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/IncorporationLocation.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/IncorporationLocation.tsx similarity index 98% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/IncorporationLocation.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/IncorporationLocation.tsx index 0eb335817744..83f287fbf8e3 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/IncorporationLocation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/IncorporationLocation.tsx @@ -11,7 +11,7 @@ import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccoun import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import {getFieldRequiredErrors} from '@libs/ValidationUtils'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -41,7 +41,7 @@ function IncorporationLocation({onNext, isEditing}: IncorporationLocationProps) const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const onyxValues = useMemo( () => - getSubstepValues( + getSubStepValues( {FORMATION_INCORPORATION_COUNTRY_CODE, FORMATION_INCORPORATION_STATE, COMPANY_COUNTRY: COMPANY_COUNTRY_CODE, COMPANY_STATE}, reimbursementAccountDraft, reimbursementAccount, diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Name.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Name.tsx similarity index 90% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Name.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Name.tsx index eb1d80ab843b..61b49a7ec7da 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Name.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Name.tsx @@ -19,8 +19,7 @@ function Name({onNext, onMove, isEditing}: NameProps) { const {translate} = useLocalize(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[COMPANY_NAME] ?? reimbursementAccountDraft?.[COMPANY_NAME] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[COMPANY_NAME] ?? ''; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/PaymentVolume.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx similarity index 94% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/PaymentVolume.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx index 6c3303a08512..70d610687212 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/PaymentVolume.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx @@ -22,7 +22,6 @@ function PaymentVolume({onNext, isEditing}: PaymentVolumeProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const [corpayOnboardingFields] = useOnyx(ONYXKEYS.CORPAY_ONBOARDING_FIELDS); const policyID = reimbursementAccount?.achData?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); @@ -39,7 +38,7 @@ function PaymentVolume({onNext, isEditing}: PaymentVolumeProps) { }, {} as Record); }, [corpayOnboardingFields]); - const annualVolumeDefaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[ANNUAL_VOLUME] ?? reimbursementAccountDraft?.[ANNUAL_VOLUME] ?? ''; + const annualVolumeDefaultValue = reimbursementAccount?.achData?.corpay?.[ANNUAL_VOLUME] ?? ''; const validate = useCallback((values: FormOnyxValues): FormInputErrors => { return getFieldRequiredErrors(values, STEP_FIELDS); diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/RegistrationNumber.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/RegistrationNumber.tsx similarity index 92% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/RegistrationNumber.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/RegistrationNumber.tsx index 14480802e374..12c9aa9dd78c 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/RegistrationNumber.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/RegistrationNumber.tsx @@ -31,9 +31,8 @@ function RegistrationNumber({onNext, isEditing}: RegistrationNumberProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValue = - reimbursementAccount?.achData?.additionalData?.corpay?.[BUSINESS_REGISTRATION_INCORPORATION_NUMBER] ?? reimbursementAccountDraft?.[BUSINESS_REGISTRATION_INCORPORATION_NUMBER] ?? ''; - const businessStepCountryDraftValue = reimbursementAccount?.achData?.additionalData?.corpay?.[COMPANY_COUNTRY_CODE] ?? reimbursementAccountDraft?.[COMPANY_COUNTRY_CODE] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[BUSINESS_REGISTRATION_INCORPORATION_NUMBER] ?? ''; + const businessStepCountryDraftValue = reimbursementAccount?.achData?.corpay?.[COMPANY_COUNTRY_CODE] ?? reimbursementAccountDraft?.[COMPANY_COUNTRY_CODE] ?? ''; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/TaxIDEINNumber.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/TaxIDEINNumber.tsx similarity index 89% rename from src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/TaxIDEINNumber.tsx rename to src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/TaxIDEINNumber.tsx index e57f2e3b909f..7cd149beb83c 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/TaxIDEINNumber.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/TaxIDEINNumber.tsx @@ -19,8 +19,7 @@ function TaxIDEINNumber({onNext, onMove, isEditing}: TaxIDEINNumberProps) { const {translate} = useLocalize(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[TAX_ID_EIN_NUMBER] ?? reimbursementAccountDraft?.[TAX_ID_EIN_NUMBER] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[TAX_ID_EIN_NUMBER] ?? ''; const validate = useCallback((values: FormOnyxValues): FormInputErrors => { return getFieldRequiredErrors(values, STEP_FIELDS); diff --git a/src/pages/ReimbursementAccount/NonUSD/Country/Country.tsx b/src/pages/ReimbursementAccount/NonUSD/Country/Country.tsx index 2faf8ac082c4..4654581fbbb9 100644 --- a/src/pages/ReimbursementAccount/NonUSD/Country/Country.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/Country/Country.tsx @@ -5,7 +5,7 @@ import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; import CONST from '@src/CONST'; -import Confirmation from './substeps/Confirmation'; +import Confirmation from './subSteps/Confirmation'; type CountryProps = { /** Handles back button press */ diff --git a/src/pages/ReimbursementAccount/NonUSD/Country/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/Country/subSteps/Confirmation.tsx similarity index 89% rename from src/pages/ReimbursementAccount/NonUSD/Country/substeps/Confirmation.tsx rename to src/pages/ReimbursementAccount/NonUSD/Country/subSteps/Confirmation.tsx index f2a7f20755a8..b75cc1045525 100644 --- a/src/pages/ReimbursementAccount/NonUSD/Country/substeps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/Country/subSteps/Confirmation.tsx @@ -13,9 +13,9 @@ import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors} from '@libs/ValidationUtils'; import mapCurrencyToCountry from '@pages/ReimbursementAccount/utils/mapCurrencyToCountry'; -import * as FormActions from '@userActions/FormActions'; +import {clearErrors, setDraftValues} from '@userActions/FormActions'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -36,7 +36,7 @@ function Confirmation({onNext}: SubStepProps) { const shouldAllowChange = currency === CONST.CURRENCY.EUR; const currencyMappedToCountry = mapCurrencyToCountry(currency); - const countryDefaultValue = reimbursementAccount?.achData?.additionalData?.[COUNTRY] ?? reimbursementAccountDraft?.[COUNTRY] ?? ''; + const countryDefaultValue = reimbursementAccount?.achData?.[COUNTRY] ?? reimbursementAccountDraft?.[COUNTRY] ?? ''; const [selectedCountry, setSelectedCountry] = useState(countryDefaultValue); const disableSubmit = !(currency in CONST.CURRENCY); @@ -50,16 +50,16 @@ function Confirmation({onNext}: SubStepProps) { }; const handleSelectingCountry = (country: string) => { - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[COUNTRY]: country}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[COUNTRY]: country}); setSelectedCountry(country); }; const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - return ValidationUtils.getFieldRequiredErrors(values, [COUNTRY]); + return getFieldRequiredErrors(values, [COUNTRY]); }, []); useEffect(() => { - FormActions.clearErrors(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM); + clearErrors(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM); }); useEffect(() => { @@ -67,7 +67,7 @@ function Confirmation({onNext}: SubStepProps) { return; } - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[COUNTRY]: currencyMappedToCountry}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[COUNTRY]: currencyMappedToCountry}); setSelectedCountry(currencyMappedToCountry); }, [currency, currencyMappedToCountry]); diff --git a/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlow.tsx b/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlow.tsx new file mode 100644 index 000000000000..1dd74768ce92 --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/NonUSDVerifiedBankAccountFlow.tsx @@ -0,0 +1,121 @@ +import React from 'react'; +import CONST from '@src/CONST'; +import Agreements from './Agreements'; +import BankInfo from './BankInfo/BankInfo'; +import BeneficialOwnerInfo from './BeneficialOwnerInfo/BeneficialOwnerInfo'; +import BusinessInfo from './BusinessInfo/BusinessInfo'; +import Country from './Country/Country'; +import Finish from './Finish'; +import SignerInfo from './SignerInfo'; + +type NonUSDVerifiedBankAccountFlowProps = { + nonUSDBankAccountStep: string; + setNonUSDBankAccountStep: (step: string | null) => void; + setShouldShowContinueSetupButton: (shouldShowConnectedVerifiedBankAccount: boolean) => void; +}; + +function NonUSDVerifiedBankAccountFlow({nonUSDBankAccountStep, setNonUSDBankAccountStep, setShouldShowContinueSetupButton}: NonUSDVerifiedBankAccountFlowProps) { + const handleNextNonUSDBankAccountStep = () => { + switch (nonUSDBankAccountStep) { + case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.FINISH); + break; + default: + return null; + } + }; + + const nonUSDBankAccountsGoBack = () => { + switch (nonUSDBankAccountStep) { + case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: + setShouldShowContinueSetupButton(true); + setNonUSDBankAccountStep(null); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO); + break; + case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO); + break; + default: + return null; + } + }; + + switch (nonUSDBankAccountStep) { + case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: + return ( + + ); + case CONST.NON_USD_BANK_ACCOUNT.STEP.FINISH: + return ; + default: + return null; + } +} + +NonUSDVerifiedBankAccountFlow.displayName = 'NonUSDVerifiedBankAccountFlow'; + +export default NonUSDVerifiedBankAccountFlow; diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/index.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/index.tsx index 1ba513c07807..045afafcc313 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/index.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/index.tsx @@ -12,11 +12,11 @@ import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; import EnterEmail from './EnterEmail'; import HangTight from './HangTight'; -import Confirmation from './substeps/Confirmation'; -import DateOfBirth from './substeps/DateOfBirth'; -import JobTitle from './substeps/JobTitle'; -import Name from './substeps/Name'; -import UploadDocuments from './substeps/UploadDocuments'; +import Confirmation from './subSteps/Confirmation'; +import DateOfBirth from './subSteps/DateOfBirth'; +import JobTitle from './subSteps/JobTitle'; +import Name from './subSteps/Name'; +import UploadDocuments from './subSteps/UploadDocuments'; type SignerInfoProps = { /** Handles back button press */ @@ -40,13 +40,13 @@ function SignerInfo({onBackButtonPress, onSubmit}: SignerInfoProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const policyID = reimbursementAccount?.achData?.policyID ?? '-1'; + const policyID = reimbursementAccount?.achData?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); const currency = policy?.outputCurrency ?? ''; // TODO set this based on param from redirect or BE response const isSecondSigner = false; - const isUserOwner = reimbursementAccount?.achData?.additionalData?.corpay?.[OWNS_MORE_THAN_25_PERCENT] ?? reimbursementAccountDraft?.[OWNS_MORE_THAN_25_PERCENT] ?? false; - const companyName = reimbursementAccount?.achData?.additionalData?.corpay?.[COMPANY_NAME] ?? reimbursementAccountDraft?.[COMPANY_NAME] ?? ''; + const isUserOwner = reimbursementAccount?.achData?.corpay?.[OWNS_MORE_THAN_25_PERCENT] ?? reimbursementAccountDraft?.[OWNS_MORE_THAN_25_PERCENT] ?? false; + const companyName = reimbursementAccount?.achData?.corpay?.[COMPANY_NAME] ?? reimbursementAccountDraft?.[COMPANY_NAME] ?? ''; const [currentSubStep, setCurrentSubStep] = useState(SUBSTEP.IS_DIRECTOR); const [isUserDirector, setIsUserDirector] = useState(false); diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Confirmation.tsx similarity index 91% rename from src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Confirmation.tsx rename to src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Confirmation.tsx index 56966bc45887..b1fb28bd39da 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Confirmation.tsx @@ -3,7 +3,7 @@ import {useOnyx} from 'react-native-onyx'; import ConfirmationStep from '@components/SubStepForms/ConfirmationStep'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -29,8 +29,8 @@ function Confirmation({onNext, onMove, isEditing, isSecondSigner}: ConfirmationP const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const isUserOwner = reimbursementAccount?.achData?.additionalData?.corpay?.[OWNS_MORE_THAN_25_PERCENT] ?? reimbursementAccountDraft?.[OWNS_MORE_THAN_25_PERCENT] ?? false; - const values = useMemo(() => getSubstepValues(SINGER_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const isUserOwner = reimbursementAccount?.achData?.corpay?.[OWNS_MORE_THAN_25_PERCENT] ?? reimbursementAccountDraft?.[OWNS_MORE_THAN_25_PERCENT] ?? false; + const values = useMemo(() => getSubStepValues(SINGER_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const IDs = values[isSecondSigner ? SECOND_SIGNER_COPY_OF_ID : SIGNER_COPY_OF_ID]; const proofs = values[isSecondSigner ? SECOND_SIGNER_ADDRESS_PROOF : SIGNER_ADDRESS_PROOF]; diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/DateOfBirth.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/DateOfBirth.tsx similarity index 93% rename from src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/DateOfBirth.tsx rename to src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/DateOfBirth.tsx index ba83edd08d97..538cff1cf8cf 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/DateOfBirth.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/DateOfBirth.tsx @@ -20,7 +20,7 @@ function DateOfBirth({onNext, onMove, isEditing, isSecondSigner}: DateOfBirthPro const inputID = isSecondSigner ? SECOND_SIGNER_DATE_OF_BIRTH : SIGNER_DATE_OF_BIRTH; const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; const handleSubmit = useReimbursementAccountStepFormSubmit({ fieldIds: [inputID], diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/JobTitle.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/JobTitle.tsx similarity index 88% rename from src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/JobTitle.tsx rename to src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/JobTitle.tsx index 30da9f4f54ec..24f3310243f1 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/JobTitle.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/JobTitle.tsx @@ -5,7 +5,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep'; import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors} from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -20,11 +20,11 @@ function JobTitle({onNext, onMove, isEditing, isSecondSigner}: JobTitleProps) { const inputID = isSecondSigner ? SECOND_SIGNER_JOB_TITLE : SIGNER_JOB_TITLE; const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const defaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { - return ValidationUtils.getFieldRequiredErrors(values, [inputID]); + return getFieldRequiredErrors(values, [inputID]); }, [inputID], ); diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Name.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Name.tsx similarity index 85% rename from src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Name.tsx rename to src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Name.tsx index 97d3c1f8b27f..1f102a0b37bb 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Name.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/Name.tsx @@ -5,7 +5,7 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep'; import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors, isValidLegalName} from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -20,13 +20,13 @@ function Name({onNext, onMove, isEditing, isSecondSigner}: NameProps) { const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const inputID = isSecondSigner ? SECOND_SIGNER_FULL_NAME : SIGNER_FULL_NAME; - const defaultValue = reimbursementAccount?.achData?.additionalData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; + const defaultValue = reimbursementAccount?.achData?.corpay?.[inputID] ?? reimbursementAccountDraft?.[inputID] ?? ''; const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, [inputID]); + const errors = getFieldRequiredErrors(values, [inputID]); - if (values[inputID] && !ValidationUtils.isValidLegalName(values[inputID])) { + if (values[inputID] && !isValidLegalName(values[inputID])) { errors[inputID] = translate('bankAccount.error.fullName'); } diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/UploadDocuments.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx similarity index 82% rename from src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/UploadDocuments.tsx rename to src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx index ed47b4bf235e..449d5a74a9d2 100644 --- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/UploadDocuments.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx @@ -11,9 +11,9 @@ import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {getFieldRequiredErrors} from '@libs/ValidationUtils'; import WhyLink from '@pages/ReimbursementAccount/NonUSD/WhyLink'; -import * as FormActions from '@userActions/FormActions'; +import {setDraftValues} from '@userActions/FormActions'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -31,15 +31,15 @@ function UploadDocuments({onNext, isEditing}: UploadDocumentsProps) { const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const defaultValues = { - [SIGNER_COPY_OF_ID]: reimbursementAccount?.achData?.additionalData?.corpay?.[SIGNER_COPY_OF_ID] ?? reimbursementAccountDraft?.[SIGNER_COPY_OF_ID] ?? [], - [SIGNER_ADDRESS_PROOF]: reimbursementAccount?.achData?.additionalData?.corpay?.[SIGNER_ADDRESS_PROOF] ?? reimbursementAccountDraft?.[SIGNER_ADDRESS_PROOF] ?? [], + [SIGNER_COPY_OF_ID]: reimbursementAccount?.achData?.corpay?.[SIGNER_COPY_OF_ID] ?? reimbursementAccountDraft?.[SIGNER_COPY_OF_ID] ?? [], + [SIGNER_ADDRESS_PROOF]: reimbursementAccount?.achData?.corpay?.[SIGNER_ADDRESS_PROOF] ?? reimbursementAccountDraft?.[SIGNER_ADDRESS_PROOF] ?? [], }; const [uploadedIDs, setUploadedID] = useState(defaultValues[SIGNER_ADDRESS_PROOF]); const [uploadedProofsOfAddress, setUploadedProofOfAddress] = useState(defaultValues[SIGNER_ADDRESS_PROOF]); const validate = useCallback((values: FormOnyxValues): FormInputErrors => { - return ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + return getFieldRequiredErrors(values, STEP_FIELDS); }, []); const handleSubmit = useReimbursementAccountStepFormSubmit({ @@ -49,24 +49,24 @@ function UploadDocuments({onNext, isEditing}: UploadDocumentsProps) { }); const handleSelectIDFile = (files: FileObject[]) => { - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_COPY_OF_ID]: [...uploadedIDs, ...files]}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_COPY_OF_ID]: [...uploadedIDs, ...files]}); setUploadedID((prev) => [...prev, ...files]); }; const handleRemoveIDFile = (fileUri: string) => { const newUploadedIDs = uploadedIDs.filter((file) => file.uri !== fileUri); - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_COPY_OF_ID]: newUploadedIDs}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_COPY_OF_ID]: newUploadedIDs}); setUploadedID(newUploadedIDs); }; const handleSelectProofOfAddressFile = (files: FileObject[]) => { - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_ADDRESS_PROOF]: [...uploadedProofsOfAddress, ...files]}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_ADDRESS_PROOF]: [...uploadedProofsOfAddress, ...files]}); setUploadedProofOfAddress((prev) => [...prev, ...files]); }; const handleRemoveProofOfAddressFile = (fileUri: string) => { const newUploadedProofsOfAddress = uploadedProofsOfAddress.filter((file) => file.uri !== fileUri); - FormActions.setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_ADDRESS_PROOF]: newUploadedProofsOfAddress}); + setDraftValues(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM, {[SIGNER_ADDRESS_PROOF]: newUploadedProofsOfAddress}); setUploadedProofOfAddress(newUploadedProofsOfAddress); }; diff --git a/src/pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues.ts b/src/pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues.ts new file mode 100644 index 000000000000..795c338954ac --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues.ts @@ -0,0 +1,68 @@ +import type {OnyxEntry} from 'react-native-onyx'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import type {ReimbursementAccount} from '@src/types/onyx'; +import type {ACHData, Corpay} from '@src/types/onyx/ReimbursementAccount'; + +type SubStepValues = { + [TKey in TProps]: ReimbursementAccountForm[TKey]; +}; + +/** Some values are send under certain key and saved under different key by BE. + * This is forced on BE side which is asking us to send it under certain keys but then saves it and returns under different keys. + * This is why we need a separate util just for this step, so we can correctly gather default values for such cases */ +function getBankInfoStepValues( + inputKeys: Record, + reimbursementAccountDraft: OnyxEntry, + reimbursementAccount: OnyxEntry, +): SubStepValues { + return Object.entries(inputKeys).reduce((acc, [, value]) => { + switch (value) { + case INPUT_IDS.ADDITIONAL_DATA.ROUTING_CODE: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.BANK_INFO_STEP.ROUTING_NUMBER as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.CORPAY.SWIFT_BIC_CODE: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.BANK_INFO_STEP.ROUTING_NUMBER as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_NAME: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.ADDRESS_NAME as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_ADDRESS_1: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STREET as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_CITY: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.ADDRESS_CITY as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_REGION: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STATE as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + case INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_POSTAL: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[INPUT_IDS.ADDITIONAL_DATA.ADDRESS_ZIP_CODE as keyof ACHData] ?? + '') as ReimbursementAccountForm[TProps]; + break; + default: + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[value as keyof ACHData] ?? + reimbursementAccount?.achData?.corpay?.[value as keyof Corpay] ?? + '') as ReimbursementAccountForm[TProps]; + break; + } + return acc; + }, {} as SubStepValues); +} + +export {getBankInfoStepValues}; +export type {SubStepValues}; diff --git a/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBankInfoStep.ts b/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBankInfoStep.ts new file mode 100644 index 000000000000..8b14dd7cde01 --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBankInfoStep.ts @@ -0,0 +1,26 @@ +import CONST from '@src/CONST'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import type {CorpayFields} from '@src/types/onyx'; +import type {SubStepValues} from './getBankInfoStepValues'; + +/** + * Returns the initial subStep for the Bank info step based on already existing data + */ +function getInitialSubStepForBusinessInfoStep(data: SubStepValues, corpayFields: CorpayFields | undefined): number { + const bankAccountDetailsFields = corpayFields?.formFields?.filter((field) => !field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX)); + const accountHolderDetailsFields = corpayFields?.formFields?.filter((field) => field.id.includes(CONST.NON_USD_BANK_ACCOUNT.BANK_INFO_STEP_ACCOUNT_HOLDER_KEY_PREFIX)); + const hasAnyMissingBankAccountDetails = bankAccountDetailsFields?.some((field) => data?.[field.id as keyof ReimbursementAccountForm] === ''); + const hasAnyMissingAccountHolderDetails = accountHolderDetailsFields?.some((field) => data?.[field.id as keyof ReimbursementAccountForm] === ''); + + if (corpayFields === undefined || hasAnyMissingBankAccountDetails) { + return 0; + } + + if (hasAnyMissingAccountHolderDetails) { + return 1; + } + + return 2; +} + +export default getInitialSubStepForBusinessInfoStep; diff --git a/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBusinessInfoStep.ts b/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBusinessInfoStep.ts new file mode 100644 index 000000000000..854d0bb1724f --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/utils/getInitialSubStepForBusinessInfoStep.ts @@ -0,0 +1,62 @@ +import CONST from '@src/CONST'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; + +const BUSINESS_INFO_STEP_KEYS = INPUT_IDS.ADDITIONAL_DATA.CORPAY; + +/** + * Returns the initial subStep for the Business info step based on already existing data + */ +function getInitialSubStepForBusinessInfoStep(data: Record): number { + if (data[BUSINESS_INFO_STEP_KEYS.COMPANY_NAME] === '') { + return 0; + } + + if ( + data[BUSINESS_INFO_STEP_KEYS.COMPANY_STREET] === '' || + data[BUSINESS_INFO_STEP_KEYS.COMPANY_CITY] === '' || + data[BUSINESS_INFO_STEP_KEYS.COMPANY_POSTAL_CODE] === '' || + data[BUSINESS_INFO_STEP_KEYS.COMPANY_COUNTRY_CODE] === '' || + ((data[BUSINESS_INFO_STEP_KEYS.COMPANY_COUNTRY_CODE] === CONST.COUNTRY.US || data[BUSINESS_INFO_STEP_KEYS.COMPANY_COUNTRY_CODE] === CONST.COUNTRY.CA) && + data[BUSINESS_INFO_STEP_KEYS.COMPANY_STATE] === '') || + (data[BUSINESS_INFO_STEP_KEYS.COMPANY_COUNTRY_CODE] === '' && data[BUSINESS_INFO_STEP_KEYS.COMPANY_STATE] === '') + ) { + return 1; + } + + if (data[BUSINESS_INFO_STEP_KEYS.BUSINESS_CONTACT_NUMBER] === '' || data[BUSINESS_INFO_STEP_KEYS.BUSINESS_CONFIRMATION_EMAIL] === '') { + return 2; + } + + if (data[BUSINESS_INFO_STEP_KEYS.BUSINESS_REGISTRATION_INCORPORATION_NUMBER] === '') { + return 3; + } + + if (data[BUSINESS_INFO_STEP_KEYS.TAX_ID_EIN_NUMBER] === '') { + return 4; + } + + if ( + data[BUSINESS_INFO_STEP_KEYS.FORMATION_INCORPORATION_COUNTRY_CODE] === '' || + ((data[BUSINESS_INFO_STEP_KEYS.FORMATION_INCORPORATION_COUNTRY_CODE] === CONST.COUNTRY.US || + data[BUSINESS_INFO_STEP_KEYS.FORMATION_INCORPORATION_COUNTRY_CODE] === CONST.COUNTRY.CA) && + data[BUSINESS_INFO_STEP_KEYS.FORMATION_INCORPORATION_STATE] === '') + ) { + return 5; + } + + if (data[BUSINESS_INFO_STEP_KEYS.BUSINESS_CATEGORY] === '' || data[BUSINESS_INFO_STEP_KEYS.APPLICANT_TYPE_ID] === '') { + return 6; + } + + if (data[BUSINESS_INFO_STEP_KEYS.ANNUAL_VOLUME] === '') { + return 7; + } + + if (data[BUSINESS_INFO_STEP_KEYS.TRADE_VOLUME] === '') { + return 8; + } + + return 9; +} + +export default getInitialSubStepForBusinessInfoStep; diff --git a/src/pages/ReimbursementAccount/NonUSD/utils/getInputKeysForBankInfoStep.ts b/src/pages/ReimbursementAccount/NonUSD/utils/getInputKeysForBankInfoStep.ts new file mode 100644 index 000000000000..4557054f71be --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/utils/getInputKeysForBankInfoStep.ts @@ -0,0 +1,12 @@ +import type {ReimbursementAccountForm} from '@src/types/form'; +import type {CorpayFields} from '@src/types/onyx'; + +function getInputKeysForBankInfoStep(corpayFields: CorpayFields | undefined): Record { + const keys: Record = {}; + corpayFields?.formFields?.forEach((field) => { + keys[field.id] = field.id as keyof ReimbursementAccountForm; + }); + return keys; +} + +export default getInputKeysForBankInfoStep; diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx index 35c89cc72285..1d5329d75fc5 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx +++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx @@ -1,6 +1,6 @@ import {Str} from 'expensify-common'; import lodashPick from 'lodash/pick'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -16,13 +16,12 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import usePrevious from '@hooks/usePrevious'; import useThemeStyles from '@hooks/useThemeStyles'; -import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirectURI'; import BankAccount from '@libs/models/BankAccount'; import Navigation from '@libs/Navigation/Navigation'; -import type {PlatformStackRouteProp, PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types'; import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils'; -import {getRouteForCurrentStep, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils'; +import {getRouteForCurrentStep} from '@libs/ReimbursementAccountUtils'; import shouldReopenOnfido from '@libs/shouldReopenOnfido'; import type {WithPolicyOnyxProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; @@ -41,90 +40,28 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {InputID} from '@src/types/form/ReimbursementAccountForm'; -import type {ACHDataReimbursementAccount, BankAccountStep as TBankAccountStep} from '@src/types/onyx/ReimbursementAccount'; +import type {ACHDataReimbursementAccount} from '@src/types/onyx/ReimbursementAccount'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import ACHContractStep from './ACHContractStep'; -import BankAccountStep from './BankAccountStep'; -import BeneficialOwnersStep from './BeneficialOwnersStep'; -import CompanyStep from './CompanyStep'; -import ConnectBankAccount from './ConnectBankAccount/ConnectBankAccount'; -import ContinueBankAccountSetup from './ContinueBankAccountSetup'; -import EnableBankAccount from './EnableBankAccount/EnableBankAccount'; -import Agreements from './NonUSD/Agreements'; -import BankInfo from './NonUSD/BankInfo/BankInfo'; -import BeneficialOwnerInfo from './NonUSD/BeneficialOwnerInfo/BeneficialOwnerInfo'; -import BusinessInfo from './NonUSD/BusinessInfo/BusinessInfo'; -import Country from './NonUSD/Country/Country'; -import Finish from './NonUSD/Finish'; -import SignerInfo from './NonUSD/SignerInfo'; -import RequestorStep from './RequestorStep'; +import ConnectedVerifiedBankAccount from './ConnectedVerifiedBankAccount'; +import NonUSDVerifiedBankAccountFlow from './NonUSD/NonUSDVerifiedBankAccountFlow'; +import USDVerifiedBankAccountFlow from './USD/USDVerifiedBankAccountFlow'; +import getFieldsForStep from './USD/utils/getFieldsForStep'; +import getStepToOpenFromRouteParams from './USD/utils/getStepToOpenFromRouteParams'; +import VerifiedBankAccountFlowEntryPoint from './VerifiedBankAccountFlowEntryPoint'; type ReimbursementAccountPageProps = WithPolicyOnyxProps & PlatformStackScreenProps; const SUPPORTED_FOREIGN_CURRENCIES: string[] = [CONST.CURRENCY.EUR, CONST.CURRENCY.GBP, CONST.CURRENCY.CAD, CONST.CURRENCY.AUD]; -/** - * We can pass stepToOpen in the URL to force which step to show. - * Mainly needed when user finished the flow in verifying state, and Ops ask them to modify some fields from a specific step. - */ -function getStepToOpenFromRouteParams(route: PlatformStackRouteProp): TBankAccountStep | '' { - switch (route.params.stepToOpen) { - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW: - return CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.COMPANY: - return CONST.BANK_ACCOUNT.STEP.COMPANY; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.PERSONAL_INFORMATION: - return CONST.BANK_ACCOUNT.STEP.REQUESTOR; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.BENEFICIAL_OWNERS: - return CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.CONTRACT: - return CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.VALIDATE: - return CONST.BANK_ACCOUNT.STEP.VALIDATION; - case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.ENABLE: - return CONST.BANK_ACCOUNT.STEP.ENABLE; - default: - return ''; - } -} - -/** - * Returns selected bank account fields based on field names provided. - */ -function getFieldsForStep(step: TBankAccountStep): InputID[] { - switch (step) { - case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT: - return ['routingNumber', 'accountNumber', 'bankName', 'plaidAccountID', 'plaidAccessToken', 'isSavings']; - case CONST.BANK_ACCOUNT.STEP.COMPANY: - return [ - 'companyName', - 'addressStreet', - 'addressZipCode', - 'addressCity', - 'addressState', - 'companyPhone', - 'website', - 'companyTaxID', - 'incorporationType', - 'incorporationDate', - 'incorporationState', - ]; - case CONST.BANK_ACCOUNT.STEP.REQUESTOR: - return ['firstName', 'lastName', 'dob', 'ssnLast4', 'requestorAddressStreet', 'requestorAddressCity', 'requestorAddressState', 'requestorAddressZipCode']; - default: - return []; - } -} - function ReimbursementAccountPage({route, policy, isLoadingPolicy}: ReimbursementAccountPageProps) { const session = useSession(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); - const [plaidLinkToken = ''] = useOnyx(ONYXKEYS.PLAID_LINK_TOKEN); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); + const [corpayFields] = useOnyx(ONYXKEYS.CORPAY_FIELDS); const [plaidCurrentEvent = ''] = useOnyx(ONYXKEYS.PLAID_CURRENT_EVENT); const [onfidoToken = ''] = useOnyx(ONYXKEYS.ONFIDO_TOKEN); const [isLoadingApp = false] = useOnyx(ONYXKEYS.IS_LOADING_APP); const [account] = useOnyx(ONYXKEYS.ACCOUNT); - const [isDebugModeEnabled] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.isDebugModeEnabled}); const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false); const policyName = policy?.name ?? ''; @@ -135,7 +72,16 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen const requestorStepRef = useRef(null); const prevReimbursementAccount = usePrevious(reimbursementAccount); const prevIsOffline = usePrevious(isOffline); + const policyCurrency = policy?.outputCurrency ?? ''; + const nonUSDCountryDraftValue = reimbursementAccountDraft?.country ?? ''; const {isDevelopment} = useEnvironment(); + const [isDebugModeEnabled] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.isDebugModeEnabled}); + + // TODO once nonUSD flow is complete update the flags below to reflect all supported currencies, this will be updated in - https://github.com/Expensify/App/issues/50912 + // TODO remove isDevelopment and isDebugModeEnabled flags once nonUSD flow is complete, this will be updated in - https://github.com/Expensify/App/issues/50912 + const hasUnsupportedCurrency = + isDevelopment || isDebugModeEnabled ? policyCurrency !== CONST.CURRENCY.USD && !SUPPORTED_FOREIGN_CURRENCIES.includes(policyCurrency) : policyCurrency !== CONST.CURRENCY.USD; + const hasForeignCurrency = isDevelopment || isDebugModeEnabled ? SUPPORTED_FOREIGN_CURRENCIES.includes(policyCurrency) : false; /** The SetupWithdrawalAccount flow allows us to continue the flow from various points depending on where the @@ -146,9 +92,11 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen */ const achData = reimbursementAccount?.achData; const isPreviousPolicy = policyIDParam === achData?.policyID; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const currentStep = !isPreviousPolicy ? CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT : achData?.currentStep || CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT; - const [nonUSDBankAccountStep, setNonUSDBankAccountStep] = useState(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); + const [nonUSDBankAccountStep, setNonUSDBankAccountStep] = useState(null); + const [USDBankAccountStep, setUSDBankAccountStep] = useState(null); function getBankAccountFields(fieldNames: InputID[]): Partial { return { @@ -159,21 +107,23 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen /** * Returns true if a VBBA exists in any state other than OPEN or LOCKED */ - function hasInProgressVBBA(): boolean { + const hasInProgressVBBA = useCallback((): boolean => { return !!achData?.bankAccountID && !!achData?.state && achData?.state !== BankAccount.STATE.OPEN && achData?.state !== BankAccount.STATE.LOCKED; - } + }, [achData?.bankAccountID, achData?.state]); - /* - * Calculates the state used to show the "Continue with setup" view. If a bank account setup is already in progress and - * no specific further step was passed in the url we'll show the workspace bank account reset modal if the user wishes to start over - */ - function getShouldShowContinueSetupButtonInitialValue(): boolean { - if (!hasInProgressVBBA()) { - // Since there is no VBBA in progress, we won't need to show the component ContinueBankAccountSetup - return false; + /** Returns true if user passed first step of flow for non USD VBBA */ + const hasInProgressNonUSDVBBA = useCallback((): boolean => { + return !!achData?.bankAccountID && !!achData?.created; + }, [achData?.bankAccountID, achData?.created]); + + /** Calculates the state used to show the "Continue with setup" view. */ + const getShouldShowContinueSetupButtonValue = useCallback(() => { + if (hasForeignCurrency) { + return hasInProgressNonUSDVBBA(); } - return achData?.state === BankAccount.STATE.PENDING || [CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT, ''].includes(getStepToOpenFromRouteParams(route)); - } + + return hasInProgressVBBA(); + }, [hasForeignCurrency, hasInProgressNonUSDVBBA, hasInProgressVBBA]); /** When this page is first opened, `reimbursementAccount` prop might not yet be fully loaded from Onyx. @@ -183,57 +133,8 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen which acts similarly to `componentDidUpdate` when the `reimbursementAccount` dependency changes. */ const [hasACHDataBeenLoaded, setHasACHDataBeenLoaded] = useState(reimbursementAccount !== CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA && isPreviousPolicy); - const [shouldShowContinueSetupButton, setShouldShowContinueSetupButton] = useState(() => getShouldShowContinueSetupButtonInitialValue()); - - const handleNextNonUSDBankAccountStep = () => { - switch (nonUSDBankAccountStep) { - case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.FINISH); - break; - default: - return null; - } - }; - - const nonUSDBankAccountsGoBack = () => { - switch (nonUSDBankAccountStep) { - case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: - Navigation.goBack(); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO); - break; - case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: - setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO); - break; - default: - return null; - } - }; + const [shouldShowContinueSetupButton, setShouldShowContinueSetupButton] = useState(() => getShouldShowContinueSetupButtonValue()); + const [shouldShowConnectedVerifiedBankAccount, setShouldShowConnectedVerifiedBankAccount] = useState(false); /** * Retrieve verified business bank account currently being set up. @@ -270,6 +171,16 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, []); // The empty dependency array ensures this runs only once after the component mounts. + useEffect(() => { + if (!isPreviousPolicy) { + return; + } + + // TODO double check condition for non USD accounts - will be done in https://github.com/Expensify/App/issues/50912 + setShouldShowConnectedVerifiedBankAccount(hasForeignCurrency ? !!achData?.corpay?.consentToPrivacyNotice : achData?.currentStep === CONST.BANK_ACCOUNT.STEP.ENABLE); + setShouldShowContinueSetupButton(getShouldShowContinueSetupButtonValue()); + }, [achData?.corpay?.consentToPrivacyNotice, achData?.currentStep, getShouldShowContinueSetupButtonValue, hasForeignCurrency, isPreviousPolicy]); + useEffect( () => { // Check for network change from offline to online @@ -326,10 +237,36 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen [isOffline, reimbursementAccount, route, hasACHDataBeenLoaded, shouldShowContinueSetupButton], ); - const setManualStep = () => { - setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL).then(() => { - setShouldShowContinueSetupButton(false); - }); + const continueUSDVBBASetup = () => { + setShouldShowContinueSetupButton(false); + setUSDBankAccountStep(currentStep); + }; + + const continueNonUSDVBBASetup = () => { + setShouldShowContinueSetupButton(false); + if (policyCurrency === CONST.CURRENCY.EUR && nonUSDCountryDraftValue !== '') { + setNonUSDBankAccountStep(corpayFields !== undefined ? CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO : CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); + return; + } + + if (achData?.created && achData?.corpay?.companyName === undefined) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO); + return; + } + + if (achData?.corpay?.companyName && achData?.corpay?.anyIndividualOwn25PercentOrMore === undefined) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO); + return; + } + + if (achData?.corpay?.anyIndividualOwn25PercentOrMore !== undefined && achData?.corpay?.signerFullName === undefined) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO); + return; + } + + if (achData?.corpay?.signerFullName && achData?.corpay?.authorizedToBindClientToAgreement === undefined) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS); + } }; const goBack = () => { @@ -342,6 +279,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen setShouldShowContinueSetupButton(true); } if (subStep) { + setUSDBankAccountStep(null); setBankAccountSubStep(null); setPlaidEvent(null); } else { @@ -386,7 +324,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen }; const isLoading = - (!!isLoadingApp || !!account?.isLoading || (reimbursementAccount?.isLoading && !reimbursementAccount?.isCreateCorpayBankAccount)) && + (isLoadingApp || !!account?.isLoading || (reimbursementAccount?.isLoading && !reimbursementAccount?.isCreateCorpayBankAccount)) && (!plaidCurrentEvent || plaidCurrentEvent === CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.EXIT); const shouldShowOfflineLoader = !( @@ -434,67 +372,11 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen const userHasPhonePrimaryEmail = Str.endsWith(session?.email ?? '', CONST.SMS.DOMAIN); const throttledDate = reimbursementAccount?.throttledDate ?? ''; - const policyCurrency = policy?.outputCurrency ?? ''; - // TODO once nonUSD flow is complete update the flag below to reflect all supported currencies, this will be updated in - https://github.com/Expensify/App/issues/50912 - const hasUnsupportedCurrency = policyCurrency !== CONST.CURRENCY.USD; - // TODO remove isDevelopment and isDebugModeEnabled flags once nonUSD flow is complete, this will be updated in - https://github.com/Expensify/App/issues/50912 - const hasForeignCurrency = SUPPORTED_FOREIGN_CURRENCIES.includes(policyCurrency) && (isDevelopment || isDebugModeEnabled); - if (userHasPhonePrimaryEmail) { errorText = translate('bankAccount.hasPhoneLoginError'); } else if (throttledDate) { errorText = translate('bankAccount.hasBeenThrottledError'); } else if (hasUnsupportedCurrency) { - if (hasForeignCurrency) { - switch (nonUSDBankAccountStep) { - case CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.BANK_INFO: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.BUSINESS_INFO: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.BENEFICIAL_OWNER_INFO: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.SIGNER_INFO: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.AGREEMENTS: - return ( - - ); - case CONST.NON_USD_BANK_ACCOUNT.STEP.FINISH: - return ; - default: - return null; - } - } errorText = translate('bankAccount.hasCurrencyError'); } @@ -504,7 +386,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen Navigation.goBack()} + onBackButtonPress={Navigation.goBack} /> {errorText} @@ -513,57 +395,55 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen ); } - if (shouldShowContinueSetupButton) { + if (shouldShowConnectedVerifiedBankAccount) { return ( - ); } - switch (currentStep) { - case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT: - return ( - - ); - case CONST.BANK_ACCOUNT.STEP.REQUESTOR: - return ( - - ); - case CONST.BANK_ACCOUNT.STEP.COMPANY: - return ; - case CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS: - return ; - case CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT: - return ; - case CONST.BANK_ACCOUNT.STEP.VALIDATION: - return ; - case CONST.BANK_ACCOUNT.STEP.ENABLE: - return ( - - ); - default: - return null; + if (hasForeignCurrency && nonUSDBankAccountStep !== null) { + return ( + + ); } + + if (USDBankAccountStep !== null) { + return ( + + ); + } + + return ( + + ); } ReimbursementAccountPage.displayName = 'ReimbursementAccountPage'; diff --git a/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx similarity index 80% rename from src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx rename to src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx index 8bb02fdda4d0..ad513746a9cc 100644 --- a/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx +++ b/src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx @@ -5,15 +5,15 @@ import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirectURI'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; -import * as BankAccounts from '@userActions/BankAccounts'; -import * as ReimbursementAccountUtils from '@userActions/ReimbursementAccount'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; +import {connectBankAccountManually, connectBankAccountWithPlaid, setBankAccountSubStep} from '@userActions/BankAccounts'; +import {hideBankAccountErrors, updateReimbursementAccountDraft} from '@userActions/ReimbursementAccount'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {ReimbursementAccountForm} from '@src/types/form'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import Manual from './substeps/Manual'; -import Plaid from './substeps/Plaid'; +import Manual from './subSteps/Manual'; +import Plaid from './subSteps/Plaid'; type BankInfoProps = { /** Goes to the previous step */ @@ -21,21 +21,28 @@ type BankInfoProps = { /** Current Policy ID */ policyID: string; + + /** Set the step of the USD verified bank account flow */ + setUSDBankAccountStep: (step: string | null) => void; +}; + +type BankInfoSubStepProps = SubStepProps & { + setUSDBankAccountStep: (step: string | null) => void; }; const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP; -const manualSubsteps: Array> = [Manual]; -const plaidSubsteps: Array> = [Plaid]; +const manualSubSteps: Array> = [Manual]; +const plaidSubSteps: Array> = [Plaid]; const receivedRedirectURI = getPlaidOAuthReceivedRedirectURI(); -function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { +function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfoProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const [plaidLinkToken] = useOnyx(ONYXKEYS.PLAID_LINK_TOKEN); const {translate} = useLocalize(); const [redirectedFromPlaidToManual, setRedirectedFromPlaidToManual] = React.useState(false); - const values = useMemo(() => getSubstepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]); let setupType = reimbursementAccount?.achData?.subStep ?? ''; @@ -49,7 +56,7 @@ function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { (submitData: unknown) => { const data = submitData as ReimbursementAccountForm; if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) { - BankAccounts.connectBankAccountManually( + connectBankAccountManually( bankAccountID, { [BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: data[BANK_INFO_STEP_KEYS.ROUTING_NUMBER] ?? '', @@ -63,7 +70,7 @@ function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { policyID, ); } else if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID) { - BankAccounts.connectBankAccountWithPlaid( + connectBankAccountWithPlaid( bankAccountID, { [BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: data[BANK_INFO_STEP_KEYS.ROUTING_NUMBER] ?? '', @@ -81,8 +88,8 @@ function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { [setupType, bankAccountID, policyID], ); - const bodyContent = setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID ? plaidSubsteps : manualSubsteps; - const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent, startFrom: 0, onFinished: submit}); + const bodyContent = setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID ? plaidSubSteps : manualSubSteps; + const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent, startFrom: 0, onFinished: submit}); // Some services user connects to via Plaid return dummy account numbers and routing numbers e.g. Chase // In this case we need to redirect user to manual flow to enter real account number and routing number @@ -110,9 +117,10 @@ function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { [BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID]: '', [BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: '', }; - ReimbursementAccountUtils.updateReimbursementAccountDraft(bankAccountData); - ReimbursementAccountUtils.hideBankAccountErrors(); - BankAccounts.setBankAccountSubStep(null); + updateReimbursementAccountDraft(bankAccountData); + hideBankAccountErrors(); + setBankAccountSubStep(null); + setUSDBankAccountStep(null); } } else { prevScreen(); @@ -132,6 +140,7 @@ function BankInfo({onBackButtonPress, policyID}: BankInfoProps) { isEditing={isEditing} onNext={nextScreen} onMove={moveTo} + setUSDBankAccountStep={setUSDBankAccountStep} /> ); diff --git a/src/pages/ReimbursementAccount/ExampleCheck.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/ExampleCheck.tsx similarity index 100% rename from src/pages/ReimbursementAccount/ExampleCheck.tsx rename to src/pages/ReimbursementAccount/USD/BankInfo/ExampleCheck.tsx diff --git a/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx similarity index 98% rename from src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx rename to src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx index 0d298f72796b..734855c254c3 100644 --- a/src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx +++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Manual.tsx @@ -11,7 +11,7 @@ import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccoun import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import ExampleCheckImage from '@pages/ReimbursementAccount/ExampleCheck'; +import ExampleCheckImage from '@pages/ReimbursementAccount/USD/BankInfo/ExampleCheck'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; diff --git a/src/pages/ReimbursementAccount/BankInfo/substeps/Plaid.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx similarity index 81% rename from src/pages/ReimbursementAccount/BankInfo/substeps/Plaid.tsx rename to src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx index 906bc8de8496..99b1fdd02a85 100644 --- a/src/pages/ReimbursementAccount/BankInfo/substeps/Plaid.tsx +++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx @@ -7,16 +7,18 @@ import InputWrapper from '@components/Form/InputWrapper'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as BankAccounts from '@userActions/BankAccounts'; -import * as ReimbursementAccountActions from '@userActions/ReimbursementAccount'; +import {setBankAccountSubStep, validatePlaidSelection} from '@userActions/BankAccounts'; +import {updateReimbursementAccountDraft} from '@userActions/ReimbursementAccount'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -type PlaidProps = SubStepProps; +type PlaidProps = SubStepProps & { + setUSDBankAccountStep: (step: string | null) => void; +}; const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP; -function Plaid({onNext}: PlaidProps) { +function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const [plaidData] = useOnyx(ONYXKEYS.PLAID_DATA); @@ -41,7 +43,7 @@ function Plaid({onNext}: PlaidProps) { [BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: plaidData?.[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN] ?? '', }; - ReimbursementAccountActions.updateReimbursementAccountDraft(bankAccountData); + updateReimbursementAccountDraft(bankAccountData); onNext(bankAccountData); }, [plaidData, reimbursementAccountDraft, onNext]); @@ -52,13 +54,19 @@ function Plaid({onNext}: PlaidProps) { if (isFocused || plaidBankAccounts.length) { return; } - BankAccounts.setBankAccountSubStep(null); - }, [isFocused, plaidData]); + setBankAccountSubStep(null); + setUSDBankAccountStep(null); + }, [isFocused, plaidData, setUSDBankAccountStep]); + + const handlePlaidExit = () => { + setBankAccountSubStep(null); + setUSDBankAccountStep(null); + }; return ( { - ReimbursementAccountActions.updateReimbursementAccountDraft({plaidAccountID}); + updateReimbursementAccountDraft({plaidAccountID}); }} plaidData={plaidData} - onExitPlaid={() => { - BankAccounts.setBankAccountSubStep(null); - }} + onExitPlaid={handlePlaidExit} allowDebit bankAccountID={bankAccountID} selectedPlaidAccountID={selectedPlaidAccountID} diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx similarity index 81% rename from src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx rename to src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx index ec894a400e16..ea9a711f43c1 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx +++ b/src/pages/ReimbursementAccount/USD/BeneficialOwnerInfo/BeneficialOwnersStep.tsx @@ -11,12 +11,12 @@ import {updateBeneficialOwnersForBankAccount} from '@userActions/BankAccounts'; import {setDraftValues} from '@userActions/FormActions'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import AddressUBO from './BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/AddressUBO'; -import ConfirmationUBO from './BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/ConfirmationUBO'; -import DateOfBirthUBO from './BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO'; -import LegalNameUBO from './BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/LegalNameUBO'; -import SocialSecurityNumberUBO from './BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/SocialSecurityNumberUBO'; -import CompanyOwnersListUBO from './BeneficialOwnerInfo/substeps/CompanyOwnersListUBO'; +import AddressUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/AddressUBO'; +import ConfirmationUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/ConfirmationUBO'; +import DateOfBirthUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/DateOfBirthUBO'; +import LegalNameUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/LegalNameUBO'; +import SocialSecurityNumberUBO from './subSteps/BeneficialOwnerDetailsFormSubSteps/SocialSecurityNumberUBO'; +import CompanyOwnersListUBO from './subSteps/CompanyOwnersListUBO'; type BeneficialOwnersStepProps = { /** Goes to the previous step */ @@ -52,7 +52,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { const [isEditingCreatedBeneficialOwner, setIsEditingCreatedBeneficialOwner] = useState(false); const [isUserUBO, setIsUserUBO] = useState(defaultValues.ownsMoreThan25Percent); const [isAnyoneElseUBO, setIsAnyoneElseUBO] = useState(defaultValues.hasOtherBeneficialOwners); - const [currentUBOSubstep, setCurrentUBOSubstep] = useState(1); + const [currentUBOSubStep, setCurrentUBOSubStep] = useState(1); const canAddMoreUBOS = beneficialOwnerKeys.length < (isUserUBO ? MAX_NUMBER_OF_UBOS - 1 : MAX_NUMBER_OF_UBOS); const submit = () => { @@ -92,7 +92,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { // Because beneficialOwnerKeys array is not yet updated at this point we need to check against lower MAX_NUMBER_OF_UBOS (account for the one that is being added) const isLastUBOThatCanBeAdded = beneficialOwnerKeys.length === (isUserUBO ? MAX_NUMBER_OF_UBOS - 2 : MAX_NUMBER_OF_UBOS - 1); - setCurrentUBOSubstep(isEditingCreatedBeneficialOwner || isLastUBOThatCanBeAdded ? SUBSTEP.UBOS_LIST : SUBSTEP.ARE_THERE_MORE_UBOS); + setCurrentUBOSubStep(isEditingCreatedBeneficialOwner || isLastUBOThatCanBeAdded ? SUBSTEP.UBOS_LIST : SUBSTEP.ARE_THERE_MORE_UBOS); setIsEditingCreatedBeneficialOwner(false); }; @@ -114,13 +114,13 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { const prepareBeneficialOwnerDetailsForm = () => { const beneficialOwnerID = Str.guid(); setBeneficialOwnerBeingModifiedID(beneficialOwnerID); - // Reset Beneficial Owner Details Form to first substep + // Reset Beneficial Owner Details Form to first subStep resetScreenIndex(); - setCurrentUBOSubstep(SUBSTEP.UBO_DETAILS_FORM); + setCurrentUBOSubStep(SUBSTEP.UBO_DETAILS_FORM); }; const handleNextUBOSubstep = (value: boolean) => { - if (currentUBOSubstep === SUBSTEP.IS_USER_UBO) { + if (currentUBOSubStep === SUBSTEP.IS_USER_UBO) { setIsUserUBO(value); // User is an owner but there are 4 other owners already added, so we remove last one @@ -128,15 +128,15 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { setBeneficialOwnerKeys((previousBeneficialOwners) => previousBeneficialOwners.slice(0, 3)); } - setCurrentUBOSubstep(SUBSTEP.IS_ANYONE_ELSE_UBO); + setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO); return; } - if (currentUBOSubstep === SUBSTEP.IS_ANYONE_ELSE_UBO) { + if (currentUBOSubStep === SUBSTEP.IS_ANYONE_ELSE_UBO) { setIsAnyoneElseUBO(value); if (!canAddMoreUBOS && value) { - setCurrentUBOSubstep(SUBSTEP.UBOS_LIST); + setCurrentUBOSubStep(SUBSTEP.UBOS_LIST); return; } @@ -153,24 +153,24 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { // User is an owner and no one else is an owner if (isUserUBO && !value) { - setCurrentUBOSubstep(SUBSTEP.UBOS_LIST); + setCurrentUBOSubStep(SUBSTEP.UBOS_LIST); return; } } // Are there more UBOs - if (currentUBOSubstep === SUBSTEP.ARE_THERE_MORE_UBOS) { + if (currentUBOSubStep === SUBSTEP.ARE_THERE_MORE_UBOS) { if (value) { prepareBeneficialOwnerDetailsForm(); return; } - setCurrentUBOSubstep(SUBSTEP.UBOS_LIST); + setCurrentUBOSubStep(SUBSTEP.UBOS_LIST); return; } // User reached the limit of UBOs - if (currentUBOSubstep === SUBSTEP.UBO_DETAILS_FORM && !canAddMoreUBOS) { - setCurrentUBOSubstep(SUBSTEP.UBOS_LIST); + if (currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && !canAddMoreUBOS) { + setCurrentUBOSubStep(SUBSTEP.UBOS_LIST); } }; @@ -181,28 +181,28 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { } // User goes back to previous step - if (currentUBOSubstep === SUBSTEP.IS_USER_UBO) { + if (currentUBOSubStep === SUBSTEP.IS_USER_UBO) { onBackButtonPress(); // User reached limit of UBOs and goes back to initial question about additional UBOs - } else if (currentUBOSubstep === SUBSTEP.UBOS_LIST && !canAddMoreUBOS) { - setCurrentUBOSubstep(SUBSTEP.IS_ANYONE_ELSE_UBO); + } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && !canAddMoreUBOS) { + setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO); // User goes back to last radio button - } else if (currentUBOSubstep === SUBSTEP.UBOS_LIST && isAnyoneElseUBO) { - setCurrentUBOSubstep(SUBSTEP.ARE_THERE_MORE_UBOS); - } else if (currentUBOSubstep === SUBSTEP.UBOS_LIST && isUserUBO && !isAnyoneElseUBO) { - setCurrentUBOSubstep(SUBSTEP.IS_ANYONE_ELSE_UBO); - // User moves between substeps of beneficial owner details form - } else if (currentUBOSubstep === SUBSTEP.UBO_DETAILS_FORM && screenIndex > 0) { + } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && isAnyoneElseUBO) { + setCurrentUBOSubStep(SUBSTEP.ARE_THERE_MORE_UBOS); + } else if (currentUBOSubStep === SUBSTEP.UBOS_LIST && isUserUBO && !isAnyoneElseUBO) { + setCurrentUBOSubStep(SUBSTEP.IS_ANYONE_ELSE_UBO); + // User moves between subSteps of beneficial owner details form + } else if (currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && screenIndex > 0) { prevScreen(); } else { - setCurrentUBOSubstep((currentSubstep) => currentSubstep - 1); + setCurrentUBOSubStep((currentSubstep) => currentSubstep - 1); } }; const handleUBOEdit = (beneficialOwnerID: string) => { setBeneficialOwnerBeingModifiedID(beneficialOwnerID); setIsEditingCreatedBeneficialOwner(true); - setCurrentUBOSubstep(SUBSTEP.UBO_DETAILS_FORM); + setCurrentUBOSubStep(SUBSTEP.UBO_DETAILS_FORM); }; return ( @@ -215,7 +215,7 @@ function BeneficialOwnersStep({onBackButtonPress}: BeneficialOwnersStepProps) { startStepIndex={4} stepNames={CONST.BANK_ACCOUNT.STEP_NAMES} > - {currentUBOSubstep === SUBSTEP.IS_USER_UBO && ( + {currentUBOSubStep === SUBSTEP.IS_USER_UBO && ( )} - {currentUBOSubstep === SUBSTEP.IS_ANYONE_ELSE_UBO && ( + {currentUBOSubStep === SUBSTEP.IS_ANYONE_ELSE_UBO && ( )} - {currentUBOSubstep === SUBSTEP.UBO_DETAILS_FORM && ( + {currentUBOSubStep === SUBSTEP.UBO_DETAILS_FORM && ( )} - {currentUBOSubstep === SUBSTEP.ARE_THERE_MORE_UBOS && ( + {currentUBOSubStep === SUBSTEP.ARE_THERE_MORE_UBOS && ( )} - {currentUBOSubstep === SUBSTEP.UBOS_LIST && ( + {currentUBOSubStep === SUBSTEP.UBOS_LIST && ( ; - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: OnyxEntry; -}; - -type CompanyOwnersListUBOProps = CompanyOwnersListUBOIOnyxProps & { +type CompanyOwnersListUBOProps = { /** Method called when user confirms data */ handleUBOsConfirmation: () => void; @@ -60,21 +37,16 @@ type CompanyOwnersListUBOProps = CompanyOwnersListUBOIOnyxProps & { const REQUESTOR_PERSONAL_INFO_KEYS = INPUT_IDS.PERSONAL_INFO_STEP; -function CompanyOwnersListUBO({ - reimbursementAccount = reimbursementAccountDefault, - reimbursementAccountDraft, - isAnyoneElseUBO, - isUserUBO, - handleUBOsConfirmation, - beneficialOwnerKeys, - handleUBOEdit, -}: CompanyOwnersListUBOProps) { +function CompanyOwnersListUBO({isAnyoneElseUBO, isUserUBO, handleUBOsConfirmation, beneficialOwnerKeys, handleUBOEdit}: CompanyOwnersListUBOProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const {isOffline} = useNetwork(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); + const isLoading = reimbursementAccount?.isLoading ?? false; - const requestorData = getSubstepValues(REQUESTOR_PERSONAL_INFO_KEYS, undefined, reimbursementAccount); + const requestorData = getSubStepValues(REQUESTOR_PERSONAL_INFO_KEYS, undefined, reimbursementAccount); const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount); const extraBeneficialOwners = @@ -157,12 +129,4 @@ function CompanyOwnersListUBO({ CompanyOwnersListUBO.displayName = 'CompanyOwnersListUBO'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, - reimbursementAccountDraft: { - key: ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, - }, -})(CompanyOwnersListUBO); +export default CompanyOwnersListUBO; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx similarity index 80% rename from src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx index 7f45de42122b..c2d8adf51c53 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/BusinessInfo.tsx @@ -8,21 +8,21 @@ import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ValidationUtils from '@libs/ValidationUtils'; -import getInitialSubstepForBusinessInfo from '@pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; -import * as BankAccounts from '@userActions/BankAccounts'; +import getInitialSubStepForBusinessInfo from '@pages/ReimbursementAccount/USD/utils/getInitialSubStepForBusinessInfo'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; +import {updateCompanyInformationForBankAccount} from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import AddressBusiness from './substeps/AddressBusiness'; -import ConfirmationBusiness from './substeps/ConfirmationBusiness'; -import IncorporationDateBusiness from './substeps/IncorporationDateBusiness'; -import IncorporationStateBusiness from './substeps/IncorporationStateBusiness'; -import NameBusiness from './substeps/NameBusiness'; -import PhoneNumberBusiness from './substeps/PhoneNumberBusiness'; -import TaxIdBusiness from './substeps/TaxIdBusiness'; -import TypeBusiness from './substeps/TypeBusiness/TypeBusiness'; -import WebsiteBusiness from './substeps/WebsiteBusiness'; +import AddressBusiness from './subSteps/AddressBusiness'; +import ConfirmationBusiness from './subSteps/ConfirmationBusiness'; +import IncorporationDateBusiness from './subSteps/IncorporationDateBusiness'; +import IncorporationStateBusiness from './subSteps/IncorporationStateBusiness'; +import NameBusiness from './subSteps/NameBusiness'; +import PhoneNumberBusiness from './subSteps/PhoneNumberBusiness'; +import TaxIdBusiness from './subSteps/TaxIdBusiness'; +import TypeBusiness from './subSteps/TypeBusiness/TypeBusiness'; +import WebsiteBusiness from './subSteps/WebsiteBusiness'; type BusinessInfoProps = { /** Goes to the previous step */ @@ -57,12 +57,12 @@ function BusinessInfo({onBackButtonPress}: BusinessInfoProps) { ); const policyID = reimbursementAccount?.achData?.policyID ?? '-1'; - const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const submit = useCallback( (isConfirmPage: boolean) => { const companyWebsite = Str.sanitizeURL(values.website, CONST.COMPANY_WEBSITE_DEFAULT_SCHEME); - BankAccounts.updateCompanyInformationForBankAccount( + updateCompanyInformationForBankAccount( Number(reimbursementAccount?.achData?.bankAccountID ?? '-1'), { ...values, @@ -78,7 +78,7 @@ function BusinessInfo({onBackButtonPress}: BusinessInfoProps) { [reimbursementAccount, values, getBankAccountFields, policyID], ); - const startFrom = useMemo(() => getInitialSubstepForBusinessInfo(values), [values]); + const startFrom = useMemo(() => getInitialSubStepForBusinessInfo(values), [values]); const { componentToRender: SubStep, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx similarity index 82% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx index 37a4db5eb146..d7e1d8df4de8 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/AddressBusiness.tsx @@ -1,6 +1,5 @@ import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import Text from '@components/Text'; @@ -12,14 +11,6 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import AddressFormFields from '@pages/ReimbursementAccount/AddressFormFields'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type AddressBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type AddressBusinessProps = AddressBusinessOnyxProps & SubStepProps; const COMPANY_BUSINESS_INFO_KEY = INPUT_IDS.BUSINESS_INFO_STEP; @@ -32,10 +23,12 @@ const INPUT_KEYS = { const STEP_FIELDS = [COMPANY_BUSINESS_INFO_KEY.STREET, COMPANY_BUSINESS_INFO_KEY.CITY, COMPANY_BUSINESS_INFO_KEY.STATE, COMPANY_BUSINESS_INFO_KEY.ZIP_CODE]; -function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) { +function AddressBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); @@ -93,9 +86,4 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusin AddressBusiness.displayName = 'AddressBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(AddressBusiness); +export default AddressBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx similarity index 84% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx index 23b59d76ffa7..4c0d2edee876 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/ConfirmationBusiness.tsx @@ -1,7 +1,6 @@ import type {CONST as COMMON_CONST} from 'expensify-common'; import React, {useCallback, useMemo} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -14,23 +13,11 @@ import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReimbursementAccountForm} from '@src/types/form'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type ConfirmationBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: OnyxEntry; -}; - -type ConfirmationBusinessProps = ConfirmationBusinessOnyxProps & SubStepProps; type States = keyof typeof COMMON_CONST.STATES; @@ -48,10 +35,13 @@ function ConfirmCompanyLabel() { ); } -function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}: ConfirmationBusinessProps) { +function ConfirmationBusiness({onNext, onMove}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); + const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); @@ -65,7 +55,7 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, [translate], ); - const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const defaultCheckboxState = reimbursementAccountDraft?.[BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; @@ -163,12 +153,4 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, ConfirmationBusiness.displayName = 'ConfirmationBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, - reimbursementAccountDraft: { - key: ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, - }, -})(ConfirmationBusiness); +export default ConfirmationBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx similarity index 73% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx index 168cb02fd925..fbf2f1e15b12 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationDateBusiness.tsx @@ -1,6 +1,5 @@ import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -12,27 +11,18 @@ import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReimbursementAccountForm} from '@src/types/form'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type IncorporationDateBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: OnyxEntry; -}; - -type IncorporationDateBusinessProps = IncorporationDateBusinessOnyxProps & SubStepProps; const COMPANY_INCORPORATION_DATE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_DATE; const STEP_FIELDS = [COMPANY_INCORPORATION_DATE_KEY]; -function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: IncorporationDateBusinessProps) { +function IncorporationDateBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); + const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); @@ -82,12 +72,4 @@ function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDr IncorporationDateBusiness.displayName = 'IncorporationDateBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, - reimbursementAccountDraft: { - key: ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, - }, -})(IncorporationDateBusiness); +export default IncorporationDateBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx similarity index 74% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx index 75a032b1568b..7e3fbad30e68 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/IncorporationStateBusiness.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -13,14 +12,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type IncorporationStateBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type IncorporationStateBusinessProps = IncorporationStateBusinessOnyxProps & SubStepProps; const COMPANY_INCORPORATION_STATE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_STATE; const STEP_FIELDS = [COMPANY_INCORPORATION_STATE_KEY]; @@ -28,9 +19,12 @@ const STEP_FIELDS = [COMPANY_INCORPORATION_STATE_KEY]; const validate = (values: FormOnyxValues): FormInputErrors => ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); -function IncorporationStateBusiness({reimbursementAccount, onNext, isEditing}: IncorporationStateBusinessProps) { +function IncorporationStateBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const defaultCompanyIncorporationState = reimbursementAccount?.achData?.incorporationState ?? ''; const handleSubmit = useReimbursementAccountStepFormSubmit({ @@ -63,9 +57,4 @@ function IncorporationStateBusiness({reimbursementAccount, onNext, isEditing}: I IncorporationStateBusiness.displayName = 'IncorporationStateBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(IncorporationStateBusiness); +export default IncorporationStateBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx similarity index 80% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx index 0d29f4718a36..b523381e4457 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/NameBusiness.tsx @@ -1,6 +1,5 @@ import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -14,22 +13,16 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type NameBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type NameBusinessProps = NameBusinessOnyxProps & SubStepProps; const COMPANY_NAME_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_NAME; const STEP_FIELDS = [COMPANY_NAME_KEY]; -function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessProps) { +function NameBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const defaultCompanyName = reimbursementAccount?.achData?.companyName ?? ''; const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? -1; @@ -82,9 +75,4 @@ function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessPro NameBusiness.displayName = 'NameBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(NameBusiness); +export default NameBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx similarity index 79% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx index 4dc6fc37b4f4..9e82accfe2f3 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/PhoneNumberBusiness.tsx @@ -1,6 +1,5 @@ import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -14,21 +13,16 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type PhoneNumberBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type PhoneNumberBusinessProps = PhoneNumberBusinessOnyxProps & SubStepProps; const COMPANY_PHONE_NUMBER_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_PHONE; const STEP_FIELDS = [COMPANY_PHONE_NUMBER_KEY]; -function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNumberBusinessProps) { +function PhoneNumberBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const defaultCompanyPhoneNumber = reimbursementAccount?.achData?.companyPhone ?? ''; const validate = useCallback( @@ -79,9 +73,4 @@ function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNum PhoneNumberBusiness.displayName = 'PhoneNumberBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(PhoneNumberBusiness); +export default PhoneNumberBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx similarity index 81% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx index 2c55a0b8c251..48f1b7f0665f 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TaxIdBusiness.tsx @@ -1,6 +1,5 @@ import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -14,20 +13,15 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; - -type TaxIdBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type TaxIdBusinessProps = TaxIdBusinessOnyxProps & SubStepProps; const COMPANY_TAX_ID_KEY = INPUT_IDS.BUSINESS_INFO_STEP.COMPANY_TAX_ID; const STEP_FIELDS = [COMPANY_TAX_ID_KEY]; -function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessProps) { +function TaxIdBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const defaultCompanyTaxId = reimbursementAccount?.achData?.companyTaxID ?? ''; const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? 0; const shouldDisableCompanyTaxID = !!(bankAccountID && defaultCompanyTaxId && reimbursementAccount?.achData?.state !== 'SETUP'); @@ -81,9 +75,4 @@ function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessP TaxIdBusiness.displayName = 'TaxIdBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(TaxIdBusiness); +export default TaxIdBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx similarity index 100% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/index.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/index.tsx similarity index 100% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/index.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/index.tsx diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/types.ts b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/types.ts similarity index 100% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/types.ts rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/BusinessTypePicker/types.ts diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/TypeBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx similarity index 76% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/TypeBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx index 3b4e89588044..4bb9cafb48ab 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/TypeBusiness.tsx +++ b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/TypeBusiness/TypeBusiness.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -12,22 +11,17 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import type {ReimbursementAccount} from '@src/types/onyx'; import BusinessTypePicker from './BusinessTypePicker'; -type TypeBusinessOnyxProps = { - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type TypeBusinessProps = TypeBusinessOnyxProps & SubStepProps; - const COMPANY_INCORPORATION_TYPE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_TYPE; const STEP_FIELDS = [COMPANY_INCORPORATION_TYPE_KEY]; -function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessProps) { +function TypeBusiness({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const validate = (values: FormOnyxValues): FormInputErrors => ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); @@ -63,9 +57,4 @@ function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessPro TypeBusiness.displayName = 'TypeBusiness'; -export default withOnyx({ - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(TypeBusiness); +export default TypeBusiness; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx b/src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx similarity index 100% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx rename to src/pages/ReimbursementAccount/USD/BusinessInfo/subSteps/WebsiteBusiness.tsx diff --git a/src/pages/ReimbursementAccount/CompleteVerification/CompleteVerification.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx similarity index 93% rename from src/pages/ReimbursementAccount/CompleteVerification/CompleteVerification.tsx rename to src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx index cbc9f8d7f403..d2f369a495dd 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/CompleteVerification.tsx +++ b/src/pages/ReimbursementAccount/USD/CompleteVerification/CompleteVerification.tsx @@ -1,16 +1,16 @@ -import type {ComponentType} from 'react'; import React, {useCallback, useMemo} from 'react'; +import type {ComponentType} from 'react'; import {useOnyx} from 'react-native-onyx'; import InteractiveStepWrapper from '@components/InteractiveStepWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import ConfirmAgreements from './substeps/ConfirmAgreements'; +import ConfirmAgreements from './subSteps/ConfirmAgreements'; type CompleteVerificationProps = { /** Handles back button press */ @@ -26,7 +26,7 @@ function CompleteVerification({onBackButtonPress}: CompleteVerificationProps) { const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); - const values = useMemo(() => getSubstepValues(COMPLETE_VERIFICATION_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(COMPLETE_VERIFICATION_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const policyID = reimbursementAccount?.achData?.policyID ?? '-1'; const submit = useCallback(() => { diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx similarity index 100% rename from src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx rename to src/pages/ReimbursementAccount/USD/CompleteVerification/subSteps/ConfirmAgreements.tsx diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx similarity index 65% rename from src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx rename to src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx index 078c216d836c..101d50df8669 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx +++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx @@ -1,7 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -9,50 +8,47 @@ import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import BankAccount from '@libs/models/BankAccount'; -import EnableBankAccount from '@pages/ReimbursementAccount/EnableBankAccount/EnableBankAccount'; +import ConnectedVerifiedBankAccount from '@pages/ReimbursementAccount/ConnectedVerifiedBankAccount'; import * as Report from '@userActions/Report'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Account, Policy, ReimbursementAccount} from '@src/types/onyx'; import BankAccountValidationForm from './components/BankAccountValidationForm'; import FinishChatCard from './components/FinishChatCard'; -type ConnectBankAccountOnyxProps = { - /** User's account who is setting up bank account */ - account: OnyxEntry; - - /** The policy which the user has access to and which the report is tied to */ - policy: OnyxEntry; - - /** Reimbursement account from ONYX */ - reimbursementAccount: OnyxEntry; -}; - -type ConnectBankAccountProps = ConnectBankAccountOnyxProps & { - /** Bank account currently in setup */ - reimbursementAccount: ReimbursementAccount; - +type ConnectBankAccountProps = { /** Handles back button press */ onBackButtonPress: () => void; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setUSDBankAccountStep: (step: string | null) => void; }; -function ConnectBankAccount({reimbursementAccount, onBackButtonPress, account, policy}: ConnectBankAccountProps) { +function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep}: ConnectBankAccountProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${reimbursementAccount?.achData?.policyID}}`); + const [account] = useOnyx(ONYXKEYS.ACCOUNT); + const handleNavigateToConciergeChat = () => Report.navigateToConciergeChat(true); - const bankAccountState = reimbursementAccount.achData?.state ?? ''; + const bankAccountState = reimbursementAccount?.achData?.state ?? ''; // If a user tries to navigate directly to the validate page we'll show them the EnableStep if (bankAccountState === BankAccount.STATE.OPEN) { return ( - ); } - const maxAttemptsReached = reimbursementAccount.maxAttemptsReached ?? false; + const maxAttemptsReached = reimbursementAccount?.maxAttemptsReached ?? false; const isBankAccountVerifying = !maxAttemptsReached && bankAccountState === BankAccount.STATE.VERIFYING; const isBankAccountPending = bankAccountState === BankAccount.STATE.PENDING; const requiresTwoFactorAuth = account?.requiresTwoFactorAuth ?? false; @@ -95,15 +91,4 @@ function ConnectBankAccount({reimbursementAccount, onBackButtonPress, account, p ConnectBankAccount.displayName = 'ConnectBankAccount'; -export default withOnyx({ - account: { - key: ONYXKEYS.ACCOUNT, - }, - policy: { - key: ({reimbursementAccount}) => `${ONYXKEYS.COLLECTION.POLICY}${reimbursementAccount?.achData?.policyID}`, - }, - // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM - reimbursementAccount: { - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - }, -})(ConnectBankAccount); +export default ConnectBankAccount; diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/BankAccountValidationForm.tsx similarity index 99% rename from src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx rename to src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/BankAccountValidationForm.tsx index fb878606aad9..14343762cfc8 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/components/BankAccountValidationForm.tsx +++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/BankAccountValidationForm.tsx @@ -21,7 +21,7 @@ import Enable2FACard from './Enable2FACard'; type BankAccountValidationFormProps = { /** Bank account currently in setup */ - reimbursementAccount: ReimbursementAccount; + reimbursementAccount?: ReimbursementAccount; /** Boolean required to display Enable2FACard component */ requiresTwoFactorAuth: boolean; diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/components/Enable2FACard.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/Enable2FACard.tsx similarity index 96% rename from src/pages/ReimbursementAccount/ConnectBankAccount/components/Enable2FACard.tsx rename to src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/Enable2FACard.tsx index 8c497aaf3697..e0d13bf654e3 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/components/Enable2FACard.tsx +++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/Enable2FACard.tsx @@ -6,7 +6,7 @@ import Section from '@components/Section'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import Navigation from '@libs/Navigation/Navigation'; +import Navigation from '@navigation/Navigation'; import ROUTES from '@src/ROUTES'; type Enable2FACardProps = { diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/components/FinishChatCard.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx similarity index 95% rename from src/pages/ReimbursementAccount/ConnectBankAccount/components/FinishChatCard.tsx rename to src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx index e6250c9767f8..930a3e2564de 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/components/FinishChatCard.tsx +++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/FinishChatCard.tsx @@ -16,7 +16,7 @@ import Enable2FACard from './Enable2FACard'; type FinishChatCardProps = { /** Bank account currently in setup */ - reimbursementAccount: ReimbursementAccount; + reimbursementAccount?: ReimbursementAccount; /** Boolean required to display Enable2FACard component */ requiresTwoFactorAuth: boolean; @@ -26,7 +26,7 @@ function FinishChatCard({requiresTwoFactorAuth, reimbursementAccount}: FinishCha const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = reimbursementAccount?.achData?.policyID ?? '-1'; - const shouldShowResetModal = reimbursementAccount.shouldShowResetModal ?? false; + const shouldShowResetModal = reimbursementAccount?.shouldShowResetModal ?? false; const handleNavigateToConciergeChat = () => Report.navigateToConciergeChat(true); return ( diff --git a/src/pages/ReimbursementAccount/PersonalInfo/HelpLinks.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks.tsx similarity index 100% rename from src/pages/ReimbursementAccount/PersonalInfo/HelpLinks.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks.tsx diff --git a/src/pages/ReimbursementAccount/PersonalInfo/PersonalInfo.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx similarity index 78% rename from src/pages/ReimbursementAccount/PersonalInfo/PersonalInfo.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx index 1764bde198af..f95f2cbd5223 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/PersonalInfo.tsx +++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/PersonalInfo.tsx @@ -5,17 +5,17 @@ import InteractiveStepWrapper from '@components/InteractiveStepWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; -import getInitialSubstepForPersonalInfo from '@pages/ReimbursementAccount/utils/getInitialSubstepForPersonalInfo'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; -import * as BankAccounts from '@userActions/BankAccounts'; +import getInitialSubStepForPersonalInfo from '@pages/ReimbursementAccount/USD/utils/getInitialSubStepForPersonalInfo'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; +import {updatePersonalInformationForBankAccount} from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import Address from './substeps/Address'; -import Confirmation from './substeps/Confirmation'; -import DateOfBirth from './substeps/DateOfBirth'; -import FullName from './substeps/FullName'; -import SocialSecurityNumber from './substeps/SocialSecurityNumber'; +import Address from './subSteps/Address'; +import Confirmation from './subSteps/Confirmation'; +import DateOfBirth from './subSteps/DateOfBirth'; +import FullName from './subSteps/FullName'; +import SocialSecurityNumber from './subSteps/SocialSecurityNumber'; type PersonalInfoProps = { /** Goes to the previous step */ @@ -32,15 +32,15 @@ function PersonalInfo({onBackButtonPress}: PersonalInfoProps, ref: React.Forward const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const policyID = reimbursementAccount?.achData?.policyID ?? '-1'; - const values = useMemo(() => getSubstepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '-1'); const submit = useCallback( (isConfirmPage: boolean) => { - BankAccounts.updatePersonalInformationForBankAccount(bankAccountID, {...values}, policyID, isConfirmPage); + updatePersonalInformationForBankAccount(bankAccountID, {...values}, policyID, isConfirmPage); }, [values, bankAccountID, policyID], ); - const startFrom = useMemo(() => getInitialSubstepForPersonalInfo(values), [values]); + const startFrom = useMemo(() => getInitialSubStepForPersonalInfo(values), [values]); const { componentToRender: SubStep, diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx similarity index 100% rename from src/pages/ReimbursementAccount/PersonalInfo/substeps/Address.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Address.tsx diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx similarity index 95% rename from src/pages/ReimbursementAccount/PersonalInfo/substeps/Confirmation.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx index 894ed0b17686..a5e28c657f16 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/Confirmation.tsx @@ -4,7 +4,7 @@ import ConfirmationStep from '@components/SubStepForms/ConfirmationStep'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import * as ErrorUtils from '@libs/ErrorUtils'; -import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import getSubStepValues from '@pages/ReimbursementAccount/utils/getSubStepValues'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; @@ -19,7 +19,7 @@ function Confirmation({onNext, onMove, isEditing}: SubStepProps) { const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT); const isLoading = reimbursementAccount?.isLoading ?? false; - const values = useMemo(() => getSubstepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); + const values = useMemo(() => getSubStepValues(PERSONAL_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount ?? {}); const summaryItems = [ diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx similarity index 95% rename from src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx index f6e7b084e0eb..68ebf324b22a 100644 --- a/src/pages/ReimbursementAccount/PersonalInfo/substeps/DateOfBirth.tsx +++ b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/DateOfBirth.tsx @@ -5,7 +5,7 @@ import useLocalize from '@hooks/useLocalize'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; -import HelpLinks from '@pages/ReimbursementAccount/PersonalInfo/HelpLinks'; +import HelpLinks from '@pages/ReimbursementAccount/USD/Requestor/PersonalInfo/HelpLinks'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx similarity index 100% rename from src/pages/ReimbursementAccount/PersonalInfo/substeps/FullName.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/FullName.tsx diff --git a/src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx b/src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx similarity index 100% rename from src/pages/ReimbursementAccount/PersonalInfo/substeps/SocialSecurityNumber.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/PersonalInfo/subSteps/SocialSecurityNumber.tsx diff --git a/src/pages/ReimbursementAccount/RequestorStep.tsx b/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx similarity index 100% rename from src/pages/ReimbursementAccount/RequestorStep.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx index ef2901b1370a..547da9e317ef 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.tsx +++ b/src/pages/ReimbursementAccount/USD/Requestor/RequestorStep.tsx @@ -1,5 +1,5 @@ -import type {ForwardedRef} from 'react'; import React, {forwardRef} from 'react'; +import type {ForwardedRef} from 'react'; import type {View} from 'react-native'; import PersonalInfo from './PersonalInfo/PersonalInfo'; import VerifyIdentity from './VerifyIdentity/VerifyIdentity'; diff --git a/src/pages/ReimbursementAccount/VerifyIdentity/VerifyIdentity.tsx b/src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx similarity index 100% rename from src/pages/ReimbursementAccount/VerifyIdentity/VerifyIdentity.tsx rename to src/pages/ReimbursementAccount/USD/Requestor/VerifyIdentity/VerifyIdentity.tsx diff --git a/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx b/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx new file mode 100644 index 000000000000..ba72458002e6 --- /dev/null +++ b/src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlow.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import type {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import BankInfo from './BankInfo/BankInfo'; +import BeneficialOwnersStep from './BeneficialOwnerInfo/BeneficialOwnersStep'; +import BusinessInfo from './BusinessInfo/BusinessInfo'; +import CompleteVerification from './CompleteVerification/CompleteVerification'; +import ConnectBankAccount from './ConnectBankAccount/ConnectBankAccount'; +import RequestorStep from './Requestor/RequestorStep'; + +type USDVerifiedBankAccountFlowProps = { + USDBankAccountStep: string; + policyID: string | undefined; + onBackButtonPress: () => void; + requestorStepRef: React.RefObject; + onfidoToken: string; + setUSDBankAccountStep: (step: string | null) => void; + setShouldShowConnectedVerifiedBankAccount: (shouldShowConnectedVerifiedBankAccount: boolean) => void; +}; + +function USDVerifiedBankAccountFlow({ + USDBankAccountStep, + policyID = '', + onBackButtonPress, + requestorStepRef, + onfidoToken, + setUSDBankAccountStep, + setShouldShowConnectedVerifiedBankAccount, +}: USDVerifiedBankAccountFlowProps) { + const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT); + + switch (USDBankAccountStep) { + case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT: + return ( + + ); + case CONST.BANK_ACCOUNT.STEP.REQUESTOR: + return ( + + ); + case CONST.BANK_ACCOUNT.STEP.COMPANY: + return ; + case CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS: + return ; + case CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT: + return ; + case CONST.BANK_ACCOUNT.STEP.VALIDATION: + return ( + + ); + default: + return null; + } +} + +USDVerifiedBankAccountFlow.displayName = 'USDVerifiedBankAccountFlow'; + +export default USDVerifiedBankAccountFlow; diff --git a/src/pages/ReimbursementAccount/USD/utils/getFieldsForStep.ts b/src/pages/ReimbursementAccount/USD/utils/getFieldsForStep.ts new file mode 100644 index 000000000000..ee00af3a315f --- /dev/null +++ b/src/pages/ReimbursementAccount/USD/utils/getFieldsForStep.ts @@ -0,0 +1,33 @@ +import CONST from '@src/CONST'; +import type {InputID} from '@src/types/form/ReimbursementAccountForm'; +import type {BankAccountStep as TBankAccountStep} from '@src/types/onyx/ReimbursementAccount'; + +/** + * Returns selected bank account fields based on field names provided. + */ +function getFieldsForStep(step: TBankAccountStep): InputID[] { + switch (step) { + case CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT: + return ['routingNumber', 'accountNumber', 'bankName', 'plaidAccountID', 'plaidAccessToken', 'isSavings']; + case CONST.BANK_ACCOUNT.STEP.COMPANY: + return [ + 'companyName', + 'addressStreet', + 'addressZipCode', + 'addressCity', + 'addressState', + 'companyPhone', + 'website', + 'companyTaxID', + 'incorporationType', + 'incorporationDate', + 'incorporationState', + ]; + case CONST.BANK_ACCOUNT.STEP.REQUESTOR: + return ['firstName', 'lastName', 'dob', 'ssnLast4', 'requestorAddressStreet', 'requestorAddressCity', 'requestorAddressState', 'requestorAddressZipCode']; + default: + return []; + } +} + +export default getFieldsForStep; diff --git a/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts b/src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForBusinessInfo.ts similarity index 74% rename from src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts rename to src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForBusinessInfo.ts index 7173455afd05..dca41edf7e98 100644 --- a/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts +++ b/src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForBusinessInfo.ts @@ -1,5 +1,5 @@ import {Str} from 'expensify-common'; -import * as ValidationUtils from '@libs/ValidationUtils'; +import {isValidWebsite} from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; import type {CompanyStepProps} from '@src/types/form/ReimbursementAccountForm'; @@ -7,9 +7,9 @@ import type {CompanyStepProps} from '@src/types/form/ReimbursementAccountForm'; const businessInfoStepKeys = INPUT_IDS.BUSINESS_INFO_STEP; /** - * Returns the initial substep for the Business Info step based on already existing data + * Returns the initial subStep for the Business Info step based on already existing data */ -function getInitialSubstepForBusinessInfo(data: CompanyStepProps): number { +function getInitialSubStepForBusinessInfo(data: CompanyStepProps): number { if (data[businessInfoStepKeys.COMPANY_NAME] === '') { return 0; } @@ -18,7 +18,7 @@ function getInitialSubstepForBusinessInfo(data: CompanyStepProps): number { return 1; } - if (!ValidationUtils.isValidWebsite(Str.sanitizeURL(data[businessInfoStepKeys.COMPANY_WEBSITE], CONST.COMPANY_WEBSITE_DEFAULT_SCHEME))) { + if (!isValidWebsite(Str.sanitizeURL(data[businessInfoStepKeys.COMPANY_WEBSITE], CONST.COMPANY_WEBSITE_DEFAULT_SCHEME))) { return 2; } @@ -45,4 +45,4 @@ function getInitialSubstepForBusinessInfo(data: CompanyStepProps): number { return 8; } -export default getInitialSubstepForBusinessInfo; +export default getInitialSubStepForBusinessInfo; diff --git a/src/pages/ReimbursementAccount/utils/getInitialSubstepForPersonalInfo.ts b/src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForPersonalInfo.ts similarity index 80% rename from src/pages/ReimbursementAccount/utils/getInitialSubstepForPersonalInfo.ts rename to src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForPersonalInfo.ts index 73cfff9e5980..da44017c7d1c 100644 --- a/src/pages/ReimbursementAccount/utils/getInitialSubstepForPersonalInfo.ts +++ b/src/pages/ReimbursementAccount/USD/utils/getInitialSubStepForPersonalInfo.ts @@ -4,9 +4,9 @@ import type {RequestorStepProps} from '@src/types/form/ReimbursementAccountForm' const personalInfoKeys = INPUT_IDS.PERSONAL_INFO_STEP; /** - * Returns the initial substep for the Personal Info step based on already existing data + * Returns the initial subStep for the Personal Info step based on already existing data */ -function getInitialSubstepForPersonalInfo(data: RequestorStepProps): number { +function getInitialSubStepForPersonalInfo(data: RequestorStepProps): number { if (data[personalInfoKeys.FIRST_NAME] === '' || data[personalInfoKeys.LAST_NAME] === '') { return 0; } @@ -26,4 +26,4 @@ function getInitialSubstepForPersonalInfo(data: RequestorStepProps): number { return 4; } -export default getInitialSubstepForPersonalInfo; +export default getInitialSubStepForPersonalInfo; diff --git a/src/pages/ReimbursementAccount/USD/utils/getStepToOpenFromRouteParams.ts b/src/pages/ReimbursementAccount/USD/utils/getStepToOpenFromRouteParams.ts new file mode 100644 index 000000000000..6aeb60749a65 --- /dev/null +++ b/src/pages/ReimbursementAccount/USD/utils/getStepToOpenFromRouteParams.ts @@ -0,0 +1,33 @@ +import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; +import type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types'; +import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils'; +import CONST from '@src/CONST'; +import type SCREENS from '@src/SCREENS'; +import type {BankAccountStep as TBankAccountStep} from '@src/types/onyx/ReimbursementAccount'; + +/** + * We can pass stepToOpen in the URL to force which step to show. + * Mainly needed when user finished the flow in verifying state, and Ops ask them to modify some fields from a specific step. + */ +function getStepToOpenFromRouteParams(route: PlatformStackRouteProp): TBankAccountStep | '' { + switch (route.params.stepToOpen) { + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW: + return CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.COMPANY: + return CONST.BANK_ACCOUNT.STEP.COMPANY; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.PERSONAL_INFORMATION: + return CONST.BANK_ACCOUNT.STEP.REQUESTOR; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.BENEFICIAL_OWNERS: + return CONST.BANK_ACCOUNT.STEP.BENEFICIAL_OWNERS; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.CONTRACT: + return CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.VALIDATE: + return CONST.BANK_ACCOUNT.STEP.VALIDATION; + case REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.ENABLE: + return CONST.BANK_ACCOUNT.STEP.ENABLE; + default: + return ''; + } +} + +export default getStepToOpenFromRouteParams; diff --git a/src/pages/ReimbursementAccount/utils/getValuesForBeneficialOwner.ts b/src/pages/ReimbursementAccount/USD/utils/getValuesForBeneficialOwner.ts similarity index 100% rename from src/pages/ReimbursementAccount/utils/getValuesForBeneficialOwner.ts rename to src/pages/ReimbursementAccount/USD/utils/getValuesForBeneficialOwner.ts diff --git a/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx b/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx new file mode 100644 index 000000000000..4998e5c974c0 --- /dev/null +++ b/src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx @@ -0,0 +1,312 @@ +import React, {useEffect, useMemo, useRef} from 'react'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import LottieAnimations from '@components/LottieAnimations'; +import MenuItem from '@components/MenuItem'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; +import ScreenWrapper from '@components/ScreenWrapper'; +import ScrollView from '@components/ScrollView'; +import Section from '@components/Section'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; +import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {getEarliestErrorField, getLatestErrorField} from '@libs/ErrorUtils'; +import getPlaidDesktopMessage from '@libs/getPlaidDesktopMessage'; +import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils'; +import WorkspaceResetBankAccountModal from '@pages/workspace/WorkspaceResetBankAccountModal'; +import {openPlaidView, updateReimbursementAccountDraft} from '@userActions/BankAccounts'; +import {openExternalLink, openExternalLinkWithToken} from '@userActions/Link'; +import {requestResetFreePlanBankAccount, resetReimbursementAccount, setBankAccountSubStep} from '@userActions/ReimbursementAccount'; +import {clearContactMethodErrors, requestValidateCodeAction, validateSecondaryLogin} from '@userActions/User'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import type * as OnyxTypes from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; + +type VerifiedBankAccountFlowEntryPointProps = { + /** Bank account currently in setup */ + reimbursementAccount: OnyxEntry; + + /** Callback to continue to the next step of the setup */ + onContinuePress: () => void; + + /** The workspace name */ + policyName?: string; + + /** The workspace ID */ + policyID?: string; + + /** Goes to the previous step */ + onBackButtonPress: () => void; + + /** Should show the continue setup button */ + shouldShowContinueSetupButton: boolean | null; + + /** Whether the bank account has non USD currency */ + hasForeignCurrency: boolean; + + /** Should ValidateCodeActionModal be displayed or not */ + isValidateCodeActionModalVisible?: boolean; + + /** Toggle ValidateCodeActionModal */ + toggleValidateCodeActionModal?: (isVisible: boolean) => void; + + /** Set step for non USD flow */ + setNonUSDBankAccountStep: (shouldShowContinueSetupButton: string | null) => void; + + /** Set step for USD flow */ + setUSDBankAccountStep: (shouldShowContinueSetupButton: string | null) => void; +}; + +const bankInfoStepKeys = INPUT_IDS.BANK_INFO_STEP; + +function VerifiedBankAccountFlowEntryPoint({ + policyName = '', + policyID = '', + onBackButtonPress, + reimbursementAccount, + onContinuePress, + shouldShowContinueSetupButton, + hasForeignCurrency, + isValidateCodeActionModalVisible, + toggleValidateCodeActionModal, + setNonUSDBankAccountStep, + setUSDBankAccountStep, +}: VerifiedBankAccountFlowEntryPointProps) { + const theme = useTheme(); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const [account] = useOnyx(ONYXKEYS.ACCOUNT); + const [isPlaidDisabled] = useOnyx(ONYXKEYS.IS_PLAID_DISABLED); + const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); + const errors = reimbursementAccount?.errors ?? {}; + const pendingAction = reimbursementAccount?.pendingAction ?? null; + const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); + const optionPressed = useRef(''); + + const contactMethod = account?.primaryLogin ?? ''; + const loginData = useMemo(() => loginList?.[contactMethod], [loginList, contactMethod]); + const validateLoginError = getEarliestErrorField(loginData, 'validateLogin'); + const hasMagicCodeBeenSent = !!loginData?.validateCodeSent; + const plaidDesktopMessage = getPlaidDesktopMessage(); + const bankAccountRoute = `${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policyID, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW, ROUTES.WORKSPACE_INITIAL.getRoute(policyID))}`; + const personalBankAccounts = bankAccountList ? Object.keys(bankAccountList).filter((key) => bankAccountList[key].accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) : []; + + const removeExistingBankAccountDetails = () => { + const bankAccountData: Partial = { + [bankInfoStepKeys.ROUTING_NUMBER]: '', + [bankInfoStepKeys.ACCOUNT_NUMBER]: '', + [bankInfoStepKeys.PLAID_MASK]: '', + [bankInfoStepKeys.IS_SAVINGS]: undefined, + [bankInfoStepKeys.BANK_NAME]: '', + [bankInfoStepKeys.PLAID_ACCOUNT_ID]: '', + [bankInfoStepKeys.PLAID_ACCESS_TOKEN]: '', + }; + updateReimbursementAccountDraft(bankAccountData); + }; + + /** + * optionPressed ref indicates what user selected before modal to validate account was displayed + * In this hook we check if account was validated and then proceed with the option user selected + * note: non USD accounts only have manual option available + */ + useEffect(() => { + if (!account?.validated) { + return; + } + + if (optionPressed.current === CONST.BANK_ACCOUNT.SUBSTEP.MANUAL) { + if (hasForeignCurrency) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); + return; + } + + setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL); + setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT); + } else if (optionPressed.current === CONST.BANK_ACCOUNT.SUBSTEP.PLAID) { + setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT); + openPlaidView(); + } + }, [account?.validated, hasForeignCurrency, setNonUSDBankAccountStep, setUSDBankAccountStep]); + + const handleConnectPlaid = () => { + if (isPlaidDisabled) { + return; + } + if (!account?.validated) { + optionPressed.current = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; + toggleValidateCodeActionModal?.(true); + return; + } + + removeExistingBankAccountDetails(); + setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID); + setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT); + openPlaidView(); + }; + + const handleConnectManually = () => { + if (!account?.validated) { + optionPressed.current = CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL; + toggleValidateCodeActionModal?.(true); + return; + } + + if (hasForeignCurrency) { + setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY); + return; + } + + removeExistingBankAccountDetails(); + setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL); + setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT); + }; + + return ( + + + + +
+ {!!plaidDesktopMessage && ( + + openExternalLinkWithToken(bankAccountRoute)}>{translate(plaidDesktopMessage)} + + )} + {!!personalBankAccounts.length && ( + + + + {translate('workspace.bankAccount.connectBankAccountNote')} + + + )} + + {shouldShowContinueSetupButton === true ? ( + <> + + + + ) : ( + <> + {!hasForeignCurrency && !shouldShowContinueSetupButton && ( + + )} + + + )} + +
+ + {translate('common.privacy')} + openExternalLink(CONST.ENCRYPTION_AND_SECURITY_HELP_URL)} + style={[styles.flexRow, styles.alignItemsCenter]} + accessibilityLabel={translate('bankAccount.yourDataIsSecure')} + > + {translate('bankAccount.yourDataIsSecure')} + + + + + +
+ + {!!reimbursementAccount?.shouldShowResetModal && } + + requestValidateCodeAction()} + handleSubmitForm={(validateCode) => validateSecondaryLogin(loginList, contactMethod, validateCode)} + validateError={!isEmptyObject(validateLoginError) ? validateLoginError : getLatestErrorField(loginData, 'validateCodeSent')} + clearError={() => clearContactMethodErrors(contactMethod, !isEmptyObject(validateLoginError) ? 'validateLogin' : 'validateCodeSent')} + onClose={() => toggleValidateCodeActionModal?.(false)} + /> +
+ ); +} + +VerifiedBankAccountFlowEntryPoint.displayName = 'VerifiedBankAccountFlowEntryPoint'; + +export default VerifiedBankAccountFlowEntryPoint; diff --git a/src/pages/ReimbursementAccount/utils/getSubStepValues.ts b/src/pages/ReimbursementAccount/utils/getSubStepValues.ts new file mode 100644 index 000000000000..2a73546075c9 --- /dev/null +++ b/src/pages/ReimbursementAccount/utils/getSubStepValues.ts @@ -0,0 +1,24 @@ +import type {OnyxEntry} from 'react-native-onyx'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import type {ReimbursementAccount} from '@src/types/onyx'; +import type {ACHData, Corpay} from '@src/types/onyx/ReimbursementAccount'; + +type SubStepValues = { + [TKey in TProps]: ReimbursementAccountForm[TKey]; +}; + +function getSubStepValues( + inputKeys: Record, + reimbursementAccountDraft: OnyxEntry, + reimbursementAccount: OnyxEntry, +): SubStepValues { + return Object.entries(inputKeys).reduce((acc, [, value]) => { + acc[value] = (reimbursementAccountDraft?.[value] ?? + reimbursementAccount?.achData?.[value as keyof ACHData] ?? + reimbursementAccount?.achData?.corpay?.[value as keyof Corpay] ?? + '') as ReimbursementAccountForm[TProps]; + return acc; + }, {} as SubStepValues); +} + +export default getSubStepValues; diff --git a/src/pages/ReimbursementAccount/utils/getSubstepValues.ts b/src/pages/ReimbursementAccount/utils/getSubstepValues.ts deleted file mode 100644 index f89625c613f7..000000000000 --- a/src/pages/ReimbursementAccount/utils/getSubstepValues.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type {OnyxEntry} from 'react-native-onyx'; -import type {ReimbursementAccountForm} from '@src/types/form'; -import type {ReimbursementAccount} from '@src/types/onyx'; -import type {ACHData} from '@src/types/onyx/ReimbursementAccount'; - -type SubstepValues = { - [TKey in TProps]: ReimbursementAccountForm[TKey]; -}; - -function getSubstepValues( - inputKeys: Record, - reimbursementAccountDraft: OnyxEntry, - reimbursementAccount: OnyxEntry, -): SubstepValues { - return Object.entries(inputKeys).reduce((acc, [, value]) => { - acc[value] = (reimbursementAccountDraft?.[value] ?? reimbursementAccount?.achData?.[value as keyof ACHData] ?? '') as ReimbursementAccountForm[TProps]; - return acc; - }, {} as SubstepValues); -} - -export default getSubstepValues; diff --git a/src/pages/workspace/WorkspaceResetBankAccountModal.tsx b/src/pages/workspace/WorkspaceResetBankAccountModal.tsx index 5856c71d0a43..d4382594e1d0 100644 --- a/src/pages/workspace/WorkspaceResetBankAccountModal.tsx +++ b/src/pages/workspace/WorkspaceResetBankAccountModal.tsx @@ -1,33 +1,47 @@ import React from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import ConfirmModal from '@components/ConfirmModal'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import BankAccount from '@libs/models/BankAccount'; -import * as BankAccounts from '@userActions/BankAccounts'; +import {cancelResetFreePlanBankAccount, resetFreePlanBankAccount} from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; -type WorkspaceResetBankAccountModalOnyxProps = { - /** Session info for the currently logged in user. */ - session: OnyxEntry; -}; - -type WorkspaceResetBankAccountModalProps = WorkspaceResetBankAccountModalOnyxProps & { +type WorkspaceResetBankAccountModalProps = { /** Reimbursement account data */ reimbursementAccount: OnyxEntry; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setShouldShowConnectedVerifiedBankAccount?: (shouldShowConnectedVerifiedBankAccount: boolean) => void; + + /** Method to set the state of shouldShowConnectedVerifiedBankAccount */ + setUSDBankAccountStep?: (step: string | null) => void; }; -function WorkspaceResetBankAccountModal({reimbursementAccount, session}: WorkspaceResetBankAccountModalProps) { +function WorkspaceResetBankAccountModal({reimbursementAccount, setShouldShowConnectedVerifiedBankAccount, setUSDBankAccountStep}: WorkspaceResetBankAccountModalProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const [session] = useOnyx(ONYXKEYS.SESSION); const achData = reimbursementAccount?.achData; const isInOpenState = achData?.state === BankAccount.STATE.OPEN; const bankAccountID = achData?.bankAccountID; const bankShortName = `${achData?.addressName ?? ''} ${(achData?.accountNumber ?? '').slice(-4)}`; + const handleConfirm = () => { + resetFreePlanBankAccount(bankAccountID, session, achData?.policyID); + + if (setShouldShowConnectedVerifiedBankAccount) { + setShouldShowConnectedVerifiedBankAccount(false); + } + + if (setUSDBankAccountStep) { + setUSDBankAccountStep(null); + } + }; + return ( BankAccounts.resetFreePlanBankAccount(bankAccountID, session, achData?.policyID ?? '-1')} + onCancel={cancelResetFreePlanBankAccount} + onConfirm={handleConfirm} shouldShowCancelButton isVisible /> @@ -55,8 +69,4 @@ function WorkspaceResetBankAccountModal({reimbursementAccount, session}: Workspa WorkspaceResetBankAccountModal.displayName = 'WorkspaceResetBankAccountModal'; -export default withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, -})(WorkspaceResetBankAccountModal); +export default WorkspaceResetBankAccountModal; diff --git a/src/types/form/ReimbursementAccountForm.ts b/src/types/form/ReimbursementAccountForm.ts index 19e1f28e0613..5c0537600db4 100644 --- a/src/types/form/ReimbursementAccountForm.ts +++ b/src/types/form/ReimbursementAccountForm.ts @@ -52,20 +52,44 @@ const INPUT_IDS = { AMOUNT1: 'amount1', AMOUNT2: 'amount2', AMOUNT3: 'amount3', + /** Some pairs are send under certain key and saved under different key by BE. + * This is forced on BE side which is asking us to send it under certain keys + * but then saves it and returns under different keys */ ADDITIONAL_DATA: { + /** This pair is send under 1ST key but saved under 2nd key */ ACCOUNT_HOLDER_NAME: 'accountHolderName', + ADDRESS_NAME: 'addressName', + + /** This pair is send under 1ST key but saved under 2nd key */ + ACCOUNT_HOLDER_ADDRESS_1: 'accountHolderAddress1', ADDRESS_STREET: 'addressStreet', + + /** This pair is send under 1ST key but saved under 2nd key */ + ACCOUNT_HOLDER_CITY: 'accountHolderCity', ADDRESS_CITY: 'addressCity', + + /** This pair is send under 1ST key but saved under 2nd key */ + ACCOUNT_HOLDER_REGION: 'accountHolderRegion', ADDRESS_STATE: 'addressState', + + /** This pair is send under 1ST key but saved under 2nd key */ + ACCOUNT_HOLDER_POSTAL: 'accountHolderPostal', ADDRESS_ZIP_CODE: 'addressZipCode', + + /** 2nd key from pair with ROUTING_NUMBER (shares it with SWIFT/BIC code) */ + ROUTING_CODE: 'routingCode', COUNTRY: 'country', CORPAY: { ACCOUNT_HOLDER_COUNTRY: 'accountHolderCountry', - SWIFT_CODE: 'swiftCode', + /** 2nd key from pair with ROUTING_NUMBER (shares it with routing code) */ + SWIFT_BIC_CODE: 'swiftBicCode', BANK_NAME: 'bankName', BANK_CITY: 'bankCity', - BANK_ADDRESS_LINE_1: 'bankAddress', - BANK_STATEMENT: 'bankStatement', + BANK_REGION: 'bankRegion', + BANK_POSTAL: 'bankPostal', + BANK_ADDRESS_LINE_1: 'bankAddressLine1', + BANK_COUNTRY: 'bankCountry', + BANK_CURRENCY: 'bankCurrency', COMPANY_NAME: 'companyName', COMPANY_STREET: 'companyStreetAddress', COMPANY_CITY: 'companyCity', @@ -201,12 +225,32 @@ type NonUSDReimbursementAccountAdditionalProps = { /** Name of the account holder */ [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_NAME]: string; + [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_NAME]: string; + + /** Street of the account holder */ + [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_ADDRESS_1]: string; + [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STREET]: string; + + /** City of the account holder */ + [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_CITY]: string; + [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_CITY]: string; + + /** State of the account holder */ + [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_REGION]: string; + [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STATE]: string; + + /** Postal code of the account holder */ + [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_POSTAL]: string; + [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_ZIP_CODE]: string; + + /** Routing code */ + [INPUT_IDS.ADDITIONAL_DATA.ROUTING_CODE]: string; /** Country of the account holder */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.ACCOUNT_HOLDER_COUNTRY]: Country | ''; /** SWIFT code */ - [INPUT_IDS.ADDITIONAL_DATA.CORPAY.SWIFT_CODE]: string; + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.SWIFT_BIC_CODE]: string; /** Bank name */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_NAME]: string; @@ -214,12 +258,21 @@ type NonUSDReimbursementAccountAdditionalProps = { /** Bank city */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_CITY]: string; + /** Bank region */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_REGION]: string; + + /** Bank postal code */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_POSTAL]: string; + + /** Bank country */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_COUNTRY]: string; + + /** Bank currency */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_CURRENCY]: string; + /** Bank address line 1 */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_ADDRESS_LINE_1]: string; - /** Bank statement file */ - [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_STATEMENT]: FileObject[]; - /** Company name */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.COMPANY_NAME]: string; diff --git a/src/types/onyx/ReimbursementAccount.ts b/src/types/onyx/ReimbursementAccount.ts index dab606844209..4ffbe7deeb8a 100644 --- a/src/types/onyx/ReimbursementAccount.ts +++ b/src/types/onyx/ReimbursementAccount.ts @@ -15,14 +15,24 @@ type BankAccountSubStep = ValueOf; /** Model of Corpay data */ type Corpay = { + /** Account holder address - country */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.ACCOUNT_HOLDER_COUNTRY]: Country | ''; /** Swift code */ - [INPUT_IDS.ADDITIONAL_DATA.CORPAY.SWIFT_CODE]?: string; + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.SWIFT_BIC_CODE]: string; /** Bank name */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_NAME]: string; /** Bank address - city */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_CITY]: string; /** Bank address - street and zip code */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_ADDRESS_LINE_1]: string; + /** Bank region */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_REGION]: string; + /** Bank postal code */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_POSTAL]: string; + /** Bank country */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_COUNTRY]: string; + /** Bank currency */ + [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_CURRENCY]: string; /** Company name */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.COMPANY_NAME]: string; /** Company address - street */ @@ -125,39 +135,14 @@ type Corpay = { [INPUT_IDS.ADDITIONAL_DATA.CORPAY.CONSENT_TO_PRIVACY_NOTICE]: boolean; /** Checkbox - authorized to bind to client to agreement */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.AUTHORIZED_TO_BIND_CLIENT_TO_AGREEMENT]: boolean; - /** Bank statement */ - [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BANK_STATEMENT]: FileObject[]; - /** Is user also an owner */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.OWNS_MORE_THAN_25_PERCENT]: boolean; - /** Are the more owners */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.ANY_INDIVIDUAL_OWN_25_PERCENT_OR_MORE]: boolean; - /** Stringified array of owners data */ [INPUT_IDS.ADDITIONAL_DATA.CORPAY.BENEFICIAL_OWNERS]?: string; }; -/** Model of Additional data */ -type AdditionalData = { - /** Account holder name */ - [INPUT_IDS.ADDITIONAL_DATA.ACCOUNT_HOLDER_NAME]: string; - /** Account holder address - street */ - [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STREET]: string; - /** Account holder address - city */ - [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_CITY]: string; - /** Account holder address - state (US and CA only) */ - [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_STATE]?: string; - /** Account holder address - zip code */ - [INPUT_IDS.ADDITIONAL_DATA.ADDRESS_ZIP_CODE]: string; - /** Account holder address - country */ - [INPUT_IDS.ADDITIONAL_DATA.CORPAY.ACCOUNT_HOLDER_COUNTRY]: string; - /** Country user selects in first step */ - [INPUT_IDS.ADDITIONAL_DATA.COUNTRY]: Country | ''; - /** Corpay fields */ - corpay: Corpay; -}; - /** Model of ACH data */ type ACHData = Partial & { /** Step of the setup flow that we are on. Determines which view is presented. */ @@ -181,9 +166,6 @@ type ACHData = Partial; export default ReimbursementAccount; -export type {BankAccountStep, BankAccountSubStep, ACHData, ReimbursementAccountStep, ReimbursementAccountSubStep, ACHDataReimbursementAccount}; +export type {Corpay, BankAccountStep, BankAccountSubStep, ACHData, ReimbursementAccountStep, ReimbursementAccountSubStep, ACHDataReimbursementAccount};