diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx index 5615f3b87cfa..3a64a3df9af9 100644 --- a/src/components/Form/FormWrapper.tsx +++ b/src/components/Form/FormWrapper.tsx @@ -108,7 +108,7 @@ function FormWrapper({ buttonText={submitButtonText} isAlertVisible={((!isEmptyObject(errors) || !isEmptyObject(formState?.errorFields)) && !shouldHideFixErrorsAlert) || !!errorMessage} isLoading={!!formState?.isLoading} - message={typeof errorMessage === 'string' && isEmptyObject(formState?.errorFields) ? errorMessage : undefined} + message={isEmptyObject(formState?.errorFields) ? errorMessage : undefined} onSubmit={onSubmit} footerContent={footerContent} onFixTheErrorsLinkPressed={onFixTheErrorsLinkPressed} diff --git a/src/components/Form/types.ts b/src/components/Form/types.ts index fe433aee69fb..37d0f730c9e9 100644 --- a/src/components/Form/types.ts +++ b/src/components/Form/types.ts @@ -6,15 +6,14 @@ import type AmountForm from '@components/AmountForm'; import type AmountTextInput from '@components/AmountTextInput'; import type CheckboxWithLabel from '@components/CheckboxWithLabel'; import type CountrySelector from '@components/CountrySelector'; -import type DatePicker from '@components/DatePicker'; import type Picker from '@components/Picker'; import type RadioButtons from '@components/RadioButtons'; import type SingleChoiceQuestion from '@components/SingleChoiceQuestion'; import type StatePicker from '@components/StatePicker'; import type TextInput from '@components/TextInput'; import type ValuePicker from '@components/ValuePicker'; -import type {MaybePhraseKey} from '@libs/Localize'; import type BusinessTypePicker from '@pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker'; +import type {TranslationPaths} from '@src/languages/types'; import type {OnyxFormKey, OnyxValues} from '@src/ONYXKEYS'; import type {BaseForm} from '@src/types/form/Form'; @@ -36,7 +35,6 @@ type ValidInputs = | typeof AmountForm | typeof BusinessTypePicker | typeof StatePicker - | typeof DatePicker | typeof ValuePicker | typeof RadioButtons; @@ -66,9 +64,6 @@ type InputComponentBaseProps = Input isFocused?: boolean; measureLayout?: (ref: unknown, callback: MeasureLayoutOnSuccessCallback) => void; focus?: () => void; - label?: string; - minDate?: Date; - maxDate?: Date; onTouched?: (event: GestureResponderEvent) => void; onBlur?: (event: FocusEvent | NativeSyntheticEvent) => void; onPressOut?: (event: GestureResponderEvent) => void; @@ -126,6 +121,6 @@ type FormProps = { type InputRefs = Record>; -type FormInputErrors = Partial, MaybePhraseKey>>; +type FormInputErrors = Partial, TranslationPaths>>; export type {FormProps, ValidInputs, InputComponentValueProps, FormValue, ValueTypeKey, FormOnyxValues, FormOnyxKeys, FormInputErrors, InputRefs, InputComponentBaseProps, ValueTypeMap}; diff --git a/src/libs/GetPhysicalCardUtils.ts b/src/libs/GetPhysicalCardUtils.ts index 97f0b6991fab..48c537f0f14c 100644 --- a/src/libs/GetPhysicalCardUtils.ts +++ b/src/libs/GetPhysicalCardUtils.ts @@ -84,15 +84,7 @@ function getUpdatedPrivatePersonalDetails(draftValues: OnyxEntry): string { - const {address} = privatePersonalDetails ?? {}; +function getFormattedAddress(privatePersonalDetails: PrivatePersonalDetails): string { + const {address} = privatePersonalDetails; const [street1, street2] = getStreetLines(address?.street); const formattedAddress = formatPiece(street1) + formatPiece(street2) + formatPiece(address?.city) + formatPiece(address?.state) + formatPiece(address?.zip) + formatPiece(address?.country); diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 669d10c4a1b8..0a46acbea102 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -11,7 +11,6 @@ import type {OnyxFormKey} from '@src/ONYXKEYS'; import type {Report} from '@src/types/onyx'; import * as CardUtils from './CardUtils'; import DateUtils from './DateUtils'; -import type {MaybePhraseKey} from './Localize'; import * as LoginUtils from './LoginUtils'; import {parsePhoneNumber} from './PhoneNumber'; import StringUtils from './StringUtils'; @@ -191,7 +190,7 @@ function meetsMaximumAgeRequirement(date: string): boolean { /** * Validate that given date is in a specified range of years before now. */ -function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): MaybePhraseKey { +function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): string | Array> { const currentDate = startOfDay(new Date()); const testDate = parse(date, CONST.DATE.FNS_FORMAT_STRING, currentDate); @@ -361,7 +360,7 @@ function isValidPersonName(value: string) { /** * Checks if the provided string includes any of the provided reserved words */ -function doesContainReservedWord(value: string, reservedWords: typeof CONST.DISPLAY_NAME.RESERVED_NAMES): boolean { +function doesContainReservedWord(value: string, reservedWords: string[]): boolean { const valueToCheck = value.trim().toLowerCase(); return reservedWords.some((reservedWord) => valueToCheck.includes(reservedWord.toLowerCase())); } diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/AddressPage.js similarity index 62% rename from src/pages/settings/Profile/PersonalDetails/AddressPage.tsx rename to src/pages/settings/Profile/PersonalDetails/AddressPage.js index cd151ffe6cb2..55d221085fcb 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -1,6 +1,6 @@ -import type {StackScreenProps} from '@react-navigation/stack'; +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import AddressForm from '@components/AddressForm'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; @@ -10,47 +10,66 @@ import useLocalize from '@hooks/useLocalize'; import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import * as PersonalDetails from '@userActions/PersonalDetails'; import ONYXKEYS from '@src/ONYXKEYS'; -import type SCREENS from '@src/SCREENS'; -import type {PrivatePersonalDetails} from '@src/types/onyx'; -import type {Address} from '@src/types/onyx/PrivatePersonalDetails'; -type AddressPageOnyxProps = { +const propTypes = { + /* Onyx Props */ + /** User's private personal details */ - privatePersonalDetails: OnyxEntry; + privatePersonalDetails: PropTypes.shape({ + /** User's home address */ + address: PropTypes.shape({ + street: PropTypes.string, + city: PropTypes.string, + state: PropTypes.string, + zip: PropTypes.string, + country: PropTypes.string, + }), + }), + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected country */ + country: PropTypes.string, + }), + }).isRequired, }; -type AddressPageProps = StackScreenProps & AddressPageOnyxProps; +const defaultProps = { + privatePersonalDetails: { + address: { + street: '', + city: '', + state: '', + zip: '', + country: '', + }, + }, +}; /** * Submit form to update user's first and last legal name - * @param values - form input values + * @param {Object} values - form input values */ -function updateAddress(values: Address) { - PersonalDetails.updateAddress( - values.addressLine1.trim(), - values.addressLine2?.trim() ?? '', - values.city.trim(), - values.state.trim(), - values?.zipPostCode.trim().toUpperCase(), - values.country, - ); +function updateAddress(values) { + PersonalDetails.updateAddress(values.addressLine1.trim(), values.addressLine2.trim(), values.city.trim(), values.state.trim(), values.zipPostCode.trim().toUpperCase(), values.country); } -function AddressPage({privatePersonalDetails, route}: AddressPageProps) { +function AddressPage({privatePersonalDetails, route}) { const styles = useThemeStyles(); usePrivatePersonalDetails(); const {translate} = useLocalize(); - const address = useMemo(() => privatePersonalDetails?.address, [privatePersonalDetails]); - const countryFromUrl = route.params?.country; - const [currentCountry, setCurrentCountry] = useState(address?.country); - const isLoadingPersonalDetails = privatePersonalDetails?.isLoading ?? true; - const [street1, street2] = (address?.street ?? '').split('\n'); - const [state, setState] = useState(address?.state); - const [city, setCity] = useState(address?.city); - const [zipcode, setZipcode] = useState(address?.zip); + const address = useMemo(() => lodashGet(privatePersonalDetails, 'address') || {}, [privatePersonalDetails]); + const countryFromUrl = lodashGet(route, 'params.country'); + const [currentCountry, setCurrentCountry] = useState(address.country); + const isLoadingPersonalDetails = lodashGet(privatePersonalDetails, 'isLoading', true); + const [street1, street2] = (address.street || '').split('\n'); + const [state, setState] = useState(address.state); + const [city, setCity] = useState(address.city); + const [zipcode, setZipcode] = useState(address.zip); useEffect(() => { if (!address) { @@ -62,7 +81,7 @@ function AddressPage({privatePersonalDetails, route}: AddressPageProps) { setZipcode(address.zip); }, [address]); - const handleAddressChange = useCallback((value: string, key: keyof Address) => { + const handleAddressChange = useCallback((value, key) => { if (key !== 'country' && key !== 'state' && key !== 'city' && key !== 'zipPostCode') { return; } @@ -124,9 +143,11 @@ function AddressPage({privatePersonalDetails, route}: AddressPageProps) { ); } +AddressPage.propTypes = propTypes; +AddressPage.defaultProps = defaultProps; AddressPage.displayName = 'AddressPage'; -export default withOnyx({ +export default withOnyx({ privatePersonalDetails: { key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, }, diff --git a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js similarity index 66% rename from src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx rename to src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js index f07d560ab454..d8327041538d 100644 --- a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js @@ -1,31 +1,46 @@ -import type {StackScreenProps} from '@react-navigation/stack'; +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React, {useCallback, useMemo, useState} from 'react'; +import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; -import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; -import type {CountryData} from '@libs/searchCountryOptions'; import searchCountryOptions from '@libs/searchCountryOptions'; import StringUtils from '@libs/StringUtils'; import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; -import type {Route} from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; -type CountrySelectionPageProps = StackScreenProps; +const propTypes = { + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected country */ + country: PropTypes.string, -function CountrySelectionPage({route, navigation}: CountrySelectionPageProps) { + /** Route to navigate back after selecting a currency */ + backTo: PropTypes.string, + }), + }).isRequired, + + /** Navigation from react-navigation */ + navigation: PropTypes.shape({ + /** getState function retrieves the current navigation state from react-navigation's navigation property */ + getState: PropTypes.func.isRequired, + }).isRequired, +}; + +function CountrySelectionPage({route, navigation}) { const [searchValue, setSearchValue] = useState(''); const {translate} = useLocalize(); - const currentCountry = route.params.country; + const currentCountry = lodashGet(route, 'params.country'); const countries = useMemo( () => - Object.keys(CONST.ALL_COUNTRIES).map((countryISO) => { - const countryName = translate(`allCountries.${countryISO}` as TranslationPaths); + _.map(_.keys(CONST.ALL_COUNTRIES), (countryISO) => { + const countryName = translate(`allCountries.${countryISO}`); return { value: countryISO, keyForList: countryISO, @@ -41,18 +56,19 @@ function CountrySelectionPage({route, navigation}: CountrySelectionPageProps) { const headerMessage = searchValue.trim() && !searchResults.length ? translate('common.noResultsFound') : ''; const selectCountry = useCallback( - (option: CountryData) => { - const backTo = route.params.backTo ?? ''; + (option) => { + const backTo = lodashGet(route, 'params.backTo', ''); + // Check the navigation state and "backTo" parameter to decide navigation behavior - if (navigation.getState().routes.length === 1 && !backTo) { + if (navigation.getState().routes.length === 1 && _.isEmpty(backTo)) { // If there is only one route and "backTo" is empty, go back in navigation Navigation.goBack(); - } else if (!!backTo && navigation.getState().routes.length === 1) { + } else if (!_.isEmpty(backTo) && navigation.getState().routes.length === 1) { // If "backTo" is not empty and there is only one route, go back to the specific route defined in "backTo" with a country parameter - Navigation.goBack(`${route.params.backTo}?country=${option.value}` as Route); + Navigation.goBack(`${route.params.backTo}?country=${option.value}`); } else { // Otherwise, navigate to the specific route defined in "backTo" with a country parameter - Navigation.navigate(`${route.params.backTo}?country=${option.value}` as Route); + Navigation.navigate(`${route.params.backTo}?country=${option.value}`); } }, [route, navigation], @@ -67,9 +83,9 @@ function CountrySelectionPage({route, navigation}: CountrySelectionPageProps) { title={translate('common.country')} shouldShowBackButton onBackButtonPress={() => { - const backTo = route.params.backTo ?? ''; - const backToRoute = backTo ? (`${backTo}?country=${currentCountry}` as const) : ''; - Navigation.goBack(backToRoute as Route); + const backTo = lodashGet(route, 'params.backTo', ''); + const backToRoute = backTo ? `${backTo}?country=${currentCountry}` : ''; + Navigation.goBack(backToRoute); }} /> @@ -89,5 +105,6 @@ function CountrySelectionPage({route, navigation}: CountrySelectionPageProps) { } CountrySelectionPage.displayName = 'CountrySelectionPage'; +CountrySelectionPage.propTypes = propTypes; export default CountrySelectionPage; diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js similarity index 70% rename from src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx rename to src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js index f00bc9322a2d..943d9fe0bab7 100644 --- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.js @@ -1,47 +1,59 @@ import {subYears} from 'date-fns'; +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React, {useCallback} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; -import type {FormOnyxValues} from '@components/Form/types'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; -import useLocalize from '@hooks/useLocalize'; +import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; import useThemeStyles from '@hooks/useThemeStyles'; +import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; 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/DateOfBirthForm'; -import type {PrivatePersonalDetails} from '@src/types/onyx'; -type DateOfBirthPageOnyxProps = { +const propTypes = { + /* Onyx Props */ + /** User's private personal details */ - privatePersonalDetails: OnyxEntry; + privatePersonalDetails: PropTypes.shape({ + dob: PropTypes.string, + }), + + ...withLocalizePropTypes, +}; + +const defaultProps = { + privatePersonalDetails: { + dob: '', + }, }; -type DateOfBirthPageProps = DateOfBirthPageOnyxProps; -function DateOfBirthPage({privatePersonalDetails}: DateOfBirthPageProps) { - const {translate} = useLocalize(); +function DateOfBirthPage({translate, privatePersonalDetails}) { const styles = useThemeStyles(); usePrivatePersonalDetails(); - const isLoadingPersonalDetails = privatePersonalDetails?.isLoading ?? true; + const isLoadingPersonalDetails = lodashGet(privatePersonalDetails, 'isLoading', true); /** - * @returns An object containing the errors for each inputID + * @param {Object} values + * @param {String} values.dob - date of birth + * @returns {Object} - An object containing the errors for each inputID */ - const validate = useCallback((values: FormOnyxValues) => { - const requiredFields = ['dob' as const]; + const validate = useCallback((values) => { + const requiredFields = ['dob']; const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); const minimumAge = CONST.DATE_BIRTH.MIN_AGE; const maximumAge = CONST.DATE_BIRTH.MAX_AGE; - const dateError = ValidationUtils.getAgeRequirementError(values.dob ?? '', minimumAge, maximumAge); + const dateError = ValidationUtils.getAgeRequirementError(values.dob, minimumAge, maximumAge); if (values.dob && dateError) { errors.dob = dateError; @@ -74,11 +86,9 @@ function DateOfBirthPage({privatePersonalDetails}: DateOfBirthPageProps) { InputComponent={DatePicker} inputID={INPUT_IDS.DOB} label={translate('common.date')} - defaultValue={privatePersonalDetails?.dob ?? ''} + defaultValue={privatePersonalDetails.dob || ''} minDate={subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE)} maxDate={subYears(new Date(), CONST.DATE_BIRTH.MIN_AGE)} - onInputChange={() => {}} - onTouched={() => {}} /> )} @@ -86,10 +96,15 @@ function DateOfBirthPage({privatePersonalDetails}: DateOfBirthPageProps) { ); } +DateOfBirthPage.propTypes = propTypes; +DateOfBirthPage.defaultProps = defaultProps; DateOfBirthPage.displayName = 'DateOfBirthPage'; -export default withOnyx({ - privatePersonalDetails: { - key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, - }, -})(DateOfBirthPage); +export default compose( + withLocalize, + withOnyx({ + privatePersonalDetails: { + key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, + }, + }), +)(DateOfBirthPage); diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js new file mode 100644 index 000000000000..0e81ea5194c1 --- /dev/null +++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.js @@ -0,0 +1,145 @@ +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import _ from 'underscore'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextInput from '@components/TextInput'; +import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; +import useThemeStyles from '@hooks/useThemeStyles'; +import compose from '@libs/compose'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; +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/LegalNameForm'; + +const propTypes = { + /* Onyx Props */ + + /** User's private personal details */ + privatePersonalDetails: PropTypes.shape({ + legalFirstName: PropTypes.string, + legalLastName: PropTypes.string, + }), + + ...withLocalizePropTypes, +}; + +const defaultProps = { + privatePersonalDetails: { + legalFirstName: '', + legalLastName: '', + }, +}; + +const updateLegalName = (values) => { + PersonalDetails.updateLegalName(values.legalFirstName.trim(), values.legalLastName.trim()); +}; + +function LegalNamePage(props) { + const styles = useThemeStyles(); + usePrivatePersonalDetails(); + const legalFirstName = lodashGet(props.privatePersonalDetails, 'legalFirstName', ''); + const legalLastName = lodashGet(props.privatePersonalDetails, 'legalLastName', ''); + const isLoadingPersonalDetails = lodashGet(props.privatePersonalDetails, 'isLoading', true); + + const validate = useCallback((values) => { + const errors = {}; + + if (!ValidationUtils.isValidLegalName(values.legalFirstName)) { + ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'privatePersonalDetails.error.hasInvalidCharacter'); + } else if (_.isEmpty(values.legalFirstName)) { + errors.legalFirstName = 'common.error.fieldRequired'; + } else if (values.legalFirstName.length > CONST.TITLE_CHARACTER_LIMIT) { + ErrorUtils.addErrorMessage(errors, 'legalFirstName', ['common.error.characterLimitExceedCounter', {length: values.legalFirstName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + } + if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { + ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); + } + + if (!ValidationUtils.isValidLegalName(values.legalLastName)) { + ErrorUtils.addErrorMessage(errors, 'legalLastName', 'privatePersonalDetails.error.hasInvalidCharacter'); + } else if (_.isEmpty(values.legalLastName)) { + errors.legalLastName = 'common.error.fieldRequired'; + } else if (values.legalLastName.length > CONST.TITLE_CHARACTER_LIMIT) { + ErrorUtils.addErrorMessage(errors, 'legalLastName', ['common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + } + if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { + ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); + } + + return errors; + }, []); + + return ( + + Navigation.goBack()} + /> + {isLoadingPersonalDetails ? ( + + ) : ( + + + + + + + + + )} + + ); +} + +LegalNamePage.propTypes = propTypes; +LegalNamePage.defaultProps = defaultProps; +LegalNamePage.displayName = 'LegalNamePage'; + +export default compose( + withLocalize, + withOnyx({ + privatePersonalDetails: { + key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, + }, + }), +)(LegalNamePage); diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx deleted file mode 100644 index 5e8e4ea493a0..000000000000 --- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, {useCallback} from 'react'; -import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import type {FormOnyxValues} from '@components/Form/types'; -import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import TextInput from '@components/TextInput'; -import useLocalize from '@hooks/useLocalize'; -import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; -import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; -import Navigation from '@libs/Navigation/Navigation'; -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/LegalNameForm'; -import type {PrivatePersonalDetails} from '@src/types/onyx'; -import type {Errors} from '@src/types/onyx/OnyxCommon'; - -type LegalNamePageOnyxProps = { - /** User's private personal details */ - privatePersonalDetails: OnyxEntry; -}; - -type LegalNamePageProps = LegalNamePageOnyxProps; - -const updateLegalName = (values: PrivatePersonalDetails) => { - PersonalDetails.updateLegalName(values.legalFirstName?.trim() ?? '', values.legalLastName?.trim() ?? ''); -}; - -function LegalNamePage({privatePersonalDetails}: LegalNamePageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - usePrivatePersonalDetails(); - const legalFirstName = privatePersonalDetails?.legalFirstName ?? ''; - const legalLastName = privatePersonalDetails?.legalLastName ?? ''; - const isLoadingPersonalDetails = privatePersonalDetails?.isLoading ?? true; - - const validate = useCallback((values: FormOnyxValues) => { - const errors: Errors = {}; - - if (typeof values.legalFirstName === 'string') { - if (!ValidationUtils.isValidLegalName(values.legalFirstName)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'privatePersonalDetails.error.hasInvalidCharacter'); - } else if (!values.legalFirstName) { - errors.legalFirstName = 'common.error.fieldRequired'; - } else if (values.legalFirstName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', [ - 'common.error.characterLimitExceedCounter', - {length: values.legalFirstName.length, limit: CONST.TITLE_CHARACTER_LIMIT}, - ]); - } - if (ValidationUtils.doesContainReservedWord(values.legalFirstName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalFirstName', 'personalDetails.error.containsReservedWord'); - } - } - - if (typeof values.legalLastName === 'string') { - if (!ValidationUtils.isValidLegalName(values.legalLastName)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'privatePersonalDetails.error.hasInvalidCharacter'); - } else if (!values.legalLastName) { - errors.legalLastName = 'common.error.fieldRequired'; - } else if (values.legalLastName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', ['common.error.characterLimitExceedCounter', {length: values.legalLastName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); - } - if (ValidationUtils.doesContainReservedWord(values.legalLastName, CONST.DISPLAY_NAME.RESERVED_NAMES)) { - ErrorUtils.addErrorMessage(errors, 'legalLastName', 'personalDetails.error.containsReservedWord'); - } - } - - return errors; - }, []); - - return ( - - Navigation.goBack()} - /> - {isLoadingPersonalDetails ? ( - - ) : ( - - - - - - - - - )} - - ); -} - -LegalNamePage.displayName = 'LegalNamePage'; - -export default withOnyx({ - privatePersonalDetails: { - key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS, - }, -})(LegalNamePage); diff --git a/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.tsx b/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.tsx index 693561a01b52..c6b4bc2272d1 100644 --- a/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.tsx +++ b/src/pages/settings/Wallet/Card/GetPhysicalCardConfirm.tsx @@ -83,8 +83,6 @@ function GetPhysicalCardConfirm({ state, zip: zipPostCode, country, - addressLine1: addressLine1 ?? '', - zipPostCode: zipPostCode ?? '', }, })} /> diff --git a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx index 78fe03d1e65c..77458384c214 100644 --- a/src/pages/settings/Wallet/WalletPage/CardDetails.tsx +++ b/src/pages/settings/Wallet/WalletPage/CardDetails.tsx @@ -23,8 +23,6 @@ const defaultPrivatePersonalDetails: PrivatePersonalDetails = { state: '', zip: '', country: '', - addressLine1: '', - zipPostCode: '', }, }; diff --git a/src/types/onyx/PrivatePersonalDetails.ts b/src/types/onyx/PrivatePersonalDetails.ts index 5efff5f9e387..780e3f71b61d 100644 --- a/src/types/onyx/PrivatePersonalDetails.ts +++ b/src/types/onyx/PrivatePersonalDetails.ts @@ -5,9 +5,6 @@ type Address = { state: string; zip: string; country: string; - zipPostCode: string; - addressLine1: string; - addressLine2?: string; }; type PrivatePersonalDetails = { @@ -24,5 +21,3 @@ type PrivatePersonalDetails = { }; export default PrivatePersonalDetails; - -export type {Address};