Skip to content

Commit

Permalink
Merge pull request Expensify#55484 from DylanDylann/Dylan/fix54041
Browse files Browse the repository at this point in the history
add new missing detail contact modal
  • Loading branch information
MarioExpensify authored Feb 18, 2025
2 parents 7ad53a7 + 4e4bc29 commit 2b5ca51
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 40 deletions.
35 changes: 20 additions & 15 deletions src/libs/actions/PersonalDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,15 @@ function clearAvatarErrors() {
});
}

/**
* Clear errors for the current user's personal details
*/
function clearPersonalDetailsErrors() {
Onyx.merge(ONYXKEYS.PRIVATE_PERSONAL_DETAILS, {
errors: null,
});
}

function updatePersonalDetailsAndShipExpensifyCards(values: FormOnyxValues<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM>, validateCode: string) {
const parameters: SetPersonalDetailsAndShipExpensifyCardsParams = {
legalFirstName: values.legalFirstName?.trim() ?? '',
Expand All @@ -502,21 +511,16 @@ function updatePersonalDetailsAndShipExpensifyCards(values: FormOnyxValues<typeo
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
value: {
addresses: [
...(privatePersonalDetails?.addresses ?? []),
{
street: PersonalDetailsUtils.getFormattedStreet(parameters.addressStreet, parameters.addressStreet2),
city: parameters.addressCity,
state: parameters.addressState,
zip: parameters.addressZip,
country: parameters.addressCountry as Country | '',
current: true,
},
],
legalFirstName: parameters.legalFirstName,
legalLastName: parameters.legalLastName,
dob: parameters.dob,
phoneNumber: parameters.phoneNumber,
isLoading: true,
},
},
],
finallyData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
value: {
isLoading: false,
},
},
],
Expand All @@ -539,4 +543,5 @@ export {
updatePronouns,
updateSelectedTimezone,
updatePersonalDetailsAndShipExpensifyCards,
clearPersonalDetailsErrors,
};
30 changes: 5 additions & 25 deletions src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import React, {useCallback, useMemo, useRef, useState} from 'react';
import type {ForwardedRef} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader';
import type {InteractiveStepSubHeaderHandle} from '@components/InteractiveStepSubHeader';
import ScreenWrapper from '@components/ScreenWrapper';
import ValidateCodeActionModal from '@components/ValidateCodeActionModal';
import useLocalize from '@hooks/useLocalize';
import useSubStep from '@hooks/useSubStep';
import useThemeStyles from '@hooks/useThemeStyles';
import {clearDraftValues} from '@libs/actions/FormActions';
import {updatePersonalDetailsAndShipExpensifyCards} from '@libs/actions/PersonalDetails';
import {requestValidateCodeAction} from '@libs/actions/User';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetailsForm} from '@src/types/form';
import type {PrivatePersonalDetails} from '@src/types/onyx';
import MissingPersonalDetailsMagicCodeModal from './MissingPersonalDetailsMagicCodeModal';
import Address from './substeps/Address';
import Confirmation from './substeps/Confirmation';
import DateOfBirth from './substeps/DateOfBirth';
Expand All @@ -37,9 +35,6 @@ const formSteps = [LegalName, DateOfBirth, Address, PhoneNumber, Confirmation];
function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: MissingPersonalDetailsContentProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE);
const primaryLogin = account?.primaryLogin ?? '';
const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false);

const ref: ForwardedRef<InteractiveStepSubHeaderHandle> = useRef(null);
Expand Down Expand Up @@ -84,23 +79,13 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi
prevScreen();
};

const handleValidateCodeEntered = useCallback(
const handleSubmitForm = useCallback(
(validateCode: string) => {
updatePersonalDetailsAndShipExpensifyCards(values, validateCode);
clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM);
Navigation.goBack();
},
[values],
);

const sendValidateCode = () => {
if (validateCodeAction?.validateCodeSent) {
return;
}

requestValidateCodeAction();
};

const handleNextScreen = useCallback(() => {
if (isEditing) {
goToTheLastStep();
Expand Down Expand Up @@ -144,15 +129,10 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi
personalDetailsValues={values}
/>

<ValidateCodeActionModal
handleSubmitForm={handleValidateCodeEntered}
sendValidateCode={sendValidateCode}
clearError={() => {}}
<MissingPersonalDetailsMagicCodeModal
onClose={() => setIsValidateCodeActionModalVisible(false)}
isVisible={isValidateCodeActionModalVisible}
title={translate('cardPage.validateCardTitle')}
descriptionPrimary={translate('cardPage.enterMagicCode', {contactMethod: primaryLogin})}
hasMagicCodeBeenSent={!!validateCodeAction?.validateCodeSent}
isValidateCodeActionModalVisible={isValidateCodeActionModalVisible}
handleSubmitForm={handleSubmitForm}
/>
</ScreenWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, {useEffect} from 'react';
import {useOnyx} from 'react-native-onyx';
import ValidateCodeActionModal from '@components/ValidateCodeActionModal';
import useLocalize from '@hooks/useLocalize';
import {clearDraftValues} from '@libs/actions/FormActions';
import {clearPersonalDetailsErrors} from '@libs/actions/PersonalDetails';
import {requestValidateCodeAction} from '@libs/actions/User';
import {getLatestError} from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import ONYXKEYS from '@src/ONYXKEYS';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type MissingPersonalDetailsMagicCodeModalProps = {
handleSubmitForm: (validateCode: string) => void;
isValidateCodeActionModalVisible: boolean;
onClose?: () => void;
};

function MissingPersonalDetailsMagicCodeModal({onClose, isValidateCodeActionModalVisible, handleSubmitForm}: MissingPersonalDetailsMagicCodeModalProps) {
const {translate} = useLocalize();
const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE);
const privateDetailsErrors = privatePersonalDetails?.errors ?? undefined;
const validateLoginError = getLatestError(privateDetailsErrors);
const primaryLogin = account?.primaryLogin ?? '';

const missingDetails =
!privatePersonalDetails?.legalFirstName ||
!privatePersonalDetails?.legalLastName ||
!privatePersonalDetails?.dob ||
!privatePersonalDetails?.phoneNumber ||
isEmptyObject(privatePersonalDetails?.addresses) ||
privatePersonalDetails.addresses.length === 0;

useEffect(() => {
if (missingDetails || !!privateDetailsErrors) {
return;
}

clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM);
Navigation.goBack();
}, [missingDetails, privateDetailsErrors]);

const onBackButtonPress = () => {
onClose?.();
};

const clearError = () => {
if (!validateLoginError) {
return;
}
clearPersonalDetailsErrors();
};

return (
<ValidateCodeActionModal
clearError={clearError}
onClose={onBackButtonPress}
validateError={validateLoginError}
isVisible={isValidateCodeActionModalVisible}
title={translate('cardPage.validateCardTitle')}
descriptionPrimary={translate('cardPage.enterMagicCode', {contactMethod: primaryLogin})}
sendValidateCode={() => requestValidateCodeAction()}
hasMagicCodeBeenSent={validateCodeAction?.validateCodeSent}
handleSubmitForm={handleSubmitForm}
isLoading={privatePersonalDetails?.isLoading}
/>
);
}

MissingPersonalDetailsMagicCodeModal.displayName = 'MissingPersonalDetailsMagicCodeModal';

export default MissingPersonalDetailsMagicCodeModal;
6 changes: 6 additions & 0 deletions src/types/onyx/PrivatePersonalDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ type PrivatePersonalDetails = {

/** Error objects keyed by field name containing errors keyed by microtime */
errorFields?: OnyxCommon.ErrorFields;

/** Authentication failure errors */
errors?: OnyxCommon.Errors | null;

/** Whether the request is being processed */
isLoading?: boolean;
};

export default PrivatePersonalDetails;
Expand Down

0 comments on commit 2b5ca51

Please sign in to comment.