From 8636802334da3bebfc28c2c50aa5f330d6514941 Mon Sep 17 00:00:00 2001 From: Michal Muzyk Date: Thu, 1 Aug 2024 09:44:46 +0200 Subject: [PATCH 01/26] feat: GR --- src/CONST.ts | 15 +- src/ONYXKEYS.ts | 3 + .../AddPaymentCard/PaymentCardForm.tsx | 2 +- src/components/AddressForm.tsx | 2 +- src/components/CountryPicker/CountryModal.tsx | 115 ++++++++++ src/components/CountryPicker/index.tsx | 62 ++++++ src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/components/PlaidLink/index.native.tsx | 2 +- src/languages/en.ts | 28 +++ src/languages/es.ts | 25 +++ src/libs/CardUtils.ts | 2 +- src/libs/PaymentUtils.ts | 2 +- src/libs/actions/BankAccounts.ts | 10 +- .../AddBankAccount/AddBankAccount.tsx | 4 +- .../FeesAndTerms/FeesAndTerms.tsx | 2 +- .../PersonalInfo/PersonalInfo.tsx | 2 +- .../substeps/SocialSecurityNumberStep.tsx | 2 +- .../VerifyIdentity/VerifyIdentity.tsx | 2 +- .../AddressFormFields.tsx | 12 +- .../ReimbursementAccount/BankAccountStep.tsx | 8 +- .../BankInfo/BankInfo.tsx | 16 +- .../BankInfo/substeps/Confirmation.tsx | 4 +- .../BankInfo/substeps/Manual.tsx | 6 +- .../AddressUBO.tsx | 4 +- .../DateOfBirthUBO.tsx | 4 +- .../LegalNameUBO.tsx | 4 +- .../SocialSecurityNumberUBO.tsx | 6 +- .../BeneficialOwnersStep.tsx | 6 +- .../BusinessInfo/BusinessInfo.tsx | 4 +- .../CompleteVerification.tsx | 4 +- .../NonUSD/Agreements/index.tsx | 75 +++++++ .../Agreements/substeps/Confirmation.tsx | 38 ++++ .../NonUSD/BankInfo/index.tsx | 77 +++++++ .../BankInfo/substeps/AccountDetails.tsx | 62 ++++++ .../NonUSD/BankInfo/substeps/Confirmation.tsx | 58 +++++ .../BankInfo/substeps/UploadStatement.tsx | 43 ++++ .../NonUSD/BusinessInfo/index.tsx | 78 +++++++ .../NonUSD/BusinessInfo/substeps/Address.tsx | 60 ++++++ .../BusinessInfo/substeps/CompanyType.tsx | 0 .../BusinessInfo/substeps/Confirmation.tsx | 38 ++++ .../substeps/IncorporationLocation.tsx | 0 .../NonUSD/BusinessInfo/substeps/Name.tsx | 48 +++++ .../BusinessInfo/substeps/PaymentVolume.tsx | 0 .../BusinessInfo/substeps/PhoneNumber.tsx | 48 +++++ .../substeps/RegistrationNumber.tsx | 0 .../NonUSD/Country/index.tsx | 75 +++++++ .../NonUSD/Country/substeps/Confirmation.tsx | 83 +++++++ .../NonUSD/Finish/index.tsx | 20 ++ .../NonUSD/Finish/substeps/Confirmation.tsx | 38 ++++ .../NonUSD/OwnershipInfo/index.tsx | 75 +++++++ .../OwnershipInfo/substeps/Confirmation.tsx | 38 ++++ .../NonUSD/SignerInfo/index.tsx | 75 +++++++ .../SignerInfo/substeps/Confirmation.tsx | 38 ++++ .../PersonalInfo/PersonalInfo.tsx | 4 +- .../substeps/SocialSecurityNumber.tsx | 2 +- .../ReimbursementAccountPage.tsx | 202 ++++++++++++++---- .../RequestorOnfidoStep.tsx | 4 +- .../VerifyIdentity/VerifyIdentity.tsx | 8 +- .../utils/getValuesForBeneficialOwner.ts | 4 +- .../TransactionDuplicate/ReviewFields.tsx | 2 +- .../settings/Wallet/WalletPage/WalletPage.tsx | 5 +- .../NetSuiteTokenInputPage.tsx | 2 +- .../workspace/card/issueNew/AssigneeStep.tsx | 2 +- .../workspace/card/issueNew/CardNameStep.tsx | 2 +- .../workspace/card/issueNew/CardTypeStep.tsx | 2 +- .../card/issueNew/ConfirmationStep.tsx | 2 +- .../workspace/card/issueNew/LimitStep.tsx | 2 +- .../workspace/card/issueNew/LimitTypeStep.tsx | 2 +- .../WorkspaceExpensifyCardPageEmptyState.tsx | 6 +- .../workflows/WorkspaceWorkflowsPage.tsx | 7 + .../form/NonUSDReimbursementAccountForm.ts | 151 +++++++++++++ src/types/form/index.ts | 1 + src/types/onyx/ReimbursementAccount.ts | 4 +- src/types/onyx/UserWallet.ts | 2 +- 74 files changed, 1717 insertions(+), 126 deletions(-) create mode 100644 src/components/CountryPicker/CountryModal.tsx create mode 100644 src/components/CountryPicker/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Agreements/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BankInfo/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/AccountDetails.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BankInfo/substeps/UploadStatement.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Address.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/CompanyType.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/IncorporationLocation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/Name.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/PaymentVolume.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/PhoneNumber.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/BusinessInfo/substeps/RegistrationNumber.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Country/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Country/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Finish/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/Finish/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/OwnershipInfo/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/OwnershipInfo/substeps/Confirmation.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/SignerInfo/index.tsx create mode 100644 src/pages/ReimbursementAccount/NonUSD/SignerInfo/substeps/Confirmation.tsx create mode 100644 src/types/form/NonUSDReimbursementAccountForm.ts diff --git a/src/CONST.ts b/src/CONST.ts index c7a6741da314..952c6a75369f 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -254,7 +254,7 @@ const CONST = { SMS: { DOMAIN: '@expensify.sms', }, - BANK_ACCOUNT: { + USD_BANK_ACCOUNT: { BENEFICIAL_OWNER_INFO_STEP: { SUBSTEP: { IS_USER_UBO: 1, @@ -351,6 +351,19 @@ const CONST = { PERSONAL: 'PERSONAL', }, }, + NON_USD_BANK_ACCOUNT: { + STEP: { + COUNTRY: 'CountryStep', + BANK_INFO: 'BankInfoStep', + BUSINESS_INFO: 'BusinessInfoStep', + OWNERSHIP_INFO: 'OwnershipInfoStep', + SIGNER_INFO: 'SignerInfoStep', + AGREEMENTS: 'AgreementsStep', + FINISH: 'FinishStep', + }, + STEP_NAMES: ['1', '2', '3', '4', '5', '6'], + STEP_HEADER_HEIGHT: 40, + }, INCORPORATION_TYPES: { LLC: 'LLC', CORPORATION: 'Corp', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 00f37508612d..75be5930fded 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -554,6 +554,8 @@ const ONYXKEYS = { REPORT_FIELDS_EDIT_FORM_DRAFT: 'reportFieldsEditFormDraft', REIMBURSEMENT_ACCOUNT_FORM: 'reimbursementAccount', REIMBURSEMENT_ACCOUNT_FORM_DRAFT: 'reimbursementAccountDraft', + NON_USD_REIMBURSEMENT_ACCOUNT_FORM: 'nonUSDReimbursementAccount', + NON_USD_REIMBURSEMENT_ACCOUNT_FORM_DRAFT: 'nonUSDReimbursementAccountDraft', PERSONAL_BANK_ACCOUNT_FORM: 'personalBankAccount', PERSONAL_BANK_ACCOUNT_FORM_DRAFT: 'personalBankAccountDraft', EXIT_SURVEY_REASON_FORM: 'exitSurveyReasonForm', @@ -647,6 +649,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM]: FormTypes.GetPhysicalCardForm; [ONYXKEYS.FORMS.REPORT_FIELDS_EDIT_FORM]: FormTypes.ReportFieldsEditForm; [ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM]: FormTypes.ReimbursementAccountForm; + [ONYXKEYS.FORMS.NON_USD_REIMBURSEMENT_ACCOUNT_FORM]: FormTypes.NonUSDReimbursementAccountForm; [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM]: FormTypes.PersonalBankAccountForm; [ONYXKEYS.FORMS.WORKSPACE_DESCRIPTION_FORM]: FormTypes.WorkspaceDescriptionForm; [ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS]: FormTypes.AdditionalDetailStepForm; diff --git a/src/components/AddPaymentCard/PaymentCardForm.tsx b/src/components/AddPaymentCard/PaymentCardForm.tsx index f38ea60f1aad..a28b0e91fe23 100644 --- a/src/components/AddPaymentCard/PaymentCardForm.tsx +++ b/src/components/AddPaymentCard/PaymentCardForm.tsx @@ -279,7 +279,7 @@ function PaymentCardForm({ aria-label={translate('common.zip')} role={CONST.ROLE.PRESENTATION} inputMode={CONST.INPUT_MODE.NUMERIC} - maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} + maxLength={CONST.USD_BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} containerStyles={[styles.mt5]} /> {!!showStateSelector && ( diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 7ca4cc3273ca..653759c94aef 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -233,7 +233,7 @@ function AddressForm({ role={CONST.ROLE.PRESENTATION} autoCapitalize="characters" defaultValue={zip} - maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} + maxLength={CONST.USD_BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} hint={zipFormat} onValueChange={onAddressChanged} shouldSaveDraft={shouldSaveDraft} diff --git a/src/components/CountryPicker/CountryModal.tsx b/src/components/CountryPicker/CountryModal.tsx new file mode 100644 index 000000000000..9a9821fe80a7 --- /dev/null +++ b/src/components/CountryPicker/CountryModal.tsx @@ -0,0 +1,115 @@ +import React, {useEffect, useState} from 'react'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Modal from '@components/Modal'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import useLocalize from '@hooks/useLocalize'; +import CONST from '@src/CONST'; +import type {Country} from '@src/CONST'; + +type ListItemType = { + value: Country; + text: string; + keyForList: string; + isSelected: boolean; +}; + +type CountryModalProps = { + /** Whether the modal is visible */ + isVisible: boolean; + + /** The currently selected country */ + selectedCountry: Country; + + /** Function to call when the user selects a country */ + onCountryChange: (country: Country) => void; + + /** Function to call when the user closes the modal */ + onClose: () => void; + + /** List of countries */ + countryList: Record; +}; + +function CountryModal({isVisible, onCountryChange, onClose, selectedCountry, countryList}: CountryModalProps) { + const {translate} = useLocalize(); + + const [searchbarInputText, setSearchbarInputText] = useState(''); + const [countryListItems, setCountryListItems] = useState( + Object.entries(countryList).map(([key, value]) => ({ + value: key as Country, + text: value, + keyForList: key, + isSelected: key === selectedCountry, + })), + ); + + useEffect(() => { + setCountryListItems((prevCountryListItems) => + prevCountryListItems.map((country) => ({ + ...country, + isSelected: country.value === selectedCountry, + })), + ); + }, [selectedCountry]); + + const filterShownCountries = (searchText: string) => { + setSearchbarInputText(searchText); + const searchWords = searchText.toLowerCase().match(/[a-z0-9]+/g) ?? []; + setCountryListItems( + countryListItems.filter((country) => + searchWords.every((word) => + country.text + .toLowerCase() + .replace(/[^a-z0-9]/g, ' ') + .includes(word), + ), + ), + ); + }; + + const handleSelectRow = (country: ListItemType) => { + onCountryChange(country.value); + onClose(); + }; + + return ( + + + + country.value === selectedCountry)?.keyForList} + showScrollIndicator + shouldShowTooltips={false} + ListItem={RadioListItem} + /> + + + ); +} + +CountryModal.displayName = 'CountryModal'; + +export type {ListItemType}; + +export default CountryModal; diff --git a/src/components/CountryPicker/index.tsx b/src/components/CountryPicker/index.tsx new file mode 100644 index 000000000000..cdf708b95ec5 --- /dev/null +++ b/src/components/CountryPicker/index.tsx @@ -0,0 +1,62 @@ +import React, {useState} from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import useLocalize from '@hooks/useLocalize'; +import type {Country} from '@src/CONST'; +import CONST from '@src/CONST'; +import CountryModal from './CountryModal'; + +type CountryPickerProps = { + /** The list of countries that we want to display where key is country code and value is country name */ + countryList: Record; + + /** The currently selected country */ + selectedCountry: Country; + + /** Function to call when the user selects a country */ + onCountryChange: (country: Country) => void; + + /** Whether the selected country is editable */ + isEditable: boolean; + + /** Additional styles to apply to container */ + wrapperStyles?: StyleProp; +}; + +function CountryPicker({selectedCountry, onCountryChange, isEditable, countryList, wrapperStyles}: CountryPickerProps) { + const {translate} = useLocalize(); + + const [isCountryModalVisible, setIsCountryModalVisible] = useState(false); + + const handleCountryModalClose = () => { + setIsCountryModalVisible(false); + }; + + const handleCountryModalOpen = () => { + setIsCountryModalVisible(true); + }; + + return ( + <> + + + + ); +} + +CountryPicker.displayName = 'CountryPicker'; + +export default CountryPicker; diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 818b4aff6b00..fd46b87ed21c 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -171,7 +171,7 @@ function KYCWall({ // Check to see if user has a valid payment method on file and display the add payment popover if they don't if ( - (isExpenseReport && reimbursementAccount?.achData?.state !== CONST.BANK_ACCOUNT.STATE.OPEN) || + (isExpenseReport && reimbursementAccount?.achData?.state !== CONST.USD_BANK_ACCOUNT.STATE.OPEN) || (!isExpenseReport && bankAccountList !== null && !PaymentUtils.hasExpensifyPaymentMethod(paymentCardList, bankAccountList, shouldIncludeDebitCard)) ) { Log.info('[KYC Wallet] User does not have valid payment method'); diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index 37b598303c3a..0c9a3fd4f667 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -11,7 +11,7 @@ function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: Pl onEvent(event.eventName, event.metadata); }); useEffect(() => { - onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); + onEvent(CONST.USD_BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); openLink({ tokenConfig: { token, diff --git a/src/languages/en.ts b/src/languages/en.ts index b37ad15004e4..7bf3c79a4a84 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1904,6 +1904,9 @@ export default { companyAddress: 'Company address', listOfRestrictedBusinesses: 'list of restricted businesses', confirmCompanyIsNot: 'I confirm that this company is not on the', + whatsTheBusinessName: "What's the business name?", + whatsTheBusinessAddress: "What's the business address?", + whatsTheBusinessPhone: "What's the business phone number?", }, beneficialOwnerInfoStep: { doYouOwn25percent: 'Do you own 25% or more of', @@ -1982,6 +1985,31 @@ export default { enable2FAText: 'We take your security seriously. Please set up 2FA now to add an extra layer of protection to your account.', secureYourAccount: 'Secure your account', }, + countryStep: { + confirmBusinessBank: 'Confirm business bank account currency and country', + yourBusiness: 'Your business bank account currency must match your workspace currency.', + youCanChange: 'You can change your workspace currency in your', + findCountry: 'Find country', + confirmCurrency: 'Confirm currency and country', + selectCountry: 'Select country', + }, + bankInfoStep: { + whatAreYour: 'What are your business bank account details?', + letsDoubleCheck: 'Let’s double check that everything looks fine.', + thisBankAccount: 'This bank account will be used for business payments on your workspace', + transitNumber: 'Transit number', + institutionNumber: 'Institution number', + accountNumber: 'Account number', + routingNumber: 'Routing number', + accountName: 'Account name', + bankStatement: 'Bank statement', + whyDoWeAsk: 'Why do we ask for this?', + chooseFile: 'Choose file', + uploadYourLatest: 'Upload your latest statement', + pleaseUpload: ({lastFourDigits}) => `Please upload the most recent monthly statement for your business bank account ending in ${lastFourDigits}.`, + bankInfo: 'Bank info', + confirmBankInfo: 'Confirm bank info', + }, reimbursementAccountLoadingAnimation: { oneMoment: 'One moment', explanationLine: "We’re taking a look at your information. You'll be able to continue with next steps shortly.", diff --git a/src/languages/es.ts b/src/languages/es.ts index 54c97e41afb1..7fe9f6b008d0 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2017,6 +2017,31 @@ export default { enable2FAText: 'Tu seguridad es importante para nosotros. Por favor, configura ahora la autenticación de dos factores para añadir una capa adicional de protección a tu cuenta.', secureYourAccount: 'Asegura tu cuenta', }, + countryStep: { + confirmBusinessBank: 'Confirm business bank account currency and country', + yourBusiness: 'Your business bank account currency must match your workspace currency', + youCanChange: 'You can change your workspace currency in your', + findCountry: 'Find country', + confirmCurrency: 'Confirm currency and country', + selectCountry: 'Select country', + }, + bankInfoStep: { + whatAreYour: 'What are your business bank account details?', + letsDoubleCheck: 'Let’s double check that everything looks fine.', + thisBankAccount: 'This bank account will be used for business payments on your workspace', + transitNumber: 'Transit number', + institutionNumber: 'Institution number', + accountNumber: 'Account number', + routingNumber: 'Routing number', + accountName: 'Account name', + bankStatement: 'Bank statement', + whyDoWeAsk: 'Why do we ask for this?', + chooseFile: 'Choose file', + uploadYourLatest: 'Upload your latest statement', + pleaseUpload: ({lastFourDigits}) => `Please upload the most recent monthly statement for your business bank account ending in ${lastFourDigits}.`, + bankInfo: 'Bank info', + confirmBankInfo: 'Confirm bank info', + }, reimbursementAccountLoadingAnimation: { oneMoment: 'Un momento', explanationLine: 'Estamos verificando tu información y podrás continuar con los siguientes pasos en unos momentos.', diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index a5dfe69bf40e..ebdf3495fb9a 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -163,7 +163,7 @@ function getEligibleBankAccountsForCard(bankAccountsList: OnyxEntry bankAccount?.accountData?.type === CONST.BANK_ACCOUNT.TYPE.BUSINESS && bankAccount?.accountData?.allowDebit); + return Object.values(bankAccountsList).filter((bankAccount) => bankAccount?.accountData?.type === CONST.USD_BANK_ACCOUNT.TYPE.BUSINESS && bankAccount?.accountData?.allowDebit); } export { diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index 60dac04a09ac..dde46433dc63 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -16,7 +16,7 @@ function hasExpensifyPaymentMethod(fundList: Record, bankAccountLi const validBankAccount = Object.values(bankAccountList).some((bankAccountJSON) => { const bankAccount = new BankAccountModel(bankAccountJSON); - return bankAccount.getPendingAction() !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && bankAccount.isOpen() && bankAccount.getType() === CONST.BANK_ACCOUNT.TYPE.PERSONAL; + return bankAccount.getPendingAction() !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && bankAccount.isOpen() && bankAccount.getType() === CONST.USD_BANK_ACCOUNT.TYPE.PERSONAL; }); // Hide any billing cards that are not P2P debit cards for now because you cannot make them your default method, or delete them diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index 5b2b3d617e58..8b8fae10f3e9 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -67,7 +67,7 @@ function clearPlaid(): Promise { } function openPlaidView() { - clearPlaid().then(() => ReimbursementAccount.setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID)); + clearPlaid().then(() => ReimbursementAccount.setBankAccountSubStep(CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID)); } function setPlaidEvent(eventName: string | null) { @@ -94,7 +94,7 @@ function openPersonalBankAccountSetupWithPlaid(exitReportID?: string) { if (exitReportID) { Onyx.merge(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {exitReportID}); } - Onyx.merge(ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM_DRAFT, {setupType: CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID}); + Onyx.merge(ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM_DRAFT, {setupType: CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID}); }); } @@ -298,7 +298,7 @@ function updatePersonalInformationForBankAccount(bankAccountID: number, params: policyID, confirm: isConfirmPage, }, - getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.REQUESTOR), + getVBBADataForOnyx(CONST.USD_BANK_ACCOUNT.STEP.REQUESTOR), ); } @@ -410,7 +410,7 @@ function updateCompanyInformationForBankAccount(bankAccountID: number, params: P policyID, confirm: isConfirmPage, }, - getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.COMPANY), + getVBBADataForOnyx(CONST.USD_BANK_ACCOUNT.STEP.COMPANY), ); } @@ -462,7 +462,7 @@ function connectBankAccountManually(bankAccountID: number, bankAccount: PlaidBan policyID, }; - API.write(WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_MANUALLY, parameters, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT)); + API.write(WRITE_COMMANDS.CONNECT_BANK_ACCOUNT_MANUALLY, parameters, getVBBADataForOnyx(CONST.USD_BANK_ACCOUNT.STEP.BANK_ACCOUNT)); } /** diff --git a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx index a274990ea6a7..f452cfef5ad6 100644 --- a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx +++ b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx @@ -48,7 +48,7 @@ function AddBankAccount({personalBankAccount, plaidData, personalBankAccountDraf } }, [personalBankAccountDraft?.plaidAccountID, plaidData?.bankAccounts]); - const isSetupTypeChosen = personalBankAccountDraft?.setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; + const isSetupTypeChosen = personalBankAccountDraft?.setupType === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID; const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent: plaidSubsteps, startFrom: 0, onFinished: submit}); @@ -96,7 +96,7 @@ function AddBankAccount({personalBankAccount, plaidData, personalBankAccountDraf {isSetupTypeChosen ? ( <> - + - + - + diff --git a/src/pages/EnablePayments/VerifyIdentity/VerifyIdentity.tsx b/src/pages/EnablePayments/VerifyIdentity/VerifyIdentity.tsx index 5b2eb962226c..a176a77e2fbe 100644 --- a/src/pages/EnablePayments/VerifyIdentity/VerifyIdentity.tsx +++ b/src/pages/EnablePayments/VerifyIdentity/VerifyIdentity.tsx @@ -62,7 +62,7 @@ function VerifyIdentity() { title={translate('onfidoStep.verifyIdentity')} onBackButtonPress={goBack} /> - + ; }; -function AddressFormFields({shouldSaveDraft = false, defaultValues, values, errors, inputKeys, onFieldChange, streetTranslationKey}: AddressFormProps) { +function AddressFormFields({shouldSaveDraft = false, defaultValues, values, errors, inputKeys, onFieldChange, streetTranslationKey, containerStyles}: AddressFormProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); return ( - <> + onFieldChange?.({zipCode: value})} errorText={errors?.zipCode ? translate('bankAccount.error.zipCode') : ''} - maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} + maxLength={CONST.USD_BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} hint={translate('common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples})} containerStyles={styles.mt3} /> - + ); } diff --git a/src/pages/ReimbursementAccount/BankAccountStep.tsx b/src/pages/ReimbursementAccount/BankAccountStep.tsx index 689b646f465a..7e6279895580 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.tsx +++ b/src/pages/ReimbursementAccount/BankAccountStep.tsx @@ -80,9 +80,9 @@ function BankAccountStep({ const styles = useThemeStyles(); const {translate} = useLocalize(); let subStep = reimbursementAccount?.achData?.subStep ?? ''; - const shouldReinitializePlaidLink = plaidLinkOAuthToken && receivedRedirectURI && subStep !== CONST.BANK_ACCOUNT.SUBSTEP.MANUAL; + const shouldReinitializePlaidLink = plaidLinkOAuthToken && receivedRedirectURI && subStep !== CONST.USD_BANK_ACCOUNT.SUBSTEP.MANUAL; if (shouldReinitializePlaidLink) { - subStep = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; + subStep = CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID; } const plaidDesktopMessage = getPlaidDesktopMessage(); const bankAccountRoute = `${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_INITIAL.getRoute(policyID))}`; @@ -101,7 +101,7 @@ function BankAccountStep({ ReimbursementAccount.updateReimbursementAccountDraft(bankAccountData); }; - if (subStep === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID || subStep === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) { + if (subStep === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID || subStep === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.MANUAL) { return ( { removeExistingBankAccountDetails(); - BankAccounts.setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL); + BankAccounts.setBankAccountSubStep(CONST.USD_BANK_ACCOUNT.SETUP_TYPE.MANUAL); }} shouldShowRightIcon wrapperStyle={[styles.cardMenuItem]} diff --git a/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx b/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx index 3e45b14253f3..d4063fea0385 100644 --- a/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx +++ b/src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx @@ -55,14 +55,14 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok let setupType = reimbursementAccount?.achData?.subStep ?? ''; - const shouldReinitializePlaidLink = plaidLinkToken && receivedRedirectURI && setupType !== CONST.BANK_ACCOUNT.SUBSTEP.MANUAL; + const shouldReinitializePlaidLink = plaidLinkToken && receivedRedirectURI && setupType !== CONST.USD_BANK_ACCOUNT.SUBSTEP.MANUAL; if (shouldReinitializePlaidLink) { - setupType = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID; + setupType = CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID; } const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '-1'); const submit = useCallback(() => { - if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) { + if (setupType === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.MANUAL) { BankAccounts.connectBankAccountManually( bankAccountID, { @@ -76,7 +76,7 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok }, policyID, ); - } else if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID) { + } else if (setupType === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.PLAID) { BankAccounts.connectBankAccountWithPlaid( bankAccountID, { @@ -93,7 +93,7 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok } }, [setupType, values, bankAccountID, policyID]); - const bodyContent = setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID ? plaidSubsteps : manualSubsteps; + const bodyContent = setupType === CONST.USD_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 @@ -104,7 +104,7 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok return; } - if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL && values.bankName !== '' && !redirectedFromPlaidToManual) { + if (setupType === CONST.USD_BANK_ACCOUNT.SETUP_TYPE.MANUAL && values.bankName !== '' && !redirectedFromPlaidToManual) { setRedirectedFromPlaidToManual(true); moveTo(0); } @@ -144,10 +144,10 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok onBackButtonPress={handleBackButtonPress} title={translate('bankAccount.bankInfo')} /> - + {translate('bankAccount.letsDoubleCheck')} {translate('bankAccount.thisBankAccount')} - {setupType === CONST.BANK_ACCOUNT.SUBSTEP.MANUAL && ( + {setupType === CONST.USD_BANK_ACCOUNT.SUBSTEP.MANUAL && ( )} - {setupType === CONST.BANK_ACCOUNT.SUBSTEP.PLAID && ( + {setupType === CONST.USD_BANK_ACCOUNT.SUBSTEP.PLAID && ( diff --git a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx index ae0fded74347..5f255dc93552 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnersStep.tsx @@ -39,7 +39,7 @@ type BeneficialOwnersStepProps = BeneficialOwnerInfoOnyxProps & { type BeneficialOwnerSubStepProps = SubStepProps & {beneficialOwnerBeingModifiedID: string; setBeneficialOwnerBeingModifiedID?: (id: string) => void}; -const SUBSTEP = CONST.BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.SUBSTEP; +const SUBSTEP = CONST.USD_BANK_ACCOUNT.BENEFICIAL_OWNER_INFO_STEP.SUBSTEP; const MAX_NUMBER_OF_UBOS = 4; const bodyContent: Array> = [LegalNameUBO, DateOfBirthUBO, SocialSecurityNumberUBO, AddressUBO, ConfirmationUBO]; @@ -226,10 +226,10 @@ function BeneficialOwnersStep({reimbursementAccount, reimbursementAccountDraft, title={translate('beneficialOwnerInfoStep.companyOwner')} onBackButtonPress={handleBackButtonPress} /> - + diff --git a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx index 814db3536973..7cd29e432a22 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx @@ -125,10 +125,10 @@ function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, onBackBu guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT} onBackButtonPress={handleBackButtonPress} /> - + - + void; + + /** Handles submit button press */ + onSubmit: () => void; +}; + +const bodyContent: Array> = [Confirmation]; + +function Agreements({onBackButtonPress, onSubmit}: AgreementsProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const submit = () => { + onSubmit(); + }; + + const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo, goToTheLastStep} = useSubStep({bodyContent, startFrom: 0, onFinished: submit}); + + const handleBackButtonPress = () => { + if (isEditing) { + goToTheLastStep(); + return; + } + + if (screenIndex === 0) { + onBackButtonPress(); + } else { + prevScreen(); + } + }; + + return ( + + + + + + + + ); +} + +Agreements.displayName = 'Agreements'; + +export default Agreements; diff --git a/src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx new file mode 100644 index 000000000000..a82fe9d83a7c --- /dev/null +++ b/src/pages/ReimbursementAccount/NonUSD/Agreements/substeps/Confirmation.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import {View} from 'react-native'; +import Button from '@components/Button'; +import SafeAreaConsumer from '@components/SafeAreaConsumer'; +import ScrollView from '@components/ScrollView'; +import useLocalize from '@hooks/useLocalize'; +import type {SubStepProps} from '@hooks/useSubStep/types'; +import useThemeStyles from '@hooks/useThemeStyles'; + +function Confirmation({onNext}: SubStepProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + return ( + + {({safeAreaPaddingBottomStyle}) => ( + + +