Skip to content

Commit

Permalink
Feat/vbba prevent autosaving in editing mode (Expensify#6)
Browse files Browse the repository at this point in the history
* feat: added hook for submit step

* feat: preventa automatically update values in editing mode in PersonalInfo

* fix: changed name of kys array

* fix: move\ hook to the main directory

* feat: applied to the BankInfo step

* feat: applied to the UBO steps

* fix: lint fixes

* refactorL: standarize variable names
  • Loading branch information
barttom authored Jan 22, 2024
1 parent eca2209 commit 997149f
Show file tree
Hide file tree
Showing 30 changed files with 334 additions and 199 deletions.
32 changes: 32 additions & 0 deletions src/hooks/useReimbursementAccountStepFormSubmit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {useCallback} from 'react';
import * as FormActions from '@userActions/FormActions';
import type {OnyxFormKeyWithoutDraft} from '@userActions/FormActions';
import ONYXKEYS from '@src/ONYXKEYS';
import type {FormValues} from '@src/types/onyx/Form';
import type {SubStepProps} from './useSubStep/types';

type UseReimbursementAccountStepFormSubmitParams = Pick<SubStepProps, 'isEditing' | 'onNext'> & {
formId?: OnyxFormKeyWithoutDraft;
fieldIds: Array<keyof FormValues>;
};

export default function useReimbursementAccountStepFormSubmit({formId = ONYXKEYS.REIMBURSEMENT_ACCOUNT, isEditing, onNext, fieldIds}: UseReimbursementAccountStepFormSubmitParams) {
return useCallback(
(values: FormValues) => {
if (isEditing) {
const stepValues = fieldIds.reduce(
(acc, key) => ({
...acc,
[key]: values[key],
}),
{},
);

FormActions.setDraftValues(formId, stepValues);
}

onNext();
},
[isEditing, onNext, formId, fieldIds],
);
}
10 changes: 0 additions & 10 deletions src/libs/actions/BankAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,6 @@ function addBusinessWebsiteForDraft(website: string) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, {website});
}

function addBusinessAddressForDraft(businessAddress: BusinessAddress) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, businessAddress);
}

function addPersonalAddressForDraft(personalAddress: {requestorAddressStreet?: string; requestorAddressCity?: string; requestorAddressState?: string; requestorAddressZipCode?: string}) {
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, personalAddress);
}

/**
* Submit Bank Account step with Plaid data so php can perform some checks.
*/
Expand Down Expand Up @@ -535,8 +527,6 @@ function setReimbursementAccountLoading(isLoading: boolean) {
export {
acceptACHContractForBankAccount,
addBusinessWebsiteForDraft,
addBusinessAddressForDraft,
addPersonalAddressForDraft,
addPersonalBankAccount,
clearOnfidoToken,
clearPersonalBankAccount,
Expand Down
1 change: 1 addition & 0 deletions src/libs/actions/FormActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ function clearDraftValues(formID: OnyxFormKeyWithoutDraft) {
Onyx.merge(FormUtils.getDraftKey(formID), undefined);
}

export type {OnyxFormKeyWithoutDraft};
export {setDraftValues, setErrorFields, setErrors, setIsLoading, clearDraftValues};
20 changes: 10 additions & 10 deletions src/pages/ReimbursementAccount/BankInfo/BankInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type BankInfoOnyxProps = {

type BankInfoProps = BankInfoOnyxProps;

const bankInfoStepKeys = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const BANK_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const manualSubsteps: Array<React.ComponentType<SubStepProps>> = [Manual, Confirmation];
const plaidSubsteps: Array<React.ComponentType<SubStepProps>> = [Plaid, Confirmation];
const receivedRedirectURI = getPlaidOAuthReceivedRedirectURI();
Expand All @@ -42,7 +42,7 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok
const styles = useThemeStyles();

const [redirectedFromPlaidToManual, setRedirectedFromPlaidToManual] = React.useState(false);
const values = useMemo(() => getSubstepValues(bankInfoStepKeys, reimbursementAccountDraft ?? {}, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]);
const values = useMemo(() => getSubstepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft ?? {}, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]);

let setupType = reimbursementAccount?.achData?.subStep ?? '';

Expand All @@ -55,17 +55,17 @@ function BankInfo({reimbursementAccount, reimbursementAccountDraft, plaidLinkTok
if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) {
BankAccounts.connectBankAccountManually(
Number(reimbursementAccount?.achData?.bankAccountID ?? '0'),
values[bankInfoStepKeys.ACCOUNT_NUMBER],
values[bankInfoStepKeys.ROUTING_NUMBER],
values[bankInfoStepKeys.PLAID_MASK],
values[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER],
values[BANK_INFO_STEP_KEYS.ROUTING_NUMBER],
values[BANK_INFO_STEP_KEYS.PLAID_MASK],
);
} else if (setupType === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID) {
BankAccounts.connectBankAccountWithPlaid(Number(reimbursementAccount?.achData?.bankAccountID ?? '0'), {
[bankInfoStepKeys.ROUTING_NUMBER]: values[bankInfoStepKeys.ROUTING_NUMBER] ?? '',
[bankInfoStepKeys.ACCOUNT_NUMBER]: values[bankInfoStepKeys.ACCOUNT_NUMBER] ?? '',
[bankInfoStepKeys.BANK_NAME]: values[bankInfoStepKeys.BANK_NAME] ?? '',
[bankInfoStepKeys.PLAID_ACCOUNT_ID]: values[bankInfoStepKeys.PLAID_ACCOUNT_ID] ?? '',
[bankInfoStepKeys.PLAID_ACCESS_TOKEN]: values[bankInfoStepKeys.PLAID_ACCESS_TOKEN] ?? '',
[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: values[BANK_INFO_STEP_KEYS.ROUTING_NUMBER] ?? '',
[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]: values[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER] ?? '',
[BANK_INFO_STEP_KEYS.BANK_NAME]: values[BANK_INFO_STEP_KEYS.BANK_NAME] ?? '',
[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID]: values[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID] ?? '',
[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: values[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN] ?? '',
});
}
}, [reimbursementAccount, setupType, values]);
Expand Down
26 changes: 13 additions & 13 deletions src/pages/ReimbursementAccount/BankInfo/substeps/Confirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type ConfirmationOnyxProps = {

type ConfirmationProps = ConfirmationOnyxProps & SubStepProps;

const bankInfoStepKeys = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const BANK_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;

function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}: ConfirmationProps) {
const {translate} = useLocalize();
Expand All @@ -41,7 +41,7 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
const isLoading = reimbursementAccount?.isLoading ?? false;
const setupType = reimbursementAccount?.achData?.subStep ?? '';
const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '0');
const values = useMemo(() => getSubstepValues(bankInfoStepKeys, reimbursementAccountDraft ?? {}, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]);
const values = useMemo(() => getSubstepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft ?? {}, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]);
const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount ?? {});

const handleConnectDifferentAccount = () => {
Expand All @@ -50,13 +50,13 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
return;
}
const bankAccountData = {
[bankInfoStepKeys.ROUTING_NUMBER]: '',
[bankInfoStepKeys.ACCOUNT_NUMBER]: '',
[bankInfoStepKeys.PLAID_MASK]: '',
[bankInfoStepKeys.IS_SAVINGS]: '',
[bankInfoStepKeys.BANK_NAME]: '',
[bankInfoStepKeys.PLAID_ACCOUNT_ID]: '',
[bankInfoStepKeys.PLAID_ACCESS_TOKEN]: '',
[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: '',
[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]: '',
[BANK_INFO_STEP_KEYS.PLAID_MASK]: '',
[BANK_INFO_STEP_KEYS.IS_SAVINGS]: '',
[BANK_INFO_STEP_KEYS.BANK_NAME]: '',
[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID]: '',
[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: '',
};
ReimbursementAccount.updateReimbursementAccountDraft(bankAccountData);

Expand All @@ -81,11 +81,11 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
<View>
<View style={[styles.mb3]}>
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.routingNumber')}</Text>
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ROUTING_NUMBER]}</Text>
<Text style={styles.confirmBankInfoNumber}>{values[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]}</Text>
</View>
<View>
<Text style={[styles.mutedTextLabel, styles.mb1]}>{translate('bankAccount.accountNumber')}</Text>
<Text style={styles.confirmBankInfoNumber}>{values[bankInfoStepKeys.ACCOUNT_NUMBER]}</Text>
<Text style={styles.confirmBankInfoNumber}>{values[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]}</Text>
</View>
</View>
</View>
Expand All @@ -98,8 +98,8 @@ function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext}:
iconStyles={[styles.confirmBankInfoCompanyIcon]}
iconFill={theme.iconHovered}
wrapperStyle={[styles.pl0, styles.mb6]}
title={values[bankInfoStepKeys.BANK_NAME]}
description={`${translate('bankAccount.accountEnding')} ${(values[bankInfoStepKeys.ACCOUNT_NUMBER] ?? '').slice(-4)}`}
title={values[BANK_INFO_STEP_KEYS.BANK_NAME]}
description={`${translate('bankAccount.accountEnding')} ${(values[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER] ?? '').slice(-4)}`}
/>
)}
<Text style={[styles.confirmBankInfoText, styles.mb4]}>{translate('bankAccount.thisBankAccount')}</Text>
Expand Down
18 changes: 9 additions & 9 deletions src/pages/ReimbursementAccount/BankInfo/substeps/Manual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ type ManualProps = ManualOnyxProps & SubStepProps;

type FormValues = {routingNumber: string; accountNumber: string};

const bankInfoStepKeys = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const BANK_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const STEP_FIELDS = [BANK_INFO_STEP_KEYS.ROUTING_NUMBER, BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER];

function Manual({reimbursementAccount, onNext}: ManualProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();

const defaultValues: FormValues = {
[bankInfoStepKeys.ROUTING_NUMBER]: reimbursementAccount?.achData?.[bankInfoStepKeys.ROUTING_NUMBER] ?? '',
[bankInfoStepKeys.ACCOUNT_NUMBER]: reimbursementAccount?.achData?.[bankInfoStepKeys.ACCOUNT_NUMBER] ?? '',
[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: reimbursementAccount?.achData?.[BANK_INFO_STEP_KEYS.ROUTING_NUMBER] ?? '',
[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]: reimbursementAccount?.achData?.[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER] ?? '',
};

/**
Expand All @@ -40,8 +41,7 @@ function Manual({reimbursementAccount, onNext}: ManualProps) {
*/
const validate = useCallback(
(values: FormValues) => {
const requiredFields = [bankInfoStepKeys.ROUTING_NUMBER, bankInfoStepKeys.ACCOUNT_NUMBER];
const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
const routingNumber = values.routingNumber?.trim();

if (
Expand Down Expand Up @@ -80,11 +80,11 @@ function Manual({reimbursementAccount, onNext}: ManualProps) {
<InputWrapper
// @ts-expect-error TODO: Remove this once InputWrapper (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript.
InputComponent={TextInput}
inputID={bankInfoStepKeys.ROUTING_NUMBER}
inputID={BANK_INFO_STEP_KEYS.ROUTING_NUMBER}
label={translate('bankAccount.routingNumber')}
aria-label={translate('bankAccount.routingNumber')}
role={CONST.ROLE.PRESENTATION}
defaultValue={defaultValues[bankInfoStepKeys.ROUTING_NUMBER]}
defaultValue={defaultValues[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]}
inputMode={CONST.INPUT_MODE.NUMERIC}
disabled={shouldDisableInputs}
shouldSaveDraft
Expand All @@ -93,12 +93,12 @@ function Manual({reimbursementAccount, onNext}: ManualProps) {
<InputWrapper
// @ts-expect-error TODO: Remove this once InputWrapper (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript.
InputComponent={TextInput}
inputID={bankInfoStepKeys.ACCOUNT_NUMBER}
inputID={BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER}
containerStyles={[styles.mt4]}
label={translate('bankAccount.accountNumber')}
aria-label={translate('bankAccount.accountNumber')}
role={CONST.ROLE.PRESENTATION}
defaultValue={defaultValues[bankInfoStepKeys.ACCOUNT_NUMBER]}
defaultValue={defaultValues[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]}
inputMode={CONST.INPUT_MODE.NUMERIC}
disabled={shouldDisableInputs}
shouldSaveDraft
Expand Down
22 changes: 12 additions & 10 deletions src/pages/ReimbursementAccount/BankInfo/substeps/Plaid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type ValuesToValidate = {
acceptTerms: boolean;
};

const bankInfoStepKeys = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;
const BANK_INFO_STEP_KEYS = CONST.BANK_ACCOUNT.BANK_INFO_STEP.INPUT_KEY;

function Plaid({reimbursementAccount, reimbursementAccountDraft, onNext, plaidData}: PlaidProps) {
const {translate} = useLocalize();
Expand All @@ -56,24 +56,26 @@ function Plaid({reimbursementAccount, reimbursementAccountDraft, onNext, plaidDa
}, [isFocused, plaidData]);

const handleNextPress = useCallback(() => {
const selectedPlaidBankAccount = (plaidData?.bankAccounts ?? []).find((account) => account.plaidAccountID === reimbursementAccountDraft?.[bankInfoStepKeys.PLAID_ACCOUNT_ID] ?? null);
const selectedPlaidBankAccount = (plaidData?.bankAccounts ?? []).find(
(account) => account.plaidAccountID === reimbursementAccountDraft?.[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID] ?? null,
);

const bankAccountData = {
[bankInfoStepKeys.ROUTING_NUMBER]: selectedPlaidBankAccount?.[bankInfoStepKeys.ROUTING_NUMBER],
[bankInfoStepKeys.ACCOUNT_NUMBER]: selectedPlaidBankAccount?.[bankInfoStepKeys.ACCOUNT_NUMBER],
[bankInfoStepKeys.PLAID_MASK]: selectedPlaidBankAccount?.mask,
[bankInfoStepKeys.IS_SAVINGS]: selectedPlaidBankAccount?.[bankInfoStepKeys.IS_SAVINGS],
[bankInfoStepKeys.BANK_NAME]: plaidData?.[bankInfoStepKeys.BANK_NAME] ?? '',
[bankInfoStepKeys.PLAID_ACCOUNT_ID]: selectedPlaidBankAccount?.[bankInfoStepKeys.PLAID_ACCOUNT_ID],
[bankInfoStepKeys.PLAID_ACCESS_TOKEN]: plaidData?.[bankInfoStepKeys.PLAID_ACCESS_TOKEN] ?? '',
[BANK_INFO_STEP_KEYS.ROUTING_NUMBER]: selectedPlaidBankAccount?.[BANK_INFO_STEP_KEYS.ROUTING_NUMBER],
[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER]: selectedPlaidBankAccount?.[BANK_INFO_STEP_KEYS.ACCOUNT_NUMBER],
[BANK_INFO_STEP_KEYS.PLAID_MASK]: selectedPlaidBankAccount?.mask,
[BANK_INFO_STEP_KEYS.IS_SAVINGS]: selectedPlaidBankAccount?.[BANK_INFO_STEP_KEYS.IS_SAVINGS],
[BANK_INFO_STEP_KEYS.BANK_NAME]: plaidData?.[BANK_INFO_STEP_KEYS.BANK_NAME] ?? '',
[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID]: selectedPlaidBankAccount?.[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID],
[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: plaidData?.[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN] ?? '',
};

ReimbursementAccount.updateReimbursementAccountDraft(bankAccountData);
onNext();
}, [plaidData, reimbursementAccountDraft, onNext]);

const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '0');
const selectedPlaidAccountID = reimbursementAccountDraft?.[bankInfoStepKeys.PLAID_ACCOUNT_ID] ?? '';
const selectedPlaidAccountID = reimbursementAccountDraft?.[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID] ?? '';

return (
// @ts-expect-error TODO: Remove this once FormProvider (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript.
Expand Down
Loading

0 comments on commit 997149f

Please sign in to comment.