From 04b2c030977272511d12ccdbf8111b86f8abde28 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Thu, 16 Jan 2025 16:57:11 +0700 Subject: [PATCH 1/6] add new missing detail contact modal --- .../MissingPersonalDetailsContent.tsx | 24 ++----- .../MissingPersonalDetailsMagicCodeModal.tsx | 71 +++++++++++++++++++ 2 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx index e09c58b54d5e..3d89366ec1c9 100644 --- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx +++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx @@ -7,12 +7,10 @@ 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 * as FormActions from '@libs/actions/FormActions'; -import {requestValidateCodeAction} from '@libs/actions/User'; import Navigation from '@libs/Navigation/Navigation'; import * as PersonalDetails from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; @@ -26,6 +24,7 @@ import LegalName from './substeps/LegalName'; import PhoneNumber from './substeps/PhoneNumber'; import type {CustomSubStepProps} from './types'; import {getInitialSubstep, getSubstepValues} from './utils'; +import MissingPersonalDetailsMagicCodeModal from './MissingPersonalDetailsMagicCodeModal'; type MissingPersonalDetailsContentProps = { privatePersonalDetails: OnyxEntry; @@ -81,7 +80,7 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi prevScreen(); }; - const handleValidateCodeEntered = useCallback( + const handleSubmitForm = useCallback( (validateCode: string) => { PersonalDetails.updatePersonalDetailsAndShipExpensifyCards(values, validateCode); FormActions.clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); @@ -90,14 +89,6 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi [values], ); - const sendValidateCode = () => { - if (validateCodeAction?.validateCodeSent) { - return; - } - - requestValidateCodeAction(); - }; - const handleNextScreen = useCallback(() => { if (isEditing) { goToTheLastStep(); @@ -132,15 +123,10 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi personalDetailsValues={values} /> - {}} + setIsValidateCodeActionModalVisible(false)} - isVisible={isValidateCodeActionModalVisible} - title={translate('cardPage.validateCardTitle')} - descriptionPrimary={translate('cardPage.enterMagicCode', {contactMethod: primaryLogin})} - hasMagicCodeBeenSent={!!validateCodeAction?.validateCodeSent} + isValidateCodeActionModalVisible={isValidateCodeActionModalVisible} + handleSubmitForm={handleSubmitForm} /> ); diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx new file mode 100644 index 000000000000..f06e11175048 --- /dev/null +++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx @@ -0,0 +1,71 @@ +import React, {useEffect} from 'react'; +import {useOnyx} from 'react-native-onyx'; +import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; +import useLocalize from '@hooks/useLocalize'; +import * as FormActions from '@libs/actions/FormActions'; +import {requestValidateCodeAction} from '@libs/actions/User'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import * as Delegate from '@userActions/Delegate'; +import ONYXKEYS from '@src/ONYXKEYS'; + +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 validateLoginError = ErrorUtils.getLatestError(); + const privateDetailValidated = privatePersonalDetails?.validated; + const primaryLogin = account?.primaryLogin ?? ''; + useEffect(() => { + if (!privateDetailValidated) { + return; + } + + FormActions.clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); + Navigation.goBack(); + }, [privateDetailValidated]); + + const sendValidateCode = () => { + if (validateCodeAction?.validateCodeSent) { + return; + } + + requestValidateCodeAction(); + }; + + const onBackButtonPress = () => { + onClose?.(); + }; + + const clearError = () => { + if (!validateLoginError) { + return; + } + Delegate.clearDelegateErrorsByField(currentDelegate?.email ?? '', 'addDelegate'); + }; + + return ( + + ); +} + +MissingPersonalDetailsMagicCodeModal.displayName = 'MissingPersonalDetailsMagicCodeModal'; + +export default MissingPersonalDetailsMagicCodeModal; From 8b52bd7dd6caa8264cae8c19a6727b7d579fa10c Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Fri, 24 Jan 2025 15:54:08 +0700 Subject: [PATCH 2/6] complete the implementation --- src/libs/actions/PersonalDetails.ts | 19 +++++++++++++++ .../MissingPersonalDetailsContent.tsx | 12 +++------- .../MissingPersonalDetailsMagicCodeModal.tsx | 24 +++++++++++++------ src/types/onyx/PrivatePersonalDetails.ts | 6 +++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 94a9dc95e846..6de62db4854e 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -465,6 +465,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, validateCode: string) { const parameters: SetPersonalDetailsAndShipExpensifyCardsParams = { legalFirstName: values.legalFirstName?.trim() ?? '', @@ -504,6 +513,15 @@ function updatePersonalDetailsAndShipExpensifyCards(values: FormOnyxValues; @@ -36,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 = useRef(null); @@ -82,9 +78,7 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues}: Mi const handleSubmitForm = useCallback( (validateCode: string) => { - PersonalDetails.updatePersonalDetailsAndShipExpensifyCards(values, validateCode); - FormActions.clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); - Navigation.goBack(); + updatePersonalDetailsAndShipExpensifyCards(values, validateCode); }, [values], ); diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx index f06e11175048..2f47022c1667 100644 --- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx +++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx @@ -3,11 +3,12 @@ import {useOnyx} from 'react-native-onyx'; import ValidateCodeActionModal from '@components/ValidateCodeActionModal'; import useLocalize from '@hooks/useLocalize'; import * as FormActions from '@libs/actions/FormActions'; +import {clearPersonalDetailsErrors} from '@libs/actions/PersonalDetails'; import {requestValidateCodeAction} from '@libs/actions/User'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import * as Delegate from '@userActions/Delegate'; import ONYXKEYS from '@src/ONYXKEYS'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; type MissingPersonalDetailsMagicCodeModalProps = { handleSubmitForm: (validateCode: string) => void; @@ -20,17 +21,26 @@ function MissingPersonalDetailsMagicCodeModal({onClose, isValidateCodeActionModa const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const [account] = useOnyx(ONYXKEYS.ACCOUNT); const [validateCodeAction] = useOnyx(ONYXKEYS.VALIDATE_ACTION_CODE); - const validateLoginError = ErrorUtils.getLatestError(); - const privateDetailValidated = privatePersonalDetails?.validated; + const privateDetailsErrors = privatePersonalDetails?.errors ?? undefined; + const validateLoginError = ErrorUtils.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 (!privateDetailValidated) { + if (missingDetails || !!privateDetailsErrors || privatePersonalDetails?.isValidating) { return; } FormActions.clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); Navigation.goBack(); - }, [privateDetailValidated]); + }, [missingDetails, privateDetailsErrors, privatePersonalDetails?.isValidating]); const sendValidateCode = () => { if (validateCodeAction?.validateCodeSent) { @@ -48,9 +58,9 @@ function MissingPersonalDetailsMagicCodeModal({onClose, isValidateCodeActionModa if (!validateLoginError) { return; } - Delegate.clearDelegateErrorsByField(currentDelegate?.email ?? '', 'addDelegate'); + clearPersonalDetailsErrors(); }; - + return ( Date: Wed, 5 Feb 2025 15:27:38 +0700 Subject: [PATCH 3/6] fix lint --- src/libs/actions/PersonalDetails.ts | 35 +------------------ .../MissingPersonalDetailsContent.tsx | 4 +-- .../MissingPersonalDetailsMagicCodeModal.tsx | 12 +++---- src/types/onyx/PrivatePersonalDetails.ts | 3 -- 4 files changed, 9 insertions(+), 45 deletions(-) diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 6de62db4854e..165a159b469b 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -489,40 +489,7 @@ function updatePersonalDetailsAndShipExpensifyCards(values: FormOnyxValues { - if (missingDetails || !!privateDetailsErrors || privatePersonalDetails?.isValidating) { + if (missingDetails || !!privateDetailsErrors) { return; } - FormActions.clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); + clearDraftValues(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM); Navigation.goBack(); - }, [missingDetails, privateDetailsErrors, privatePersonalDetails?.isValidating]); + }, [missingDetails, privateDetailsErrors]); const sendValidateCode = () => { if (validateCodeAction?.validateCodeSent) { diff --git a/src/types/onyx/PrivatePersonalDetails.ts b/src/types/onyx/PrivatePersonalDetails.ts index 2674f140812d..528463b6af21 100644 --- a/src/types/onyx/PrivatePersonalDetails.ts +++ b/src/types/onyx/PrivatePersonalDetails.ts @@ -71,9 +71,6 @@ type PrivatePersonalDetails = { /** Authentication failure errors */ errors?: OnyxCommon.Errors | null; - - /** Whether the API is loading */ - isValidating?: boolean; }; export default PrivatePersonalDetails; From 60d8cdfc2dec3d42c94c116ec5aed09d121a18d4 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Wed, 5 Feb 2025 16:33:50 +0700 Subject: [PATCH 4/6] fix error resend code --- .../MissingPersonalDetailsMagicCodeModal.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx index 301f2b61860e..a72186611c20 100644 --- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx +++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsMagicCodeModal.tsx @@ -42,14 +42,6 @@ function MissingPersonalDetailsMagicCodeModal({onClose, isValidateCodeActionModa Navigation.goBack(); }, [missingDetails, privateDetailsErrors]); - const sendValidateCode = () => { - if (validateCodeAction?.validateCodeSent) { - return; - } - - requestValidateCodeAction(); - }; - const onBackButtonPress = () => { onClose?.(); }; @@ -69,7 +61,7 @@ function MissingPersonalDetailsMagicCodeModal({onClose, isValidateCodeActionModa isVisible={isValidateCodeActionModalVisible} title={translate('cardPage.validateCardTitle')} descriptionPrimary={translate('cardPage.enterMagicCode', {contactMethod: primaryLogin})} - sendValidateCode={sendValidateCode} + sendValidateCode={() => requestValidateCodeAction()} hasMagicCodeBeenSent={validateCodeAction?.validateCodeSent} handleSubmitForm={handleSubmitForm} /> From 8da87f2167a4eb0665c6153a433dbdd1379227b3 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Fri, 7 Feb 2025 10:40:04 +0700 Subject: [PATCH 5/6] add loading spinner --- src/libs/actions/PersonalDetails.ts | 21 ++++++++++++++++++- .../MissingPersonalDetailsMagicCodeModal.tsx | 1 + src/types/onyx/PrivatePersonalDetails.ts | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 165a159b469b..05fc87cf2802 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -489,7 +489,26 @@ function updatePersonalDetailsAndShipExpensifyCards(values: FormOnyxValues requestValidateCodeAction()} hasMagicCodeBeenSent={validateCodeAction?.validateCodeSent} handleSubmitForm={handleSubmitForm} + isLoading={privatePersonalDetails?.isLoading} /> ); } diff --git a/src/types/onyx/PrivatePersonalDetails.ts b/src/types/onyx/PrivatePersonalDetails.ts index 528463b6af21..519cd7d26386 100644 --- a/src/types/onyx/PrivatePersonalDetails.ts +++ b/src/types/onyx/PrivatePersonalDetails.ts @@ -71,6 +71,9 @@ type PrivatePersonalDetails = { /** Authentication failure errors */ errors?: OnyxCommon.Errors | null; + + /** Whether the request is being processed */ + isLoading?: boolean; }; export default PrivatePersonalDetails; From 41d564feba15822fde9c4ffbd00ab1b49e023d0b Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 11 Feb 2025 14:12:58 +0700 Subject: [PATCH 6/6] merge main --- .../MissingPersonalDetails/MissingPersonalDetailsContent.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx index 422c3ba4fbcd..6196383df471 100644 --- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx +++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx @@ -11,7 +11,6 @@ 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';