From 67c8663db30270e867650222c62b4dfb4215f00f Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Thu, 19 Sep 2024 15:15:44 +0530 Subject: [PATCH 01/16] Refactor on missing details flow --- src/CONST.ts | 1 + src/ROUTES.ts | 5 +- .../ReportActionItem/IssueCardMessage.tsx | 6 +- src/hooks/usePersonalDetailsFormSubmit.ts | 27 ++ src/libs/Navigation/linkingConfig/config.ts | 2 +- src/libs/Navigation/types.ts | 4 +- src/pages/MissingPersonalDetails/index.tsx | 139 ++-------- .../substeps/Address.tsx | 238 ++++++++++++------ .../substeps/Confirmation.tsx | 96 +++++++ .../substeps/DateOfBirth.tsx | 66 +++-- .../substeps/LegalName.tsx | 116 ++++++--- .../substeps/PhoneNumber.tsx | 74 ++++-- src/pages/home/report/ReportActionItem.tsx | 7 +- 13 files changed, 501 insertions(+), 280 deletions(-) create mode 100644 src/hooks/usePersonalDetailsFormSubmit.ts create mode 100644 src/pages/MissingPersonalDetails/substeps/Confirmation.tsx diff --git a/src/CONST.ts b/src/CONST.ts index 8100465f7c79..8946bc269279 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1836,6 +1836,7 @@ const CONST = { DATE_OF_BIRTH: 1, ADDRESS: 2, PHONE_NUMBER: 3, + CONFIRM: 4, }, INDEX_LIST: ['1', '2', '3', '4'], }, diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 3238683379ea..2b55864cca1e 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1261,10 +1261,7 @@ const ROUTES = { route: 'restricted-action/workspace/:policyID', getRoute: (policyID: string) => `restricted-action/workspace/${policyID}` as const, }, - MISSING_PERSONAL_DETAILS: { - route: 'missing-personal-details/workspace/:policyID', - getRoute: (policyID: string) => `missing-personal-details/workspace/${policyID}` as const, - }, + MISSING_PERSONAL_DETAILS: 'missing-personal-details', POLICY_ACCOUNTING_NETSUITE_SUBSIDIARY_SELECTOR: { route: 'settings/workspaces/:policyID/accounting/netsuite/subsidiary-selector', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/netsuite/subsidiary-selector` as const, diff --git a/src/components/ReportActionItem/IssueCardMessage.tsx b/src/components/ReportActionItem/IssueCardMessage.tsx index d12a20c4598d..ca152c9492cb 100644 --- a/src/components/ReportActionItem/IssueCardMessage.tsx +++ b/src/components/ReportActionItem/IssueCardMessage.tsx @@ -16,11 +16,9 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; type IssueCardMessageProps = { action: OnyxEntry; - - policyID: string | undefined; }; -function IssueCardMessage({action, policyID}: IssueCardMessageProps) { +function IssueCardMessage({action}: IssueCardMessageProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); @@ -49,7 +47,7 @@ function IssueCardMessage({action, policyID}: IssueCardMessageProps) { if (!policyID) { return; } - Navigation.navigate(ROUTES.MISSING_PERSONAL_DETAILS.getRoute(policyID)); + Navigation.navigate(ROUTES.MISSING_PERSONAL_DETAILS); }} success style={[styles.alignSelfStart, styles.mt3]} diff --git a/src/hooks/usePersonalDetailsFormSubmit.ts b/src/hooks/usePersonalDetailsFormSubmit.ts new file mode 100644 index 000000000000..4c86958d085f --- /dev/null +++ b/src/hooks/usePersonalDetailsFormSubmit.ts @@ -0,0 +1,27 @@ +import type {FormOnyxKeys} from '@components/Form/types'; +import type {OnyxFormKey} from '@src/ONYXKEYS'; +import ONYXKEYS from '@src/ONYXKEYS'; +import useStepFormSubmit from './useStepFormSubmit'; +import type {SubStepProps} from './useSubStep/types'; + +type UsePersonalDetailsFormSubmitParams = Pick & { + formId?: OnyxFormKey; + fieldIds: Array>; + shouldSaveDraft: boolean; +}; + +/** + * Hook for handling submit method in Missing Personal Details substeps. + * When user is in editing mode, we should save values only when user confirms the change + * @param onNext - callback + * @param fieldIds - field IDs for particular step + * @param shouldSaveDraft - if we should save draft values + */ +export default function usePersonalDetailsFormSubmit({onNext, fieldIds, shouldSaveDraft}: UsePersonalDetailsFormSubmitParams) { + return useStepFormSubmit({ + formId: ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM, + onNext, + fieldIds, + shouldSaveDraft, + }); +} diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 2d5d3a1bd38f..090ed31aac1f 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1163,7 +1163,7 @@ const config: LinkingOptions['config'] = { }, [SCREENS.RIGHT_MODAL.MISSING_PERSONAL_DETAILS]: { screens: { - [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: ROUTES.MISSING_PERSONAL_DETAILS.route, + [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: ROUTES.MISSING_PERSONAL_DETAILS, }, }, [SCREENS.RIGHT_MODAL.DEBUG]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index a2e80454315a..b34a4c5d73c4 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1425,9 +1425,7 @@ type RestrictedActionParamList = { }; type MissingPersonalDetailsParamList = { - [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: { - policyID: string; - }; + [SCREENS.MISSING_PERSONAL_DETAILS_ROOT]: undefined; }; type DebugParamList = { diff --git a/src/pages/MissingPersonalDetails/index.tsx b/src/pages/MissingPersonalDetails/index.tsx index 9a2266f6384b..4e468337a7c6 100644 --- a/src/pages/MissingPersonalDetails/index.tsx +++ b/src/pages/MissingPersonalDetails/index.tsx @@ -1,11 +1,7 @@ -/* eslint-disable no-case-declarations */ -import {Str} from 'expensify-common'; import React, {useCallback, useMemo, useRef} from 'react'; import type {ForwardedRef} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; -import FormProvider from '@components/Form/FormProvider'; -import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import type {InteractiveStepSubHeaderHandle} from '@components/InteractiveStepSubHeader'; @@ -13,22 +9,18 @@ import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; -import * as LoginUtils from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; -import * as PhoneNumberUtils from '@libs/PhoneNumber'; -import * as ValidationUtils from '@libs/ValidationUtils'; import * as PersonalDetails from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import INPUT_IDS from '@src/types/form/PersonalDetailsForm'; import Address from './substeps/Address'; +import Confirmation from './substeps/Confirmation'; import DateOfBirth from './substeps/DateOfBirth'; import LegalName from './substeps/LegalName'; import PhoneNumber from './substeps/PhoneNumber'; -import type {CountryZipRegex, CustomSubStepProps} from './types'; +import type {CustomSubStepProps} from './types'; -const formSteps = [LegalName, DateOfBirth, Address, PhoneNumber]; +const formSteps = [LegalName, DateOfBirth, Address, PhoneNumber, Confirmation]; function MissingPersonalDetails() { const styles = useThemeStyles(); @@ -36,12 +28,17 @@ function MissingPersonalDetails() { const ref: ForwardedRef = useRef(null); const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS); const [cardList] = useOnyx(ONYXKEYS.CARD_LIST); + const [values] = useOnyx(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM_DRAFT); const firstUnissuedCard = useMemo(() => Object.values(cardList ?? {}).find((card) => card.state === CONST.EXPENSIFY_CARD.STATE.STATE_NOT_ISSUED), [cardList]); const handleFinishStep = useCallback(() => { + if (!values) { + return; + } + PersonalDetails.updatePersonalDetailsAndShipExpensifyCard(values, firstUnissuedCard?.cardID ?? 0); Navigation.goBack(); - }, []); + }, [firstUnissuedCard?.cardID, values]); const { componentToRender: SubStep, @@ -77,98 +74,6 @@ function MissingPersonalDetails() { nextScreen(); }, [goToTheLastStep, isEditing, nextScreen]); - const validate = useCallback( - (values: FormOnyxValues): FormInputErrors => { - const errors: FormInputErrors = {}; - switch (screenIndex) { - case CONST.MISSING_PERSONAL_DETAILS_INDEXES.MAPPING.LEGAL_NAME: - if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.LEGAL_FIRST_NAME])) { - errors[INPUT_IDS.LEGAL_FIRST_NAME] = translate('common.error.fieldRequired'); - } else if (!ValidationUtils.isValidLegalName(values[INPUT_IDS.LEGAL_FIRST_NAME])) { - errors[INPUT_IDS.LEGAL_FIRST_NAME] = translate('privatePersonalDetails.error.hasInvalidCharacter'); - } else if (values[INPUT_IDS.LEGAL_FIRST_NAME].length > CONST.LEGAL_NAME.MAX_LENGTH) { - errors[INPUT_IDS.LEGAL_FIRST_NAME] = translate('common.error.characterLimitExceedCounter', { - length: values[INPUT_IDS.LEGAL_FIRST_NAME].length, - limit: CONST.LEGAL_NAME.MAX_LENGTH, - }); - } - if (ValidationUtils.doesContainReservedWord(values[INPUT_IDS.LEGAL_FIRST_NAME], CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.LEGAL_FIRST_NAME, translate('personalDetails.error.containsReservedWord')); - } - if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.LEGAL_LAST_NAME])) { - errors[INPUT_IDS.LEGAL_LAST_NAME] = translate('common.error.fieldRequired'); - } else if (!ValidationUtils.isValidLegalName(values[INPUT_IDS.LEGAL_LAST_NAME])) { - errors[INPUT_IDS.LEGAL_LAST_NAME] = translate('privatePersonalDetails.error.hasInvalidCharacter'); - } else if (values[INPUT_IDS.LEGAL_LAST_NAME].length > CONST.LEGAL_NAME.MAX_LENGTH) { - errors[INPUT_IDS.LEGAL_LAST_NAME] = translate('common.error.characterLimitExceedCounter', { - length: values[INPUT_IDS.LEGAL_LAST_NAME].length, - limit: CONST.LEGAL_NAME.MAX_LENGTH, - }); - } - if (ValidationUtils.doesContainReservedWord(values[INPUT_IDS.LEGAL_LAST_NAME], CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, INPUT_IDS.LEGAL_LAST_NAME, translate('personalDetails.error.containsReservedWord')); - } - return errors; - case CONST.MISSING_PERSONAL_DETAILS_INDEXES.MAPPING.DATE_OF_BIRTH: - if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.DATE_OF_BIRTH])) { - errors[INPUT_IDS.DATE_OF_BIRTH] = translate('common.error.fieldRequired'); - } else if (!ValidationUtils.isValidPastDate(values[INPUT_IDS.DATE_OF_BIRTH]) || !ValidationUtils.meetsMaximumAgeRequirement(values[INPUT_IDS.DATE_OF_BIRTH])) { - errors[INPUT_IDS.DATE_OF_BIRTH] = translate('bankAccount.error.dob'); - } - return errors; - case CONST.MISSING_PERSONAL_DETAILS_INDEXES.MAPPING.ADDRESS: - const addressRequiredFields = [INPUT_IDS.ADDRESS_LINE_1, INPUT_IDS.CITY, INPUT_IDS.COUNTRY, INPUT_IDS.STATE] as const; - addressRequiredFields.forEach((fieldKey) => { - const fieldValue = values[fieldKey] ?? ''; - if (ValidationUtils.isRequiredFulfilled(fieldValue)) { - return; - } - errors[fieldKey] = translate('common.error.fieldRequired'); - }); - - // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object - const countryRegexDetails = (values.country ? CONST.COUNTRY_ZIP_REGEX_DATA?.[values.country] : {}) as CountryZipRegex; - - // The postal code system might not exist for a country, so no regex either for them. - const countrySpecificZipRegex = countryRegexDetails?.regex; - const countryZipFormat = countryRegexDetails?.samples ?? ''; - if (countrySpecificZipRegex) { - if (!countrySpecificZipRegex.test(values[INPUT_IDS.ZIP_POST_CODE]?.trim().toUpperCase())) { - if (ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.ZIP_POST_CODE]?.trim())) { - errors[INPUT_IDS.ZIP_POST_CODE] = translate('privatePersonalDetails.error.incorrectZipFormat', countryZipFormat); - } else { - errors[INPUT_IDS.ZIP_POST_CODE] = translate('common.error.fieldRequired'); - } - } - } else if (!CONST.GENERIC_ZIP_CODE_REGEX.test(values[INPUT_IDS.ZIP_POST_CODE]?.trim()?.toUpperCase() ?? '')) { - errors[INPUT_IDS.ZIP_POST_CODE] = translate('privatePersonalDetails.error.incorrectZipFormat'); - } - return errors; - case CONST.MISSING_PERSONAL_DETAILS_INDEXES.MAPPING.PHONE_NUMBER: - if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) { - errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired'); - } - const phoneNumber = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]); - const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumber); - if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumber.slice(0))) { - errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber'); - } - return errors; - default: - return errors; - } - }, - [screenIndex, translate], - ); - - const updatePersonalDetails = useCallback( - (formValues: FormOnyxValues) => { - PersonalDetails.updatePersonalDetailsAndShipExpensifyCard(formValues, firstUnissuedCard?.cardID ?? 0); - nextScreen(); - }, - [nextScreen, firstUnissuedCard], - ); - return ( - - - - - + ); } diff --git a/src/pages/MissingPersonalDetails/substeps/Address.tsx b/src/pages/MissingPersonalDetails/substeps/Address.tsx index 384a2648b307..3413a62fa2d8 100644 --- a/src/pages/MissingPersonalDetails/substeps/Address.tsx +++ b/src/pages/MissingPersonalDetails/substeps/Address.tsx @@ -1,32 +1,55 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; import AddressSearch from '@components/AddressSearch'; import CountryPicker from '@components/CountryPicker'; +import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import StatePicker from '@components/StatePicker'; import type {State} from '@components/StateSelector'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; +import usePersonalDetailsFormSubmit from '@hooks/usePersonalDetailsFormSubmit'; import useThemeStyles from '@hooks/useThemeStyles'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; +import * as ValidationUtils from '@libs/ValidationUtils'; import type {CountryZipRegex, CustomSubStepProps} from '@pages/MissingPersonalDetails/types'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/PersonalDetailsForm'; import type {Address} from '@src/types/onyx/PrivatePersonalDetails'; -function AddressStep({privatePersonalDetails}: CustomSubStepProps) { +const STEP_FIELDS = [INPUT_IDS.ADDRESS_LINE_1, INPUT_IDS.ADDRESS_LINE_2, INPUT_IDS.CITY, INPUT_IDS.STATE, INPUT_IDS.ZIP_POST_CODE, INPUT_IDS.COUNTRY]; + +function AddressStep({isEditing, onNext, privatePersonalDetails}: CustomSubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const address = useMemo(() => PersonalDetailsUtils.getCurrentAddress(privatePersonalDetails), [privatePersonalDetails]); + const [draftForm] = useOnyx(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM_DRAFT); const {street} = address ?? {}; const [street1, street2] = street ? street.split('\n') : [undefined, undefined]; - const [currentCountry, setCurrentCountry] = useState(address?.country); - const [state, setState] = useState(address?.state); - const [city, setCity] = useState(address?.city); - const [zipcode, setZipcode] = useState(address?.zip); + const defaultValues = { + street1: draftForm?.[INPUT_IDS.ADDRESS_LINE_1] ? draftForm?.[INPUT_IDS.ADDRESS_LINE_1] : street1, + street2: draftForm?.[INPUT_IDS.ADDRESS_LINE_2] ? draftForm?.[INPUT_IDS.ADDRESS_LINE_2] : street2, + city: draftForm?.[INPUT_IDS.CITY] ? draftForm?.[INPUT_IDS.CITY] : address?.city, + state: draftForm?.[INPUT_IDS.STATE] ? draftForm?.[INPUT_IDS.STATE] : address?.state, + zip: draftForm?.[INPUT_IDS.ZIP_POST_CODE] ? draftForm?.[INPUT_IDS.ZIP_POST_CODE] : address?.zip, + country: draftForm?.[INPUT_IDS.COUNTRY] ? draftForm?.[INPUT_IDS.COUNTRY] : address?.country, + }; + const [currentCountry, setCurrentCountry] = useState(defaultValues.country); + const [state, setState] = useState(defaultValues.state); + const [city, setCity] = useState(defaultValues.city); + const [zipcode, setZipcode] = useState(defaultValues.zip); + + const handleSubmit = usePersonalDetailsFormSubmit({ + fieldIds: STEP_FIELDS, + onNext, + shouldSaveDraft: isEditing, + }); useEffect(() => { if (!address) { @@ -73,98 +96,149 @@ function AddressStep({privatePersonalDetails}: CustomSubStepProps) { const zipFormat = translate('common.zipCodeExampleFormat', {zipSampleFormat}); + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors: FormInputErrors = {}; + const addressRequiredFields = [INPUT_IDS.ADDRESS_LINE_1, INPUT_IDS.CITY, INPUT_IDS.COUNTRY, INPUT_IDS.STATE] as const; + addressRequiredFields.forEach((fieldKey) => { + const fieldValue = values[fieldKey] ?? ''; + if (ValidationUtils.isRequiredFulfilled(fieldValue)) { + return; + } + errors[fieldKey] = translate('common.error.fieldRequired'); + }); + + // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object + const countryRegexDetails = (values.country ? CONST.COUNTRY_ZIP_REGEX_DATA?.[values.country] : {}) as CountryZipRegex; + + // The postal code system might not exist for a country, so no regex either for them. + const countrySpecificZipRegex = countryRegexDetails?.regex; + const countryZipFormat = countryRegexDetails?.samples ?? ''; + if (countrySpecificZipRegex) { + if (!countrySpecificZipRegex.test(values[INPUT_IDS.ZIP_POST_CODE]?.trim().toUpperCase())) { + if (ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.ZIP_POST_CODE]?.trim())) { + errors[INPUT_IDS.ZIP_POST_CODE] = translate('privatePersonalDetails.error.incorrectZipFormat', countryZipFormat); + } else { + errors[INPUT_IDS.ZIP_POST_CODE] = translate('common.error.fieldRequired'); + } + } + } else if (!CONST.GENERIC_ZIP_CODE_REGEX.test(values[INPUT_IDS.ZIP_POST_CODE]?.trim()?.toUpperCase() ?? '')) { + errors[INPUT_IDS.ZIP_POST_CODE] = translate('privatePersonalDetails.error.incorrectZipFormat'); + } + return errors; + }, + [translate], + ); + return ( - <> - {translate('privatePersonalDetails.enterAddress')} - - { - handleAddressChange(data, key); - }} - defaultValue={street1} - containerStyles={styles.mt3} - renamedInputKeys={{ - street: INPUT_IDS.ADDRESS_LINE_1, - street2: INPUT_IDS.ADDRESS_LINE_2, - city: INPUT_IDS.CITY, - state: INPUT_IDS.STATE, - zipCode: INPUT_IDS.ZIP_POST_CODE, - country: INPUT_IDS.COUNTRY as Country, - }} - maxInputLength={CONST.FORM_CHARACTER_LIMIT} - /> - - - + + + {translate('privatePersonalDetails.enterAddress')} + + { + handleAddressChange(data, key); + }} + defaultValue={defaultValues.street1} + containerStyles={styles.mt3} + renamedInputKeys={{ + street: INPUT_IDS.ADDRESS_LINE_1, + street2: INPUT_IDS.ADDRESS_LINE_2, + city: INPUT_IDS.CITY, + state: INPUT_IDS.STATE, + zipCode: INPUT_IDS.ZIP_POST_CODE, + country: INPUT_IDS.COUNTRY as Country, + }} + maxInputLength={CONST.FORM_CHARACTER_LIMIT} + shouldSaveDraft={!isEditing} + /> + - - {isUSAForm ? ( - ) : ( + {isUSAForm ? ( + + + + ) : ( + + )} - )} - - - + + + ); } diff --git a/src/pages/MissingPersonalDetails/substeps/Confirmation.tsx b/src/pages/MissingPersonalDetails/substeps/Confirmation.tsx new file mode 100644 index 000000000000..be6726262061 --- /dev/null +++ b/src/pages/MissingPersonalDetails/substeps/Confirmation.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import SafeAreaConsumer from '@components/SafeAreaConsumer'; +import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; +import useThemeStyles from '@hooks/useThemeStyles'; +import type {CustomSubStepProps} from '@pages/MissingPersonalDetails/types'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import INPUT_IDS from '@src/types/form/PersonalDetailsForm'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; + +const PERSONAL_DETAILS_STEP_INDEXES = CONST.MISSING_PERSONAL_DETAILS_INDEXES.MAPPING; + +function Confirmation({onNext, onMove}: CustomSubStepProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const {isOffline} = useNetwork(); + + const [values, formMetadata] = useOnyx(ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM_DRAFT); + + const isLoading = isLoadingOnyxValue(formMetadata); + + if (isEmptyObject(values)) { + return ; + } + + return ( + + {({safeAreaPaddingBottomStyle}) => ( + + {translate('personalInfoStep.letsDoubleCheck')} + { + onMove(PERSONAL_DETAILS_STEP_INDEXES.LEGAL_NAME); + }} + /> + { + onMove(PERSONAL_DETAILS_STEP_INDEXES.DATE_OF_BIRTH); + }} + /> + { + onMove(PERSONAL_DETAILS_STEP_INDEXES.ADDRESS); + }} + /> + { + onMove(PERSONAL_DETAILS_STEP_INDEXES.PHONE_NUMBER); + }} + /> + +