From 929933c684dae1fb225c32185e03285a34f749f9 Mon Sep 17 00:00:00 2001 From: Marcin Swornowski Date: Fri, 22 Dec 2023 15:31:25 +0100 Subject: [PATCH 1/4] feat: migrate BusinessInfo step to TS --- src/components/MenuItem.tsx | 12 +-- .../{useSubStep.ts => useSubStep/index.ts} | 11 +-- src/hooks/useSubStep/types.ts | 31 ++++++++ src/libs/actions/BankAccounts.ts | 6 +- .../{BusinessInfo.js => BusinessInfo.tsx} | 74 +++++++------------ ...AddressBusiness.js => AddressBusiness.tsx} | 37 +++++----- ...onBusiness.js => ConfirmationBusiness.tsx} | 52 ++++++------- ...iness.js => IncorporationDateBusiness.tsx} | 47 +++++------- ...ness.js => IncorporationStateBusiness.tsx} | 32 ++++---- .../{NameBusiness.js => NameBusiness.tsx} | 36 ++++----- ...berBusiness.js => PhoneNumberBusiness.tsx} | 40 +++++----- .../{TaxIdBusiness.js => TaxIdBusiness.tsx} | 46 ++++++------ .../{TypeBusiness.js => TypeBusiness.tsx} | 35 ++++----- ...WebsiteBusiness.js => WebsiteBusiness.tsx} | 67 +++++++---------- .../utils/getInitialSubstepForBusinessInfo.ts | 6 +- src/types/onyx/ReimbursementAccountDraft.ts | 2 +- 16 files changed, 255 insertions(+), 279 deletions(-) rename src/hooks/{useSubStep.ts => useSubStep/index.ts} (86%) create mode 100644 src/hooks/useSubStep/types.ts rename src/pages/ReimbursementAccount/BusinessInfo/{BusinessInfo.js => BusinessInfo.tsx} (67%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{AddressBusiness.js => AddressBusiness.tsx} (80%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{ConfirmationBusiness.js => ConfirmationBusiness.tsx} (82%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{IncorporationDateBusiness.js => IncorporationDateBusiness.tsx} (69%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{IncorporationStateBusiness.js => IncorporationStateBusiness.tsx} (66%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{NameBusiness.js => NameBusiness.tsx} (66%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{PhoneNumberBusiness.js => PhoneNumberBusiness.tsx} (70%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{TaxIdBusiness.js => TaxIdBusiness.tsx} (73%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{TypeBusiness.js => TypeBusiness.tsx} (61%) rename src/pages/ReimbursementAccount/BusinessInfo/substeps/{WebsiteBusiness.js => WebsiteBusiness.tsx} (65%) diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 96e6ea0bbc44..099b414341e0 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -48,14 +48,14 @@ type UnresponsiveProps = { type IconProps = { /** Flag to choose between avatar image or an icon */ - iconType: typeof CONST.ICON_TYPE_ICON; + iconType?: typeof CONST.ICON_TYPE_ICON; /** Icon to display on the left side of component */ icon: (props: SrcProps) => ReactNode; }; type AvatarProps = { - iconType: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; + iconType?: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE; icon: AvatarSource; }; @@ -84,7 +84,7 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & titleStyle?: ViewStyle; /** Any adjustments to style when menu item is hovered or pressed */ - hoverAndPressStyle: StyleProp>; + hoverAndPressStyle?: StyleProp>; /** Additional styles to style the description text below the title */ descriptionTextStyle?: StyleProp; @@ -174,7 +174,7 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & isSelected?: boolean; /** Prop to identify if we should load avatars vertically instead of diagonally */ - shouldStackHorizontally: boolean; + shouldStackHorizontally?: boolean; /** Prop to represent the size of the avatar images to be shown */ avatarSize?: (typeof CONST.AVATAR_SIZE)[keyof typeof CONST.AVATAR_SIZE]; @@ -219,10 +219,10 @@ type MenuItemProps = (ResponsiveProps | UnresponsiveProps) & furtherDetails?: string; /** The function that should be called when this component is LongPressed or right-clicked. */ - onSecondaryInteraction: () => void; + onSecondaryInteraction?: () => void; /** Array of objects that map display names to their corresponding tooltip */ - titleWithTooltips: DisplayNameWithTooltip[]; + titleWithTooltips?: DisplayNameWithTooltip[]; }; function MenuItem( diff --git a/src/hooks/useSubStep.ts b/src/hooks/useSubStep/index.ts similarity index 86% rename from src/hooks/useSubStep.ts rename to src/hooks/useSubStep/index.ts index 18519ba5b343..647b84308792 100644 --- a/src/hooks/useSubStep.ts +++ b/src/hooks/useSubStep/index.ts @@ -1,12 +1,7 @@ -import {ReactNode, useCallback, useRef, useState} from 'react'; +import {useCallback, useRef, useState} from 'react'; +import type {UseSubStep} from './types'; -type Props = { - bodyContent: ReactNode[]; - onFinished: () => void; - startFrom?: number; -}; - -export default function useSubStep({bodyContent, onFinished, startFrom = 0}: Props) { +export default function useSubStep({bodyContent, onFinished, startFrom = 0}: UseSubStep) { const [screenIndex, setScreenIndex] = useState(startFrom); const isEditing = useRef(false); diff --git a/src/hooks/useSubStep/types.ts b/src/hooks/useSubStep/types.ts new file mode 100644 index 000000000000..a039cad3a23b --- /dev/null +++ b/src/hooks/useSubStep/types.ts @@ -0,0 +1,31 @@ +import {ComponentType} from 'react'; + +type SubStepProps = { + /** value indicating whether user is editing one of the sub steps */ + isEditing: boolean; + + /** continues to next sub step */ + onNext: () => void; + + /** moves user to passed sub step */ + onMove: (step: number) => void; + + /** index of currently displayed sub step */ + screenIndex?: number; + + /** moves user to previous sub step */ + prevScreen?: () => void; +}; + +type UseSubStep = { + /** array of components that will become sub steps */ + bodyContent: Array>; + + /** called on last sub step */ + onFinished: () => void; + + /** index of initial sub step to display */ + startFrom?: number; +}; + +export type {SubStepProps, UseSubStep}; diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index 2d0b7d4dfa8b..664eef605fe9 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -131,7 +131,9 @@ function addBusinessWebsiteForDraft(website: string) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, {website}); } -function addBusinessAddressForDraft(businessAddress: {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}) { +type AddBusinessAddressForDraftProps = {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}; + +function addBusinessAddressForDraft(businessAddress: AddBusinessAddressForDraftProps) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, businessAddress); } @@ -486,3 +488,5 @@ export { verifyIdentityForBankAccount, setReimbursementAccountLoading, }; + +export type {AddBusinessAddressForDraftProps}; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.js b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx similarity index 67% rename from src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.js rename to src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx index c942dc972cce..7ab63ea94443 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx @@ -1,25 +1,21 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import lodashPick from 'lodash/pick'; import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import {parsePhoneNumber} from '@libs/PhoneNumber'; -import reimbursementAccountDraftPropTypes from '@pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes'; -import {reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import getInitialSubstepForBusinessInfo from '@pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo'; import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; import AddressBusiness from './substeps/AddressBusiness'; import ConfirmationBusiness from './substeps/ConfirmationBusiness'; import IncorporationDateBusiness from './substeps/IncorporationDateBusiness'; @@ -30,30 +26,7 @@ import TaxIdBusiness from './substeps/TaxIdBusiness'; import TypeBusiness from './substeps/TypeBusiness'; import WebsiteBusiness from './substeps/WebsiteBusiness'; -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: reimbursementAccountDraftPropTypes, - - /** Goes to the previous step */ - onBackButtonPress: PropTypes.func.isRequired, - - /** Exits flow and goes back to the workspace initial page */ - onCloseButtonPress: PropTypes.func.isRequired, - - /* The workspace policyID */ - policyID: PropTypes.string, -}; - -const defaultProps = { - reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps, - reimbursementAccountDraft: {}, - policyID: '', -}; - -const bodyContent = [ +const bodyContent: Array> = [ NameBusiness, TaxIdBusiness, WebsiteBusiness, @@ -67,19 +40,27 @@ const bodyContent = [ const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; -function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID, onBackButtonPress, onCloseButtonPress}) { +type BusinessInfoOnyxProps = { + reimbursementAccount: OnyxEntry; + reimbursementAccountDraft: OnyxEntry; +}; + +type BusinessInfoProps = { + reimbursementAccount: ReimbursementAccount; + reimbursementAccountDraft: ReimbursementAccountDraft; + policyID: string; + onBackButtonPress: () => void; + onCloseButtonPress: () => void; +}; + +function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID, onBackButtonPress, onCloseButtonPress}: BusinessInfoProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - /** - * @param {Array} fieldNames - * - * @returns {*} - */ const getBankAccountFields = useCallback( - (fieldNames) => ({ - ..._.pick(lodashGet(reimbursementAccount, 'achData'), ...fieldNames), - ..._.pick(reimbursementAccountDraft, ...fieldNames), + (fieldNames: string[]) => ({ + ...lodashPick(reimbursementAccount.achData, ...fieldNames), + ...lodashPick(reimbursementAccountDraft, ...fieldNames), }), [reimbursementAccount, reimbursementAccountDraft], ); @@ -88,11 +69,11 @@ function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID const submit = useCallback(() => { const payload = { - bankAccountID: getDefaultValueForReimbursementAccountField(reimbursementAccount, 'bankAccountID', 0), + bankAccountID: reimbursementAccount.achData?.bankAccountID ?? 0, ...values, ...getBankAccountFields(['routingNumber', 'accountNumber', 'bankName', 'plaidAccountID', 'plaidAccessToken', 'isSavings']), - companyTaxID: values.companyTaxID.replace(CONST.REGEX.NON_NUMERIC, ''), - companyPhone: parsePhoneNumber(values.companyPhone, {regionCode: CONST.COUNTRY.US}).number.significant, + companyTaxID: values.companyTaxID?.replace(CONST.REGEX.NON_NUMERIC, ''), + companyPhone: parsePhoneNumber(values.companyPhone ?? '', {regionCode: CONST.COUNTRY.US}).number?.significant, }; BankAccounts.updateCompanyInformationForBankAccount(payload, policyID); @@ -111,6 +92,7 @@ function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID }; return ( + // @ts-expect-error TODO: Remove this once ScreenWrapper (https://github.com/Expensify/App/issues/25128) is migrated to TypeScript ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx similarity index 80% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx index feed88c43257..a70a6ac8f047 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx @@ -1,28 +1,18 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import AddressForm from '@pages/ReimbursementAccount/AddressForm'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, -}; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const companyBusinessInfoKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; @@ -35,7 +25,7 @@ const INPUT_KEYS = { const REQUIRED_FIELDS = [companyBusinessInfoKey.STREET, companyBusinessInfoKey.CITY, companyBusinessInfoKey.STATE, companyBusinessInfoKey.ZIP_CODE]; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS); if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { @@ -49,7 +39,15 @@ const validate = (values) => { return errors; }; -function AddressBusiness({reimbursementAccount, onNext, isEditing}) { +type AddressBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; +}; + +type AddressBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; + +function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -60,12 +58,13 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}) { zipCode: getDefaultValueForReimbursementAccountField(reimbursementAccount, companyBusinessInfoKey.ZIP_CODE, ''), }; - const handleSubmit = (values) => { + const handleSubmit = (values: BankAccounts.AddBusinessAddressForDraftProps) => { BankAccounts.addBusinessAddressForDraft(values); onNext(); }; return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx similarity index 82% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index 17855aee0952..09302fd448d1 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -1,6 +1,6 @@ import React, {useMemo} from 'react'; import {ScrollView, View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; import DotIndicatorMessage from '@components/DotIndicatorMessage'; import FormProvider from '@components/Form/FormProvider'; @@ -9,36 +9,20 @@ import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; -import reimbursementAccountDraftPropTypes from '@pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes'; -import {reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; -import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; import CONST from '@src/CONST'; +import {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: reimbursementAccountDraftPropTypes, - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps, - reimbursementAccountDraft: {}, -}; +import {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, [businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS]); if (!values.hasNoConnectionToCannabis) { @@ -48,7 +32,17 @@ const validate = (values) => { return errors; }; -function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}) { +type ConfirmationBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; + reimbursementAccountDraft: OnyxEntry; +}; + +type ConfirmationBusinessProps = { + reimbursementAccount: ReimbursementAccount; + reimbursementAccountDraft: ReimbursementAccountDraft; +} & SubStepProps; + +function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}: ConfirmationBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -56,9 +50,10 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount); - const defaultCheckboxState = getDefaultValueForReimbursementAccountField(reimbursementAccount, businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS, false); + const defaultCheckboxState = reimbursementAccountDraft[businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; return ( + // @ts-expect-error TODO: Remove this once ScreenWrapper (https://github.com/Expensify/App/issues/25128) is migrated to TypeScript { onMove(7); }} /> + {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript */} )} @@ -172,11 +168,9 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, ); } -ConfirmationBusiness.propTypes = propTypes; -ConfirmationBusiness.defaultProps = defaultProps; ConfirmationBusiness.displayName = 'ConfirmationBusiness'; -export default withOnyx({ +export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx similarity index 69% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 7ad856aeff0d..9d7793ff97bd 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -1,39 +1,22 @@ -import lodashGet from 'lodash/get'; import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import reimbursementAccountDraftPropTypes from '@pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes'; -import {reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - /** The draft values of the bank account being setup */ - reimbursementAccountDraft: reimbursementAccountDraftPropTypes, - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps, - reimbursementAccountDraft: {}, -}; +import {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const companyIncorporationDateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_DATE; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationDateKey]); if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { @@ -45,14 +28,25 @@ const validate = (values) => { return errors; }; -function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}) { +type IncorporationDateBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; + reimbursementAccountDraft: OnyxEntry; +}; + +type IncorporationDateBusinessProps = { + reimbursementAccount: ReimbursementAccount; + reimbursementAccountDraft: ReimbursementAccountDraft; +} & SubStepProps; + +function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: IncorporationDateBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultCompanyIncorporationDate = - getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationDateKey, '') || lodashGet(reimbursementAccountDraft, companyIncorporationDateKey, ''); + getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationDateKey, '') || (reimbursementAccountDraft[companyIncorporationDateKey] ?? ''); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript {translate('businessInfoStep.selectYourCompanysIncorporationDate')} ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx similarity index 66% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx index dae6f5d3589e..5e004b0bb22a 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx @@ -1,39 +1,38 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; import StatePicker from '@components/StatePicker'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, +const companyIncorporationStateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_STATE; - ...subStepPropTypes, -}; +const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationStateKey]); -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, +type IncorporationStateBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; }; -const companyIncorporationStateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_STATE; - -const validate = (values) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationStateKey]); +type IncorporationStateBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; -function IncorporationStateBusiness({reimbursementAccount, onNext, isEditing}) { +function IncorporationStateBusiness({reimbursementAccount, onNext, isEditing}: IncorporationStateBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultCompanyIncorporationState = getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationStateKey, ''); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript
{translate('businessInfoStep.pleaseSelectTheStateYourCompanyWasIncorporatedIn')} ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx similarity index 66% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx index f25272a9857d..9e3b3856eb7e 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx @@ -1,33 +1,32 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; +import InputWrapper from '@components/Form/InputWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, +const companyNameKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_NAME; - ...subStepPropTypes, -}; +const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyNameKey]); -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, +type NameBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; }; -const companyNameKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_NAME; - -const validate = (values) => ValidationUtils.getFieldRequiredErrors(values, [companyNameKey]); +type NameBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; -function NameBusiness({reimbursementAccount, onNext, isEditing}) { +function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -38,6 +37,7 @@ function NameBusiness({reimbursementAccount, onNext, isEditing}) { const shouldDisableCompanyName = Boolean(bankAccountID && defaultCompanyName); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript {translate('businessInfoStep.enterTheNameOfYourBusiness')} - ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx similarity index 70% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx index dfb52ff49308..c51fd8f08345 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx @@ -1,31 +1,22 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; +import InputWrapper from '@components/Form/InputWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, -}; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const companyPhoneNumberKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_PHONE; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyPhoneNumberKey]); if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { @@ -35,13 +26,22 @@ const validate = (values) => { return errors; }; -function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}) { +type PhoneNumberBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; +}; + +type PhoneNumberBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; + +function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNumberBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultCompanyPhoneNumber = getDefaultValueForReimbursementAccountField(reimbursementAccount, companyPhoneNumberKey, ''); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript {translate('businessInfoStep.enterYourCompanysPhoneNumber')} - ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx similarity index 73% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx index c1ba2f5942ae..a33a3f992526 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx @@ -1,31 +1,22 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; +import InputWrapper from '@components/Form/InputWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, -}; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const companyTaxIdKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_TAX_ID; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyTaxIdKey]); if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { @@ -35,7 +26,15 @@ const validate = (values) => { return errors; }; -function TaxIdBusiness({reimbursementAccount, onNext, isEditing}) { +type TaxIdBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; +}; + +type TaxIdBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; + +function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -46,6 +45,7 @@ function TaxIdBusiness({reimbursementAccount, onNext, isEditing}) { const shouldDisableCompanyTaxID = Boolean(bankAccountID && defaultCompanyTaxId); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript {translate('businessInfoStep.enterYourCompanysTaxIdNumber')} - ); } -TaxIdBusiness.propTypes = propTypes; -TaxIdBusiness.defaultProps = defaultProps; TaxIdBusiness.displayName = 'TaxIdBusiness'; -export default withOnyx({ +export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx similarity index 61% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx index 59653fe78804..93a7d5ba2ff7 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx @@ -1,40 +1,38 @@ import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; import Picker from '@components/Picker'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {ReimbursementAccount} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, +const companyIncorporationTypeKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_TYPE; - ...subStepPropTypes, -}; +const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationTypeKey]); -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, +type TypeBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; }; -const companyIncorporationTypeKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_TYPE; - -const validate = (values) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationTypeKey]); +type TypeBusinessProps = { + reimbursementAccount: ReimbursementAccount; +} & SubStepProps; -function TypeBusiness({reimbursementAccount, onNext, isEditing}) { +function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultIncorporationType = getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationTypeKey, ''); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript
({value: key, label: translate(`businessInfoStep.incorporationType.${key}`)}))} + items={Object.keys(CONST.INCORPORATION_TYPES).map((key) => ({value: key, label: translate(`businessInfoStep.incorporationType.${key}`)}))} placeholder={{value: '', label: '-'}} + // @ts-expect-error TODO: Remove this once Picker (https://github.com/Expensify/App/issues/25091) is migrated to TypeScript defaultValue={defaultIncorporationType} shouldSaveDraft /> @@ -56,11 +55,9 @@ function TypeBusiness({reimbursementAccount, onNext, isEditing}) { ); } -TypeBusiness.propTypes = propTypes; -TypeBusiness.defaultProps = defaultProps; TypeBusiness.displayName = 'TypeBusiness'; -export default withOnyx({ +export default withOnyx({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.js b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx similarity index 65% rename from src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.js rename to src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx index 6118d43f779b..6eb84957f8fd 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.js +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx @@ -1,51 +1,24 @@ import Str from 'expensify-common/lib/str'; -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useEffect, useMemo} from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import Form from '@components/Form'; +import InputWrapper from '@components/Form/InputWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; +import {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; -import {reimbursementAccountDefaultProps, reimbursementAccountPropTypes} from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; -import subStepPropTypes from '@pages/ReimbursementAccount/subStepPropTypes'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** Reimbursement account from ONYX */ - reimbursementAccount: reimbursementAccountPropTypes, - - /** Session info for the currently logged in user. */ - session: PropTypes.shape({ - /** Currently logged in user email */ - email: PropTypes.string, - }), - - /** Object with various information about the user */ - user: PropTypes.shape({ - /** Whether or not the user is on a public domain email account or not */ - isFromPublicDomain: PropTypes.bool, - }), - - ...subStepPropTypes, -}; - -const defaultProps = { - reimbursementAccount: reimbursementAccountDefaultProps, - session: { - email: null, - }, - user: {}, -}; +import {ReimbursementAccount, Session, User} from '@src/types/onyx'; +import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; const companyWebsiteKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_WEBSITE; -const validate = (values) => { +const validate = (values: OnyxCommon.Errors) => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyWebsiteKey]); if (values.website && !ValidationUtils.isValidWebsite(values.website)) { @@ -55,11 +28,26 @@ const validate = (values) => { return errors; }; -function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing}) { +type WebsiteBusinessOnyxProps = { + reimbursementAccount: OnyxEntry; + session: OnyxEntry; + user: OnyxEntry; +}; + +type WebsiteBusinessProps = { + reimbursementAccount: ReimbursementAccount; + session: Session; + user: User; +} & SubStepProps; + +function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing}: WebsiteBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const defaultWebsiteExample = useMemo(() => (lodashGet(user, 'isFromPublicDomain', false) ? 'https://' : `https://www.${Str.extractEmailDomain(session.email, '')}`), [user, session]); + const defaultWebsiteExample = useMemo( + () => (user.isFromPublicDomain ?? false ? 'https://' : `https://www.${Str.extractEmailDomain(session.email ?? '')}`), + [session.email, user.isFromPublicDomain], + ); const defaultCompanyWebsite = getDefaultValueForReimbursementAccountField(reimbursementAccount, companyWebsiteKey, defaultWebsiteExample); @@ -68,6 +56,7 @@ function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing }, [defaultCompanyWebsite]); return ( + // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript {translate('businessInfoStep.enterYourCompanysWebsite')} {translate('common.websiteExample')} - ({ reimbursementAccount: { key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, }, diff --git a/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts b/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts index 32a25254171f..2188917b6bef 100644 --- a/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts +++ b/src/pages/ReimbursementAccount/utils/getInitialSubstepForBusinessInfo.ts @@ -1,14 +1,12 @@ -import {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; +import {CompanyStepProps} from '@src/types/onyx/ReimbursementAccountDraft'; const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; -type BusinessInfoData = Record, string>; - /** * Returns the initial substep for the Business Info step based on already existing data */ -function getInitialSubstepForBusinessInfo(data: BusinessInfoData): number { +function getInitialSubstepForBusinessInfo(data: CompanyStepProps): number { if (data[businessInfoStepKeys.COMPANY_NAME] === '') { return 0; } diff --git a/src/types/onyx/ReimbursementAccountDraft.ts b/src/types/onyx/ReimbursementAccountDraft.ts index 1edfa591cc34..03b2c8f1a0f0 100644 --- a/src/types/onyx/ReimbursementAccountDraft.ts +++ b/src/types/onyx/ReimbursementAccountDraft.ts @@ -18,7 +18,7 @@ type CompanyStepProps = { website?: string; companyTaxID?: string; incorporationType?: string; - incorporationDate?: string | Date; + incorporationDate?: string; incorporationState?: string; hasNoConnectionToCannabis?: boolean; }; From 59361312fa28e3a2e2bda14ecc1608de009834bc Mon Sep 17 00:00:00 2001 From: Marcin Swornowski Date: Fri, 22 Dec 2023 15:42:29 +0100 Subject: [PATCH 2/4] fix: added casting to TranslationPaths --- .../BusinessInfo/substeps/TypeBusiness.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx index 93a7d5ba2ff7..c4764f2e78b6 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx @@ -9,6 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; +import {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; @@ -45,7 +46,7 @@ function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessPro ({value: key, label: translate(`businessInfoStep.incorporationType.${key}`)}))} + items={Object.keys(CONST.INCORPORATION_TYPES).map((key) => ({value: key, label: translate(`businessInfoStep.incorporationType.${key}` as TranslationPaths)}))} placeholder={{value: '', label: '-'}} // @ts-expect-error TODO: Remove this once Picker (https://github.com/Expensify/App/issues/25091) is migrated to TypeScript defaultValue={defaultIncorporationType} From 4064f8c52dfaa74a00d4be73724d1c11b5c9cb5d Mon Sep 17 00:00:00 2001 From: Marcin Swornowski Date: Thu, 28 Dec 2023 17:01:02 +0100 Subject: [PATCH 3/4] fix: CR comments --- src/libs/actions/BankAccounts.ts | 8 ++--- .../BusinessInfo/BusinessInfo.tsx | 36 +++++++++++-------- .../BusinessInfo/substeps/AddressBusiness.tsx | 20 +++++------ .../substeps/ConfirmationBusiness.tsx | 33 +++++++++-------- .../substeps/IncorporationDateBusiness.tsx | 25 ++++++------- .../substeps/IncorporationStateBusiness.tsx | 14 ++++---- .../BusinessInfo/substeps/NameBusiness.tsx | 14 ++++---- .../substeps/PhoneNumberBusiness.tsx | 18 +++++----- .../BusinessInfo/substeps/TaxIdBusiness.tsx | 18 +++++----- .../BusinessInfo/substeps/TypeBusiness.tsx | 22 +++++++----- .../BusinessInfo/substeps/WebsiteBusiness.tsx | 32 +++++++++-------- ...efaultValueForReimbursementAccountField.js | 2 +- .../utils/getSubstepValues.ts | 7 ++-- src/types/onyx/Form.ts | 4 ++- 14 files changed, 136 insertions(+), 117 deletions(-) diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index e94c28416052..6f8dcca1f2ec 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -43,6 +43,8 @@ type ReimbursementAccountSubStep = BankAccountSubStep | ''; type PlaidBankAccountToConnect = Omit; +type BusinessAddress = {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}; + function clearPlaid(): Promise { Onyx.set(ONYXKEYS.PLAID_LINK_TOKEN, ''); Onyx.set(ONYXKEYS.PLAID_CURRENT_EVENT, null); @@ -133,9 +135,7 @@ function addBusinessWebsiteForDraft(website: string) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, {website}); } -type AddBusinessAddressForDraftProps = {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}; - -function addBusinessAddressForDraft(businessAddress: AddBusinessAddressForDraftProps) { +function addBusinessAddressForDraft(businessAddress: BusinessAddress) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, businessAddress); } @@ -491,4 +491,4 @@ export { setReimbursementAccountLoading, }; -export type {AddBusinessAddressForDraftProps}; +export type {BusinessAddress}; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx index 7ab63ea94443..833f62e19499 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx @@ -26,6 +26,25 @@ import TaxIdBusiness from './substeps/TaxIdBusiness'; import TypeBusiness from './substeps/TypeBusiness'; import WebsiteBusiness from './substeps/WebsiteBusiness'; +type BusinessInfoOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; + + /** The draft values of the bank account being setup */ + reimbursementAccountDraft: OnyxEntry; +}; + +type BusinessInfoProps = BusinessInfoOnyxProps & { + /* The workspace policyID */ + policyID: string; + + /** Goes to the previous step */ + onBackButtonPress: () => void; + + /** Exits flow and goes back to the workspace initial page */ + onCloseButtonPress: () => void; +}; + const bodyContent: Array> = [ NameBusiness, TaxIdBusiness, @@ -40,26 +59,13 @@ const bodyContent: Array> = [ const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; -type BusinessInfoOnyxProps = { - reimbursementAccount: OnyxEntry; - reimbursementAccountDraft: OnyxEntry; -}; - -type BusinessInfoProps = { - reimbursementAccount: ReimbursementAccount; - reimbursementAccountDraft: ReimbursementAccountDraft; - policyID: string; - onBackButtonPress: () => void; - onCloseButtonPress: () => void; -}; - function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID, onBackButtonPress, onCloseButtonPress}: BusinessInfoProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const getBankAccountFields = useCallback( (fieldNames: string[]) => ({ - ...lodashPick(reimbursementAccount.achData, ...fieldNames), + ...lodashPick(reimbursementAccount?.achData, ...fieldNames), ...lodashPick(reimbursementAccountDraft, ...fieldNames), }), [reimbursementAccount, reimbursementAccountDraft], @@ -69,7 +75,7 @@ function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID const submit = useCallback(() => { const payload = { - bankAccountID: reimbursementAccount.achData?.bankAccountID ?? 0, + bankAccountID: reimbursementAccount?.achData?.bankAccountID ?? 0, ...values, ...getBankAccountFields(['routingNumber', 'accountNumber', 'bankName', 'plaidAccountID', 'plaidAccessToken', 'isSavings']), companyTaxID: values.companyTaxID?.replace(CONST.REGEX.NON_NUMERIC, ''), diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx index a70a6ac8f047..2727d06776e2 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/AddressBusiness.tsx @@ -12,8 +12,16 @@ import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type AddressBusinessOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; +}; + +type AddressBusinessProps = AddressBusinessOnyxProps & SubStepProps; + const companyBusinessInfoKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; const INPUT_KEYS = { @@ -25,7 +33,7 @@ const INPUT_KEYS = { const REQUIRED_FIELDS = [companyBusinessInfoKey.STREET, companyBusinessInfoKey.CITY, companyBusinessInfoKey.STATE, companyBusinessInfoKey.ZIP_CODE]; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS); if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { @@ -39,14 +47,6 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type AddressBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; -}; - -type AddressBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; - function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -58,7 +58,7 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusin zipCode: getDefaultValueForReimbursementAccountField(reimbursementAccount, companyBusinessInfoKey.ZIP_CODE, ''), }; - const handleSubmit = (values: BankAccounts.AddBusinessAddressForDraftProps) => { + const handleSubmit = (values: BankAccounts.BusinessAddress) => { BankAccounts.addBusinessAddressForDraft(values); onNext(); }; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index 09302fd448d1..d3ea3154c845 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -1,3 +1,4 @@ +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import React, {useMemo} from 'react'; import {ScrollView, View} from 'react-native'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; @@ -15,14 +16,26 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; import CONST from '@src/CONST'; -import {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +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; + const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS]); if (!values.hasNoConnectionToCannabis) { @@ -32,25 +45,15 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type ConfirmationBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; - reimbursementAccountDraft: OnyxEntry; -}; - -type ConfirmationBusinessProps = { - reimbursementAccount: ReimbursementAccount; - reimbursementAccountDraft: ReimbursementAccountDraft; -} & SubStepProps; - function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}: ConfirmationBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const values = useMemo(() => getSubstepValues(businessInfoStepKeys, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); - const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount); + const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount ?? {}); - const defaultCheckboxState = reimbursementAccountDraft[businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; + const defaultCheckboxState = reimbursementAccountDraft?.[businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; return ( // @ts-expect-error TODO: Remove this once ScreenWrapper (https://github.com/Expensify/App/issues/25128) is migrated to TypeScript @@ -119,7 +122,7 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, /> { onMove(7); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 9d7793ff97bd..5ca0cc0b110a 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -12,11 +12,22 @@ import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAcc import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type IncorporationDateBusinessOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; + + /** The draft values of the bank account being setup */ + reimbursementAccountDraft: OnyxEntry; +}; + +type IncorporationDateBusinessProps = IncorporationDateBusinessOnyxProps & SubStepProps; + const companyIncorporationDateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_DATE; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationDateKey]); if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { @@ -28,22 +39,12 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type IncorporationDateBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; - reimbursementAccountDraft: OnyxEntry; -}; - -type IncorporationDateBusinessProps = { - reimbursementAccount: ReimbursementAccount; - reimbursementAccountDraft: ReimbursementAccountDraft; -} & SubStepProps; - function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: IncorporationDateBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultCompanyIncorporationDate = - getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationDateKey, '') || (reimbursementAccountDraft[companyIncorporationDateKey] ?? ''); + getDefaultValueForReimbursementAccountField(reimbursementAccount, companyIncorporationDateKey, '') || (reimbursementAccountDraft?.[companyIncorporationDateKey] ?? ''); return ( // @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx index 5e004b0bb22a..91b1cd729a1f 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationStateBusiness.tsx @@ -11,19 +11,19 @@ import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAcc import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const companyIncorporationStateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_STATE; - -const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationStateKey]); - type IncorporationStateBusinessOnyxProps = { + /** Reimbursement account from ONYX */ reimbursementAccount: OnyxEntry; }; -type IncorporationStateBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; +type IncorporationStateBusinessProps = IncorporationStateBusinessOnyxProps & SubStepProps; + +const companyIncorporationStateKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_STATE; + +const validate = (values: FormValues): OnyxCommon.Errors => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationStateKey]); function IncorporationStateBusiness({reimbursementAccount, onNext, isEditing}: IncorporationStateBusinessProps) { const {translate} = useLocalize(); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx index 9e3b3856eb7e..49a76155ca91 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/NameBusiness.tsx @@ -12,19 +12,19 @@ import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAcc import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const companyNameKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_NAME; - -const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyNameKey]); - type NameBusinessOnyxProps = { + /** Reimbursement account from ONYX */ reimbursementAccount: OnyxEntry; }; -type NameBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; +type NameBusinessProps = NameBusinessOnyxProps & SubStepProps; + +const companyNameKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_NAME; + +const validate = (values: FormValues): OnyxCommon.Errors => ValidationUtils.getFieldRequiredErrors(values, [companyNameKey]); function NameBusiness({reimbursementAccount, onNext, isEditing}: NameBusinessProps) { const {translate} = useLocalize(); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx index c51fd8f08345..28aafc05718e 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/PhoneNumberBusiness.tsx @@ -12,11 +12,19 @@ import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAcc import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type PhoneNumberBusinessOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; +}; + +type PhoneNumberBusinessProps = PhoneNumberBusinessOnyxProps & SubStepProps; + const companyPhoneNumberKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_PHONE; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyPhoneNumberKey]); if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) { @@ -26,14 +34,6 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type PhoneNumberBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; -}; - -type PhoneNumberBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; - function PhoneNumberBusiness({reimbursementAccount, onNext, isEditing}: PhoneNumberBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx index a33a3f992526..3b1d47d7ba31 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TaxIdBusiness.tsx @@ -12,11 +12,19 @@ import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAcc import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type TaxIdBusinessOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; +}; + +type TaxIdBusinessProps = TaxIdBusinessOnyxProps & SubStepProps; + const companyTaxIdKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_TAX_ID; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyTaxIdKey]); if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) { @@ -26,14 +34,6 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type TaxIdBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; -}; - -type TaxIdBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; - function TaxIdBusiness({reimbursementAccount, onNext, isEditing}: TaxIdBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx index c4764f2e78b6..78415723f674 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness.tsx @@ -9,22 +9,23 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; import getDefaultValueForReimbursementAccountField from '@pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField'; import CONST from '@src/CONST'; -import {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -const companyIncorporationTypeKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_TYPE; - -const validate = (values: OnyxCommon.Errors) => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationTypeKey]); - type TypeBusinessOnyxProps = { + /** Reimbursement account from ONYX */ reimbursementAccount: OnyxEntry; }; -type TypeBusinessProps = { - reimbursementAccount: ReimbursementAccount; -} & SubStepProps; +type TypeBusinessProps = TypeBusinessOnyxProps & SubStepProps; + +type IncorporationType = keyof typeof CONST.INCORPORATION_TYPES; + +const companyIncorporationTypeKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.INCORPORATION_TYPE; + +const validate = (values: FormValues): OnyxCommon.Errors => ValidationUtils.getFieldRequiredErrors(values, [companyIncorporationTypeKey]); function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessProps) { const {translate} = useLocalize(); @@ -46,7 +47,10 @@ function TypeBusiness({reimbursementAccount, onNext, isEditing}: TypeBusinessPro ({value: key, label: translate(`businessInfoStep.incorporationType.${key}` as TranslationPaths)}))} + items={Object.keys(CONST.INCORPORATION_TYPES).map((key) => ({ + value: key, + label: translate(`businessInfoStep.incorporationType.${key as IncorporationType}`), + }))} placeholder={{value: '', label: '-'}} // @ts-expect-error TODO: Remove this once Picker (https://github.com/Expensify/App/issues/25091) is migrated to TypeScript defaultValue={defaultIncorporationType} diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx index 6eb84957f8fd..ed73de95a04a 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/WebsiteBusiness.tsx @@ -14,11 +14,25 @@ import * as BankAccounts from '@userActions/BankAccounts'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {ReimbursementAccount, Session, User} from '@src/types/onyx'; +import {FormValues} from '@src/types/onyx/Form'; import * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +type WebsiteBusinessOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; + + /** Session info for the currently logged in user. */ + session: OnyxEntry; + + /** Object with various information about the user */ + user: OnyxEntry; +}; + +type WebsiteBusinessProps = WebsiteBusinessOnyxProps & SubStepProps; + const companyWebsiteKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY.COMPANY_WEBSITE; -const validate = (values: OnyxCommon.Errors) => { +const validate = (values: FormValues): OnyxCommon.Errors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [companyWebsiteKey]); if (values.website && !ValidationUtils.isValidWebsite(values.website)) { @@ -28,25 +42,13 @@ const validate = (values: OnyxCommon.Errors) => { return errors; }; -type WebsiteBusinessOnyxProps = { - reimbursementAccount: OnyxEntry; - session: OnyxEntry; - user: OnyxEntry; -}; - -type WebsiteBusinessProps = { - reimbursementAccount: ReimbursementAccount; - session: Session; - user: User; -} & SubStepProps; - function WebsiteBusiness({reimbursementAccount, user, session, onNext, isEditing}: WebsiteBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const defaultWebsiteExample = useMemo( - () => (user.isFromPublicDomain ?? false ? 'https://' : `https://www.${Str.extractEmailDomain(session.email ?? '')}`), - [session.email, user.isFromPublicDomain], + () => (user?.isFromPublicDomain ? 'https://' : `https://www.${Str.extractEmailDomain(session?.email ?? '')}`), + [session?.email, user?.isFromPublicDomain], ); const defaultCompanyWebsite = getDefaultValueForReimbursementAccountField(reimbursementAccount, companyWebsiteKey, defaultWebsiteExample); diff --git a/src/pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField.js b/src/pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField.js index 9c0c25146933..9806ff2f38a7 100644 --- a/src/pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField.js +++ b/src/pages/ReimbursementAccount/utils/getDefaultValueForReimbursementAccountField.js @@ -1,7 +1,7 @@ import lodashGet from 'lodash/get'; /** - * @param {Object} reimbursementAccount + * @param {Object | null} reimbursementAccount * @param {String} fieldName * @param {* | undefined} defaultValue * @returns {String} diff --git a/src/pages/ReimbursementAccount/utils/getSubstepValues.ts b/src/pages/ReimbursementAccount/utils/getSubstepValues.ts index 857547038b43..1201cedd86d0 100644 --- a/src/pages/ReimbursementAccount/utils/getSubstepValues.ts +++ b/src/pages/ReimbursementAccount/utils/getSubstepValues.ts @@ -1,15 +1,16 @@ +import {OnyxEntry} from 'react-native-onyx'; import type {ReimbursementAccount, ReimbursementAccountDraft} from '@src/types/onyx'; import getDefaultValueForReimbursementAccountField from './getDefaultValueForReimbursementAccountField'; function getSubstepValues( inputKeys: Record, - reimbursementAccountDraft: ReimbursementAccountDraft, - reimbursementAccount: ReimbursementAccount, + reimbursementAccountDraft: OnyxEntry, + reimbursementAccount: OnyxEntry, ): {[K in T]: ReimbursementAccountDraft[K]} { return Object.entries(inputKeys).reduce( (acc, [, value]) => ({ ...acc, - [value]: reimbursementAccountDraft[value] ?? getDefaultValueForReimbursementAccountField(reimbursementAccount, value, ''), + [value]: reimbursementAccountDraft?.[value] ?? getDefaultValueForReimbursementAccountField(reimbursementAccount, value, ''), }), {} as {[K in T]: ReimbursementAccountDraft[K]}, ); diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts index 7b7d8d76536a..559834144338 100644 --- a/src/types/onyx/Form.ts +++ b/src/types/onyx/Form.ts @@ -21,6 +21,8 @@ type DateOfBirthForm = Form & { dob?: string; }; +type FormValues = Record; + export default Form; -export type {AddDebitCardForm, DateOfBirthForm}; +export type {AddDebitCardForm, DateOfBirthForm, FormValues}; From 47634ab6ecc0ddd33920d927488554ac6c001343 Mon Sep 17 00:00:00 2001 From: Marcin Swornowski Date: Fri, 29 Dec 2023 11:15:44 +0100 Subject: [PATCH 4/4] fix: CR comments --- src/libs/actions/BankAccounts.ts | 7 ++++++- .../ReimbursementAccount/BusinessInfo/BusinessInfo.tsx | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/BankAccounts.ts b/src/libs/actions/BankAccounts.ts index 6f8dcca1f2ec..38544037396a 100644 --- a/src/libs/actions/BankAccounts.ts +++ b/src/libs/actions/BankAccounts.ts @@ -43,7 +43,12 @@ type ReimbursementAccountSubStep = BankAccountSubStep | ''; type PlaidBankAccountToConnect = Omit; -type BusinessAddress = {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}; +type BusinessAddress = { + addressStreet?: string; + addressCity?: string; + addressState?: string; + addressZipCode?: string; +}; function clearPlaid(): Promise { Onyx.set(ONYXKEYS.PLAID_LINK_TOKEN, ''); diff --git a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx index 833f62e19499..ef33c515bf76 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/BusinessInfo.tsx @@ -35,7 +35,7 @@ type BusinessInfoOnyxProps = { }; type BusinessInfoProps = BusinessInfoOnyxProps & { - /* The workspace policyID */ + /** The workspace policyID */ policyID: string; /** Goes to the previous step */