Skip to content

Commit

Permalink
Merge pull request #33495 from Swor71/marcin/migrate-businessInfo-ts
Browse files Browse the repository at this point in the history
feat: migrate BusinessInfo step to TS
  • Loading branch information
mountiny authored Dec 29, 2023
2 parents 2cfe13d + 47634ab commit 68b0160
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 227 deletions.
4 changes: 2 additions & 2 deletions src/components/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSubStep/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useCallback, useRef, useState} from 'react';
import {UseSubStep} from './types';
import type {UseSubStep} from './types';

export default function useSubStep({bodyContent, onFinished, startFrom = 0}: UseSubStep) {
const [screenIndex, setScreenIndex] = useState(startFrom);
Expand Down
11 changes: 10 additions & 1 deletion src/libs/actions/BankAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ type ReimbursementAccountSubStep = BankAccountSubStep | '';

type PlaidBankAccountToConnect = Omit<PlaidBankAccount, 'isSavings' | 'addressName' | 'mask'>;

type BusinessAddress = {
addressStreet?: string;
addressCity?: string;
addressState?: string;
addressZipCode?: string;
};

function clearPlaid(): Promise<void> {
Onyx.set(ONYXKEYS.PLAID_LINK_TOKEN, '');
Onyx.set(ONYXKEYS.PLAID_CURRENT_EVENT, null);
Expand Down Expand Up @@ -133,7 +140,7 @@ function addBusinessWebsiteForDraft(website: string) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, {website});
}

function addBusinessAddressForDraft(businessAddress: {addressStreet?: string; addressCity?: string; addressState?: string; addressZipCode?: string}) {
function addBusinessAddressForDraft(businessAddress: BusinessAddress) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, businessAddress);
}

Expand Down Expand Up @@ -488,3 +495,5 @@ export {
verifyIdentityForBankAccount,
setReimbursementAccountLoading,
};

export type {BusinessAddress};
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -30,30 +26,26 @@ import TaxIdBusiness from './substeps/TaxIdBusiness';
import TypeBusiness from './substeps/TypeBusiness';
import WebsiteBusiness from './substeps/WebsiteBusiness';

const propTypes = {
type BusinessInfoOnyxProps = {
/** Reimbursement account from ONYX */
reimbursementAccount: reimbursementAccountPropTypes,
reimbursementAccount: OnyxEntry<ReimbursementAccount>;

/** The draft values of the bank account being setup */
reimbursementAccountDraft: reimbursementAccountDraftPropTypes,
reimbursementAccountDraft: OnyxEntry<ReimbursementAccountDraft>;
};

type BusinessInfoProps = BusinessInfoOnyxProps & {
/** The workspace policyID */
policyID: string;

/** Goes to the previous step */
onBackButtonPress: PropTypes.func.isRequired,
onBackButtonPress: () => void;

/** 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: '',
onCloseButtonPress: () => void;
};

const bodyContent = [
const bodyContent: Array<React.ComponentType<SubStepProps>> = [
NameBusiness,
TaxIdBusiness,
WebsiteBusiness,
Expand All @@ -67,19 +59,14 @@ const bodyContent = [

const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY;

function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID, onBackButtonPress, onCloseButtonPress}) {
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],
);
Expand All @@ -88,11 +75,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);
Expand All @@ -111,6 +98,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
<ScreenWrapper
testID={BusinessInfo.displayName}
includeSafeAreaPaddingBottom={false}
Expand Down Expand Up @@ -139,11 +127,9 @@ function BusinessInfo({reimbursementAccount, reimbursementAccountDraft, policyID
);
}

BusinessInfo.propTypes = propTypes;
BusinessInfo.defaultProps = defaultProps;
BusinessInfo.displayName = 'BusinessInfo';

export default withOnyx({
export default withOnyx<BusinessInfoProps, BusinessInfoOnyxProps>({
reimbursementAccount: {
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
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';
import {ReimbursementAccount} from '@src/types/onyx';
import {FormValues} from '@src/types/onyx/Form';
import * as OnyxCommon from '@src/types/onyx/OnyxCommon';

const propTypes = {
type AddressBusinessOnyxProps = {
/** Reimbursement account from ONYX */
reimbursementAccount: reimbursementAccountPropTypes,

...subStepPropTypes,
reimbursementAccount: OnyxEntry<ReimbursementAccount>;
};

const defaultProps = {
reimbursementAccount: reimbursementAccountDefaultProps,
};
type AddressBusinessProps = AddressBusinessOnyxProps & SubStepProps;

const companyBusinessInfoKey = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY;

Expand All @@ -35,7 +33,7 @@ const INPUT_KEYS = {

const REQUIRED_FIELDS = [companyBusinessInfoKey.STREET, companyBusinessInfoKey.CITY, companyBusinessInfoKey.STATE, companyBusinessInfoKey.ZIP_CODE];

const validate = (values) => {
const validate = (values: FormValues): OnyxCommon.Errors => {
const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS);

if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) {
Expand All @@ -49,7 +47,7 @@ const validate = (values) => {
return errors;
};

function AddressBusiness({reimbursementAccount, onNext, isEditing}) {
function AddressBusiness({reimbursementAccount, onNext, isEditing}: AddressBusinessProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();

Expand All @@ -60,12 +58,13 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}) {
zipCode: getDefaultValueForReimbursementAccountField(reimbursementAccount, companyBusinessInfoKey.ZIP_CODE, ''),
};

const handleSubmit = (values) => {
const handleSubmit = (values: BankAccounts.BusinessAddress) => {
BankAccounts.addBusinessAddressForDraft(values);
onNext();
};

return (
// @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript
<FormProvider
formID={ONYXKEYS.REIMBURSEMENT_ACCOUNT}
submitButtonText={isEditing ? translate('common.confirm') : translate('common.next')}
Expand All @@ -87,11 +86,9 @@ function AddressBusiness({reimbursementAccount, onNext, isEditing}) {
);
}

AddressBusiness.propTypes = propTypes;
AddressBusiness.defaultProps = defaultProps;
AddressBusiness.displayName = 'AddressBusiness';

export default withOnyx({
export default withOnyx<AddressBusinessProps, AddressBusinessOnyxProps>({
reimbursementAccount: {
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST';
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';
Expand All @@ -9,36 +10,32 @@ 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 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';

const propTypes = {
type ConfirmationBusinessOnyxProps = {
/** Reimbursement account from ONYX */
reimbursementAccount: reimbursementAccountPropTypes,
reimbursementAccount: OnyxEntry<ReimbursementAccount>;

/** The draft values of the bank account being setup */
reimbursementAccountDraft: reimbursementAccountDraftPropTypes,

...subStepPropTypes,
reimbursementAccountDraft: OnyxEntry<ReimbursementAccountDraft>;
};

const defaultProps = {
reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps,
reimbursementAccountDraft: {},
};
type ConfirmationBusinessProps = ConfirmationBusinessOnyxProps & SubStepProps;

type States = keyof typeof COMMON_CONST.STATES;

const businessInfoStepKeys = CONST.BANK_ACCOUNT.BUSINESS_INFO_STEP.INPUT_KEY;

const validate = (values) => {
const validate = (values: FormValues): OnyxCommon.Errors => {
const errors = ValidationUtils.getFieldRequiredErrors(values, [businessInfoStepKeys.HAS_NO_CONNECTION_TO_CANNABIS]);

if (!values.hasNoConnectionToCannabis) {
Expand All @@ -48,17 +45,18 @@ const validate = (values) => {
return errors;
};

function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}) {
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 = 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
<ScreenWrapper
testID={ConfirmationBusiness.displayName}
style={[styles.pt0]}
Expand Down Expand Up @@ -124,12 +122,13 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft,
/>
<MenuItemWithTopDescription
description={translate('businessInfoStep.incorporationState')}
title={translate(`allStates.${values[businessInfoStepKeys.INCORPORATION_STATE]}.stateName`)}
title={translate(`allStates.${values[businessInfoStepKeys.INCORPORATION_STATE] as States}.stateName`)}
shouldShowRightIcon
onPress={() => {
onMove(7);
}}
/>
{/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript */}
<FormProvider
formID={ONYXKEYS.REIMBURSEMENT_ACCOUNT}
validate={validate}
Expand Down Expand Up @@ -163,7 +162,7 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft,
<DotIndicatorMessage
textStyles={[styles.formError]}
type="error"
messages={{0: error}}
messages={{error}}
/>
)}
</View>
Expand All @@ -172,11 +171,9 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft,
);
}

ConfirmationBusiness.propTypes = propTypes;
ConfirmationBusiness.defaultProps = defaultProps;
ConfirmationBusiness.displayName = 'ConfirmationBusiness';

export default withOnyx({
export default withOnyx<ConfirmationBusinessProps, ConfirmationBusinessOnyxProps>({
reimbursementAccount: {
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
},
Expand Down
Loading

0 comments on commit 68b0160

Please sign in to comment.