From 4c04f9b3f329a3b082ccb41ca7f634630576a93c Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 18 Jan 2024 12:21:34 +0100 Subject: [PATCH 1/6] [TS migration] Migrate 'SettingsSecurityCloseAccount' page --- ...oseAccountPage.js => CloseAccountPage.tsx} | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) rename src/pages/settings/Security/{CloseAccountPage.js => CloseAccountPage.tsx} (60%) diff --git a/src/pages/settings/Security/CloseAccountPage.js b/src/pages/settings/Security/CloseAccountPage.tsx similarity index 60% rename from src/pages/settings/Security/CloseAccountPage.js rename to src/pages/settings/Security/CloseAccountPage.tsx index 9aad345d7b3d..4922a536a8e4 100644 --- a/src/pages/settings/Security/CloseAccountPage.js +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -1,8 +1,9 @@ +import type {StackScreenProps} from '@react-navigation/stack'; import Str from 'expensify-common/lib/str'; -import PropTypes from 'prop-types'; import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx/lib/types'; import ConfirmModal from '@components/ConfirmModal'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -10,37 +11,36 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as ValidationUtils from '@libs/ValidationUtils'; +import type {SettingsNavigatorParamList} from '@navigation/types'; import * as CloseAccount from '@userActions/CloseAccount'; import * as User from '@userActions/User'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; +import type {Session} from '@src/types/onyx'; +import type {Errors} from '@src/types/onyx/OnyxCommon'; -const propTypes = { +type CloseAccountPageOnyxProps = { /** Session of currently logged in user */ - session: PropTypes.shape({ - /** Email address */ - email: PropTypes.string.isRequired, - }), - - ...windowDimensionsPropTypes, - ...withLocalizePropTypes, + session: OnyxEntry; }; -const defaultProps = { - session: { - email: null, - }, +type CloseAccountPageProps = CloseAccountPageOnyxProps & StackScreenProps; + +type CloseAccountFormValues = { + reasonForLeaving: string; + phoneOrEmail: string; }; -function CloseAccountPage(props) { +function CloseAccountPage({session}: CloseAccountPageProps) { const styles = useThemeStyles(); + const {translate, formatPhoneNumber} = useLocalize(); + const [isConfirmModalVisible, setConfirmModalVisibility] = useState(false); const [reasonForLeaving, setReasonForLeaving] = useState(''); @@ -59,21 +59,21 @@ function CloseAccountPage(props) { hideConfirmModal(); }; - const showConfirmModal = (values) => { + const showConfirmModal = (values: CloseAccountFormValues) => { setConfirmModalVisibility(true); setReasonForLeaving(values.reasonForLeaving); }; /** * Removes spaces and transform the input string to lowercase. - * @param {String} phoneOrEmail - The input string to be sanitized. - * @returns {String} The sanitized string + * @param phoneOrEmail - The input string to be sanitized. + * @returns The sanitized string */ - const sanitizePhoneOrEmail = (phoneOrEmail) => phoneOrEmail.replace(/\s+/g, '').toLowerCase(); + const sanitizePhoneOrEmail = (phoneOrEmail: string): string => phoneOrEmail.replace(/\s+/g, '').toLowerCase(); - const validate = (values) => { + const validate = (values: CloseAccountFormValues): Errors => { const requiredFields = ['phoneOrEmail']; - const userEmailOrPhone = props.formatPhoneNumber(props.session.email); + const userEmailOrPhone = formatPhoneNumber(session?.email ?? ''); const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); if (values.phoneOrEmail && sanitizePhoneOrEmail(userEmailOrPhone) !== sanitizePhoneOrEmail(values.phoneOrEmail)) { @@ -82,7 +82,7 @@ function CloseAccountPage(props) { return errors; }; - const userEmailOrPhone = props.formatPhoneNumber(props.session.email); + const userEmailOrPhone = formatPhoneNumber(session?.email ?? ''); return ( Navigation.goBack(ROUTES.SETTINGS_SECURITY)} /> + {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. */} - {props.translate('closeAccountPage.reasonForLeavingPrompt')} + {translate('closeAccountPage.reasonForLeavingPrompt')} - {props.translate('closeAccountPage.enterDefaultContactToConfirm')} {userEmailOrPhone} + {translate('closeAccountPage.enterDefaultContactToConfirm')} {userEmailOrPhone} @@ -144,16 +147,10 @@ function CloseAccountPage(props) { ); } -CloseAccountPage.propTypes = propTypes; -CloseAccountPage.defaultProps = defaultProps; CloseAccountPage.displayName = 'CloseAccountPage'; -export default compose( - withLocalize, - withWindowDimensions, - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - }), -)(CloseAccountPage); +export default withOnyx({ + session: { + key: ONYXKEYS.SESSION, + }, +})(CloseAccountPage); From d788f79ecd2cb234f35dc79644681de387c05ff0 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 25 Jan 2024 17:21:15 +0100 Subject: [PATCH 2/6] Remove extra TODOs, add CloseAccountForm type --- src/ONYXKEYS.ts | 4 ++-- src/pages/settings/Security/CloseAccountPage.tsx | 13 +++---------- src/types/onyx/Form.ts | 7 ++++++- src/types/onyx/index.ts | 3 ++- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 7abf6db1769d..e314acd99f8c 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -480,8 +480,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM]: OnyxTypes.Form; [ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM_DRAFT]: OnyxTypes.Form; - [ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM]: OnyxTypes.Form; - [ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM_DRAFT]: OnyxTypes.Form; + [ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM]: OnyxTypes.CloseAccountForm; + [ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM_DRAFT]: OnyxTypes.CloseAccountForm; [ONYXKEYS.FORMS.PROFILE_SETTINGS_FORM]: OnyxTypes.Form; [ONYXKEYS.FORMS.PROFILE_SETTINGS_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.DISPLAY_NAME_FORM]: OnyxTypes.DisplayNameForm; diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 4922a536a8e4..95faa99dff76 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -7,6 +7,7 @@ import type {OnyxEntry} from 'react-native-onyx/lib/types'; import ConfirmModal from '@components/ConfirmModal'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; +import type {OnyxFormValuesFields} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -32,11 +33,6 @@ type CloseAccountPageOnyxProps = { type CloseAccountPageProps = CloseAccountPageOnyxProps & StackScreenProps; -type CloseAccountFormValues = { - reasonForLeaving: string; - phoneOrEmail: string; -}; - function CloseAccountPage({session}: CloseAccountPageProps) { const styles = useThemeStyles(); const {translate, formatPhoneNumber} = useLocalize(); @@ -59,7 +55,7 @@ function CloseAccountPage({session}: CloseAccountPageProps) { hideConfirmModal(); }; - const showConfirmModal = (values: CloseAccountFormValues) => { + const showConfirmModal = (values: OnyxFormValuesFields) => { setConfirmModalVisibility(true); setReasonForLeaving(values.reasonForLeaving); }; @@ -71,7 +67,7 @@ function CloseAccountPage({session}: CloseAccountPageProps) { */ const sanitizePhoneOrEmail = (phoneOrEmail: string): string => phoneOrEmail.replace(/\s+/g, '').toLowerCase(); - const validate = (values: CloseAccountFormValues): Errors => { + const validate = (values: OnyxFormValuesFields): Errors => { const requiredFields = ['phoneOrEmail']; const userEmailOrPhone = formatPhoneNumber(session?.email ?? ''); const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); @@ -93,7 +89,6 @@ function CloseAccountPage({session}: CloseAccountPageProps) { title={translate('closeAccountPage.closeAccount')} onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_SECURITY)} /> - {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. */} {translate('closeAccountPage.reasonForLeavingPrompt')} {userEmailOrPhone} ; +type CloseAccountForm = Form<{ + reasonForLeaving: string; + phoneOrEmail: string; +}>; + export default Form; -export type {AddDebitCardForm, DateOfBirthForm, PrivateNotesForm, DisplayNameForm, FormValueType, NewRoomForm, BaseForm, IKnowATeacherForm, IntroSchoolPrincipalForm}; +export type {AddDebitCardForm, DateOfBirthForm, PrivateNotesForm, DisplayNameForm, FormValueType, NewRoomForm, BaseForm, IKnowATeacherForm, IntroSchoolPrincipalForm, CloseAccountForm}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 5b04cae58671..80c65c4b70be 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -9,7 +9,7 @@ import type Credentials from './Credentials'; import type Currency from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; -import type {AddDebitCardForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, PrivateNotesForm} from './Form'; +import type {AddDebitCardForm, CloseAccountForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, PrivateNotesForm} from './Form'; import type Form from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; @@ -82,6 +82,7 @@ export type { Credentials, Currency, CustomStatusDraft, + CloseAccountForm, DateOfBirthForm, Download, Form, From fc2ab2b09ec50eb5b15c9f150d53bc54da86aba6 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 29 Jan 2024 17:40:46 +0100 Subject: [PATCH 3/6] Update formatPhoneNumber typing --- src/components/LocaleContextProvider.tsx | 2 +- src/libs/LocalePhoneNumber.ts | 2 +- src/pages/settings/Security/CloseAccountPage.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 7313bb4aa7bb..48e9aa49d0de 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -45,7 +45,7 @@ type LocaleContextProps = { /** Returns a locally converted phone number for numbers from the same region * and an internationally converted phone number with the country code for numbers from other regions */ - formatPhoneNumber: (phoneNumber: string) => string; + formatPhoneNumber: (phoneNumber: string | undefined) => string; /** Gets the locale digit corresponding to a standard digit */ toLocaleDigit: (digit: string) => string; diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index 933aa7937560..9aacc6968e1e 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -13,7 +13,7 @@ Onyx.connect({ * Returns a locally converted phone number for numbers from the same region * and an internationally converted phone number with the country code for numbers from other regions */ -function formatPhoneNumber(number: string): string { +function formatPhoneNumber(number: string | undefined): string { if (!number) { return ''; } diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 95faa99dff76..2287752cd786 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -69,7 +69,7 @@ function CloseAccountPage({session}: CloseAccountPageProps) { const validate = (values: OnyxFormValuesFields): Errors => { const requiredFields = ['phoneOrEmail']; - const userEmailOrPhone = formatPhoneNumber(session?.email ?? ''); + const userEmailOrPhone = formatPhoneNumber(session?.email); const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); if (values.phoneOrEmail && sanitizePhoneOrEmail(userEmailOrPhone) !== sanitizePhoneOrEmail(values.phoneOrEmail)) { @@ -78,7 +78,7 @@ function CloseAccountPage({session}: CloseAccountPageProps) { return errors; }; - const userEmailOrPhone = formatPhoneNumber(session?.email ?? ''); + const userEmailOrPhone = formatPhoneNumber(session?.email); return ( Date: Tue, 30 Jan 2024 11:48:11 +0100 Subject: [PATCH 4/6] Fix Onyx types import --- src/pages/settings/Security/CloseAccountPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 2287752cd786..f1a0d064fe0a 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -3,7 +3,7 @@ import Str from 'expensify-common/lib/str'; import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx/lib/types'; +import type {OnyxEntry} from 'react-native-onyx'; import ConfirmModal from '@components/ConfirmModal'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; From 39ef206b1f26d2b30467dd8535707dccbf1c74ba Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 1 Feb 2024 09:48:54 +0100 Subject: [PATCH 5/6] Lint fix --- src/types/onyx/index.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 64ffddc6935f..c6f8d43c75e1 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -9,7 +9,17 @@ import type Credentials from './Credentials'; import type Currency from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; -import type {AddDebitCardForm, CloseAccountForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, PrivateNotesForm, ReportFieldEditForm} from './Form'; +import type { + AddDebitCardForm, + CloseAccountForm, + DateOfBirthForm, + DisplayNameForm, + IKnowATeacherForm, + IntroSchoolPrincipalForm, + NewRoomForm, + PrivateNotesForm, + ReportFieldEditForm, +} from './Form'; import type Form from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; From d2f71a868303f9a133265be8bb4f5e8b2a02cd08 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 2 Feb 2024 11:07:13 +0100 Subject: [PATCH 6/6] Fix lint error --- src/types/onyx/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 787b9298b011..d0ac2ce395fa 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -11,6 +11,7 @@ import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; import type { AddDebitCardForm, + CloseAccountForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, @@ -19,7 +20,6 @@ import type { PrivateNotesForm, ReportFieldEditForm, WorkspaceSettingsForm, - CloseAccountForm, } from './Form'; import type Form from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji';