From 2060d5e2bfc161a08b7058ce88b3603add93a3bc Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 30 Jan 2024 20:15:47 +0530 Subject: [PATCH 001/202] TS-migration: TermsStep Page --- .../{TermsStep.js => TermsStep.tsx} | 69 ++++++++----------- 1 file changed, 30 insertions(+), 39 deletions(-) rename src/pages/EnablePayments/{TermsStep.js => TermsStep.tsx} (67%) diff --git a/src/pages/EnablePayments/TermsStep.js b/src/pages/EnablePayments/TermsStep.tsx similarity index 67% rename from src/pages/EnablePayments/TermsStep.js rename to src/pages/EnablePayments/TermsStep.tsx index a09e1801c3b0..a03f3607d56e 100644 --- a/src/pages/EnablePayments/TermsStep.js +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -6,39 +6,34 @@ import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; import LongTermsForm from './TermsPage/LongTermsForm'; import ShortTermsForm from './TermsPage/ShortTermsForm'; -import userWalletPropTypes from './userWalletPropTypes'; -import walletTermsPropTypes from './walletTermsPropTypes'; - -const propTypes = { - /** The user's wallet */ - userWallet: userWalletPropTypes, +import useLocalize from '@hooks/useLocalize'; +import type {OnyxEntry} from 'react-native-onyx'; +import {WalletTerms, UserWallet} from '@src/types/onyx'; +type TermsStepOnyxProps = { /** Comes from Onyx. Information about the terms for the wallet */ - walletTerms: walletTermsPropTypes, - - ...withLocalizePropTypes, -}; + walletTerms: OnyxEntry; +} -const defaultProps = { - userWallet: {}, - walletTerms: {}, +type TermsStepProps = TermsStepOnyxProps & { + /** The user's wallet */ + userWallet: OnyxEntry; }; -function TermsStep(props) { +function TermsStep(props: TermsStepProps) { const styles = useThemeStyles(); const [hasAcceptedDisclosure, setHasAcceptedDisclosure] = useState(false); const [hasAcceptedPrivacyPolicyAndWalletAgreement, setHasAcceptedPrivacyPolicyAndWalletAgreement] = useState(false); const [error, setError] = useState(false); + const {translate} = useLocalize(); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms) || ''; + const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms??{}) || ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); @@ -59,7 +54,7 @@ function TermsStep(props) { return ( <> - + ( - {`${props.translate('termsStep.haveReadAndAgree')}`} - {`${props.translate('termsStep.electronicDisclosures')}.`} + {`${translate('termsStep.haveReadAndAgree')}`} + {`${translate('termsStep.electronicDisclosures')}.`} )} /> ( - {`${props.translate('termsStep.agreeToThe')} `} + {`${translate('termsStep.agreeToThe')} `} - {`${props.translate('common.privacy')} `} + {`${translate('common.privacy')} `} - {`${props.translate('common.and')} `} + {`${translate('common.and')} `} - {`${props.translate('termsStep.walletAgreement')}.`} + {`${translate('termsStep.walletAgreement')}.`} )} /> { if (!hasAcceptedDisclosure || !hasAcceptedPrivacyPolicyAndWalletAgreement) { setError(true); @@ -104,12 +99,12 @@ function TermsStep(props) { setError(false); BankAccounts.acceptWalletTerms({ hasAcceptedTerms: hasAcceptedDisclosure && hasAcceptedPrivacyPolicyAndWalletAgreement, - reportID: props.walletTerms.chatReportID, + reportID: props.walletTerms?.chatReportID??'', }); }} message={errorMessage} isAlertVisible={error || Boolean(errorMessage)} - isLoading={!!props.walletTerms.isLoading} + isLoading={!!props.walletTerms?.isLoading} containerStyles={[styles.mh0, styles.mv4]} /> @@ -118,13 +113,9 @@ function TermsStep(props) { } TermsStep.displayName = 'TermsPage'; -TermsStep.propTypes = propTypes; -TermsStep.defaultProps = defaultProps; -export default compose( - withLocalize, - withOnyx({ - walletTerms: { - key: ONYXKEYS.WALLET_TERMS, - }, - }), -)(TermsStep); + +export default withOnyx({ + walletTerms: { + key: ONYXKEYS.WALLET_TERMS, + }, +})(TermsStep); From 744a3b5f380317b65ac91925a7e1f37d36273a79 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 30 Jan 2024 20:19:34 +0530 Subject: [PATCH 002/202] TS-migration: ShortTermsForm Page --- .../{ShortTermsForm.js => ShortTermsForm.tsx} | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) rename src/pages/EnablePayments/TermsPage/{ShortTermsForm.js => ShortTermsForm.tsx} (93%) diff --git a/src/pages/EnablePayments/TermsPage/ShortTermsForm.js b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx similarity index 93% rename from src/pages/EnablePayments/TermsPage/ShortTermsForm.js rename to src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx index 40824f47b036..1c9d37bb30e9 100644 --- a/src/pages/EnablePayments/TermsPage/ShortTermsForm.js +++ b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx @@ -5,19 +5,16 @@ import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CurrencyUtils from '@libs/CurrencyUtils'; -import userWalletPropTypes from '@pages/EnablePayments/userWalletPropTypes'; import CONST from '@src/CONST'; +import type {OnyxEntry} from 'react-native-onyx'; +import {UserWallet} from '@src/types/onyx'; -const propTypes = { - /** The user's wallet */ - userWallet: userWalletPropTypes, +type ShortTermsFormProps = { + /** The user's wallet */ + userWallet: OnyxEntry; }; -const defaultProps = { - userWallet: {}, -}; - -function ShortTermsForm(props) { +function ShortTermsForm(props: ShortTermsFormProps) { const styles = useThemeStyles(); const {translate, numberFormat} = useLocalize(); return ( @@ -25,7 +22,7 @@ function ShortTermsForm(props) { {translate('termsStep.shortTermsForm.expensifyPaymentsAccount', { walletProgram: - props.userWallet.walletProgramID === CONST.WALLET.MTL_WALLET_PROGRAM_ID ? CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS : CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK, + props.userWallet?.walletProgramID === CONST.WALLET.MTL_WALLET_PROGRAM_ID ? CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS : CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK, })} @@ -150,8 +147,6 @@ function ShortTermsForm(props) { ); } -ShortTermsForm.propTypes = propTypes; -ShortTermsForm.defaultProps = defaultProps; ShortTermsForm.displayName = 'ShortTermsForm'; export default ShortTermsForm; From 3f86b2eb3d06eef77cfc51c34a51b4945dddc1a3 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 30 Jan 2024 20:22:23 +0530 Subject: [PATCH 003/202] TS-migration: LongTermsForm Page --- .../TermsPage/{LongTermsForm.js => LongTermsForm.tsx} | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/pages/EnablePayments/TermsPage/{LongTermsForm.js => LongTermsForm.tsx} (98%) diff --git a/src/pages/EnablePayments/TermsPage/LongTermsForm.js b/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx similarity index 98% rename from src/pages/EnablePayments/TermsPage/LongTermsForm.js rename to src/pages/EnablePayments/TermsPage/LongTermsForm.tsx index fad19c5ecf6f..ec89856642d9 100644 --- a/src/pages/EnablePayments/TermsPage/LongTermsForm.js +++ b/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx @@ -66,7 +66,7 @@ function LongTermsForm() { ]; const getLongTermsSections = () => - _.map(termsData, (section, index) => ( + termsData.map((section, index) => ( // eslint-disable-next-line react/no-array-index-key @@ -105,7 +105,6 @@ function LongTermsForm() { Date: Tue, 30 Jan 2024 20:24:10 +0530 Subject: [PATCH 004/202] TS-migration: FailedKYC Page --- .../{FailedKYC.js => FailedKYC.tsx} | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) rename src/pages/EnablePayments/{FailedKYC.js => FailedKYC.tsx} (65%) diff --git a/src/pages/EnablePayments/FailedKYC.js b/src/pages/EnablePayments/FailedKYC.tsx similarity index 65% rename from src/pages/EnablePayments/FailedKYC.js rename to src/pages/EnablePayments/FailedKYC.tsx index fc54ea9c1074..25672772c216 100644 --- a/src/pages/EnablePayments/FailedKYC.js +++ b/src/pages/EnablePayments/FailedKYC.tsx @@ -2,35 +2,31 @@ import React from 'react'; import {View} from 'react-native'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; +import useLocalize from '@hooks/useLocalize'; -const propTypes = { - ...withLocalizePropTypes, -}; - -function FailedKYC(props) { +function FailedKYC() { + const {translate} = useLocalize(); const styles = useThemeStyles(); return ( - {props.translate('additionalDetailsStep.failedKYCTextBefore')} + {translate('additionalDetailsStep.failedKYCTextBefore')} {CONST.EMAIL.CONCIERGE} - {props.translate('additionalDetailsStep.failedKYCTextAfter')} + {translate('additionalDetailsStep.failedKYCTextAfter')} ); } -FailedKYC.propTypes = propTypes; FailedKYC.displayName = 'FailedKYC'; -export default withLocalize(FailedKYC); +export default FailedKYC; From b4c5a8a9d66a629167114fd56c2bb68850a27d11 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 30 Jan 2024 20:38:51 +0530 Subject: [PATCH 005/202] TS-migration: ActivateStep Page --- src/pages/EnablePayments/ActivateStep.js | 72 ----------------------- src/pages/EnablePayments/ActivateStep.tsx | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 72 deletions(-) delete mode 100644 src/pages/EnablePayments/ActivateStep.js create mode 100644 src/pages/EnablePayments/ActivateStep.tsx diff --git a/src/pages/EnablePayments/ActivateStep.js b/src/pages/EnablePayments/ActivateStep.js deleted file mode 100644 index 92342c28af73..000000000000 --- a/src/pages/EnablePayments/ActivateStep.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import ConfirmationPage from '@components/ConfirmationPage'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import LottieAnimations from '@components/LottieAnimations'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import compose from '@libs/compose'; -import * as PaymentMethods from '@userActions/PaymentMethods'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import userWalletPropTypes from './userWalletPropTypes'; -import walletTermsPropTypes from './walletTermsPropTypes'; - -const propTypes = { - ...withLocalizePropTypes, - - /** The user's wallet */ - userWallet: userWalletPropTypes, - - /** Information about the user accepting the terms for payments */ - walletTerms: walletTermsPropTypes, -}; - -const defaultProps = { - userWallet: {}, - walletTerms: { - source: '', - chatReportID: 0, - }, -}; - -function ActivateStep(props) { - const isActivatedWallet = _.contains([CONST.WALLET.TIER_NAME.GOLD, CONST.WALLET.TIER_NAME.PLATINUM], props.userWallet.tierName); - const animation = isActivatedWallet ? LottieAnimations.Fireworks : LottieAnimations.ReviewingBankInfo; - let continueButtonText = ''; - - if (props.walletTerms.chatReportID) { - continueButtonText = props.translate('activateStep.continueToPayment'); - } else if (props.walletTerms.source === CONST.KYC_WALL_SOURCE.ENABLE_WALLET) { - continueButtonText = props.translate('common.continue'); - } else { - continueButtonText = props.translate('activateStep.continueToTransfer'); - } - - return ( - <> - - PaymentMethods.continueSetup()} - /> - - ); -} - -ActivateStep.propTypes = propTypes; -ActivateStep.defaultProps = defaultProps; -ActivateStep.displayName = 'ActivateStep'; - -export default compose( - withLocalize, - withOnyx({ - walletTerms: { - key: ONYXKEYS.WALLET_TERMS, - }, - }), -)(ActivateStep); diff --git a/src/pages/EnablePayments/ActivateStep.tsx b/src/pages/EnablePayments/ActivateStep.tsx new file mode 100644 index 000000000000..d16190f0c0af --- /dev/null +++ b/src/pages/EnablePayments/ActivateStep.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import {withOnyx} from 'react-native-onyx'; +import ConfirmationPage from '@components/ConfirmationPage'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import LottieAnimations from '@components/LottieAnimations'; +import * as PaymentMethods from '@userActions/PaymentMethods'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import useLocalize from '@hooks/useLocalize'; +import type {OnyxEntry} from 'react-native-onyx'; +import {WalletTerms, UserWallet} from '@src/types/onyx'; + +type ActivateStepOnyxProps = { + /** Information about the user accepting the terms for payments */ + walletTerms: OnyxEntry; +}; + +type ActivateStepProps = ActivateStepOnyxProps & { + /** The user's wallet */ + userWallet: OnyxEntry; +}; + +function ActivateStep({ + userWallet, + walletTerms +}: ActivateStepProps) { + const {translate} = useLocalize(); + const isActivatedWallet = userWallet?.tierName && [CONST.WALLET.TIER_NAME.GOLD, CONST.WALLET.TIER_NAME.PLATINUM].some((name) => name === userWallet.tierName); + + const animation = isActivatedWallet ? LottieAnimations.Fireworks : LottieAnimations.ReviewingBankInfo; + let continueButtonText = ''; + + if (walletTerms?.chatReportID) { + continueButtonText = translate('activateStep.continueToPayment'); + } else if (walletTerms?.source === CONST.KYC_WALL_SOURCE.ENABLE_WALLET) { + continueButtonText = translate('common.continue'); + } else { + continueButtonText = translate('activateStep.continueToTransfer'); + } + + return ( + <> + + PaymentMethods.continueSetup()} + /> + + ); +} + +ActivateStep.displayName = 'ActivateStep'; + +export default withOnyx({ + walletTerms: { + key: ONYXKEYS.WALLET_TERMS, + }, +})(ActivateStep); \ No newline at end of file From 0ac0bedbd17cf7e86935e71828efd1175a7ac131 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Wed, 31 Jan 2024 01:59:28 +0530 Subject: [PATCH 006/202] TS-migration: OnfidoStep & OnfidoPrivacy Page --- src/pages/EnablePayments/ActivateStep.tsx | 13 ++-- src/pages/EnablePayments/FailedKYC.tsx | 2 +- .../{OnfidoPrivacy.js => OnfidoPrivacy.tsx} | 64 +++++++++---------- .../{OnfidoStep.js => OnfidoStep.tsx} | 35 +++++----- .../TermsPage/ShortTermsForm.tsx | 8 ++- src/pages/EnablePayments/TermsStep.tsx | 12 ++-- 6 files changed, 64 insertions(+), 70 deletions(-) rename src/pages/EnablePayments/{OnfidoPrivacy.js => OnfidoPrivacy.tsx} (74%) rename src/pages/EnablePayments/{OnfidoStep.js => OnfidoStep.tsx} (69%) diff --git a/src/pages/EnablePayments/ActivateStep.tsx b/src/pages/EnablePayments/ActivateStep.tsx index d16190f0c0af..0dbb98e53a5f 100644 --- a/src/pages/EnablePayments/ActivateStep.tsx +++ b/src/pages/EnablePayments/ActivateStep.tsx @@ -1,14 +1,14 @@ import React from 'react'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import ConfirmationPage from '@components/ConfirmationPage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import LottieAnimations from '@components/LottieAnimations'; +import useLocalize from '@hooks/useLocalize'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import useLocalize from '@hooks/useLocalize'; -import type {OnyxEntry} from 'react-native-onyx'; -import {WalletTerms, UserWallet} from '@src/types/onyx'; +import {UserWallet, WalletTerms} from '@src/types/onyx'; type ActivateStepOnyxProps = { /** Information about the user accepting the terms for payments */ @@ -20,10 +20,7 @@ type ActivateStepProps = ActivateStepOnyxProps & { userWallet: OnyxEntry; }; -function ActivateStep({ - userWallet, - walletTerms -}: ActivateStepProps) { +function ActivateStep({userWallet, walletTerms}: ActivateStepProps) { const {translate} = useLocalize(); const isActivatedWallet = userWallet?.tierName && [CONST.WALLET.TIER_NAME.GOLD, CONST.WALLET.TIER_NAME.PLATINUM].some((name) => name === userWallet.tierName); @@ -59,4 +56,4 @@ export default withOnyx({ walletTerms: { key: ONYXKEYS.WALLET_TERMS, }, -})(ActivateStep); \ No newline at end of file +})(ActivateStep); diff --git a/src/pages/EnablePayments/FailedKYC.tsx b/src/pages/EnablePayments/FailedKYC.tsx index 25672772c216..6b393229d62f 100644 --- a/src/pages/EnablePayments/FailedKYC.tsx +++ b/src/pages/EnablePayments/FailedKYC.tsx @@ -2,9 +2,9 @@ import React from 'react'; import {View} from 'react-native'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import useLocalize from '@hooks/useLocalize'; function FailedKYC() { const {translate} = useLocalize(); diff --git a/src/pages/EnablePayments/OnfidoPrivacy.js b/src/pages/EnablePayments/OnfidoPrivacy.tsx similarity index 74% rename from src/pages/EnablePayments/OnfidoPrivacy.js rename to src/pages/EnablePayments/OnfidoPrivacy.tsx index 77b884fb2934..d8e9f616b8a7 100644 --- a/src/pages/EnablePayments/OnfidoPrivacy.js +++ b/src/pages/EnablePayments/OnfidoPrivacy.tsx @@ -1,7 +1,8 @@ import lodashGet from 'lodash/get'; import React, {useRef} from 'react'; -import {View} from 'react-native'; +import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import _ from 'underscore'; import FixedFooter from '@components/FixedFooter'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; @@ -9,43 +10,41 @@ import FormScrollView from '@components/FormScrollView'; import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; -import walletOnfidoDataPropTypes from './walletOnfidoDataPropTypes'; +import {WalletOnfido} from '@src/types/onyx'; -const propTypes = { - /** Stores various information used to build the UI and call any APIs */ - walletOnfidoData: walletOnfidoDataPropTypes, - - ...withLocalizePropTypes, +const DEFAULT_WALLET_ONFIDO_DATA = { + applicantID: '', + sdkToken: '', + loading: false, + errors: {}, + fixableErrors: [], + hasAcceptedPrivacyPolicy: false, }; -const defaultProps = { - walletOnfidoData: { - applicantID: '', - sdkToken: '', - loading: false, - errors: {}, - fixableErrors: [], - hasAcceptedPrivacyPolicy: false, - }, +type OnfidoPrivacyOnyxProps = { + /** Stores various information used to build the UI and call any APIs */ + walletOnfidoData: OnyxEntry; }; -function OnfidoPrivacy({walletOnfidoData, translate, form}) { +type OnfidoPrivacyProps = OnfidoPrivacyOnyxProps & {}; + +function OnfidoPrivacy({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoPrivacyProps) { + const {translate} = useLocalize(); const styles = useThemeStyles(); - const {isLoading = false, hasAcceptedPrivacyPolicy} = walletOnfidoData; + const {isLoading = false, hasAcceptedPrivacyPolicy} = walletOnfidoData ?? {}; - const formRef = useRef(null); + const formRef = useRef(null); const openOnfidoFlow = () => { BankAccounts.openOnfidoFlow(); }; - let onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData) || ''; + let onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData ?? {}) || ''; const onfidoFixableErrors = lodashGet(walletOnfidoData, 'fixableErrors', []); onfidoError += !_.isEmpty(onfidoFixableErrors) ? `\n${onfidoFixableErrors.join('\n')}` : ''; @@ -70,7 +69,7 @@ function OnfidoPrivacy({walletOnfidoData, translate, form}) { isAlertVisible={Boolean(onfidoError)} onSubmit={openOnfidoFlow} onFixTheErrorsLinkPressed={() => { - form.scrollTo({y: 0, animated: true}); + formRef.current?.scrollTo({y: 0, animated: true}); }} message={onfidoError} isLoading={isLoading} @@ -85,18 +84,13 @@ function OnfidoPrivacy({walletOnfidoData, translate, form}) { ); } -OnfidoPrivacy.propTypes = propTypes; -OnfidoPrivacy.defaultProps = defaultProps; OnfidoPrivacy.displayName = 'OnfidoPrivacy'; -export default compose( - withLocalize, - withOnyx({ - walletOnfidoData: { - key: ONYXKEYS.WALLET_ONFIDO, +export default withOnyx({ + walletOnfidoData: { + key: ONYXKEYS.WALLET_ONFIDO, - // Let's get a new onfido token each time the user hits this flow (as it should only be once) - initWithStoredValues: false, - }, - }), -)(OnfidoPrivacy); + // Let's get a new onfido token each time the user hits this flow (as it should only be once) + initWithStoredValues: false, + }, +})(OnfidoPrivacy); diff --git a/src/pages/EnablePayments/OnfidoStep.js b/src/pages/EnablePayments/OnfidoStep.tsx similarity index 69% rename from src/pages/EnablePayments/OnfidoStep.js rename to src/pages/EnablePayments/OnfidoStep.tsx index 8b40c88f62fb..5e36f2f302a6 100644 --- a/src/pages/EnablePayments/OnfidoStep.js +++ b/src/pages/EnablePayments/OnfidoStep.tsx @@ -1,7 +1,9 @@ import React, {useCallback} from 'react'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +// @ts-expect-error TODO: Remove this once Onfido (https://github.com/Expensify/App/issues/25136) is migrated to TypeScript. import Onfido from '@components/Onfido'; import useLocalize from '@hooks/useLocalize'; import Growl from '@libs/Growl'; @@ -11,25 +13,25 @@ import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import {WalletOnfido} from '@src/types/onyx'; import OnfidoPrivacy from './OnfidoPrivacy'; -import walletOnfidoDataPropTypes from './walletOnfidoDataPropTypes'; -const propTypes = { - /** Stores various information used to build the UI and call any APIs */ - walletOnfidoData: walletOnfidoDataPropTypes, +const DEFAULT_WALLET_ONFIDO_DATA = { + loading: false, + hasAcceptedPrivacyPolicy: false, }; -const defaultProps = { - walletOnfidoData: { - loading: false, - hasAcceptedPrivacyPolicy: false, - }, +type OnfidoStepOnyxProps = { + /** Stores various information used to build the UI and call any APIs */ + walletOnfidoData: OnyxEntry; }; -function OnfidoStep({walletOnfidoData}) { +type OnfidoStepProps = OnfidoStepOnyxProps; + +function OnfidoStep({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoStepProps) { const {translate} = useLocalize(); - const shouldShowOnfido = walletOnfidoData.hasAcceptedPrivacyPolicy && !walletOnfidoData.isLoading && !walletOnfidoData.error && walletOnfidoData.sdkToken; + const shouldShowOnfido = walletOnfidoData?.hasAcceptedPrivacyPolicy && !walletOnfidoData.isLoading && !walletOnfidoData.errors && walletOnfidoData.sdkToken; const goBack = useCallback(() => { Navigation.goBack(ROUTES.HOME); @@ -44,15 +46,16 @@ function OnfidoStep({walletOnfidoData}) { }, [translate]); const verifyIdentity = useCallback( + // @ts-expect-error TODO: Remove this once Onfido (https://github.com/Expensify/App/issues/25136) is migrated to TypeScript. (data) => { BankAccounts.verifyIdentity({ onfidoData: JSON.stringify({ ...data, - applicantID: walletOnfidoData.applicantID, + applicantID: walletOnfidoData?.applicantID, }), }); }, - [walletOnfidoData.applicantID], + [walletOnfidoData?.applicantID], ); return ( @@ -70,18 +73,16 @@ function OnfidoStep({walletOnfidoData}) { onSuccess={verifyIdentity} /> ) : ( - + )} ); } -OnfidoStep.propTypes = propTypes; -OnfidoStep.defaultProps = defaultProps; OnfidoStep.displayName = 'OnfidoStep'; -export default withOnyx({ +export default withOnyx({ walletOnfidoData: { key: ONYXKEYS.WALLET_ONFIDO, diff --git a/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx index 1c9d37bb30e9..b45b8b657a75 100644 --- a/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx +++ b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx @@ -1,16 +1,16 @@ import React from 'react'; import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import CONST from '@src/CONST'; -import type {OnyxEntry} from 'react-native-onyx'; import {UserWallet} from '@src/types/onyx'; type ShortTermsFormProps = { - /** The user's wallet */ + /** The user's wallet */ userWallet: OnyxEntry; }; @@ -22,7 +22,9 @@ function ShortTermsForm(props: ShortTermsFormProps) { {translate('termsStep.shortTermsForm.expensifyPaymentsAccount', { walletProgram: - props.userWallet?.walletProgramID === CONST.WALLET.MTL_WALLET_PROGRAM_ID ? CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS : CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK, + props.userWallet?.walletProgramID === CONST.WALLET.MTL_WALLET_PROGRAM_ID + ? CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS + : CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK, })} diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index a03f3607d56e..cef54ba463e6 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -1,25 +1,25 @@ import React, {useEffect, useState} from 'react'; import {ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; +import {UserWallet, WalletTerms} from '@src/types/onyx'; import LongTermsForm from './TermsPage/LongTermsForm'; import ShortTermsForm from './TermsPage/ShortTermsForm'; -import useLocalize from '@hooks/useLocalize'; -import type {OnyxEntry} from 'react-native-onyx'; -import {WalletTerms, UserWallet} from '@src/types/onyx'; type TermsStepOnyxProps = { /** Comes from Onyx. Information about the terms for the wallet */ walletTerms: OnyxEntry; -} +}; type TermsStepProps = TermsStepOnyxProps & { /** The user's wallet */ @@ -33,7 +33,7 @@ function TermsStep(props: TermsStepProps) { const [error, setError] = useState(false); const {translate} = useLocalize(); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms??{}) || ''; + const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) || ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); @@ -99,7 +99,7 @@ function TermsStep(props: TermsStepProps) { setError(false); BankAccounts.acceptWalletTerms({ hasAcceptedTerms: hasAcceptedDisclosure && hasAcceptedPrivacyPolicyAndWalletAgreement, - reportID: props.walletTerms?.chatReportID??'', + reportID: props.walletTerms?.chatReportID ?? '', }); }} message={errorMessage} From 0feb8c4e71dad1c3cd3d11f7a2c7670387bd09c7 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Wed, 31 Jan 2024 04:23:28 +0530 Subject: [PATCH 007/202] TS-migration: EnablePaymentsPage Page --- ...PaymentsPage.js => EnablePaymentsPage.tsx} | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) rename src/pages/EnablePayments/{EnablePaymentsPage.js => EnablePaymentsPage.tsx} (78%) diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.tsx similarity index 78% rename from src/pages/EnablePayments/EnablePaymentsPage.js rename to src/pages/EnablePayments/EnablePaymentsPage.tsx index 257eab1d38d3..6d2defc82df0 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.tsx @@ -1,6 +1,6 @@ import React, {useEffect} from 'react'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -11,28 +11,27 @@ import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {UserWallet} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; import ActivateStep from './ActivateStep'; import AdditionalDetailsStep from './AdditionalDetailsStep'; import FailedKYC from './FailedKYC'; // Steps import OnfidoStep from './OnfidoStep'; import TermsStep from './TermsStep'; -import userWalletPropTypes from './userWalletPropTypes'; -const propTypes = { +type EnablePaymentsPageOnyxProps = { /** The user's wallet */ - userWallet: userWalletPropTypes, + userWallet: OnyxEntry; }; -const defaultProps = { - userWallet: {}, -}; +type EnablePaymentsPageProps = EnablePaymentsPageOnyxProps & {}; -function EnablePaymentsPage({userWallet}) { +function EnablePaymentsPage({userWallet}: EnablePaymentsPageProps) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const {isPendingOnfidoResult, hasFailedOnfido} = userWallet; + const {isPendingOnfidoResult, hasFailedOnfido} = userWallet ?? {}; useEffect(() => { if (isOffline) { @@ -47,18 +46,18 @@ function EnablePaymentsPage({userWallet}) { Wallet.openEnablePaymentsPage(); }, [isOffline, isPendingOnfidoResult, hasFailedOnfido]); - if (_.isEmpty(userWallet)) { + if (isEmptyObject(userWallet)) { return ; } return ( {() => { - if (userWallet.errorCode === CONST.WALLET.ERROR.KYC) { + if (userWallet?.errorCode === CONST.WALLET.ERROR.KYC) { return ( <> ({ userWallet: { key: ONYXKEYS.USER_WALLET, From 9bd67d67aee253e4614ef64854169229282f806d Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 5 Feb 2024 16:14:46 +0530 Subject: [PATCH 008/202] merge main, fix lint --- src/pages/EnablePayments/ActivateStep.tsx | 2 +- .../EnablePayments/EnablePaymentsPage.tsx | 3 ++- src/pages/EnablePayments/OnfidoPrivacy.tsx | 23 +++++++++++-------- src/pages/EnablePayments/OnfidoStep.tsx | 2 +- .../TermsPage/LongTermsForm.tsx | 1 - .../TermsPage/ShortTermsForm.tsx | 2 +- src/pages/EnablePayments/TermsStep.tsx | 2 +- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/pages/EnablePayments/ActivateStep.tsx b/src/pages/EnablePayments/ActivateStep.tsx index 0dbb98e53a5f..e0bea7488140 100644 --- a/src/pages/EnablePayments/ActivateStep.tsx +++ b/src/pages/EnablePayments/ActivateStep.tsx @@ -8,7 +8,7 @@ import useLocalize from '@hooks/useLocalize'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {UserWallet, WalletTerms} from '@src/types/onyx'; +import type {UserWallet, WalletTerms} from '@src/types/onyx'; type ActivateStepOnyxProps = { /** Information about the user accepting the terms for payments */ diff --git a/src/pages/EnablePayments/EnablePaymentsPage.tsx b/src/pages/EnablePayments/EnablePaymentsPage.tsx index 6d2defc82df0..1384875fe031 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.tsx +++ b/src/pages/EnablePayments/EnablePaymentsPage.tsx @@ -25,7 +25,7 @@ type EnablePaymentsPageOnyxProps = { userWallet: OnyxEntry; }; -type EnablePaymentsPageProps = EnablePaymentsPageOnyxProps & {}; +type EnablePaymentsPageProps = EnablePaymentsPageOnyxProps; function EnablePaymentsPage({userWallet}: EnablePaymentsPageProps) { const {translate} = useLocalize(); @@ -38,6 +38,7 @@ function EnablePaymentsPage({userWallet}: EnablePaymentsPageProps) { return; } + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing if (isPendingOnfidoResult || hasFailedOnfido) { Navigation.navigate(ROUTES.SETTINGS_WALLET, CONST.NAVIGATION.TYPE.UP); return; diff --git a/src/pages/EnablePayments/OnfidoPrivacy.tsx b/src/pages/EnablePayments/OnfidoPrivacy.tsx index d8e9f616b8a7..80fa08c009ca 100644 --- a/src/pages/EnablePayments/OnfidoPrivacy.tsx +++ b/src/pages/EnablePayments/OnfidoPrivacy.tsx @@ -1,9 +1,8 @@ -import lodashGet from 'lodash/get'; import React, {useRef} from 'react'; -import {ScrollView, View} from 'react-native'; +import {View} from 'react-native'; +import type {ScrollView} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; -import _ from 'underscore'; import FixedFooter from '@components/FixedFooter'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import FormScrollView from '@components/FormScrollView'; @@ -15,7 +14,8 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; -import {WalletOnfido} from '@src/types/onyx'; +import type {WalletOnfido} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; const DEFAULT_WALLET_ONFIDO_DATA = { applicantID: '', @@ -31,22 +31,25 @@ type OnfidoPrivacyOnyxProps = { walletOnfidoData: OnyxEntry; }; -type OnfidoPrivacyProps = OnfidoPrivacyOnyxProps & {}; +type OnfidoPrivacyProps = OnfidoPrivacyOnyxProps; function OnfidoPrivacy({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoPrivacyProps) { const {translate} = useLocalize(); - const styles = useThemeStyles(); - const {isLoading = false, hasAcceptedPrivacyPolicy} = walletOnfidoData ?? {}; - const formRef = useRef(null); + const styles = useThemeStyles(); + if (!walletOnfidoData) { + return; + } + const {isLoading = false, hasAcceptedPrivacyPolicy} = walletOnfidoData; const openOnfidoFlow = () => { BankAccounts.openOnfidoFlow(); }; let onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData ?? {}) || ''; - const onfidoFixableErrors = lodashGet(walletOnfidoData, 'fixableErrors', []); - onfidoError += !_.isEmpty(onfidoFixableErrors) ? `\n${onfidoFixableErrors.join('\n')}` : ''; + + const onfidoFixableErrors = walletOnfidoData?.fixableErrors ?? []; + onfidoError += !isEmptyObject(onfidoFixableErrors) ? `\n${onfidoFixableErrors.join('\n')}` : ''; return ( diff --git a/src/pages/EnablePayments/OnfidoStep.tsx b/src/pages/EnablePayments/OnfidoStep.tsx index 5e36f2f302a6..04cadb24fecf 100644 --- a/src/pages/EnablePayments/OnfidoStep.tsx +++ b/src/pages/EnablePayments/OnfidoStep.tsx @@ -13,7 +13,7 @@ import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {WalletOnfido} from '@src/types/onyx'; +import type {WalletOnfido} from '@src/types/onyx'; import OnfidoPrivacy from './OnfidoPrivacy'; const DEFAULT_WALLET_ONFIDO_DATA = { diff --git a/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx b/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx index ec89856642d9..81d18c5dfc44 100644 --- a/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx +++ b/src/pages/EnablePayments/TermsPage/LongTermsForm.tsx @@ -1,6 +1,5 @@ import React from 'react'; import {View} from 'react-native'; -import _ from 'underscore'; import CollapsibleSection from '@components/CollapsibleSection'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; diff --git a/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx index b45b8b657a75..f4db904c07f3 100644 --- a/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx +++ b/src/pages/EnablePayments/TermsPage/ShortTermsForm.tsx @@ -7,7 +7,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import CONST from '@src/CONST'; -import {UserWallet} from '@src/types/onyx'; +import type {UserWallet} from '@src/types/onyx'; type ShortTermsFormProps = { /** The user's wallet */ diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index cef54ba463e6..fe463f88792d 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -12,7 +12,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; -import {UserWallet, WalletTerms} from '@src/types/onyx'; +import type {UserWallet, WalletTerms} from '@src/types/onyx'; import LongTermsForm from './TermsPage/LongTermsForm'; import ShortTermsForm from './TermsPage/ShortTermsForm'; From c0f4f030db1ff9e61da920b9c4393a82cf42a59b Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 5 Feb 2024 19:22:28 +0530 Subject: [PATCH 009/202] TS-migration: IdologyQuestions Page --- src/ONYXKEYS.ts | 4 + ...ologyQuestions.js => IdologyQuestions.tsx} | 81 +++++++------------ src/types/onyx/Form.ts | 5 ++ src/types/onyx/index.ts | 2 + 4 files changed, 39 insertions(+), 53 deletions(-) rename src/pages/EnablePayments/{IdologyQuestions.js => IdologyQuestions.tsx} (69%) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 7328fb2543ad..3046b5a16bdd 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -367,6 +367,8 @@ const ONYXKEYS = { REIMBURSEMENT_ACCOUNT_FORM_DRAFT: 'reimbursementAccountDraft', PERSONAL_BANK_ACCOUNT: 'personalBankAccountForm', PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', + IDOLOGY_QUESTIONS_FORM: 'idologyQuestions', + IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsDraft', }, } as const; @@ -556,6 +558,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount; [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_DRAFT]: OnyxTypes.PersonalBankAccount; + [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM]: OnyxTypes.IdologyQuestionsForm; + [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM_DRAFT]: OnyxTypes.IdologyQuestionsForm; }; type OnyxKeyValue = OnyxEntry; diff --git a/src/pages/EnablePayments/IdologyQuestions.js b/src/pages/EnablePayments/IdologyQuestions.tsx similarity index 69% rename from src/pages/EnablePayments/IdologyQuestions.js rename to src/pages/EnablePayments/IdologyQuestions.tsx index a0c202b0bbbc..4a5ef72019c0 100644 --- a/src/pages/EnablePayments/IdologyQuestions.js +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -1,10 +1,10 @@ -import PropTypes from 'prop-types'; import React, {useState} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {WalletAdditionalQuestionDetails} from 'src/types/onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; +import type {OnyxFormValuesFields} from '@components/Form/types'; +import type {Choice} from '@components/RadioButtons'; import SingleChoiceQuestion from '@components/SingleChoiceQuestion'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; @@ -12,53 +12,36 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as BankAccounts from '@userActions/BankAccounts'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Errors} from '@src/types/onyx/OnyxCommon'; const MAX_SKIP = 1; const SKIP_QUESTION_TEXT = 'Skip Question'; -const propTypes = { +type IdologyQuestionsProps = { /** Questions returned by Idology */ /** example: [{"answer":["1251","6253","113","None of the above","Skip Question"],"prompt":"Which number goes with your address on MASONIC AVE?","type":"street.number.b"}, ...] */ - questions: PropTypes.arrayOf( - PropTypes.shape({ - prompt: PropTypes.string, - type: PropTypes.string, - answer: PropTypes.arrayOf(PropTypes.string), - }), - ), + questions: WalletAdditionalQuestionDetails[]; /** ID from Idology, referencing those questions */ - idNumber: PropTypes.string, - - walletAdditionalDetails: PropTypes.shape({ - /** Are we waiting for a response? */ - isLoading: PropTypes.bool, - - /** Any additional error message to show */ - errors: PropTypes.objectOf(PropTypes.string), - - /** What error do we need to handle */ - errorCode: PropTypes.string, - }), + idNumber: string; }; -const defaultProps = { - questions: [], - idNumber: '', - walletAdditionalDetails: {}, +type Answer = { + question: string; + answer: string; }; -function IdologyQuestions({questions, idNumber}) { +function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0); const [shouldHideSkipAnswer, setShouldHideSkipAnswer] = useState(false); - const [userAnswers, setUserAnswers] = useState([]); + const [userAnswers, setUserAnswers] = useState([]); const currentQuestion = questions[currentQuestionIndex] || {}; - const possibleAnswers = _.filter( - _.map(currentQuestion.answer, (answer) => { + const possibleAnswers: Choice[] = currentQuestion.answer + .map((answer) => { if (shouldHideSkipAnswer && answer === SKIP_QUESTION_TEXT) { return; } @@ -67,15 +50,11 @@ function IdologyQuestions({questions, idNumber}) { label: answer, value: answer, }; - }), - ); + }) + .filter((answer): answer is Choice => answer !== undefined); - /** - * Put question answer in the state. - * @param {String} answer - */ - const chooseAnswer = (answer) => { - const tempAnswers = _.map(userAnswers, _.clone); + const chooseAnswer = (answer: string) => { + const tempAnswers: Answer[] = userAnswers.map((userAnswer) => ({...userAnswer})); tempAnswers[currentQuestionIndex] = {question: currentQuestion.type, answer}; @@ -90,11 +69,11 @@ function IdologyQuestions({questions, idNumber}) { return; } // Get the number of questions that were skipped by the user. - const skippedQuestionsCount = _.filter(userAnswers, (answer) => answer.answer === SKIP_QUESTION_TEXT).length; + const skippedQuestionsCount = userAnswers.filter((answer) => answer.answer === SKIP_QUESTION_TEXT).length; // We have enough answers, let's call expectID KBA to verify them if (userAnswers.length - skippedQuestionsCount >= questions.length - MAX_SKIP) { - const tempAnswers = _.map(userAnswers, _.clone); + const tempAnswers: Answer[] = userAnswers.map((answer) => ({...answer})); // Auto skip any remaining questions if (tempAnswers.length < questions.length) { @@ -112,8 +91,8 @@ function IdologyQuestions({questions, idNumber}) { } }; - const validate = (values) => { - const errors = {}; + const validate = (values: OnyxFormValuesFields) => { + const errors: Errors = {}; if (!values.answer) { errors.answer = translate('additionalDetailsStep.selectAnswer'); } @@ -132,7 +111,7 @@ function IdologyQuestions({questions, idNumber}) { @@ -155,11 +136,5 @@ function IdologyQuestions({questions, idNumber}) { } IdologyQuestions.displayName = 'IdologyQuestions'; -IdologyQuestions.propTypes = propTypes; -IdologyQuestions.defaultProps = defaultProps; - -export default withOnyx({ - walletAdditionalDetails: { - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, - }, -})(IdologyQuestions); + +export default IdologyQuestions; diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts index 48f386afcbb0..79190aa3e6f6 100644 --- a/src/types/onyx/Form.ts +++ b/src/types/onyx/Form.ts @@ -68,6 +68,10 @@ type CloseAccountForm = Form<{ phoneOrEmail: string; }>; +type IdologyQuestionsForm = Form<{ + answer: string; +}>; + export default Form; export type { @@ -84,4 +88,5 @@ export type { WorkspaceSettingsForm, ReportFieldEditForm, CloseAccountForm, + IdologyQuestionsForm, }; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index d0ac2ce395fa..13c305abe384 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -14,6 +14,7 @@ import type { CloseAccountForm, DateOfBirthForm, DisplayNameForm, + IdologyQuestionsForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, @@ -165,4 +166,5 @@ export type { IntroSchoolPrincipalForm, PrivateNotesForm, ReportFieldEditForm, + IdologyQuestionsForm, }; From 61d24b89c0132dd7ce1049a62b0e88e9814b3c5f Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 5 Feb 2024 21:29:42 +0530 Subject: [PATCH 010/202] TS-migration: AdditionalDetailsStep Page --- src/ONYXKEYS.ts | 4 + .../withCurrentUserPersonalDetails.tsx | 2 +- src/libs/actions/PersonalDetails.ts | 3 +- ...tailsStep.js => AdditionalDetailsStep.tsx} | 120 ++++++------------ src/types/onyx/Form.ts | 13 ++ src/types/onyx/index.ts | 2 + 6 files changed, 64 insertions(+), 80 deletions(-) rename src/pages/EnablePayments/{AdditionalDetailsStep.js => AdditionalDetailsStep.tsx} (73%) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 3046b5a16bdd..2e4e5b564616 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -369,6 +369,8 @@ const ONYXKEYS = { PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', IDOLOGY_QUESTIONS_FORM: 'idologyQuestions', IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsDraft', + ADDITIONAL_DETAILS_FORM: 'additionalDetailStep', + ADDITIONAL_DETAILS_FORM_DRAFT: 'additionalDetailStepDraft', }, } as const; @@ -560,6 +562,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_DRAFT]: OnyxTypes.PersonalBankAccount; [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM]: OnyxTypes.IdologyQuestionsForm; [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM_DRAFT]: OnyxTypes.IdologyQuestionsForm; + [ONYXKEYS.FORMS.ADDITIONAL_DETAILS_FORM]: OnyxTypes.AdditionalDetailStepForm; + [ONYXKEYS.FORMS.ADDITIONAL_DETAILS_FORM_DRAFT]: OnyxTypes.AdditionalDetailStepForm; }; type OnyxKeyValue = OnyxEntry; diff --git a/src/components/withCurrentUserPersonalDetails.tsx b/src/components/withCurrentUserPersonalDetails.tsx index 9406c8634c1b..75bdb03ea6d8 100644 --- a/src/components/withCurrentUserPersonalDetails.tsx +++ b/src/components/withCurrentUserPersonalDetails.tsx @@ -64,4 +64,4 @@ export default function ; }; -const defaultProps = { - walletAdditionalDetails: { - errorFields: {}, - isLoading: false, - errors: {}, - questions: [], - idNumber: '', - errorCode: '', - }, - ...withCurrentUserPersonalDetailsDefaultProps, -}; +type AdditionalDetailsStepProps = AdditionalDetailsStepOnyxProps & WithCurrentUserPersonalDetailsProps; const fieldNameTranslationKeys = { legalFirstName: 'additionalDetailsStep.legalFirstNameLabel', @@ -77,20 +50,17 @@ const fieldNameTranslationKeys = { dob: 'common.dob', ssn: 'common.ssnLast4', ssnFull9: 'common.ssnFull9', -}; +} as const; -function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserPersonalDetails}) { +function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIONAL_DETAILS, currentUserPersonalDetails}: AdditionalDetailsStepProps) { + const {translate} = useLocalize(); const styles = useThemeStyles(); const currentDate = new Date(); const minDate = subYears(currentDate, CONST.DATE_BIRTH.MAX_AGE); const maxDate = subYears(currentDate, CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); - const shouldAskForFullSSN = walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN; + const shouldAskForFullSSN = walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN; - /** - * @param {Object} values The values object is passed from FormProvider and contains info for each form element that has an inputID - * @returns {Object} - */ - const validate = (values) => { + const validate = (values: OnyxFormValuesFields) => { const requiredFields = ['legalFirstName', 'legalLastName', 'addressStreet', 'addressCity', 'addressZipCode', 'phoneNumber', 'dob', 'ssn', 'addressState']; const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); @@ -116,7 +86,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP // walletAdditionalDetails stores errors returned by the server. If the server returns an SSN error // then the user needs to provide the full 9 digit SSN. - if (walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN) { + if (walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN) { if (values.ssn && !ValidationUtils.isValidSSNFullNine(values.ssn)) { errors.ssn = 'additionalDetailsStep.ssnFull9Error'; } @@ -127,26 +97,23 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP return errors; }; - /** - * @param {Object} values The values object is passed from FormProvider and contains info for each form element that has an inputID - */ - const activateWallet = (values) => { + const activateWallet = (values: OnyxFormValuesFields) => { const personalDetails = { - phoneNumber: parsePhoneNumber(values.phoneNumber, {regionCode: CONST.COUNTRY.US}).number.significant || '', - legalFirstName: values.legalFirstName || '', - legalLastName: values.legalLastName || '', - addressStreet: values.addressStreet || '', - addressCity: values.addressCity || '', - addressState: values.addressState || '', - addressZip: values.addressZipCode || '', - dob: values.dob || '', - ssn: values.ssn || '', + phoneNumber: (values.phoneNumber && parsePhoneNumber(values.phoneNumber, {regionCode: CONST.COUNTRY.US}).number?.significant) ?? '', + legalFirstName: values.legalFirstName ?? '', + legalLastName: values.legalLastName ?? '', + addressStreet: values.addressStreet ?? '', + addressCity: values.addressCity ?? '', + addressState: values.addressState ?? '', + addressZip: values.addressZipCode ?? '', + dob: values.dob ?? '', + ssn: values.ssn ?? '', }; // Attempt to set the personal details Wallet.updatePersonalDetails(personalDetails); }; - if (!_.isEmpty(walletAdditionalDetails.questions)) { + if (walletAdditionalDetails?.questions && walletAdditionalDetails.questions.length > 0) { return ( Wallet.setAdditionalDetailsQuestions(null)} + onBackButtonPress={() => Wallet.setAdditionalDetailsQuestions([], walletAdditionalDetails?.idNumber ?? '')} /> ); @@ -180,7 +147,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP ({ walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, }, - }), -)(AdditionalDetailsStep); + })(AdditionalDetailsStep), +); diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts index 79190aa3e6f6..646950dcb986 100644 --- a/src/types/onyx/Form.ts +++ b/src/types/onyx/Form.ts @@ -72,6 +72,18 @@ type IdologyQuestionsForm = Form<{ answer: string; }>; +type AdditionalDetailStepForm = Form<{ + legalFirstName: string; + legalLastName: string; + addressStreet: string; + addressCity: string; + addressZipCode: string; + phoneNumber: string; + dob: string; + ssn: string; + addressState: string; +}>; + export default Form; export type { @@ -89,4 +101,5 @@ export type { ReportFieldEditForm, CloseAccountForm, IdologyQuestionsForm, + AdditionalDetailStepForm, }; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 13c305abe384..ff6c782a37e1 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, + AdditionalDetailStepForm, CloseAccountForm, DateOfBirthForm, DisplayNameForm, @@ -167,4 +168,5 @@ export type { PrivateNotesForm, ReportFieldEditForm, IdologyQuestionsForm, + AdditionalDetailStepForm, }; From 21e3ec0ad48fc8a99f30c75c27fc809be6a5f1bf Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 6 Feb 2024 23:51:15 +0700 Subject: [PATCH 011/202] fix: app crashes when changing from auditor to employee --- src/pages/home/ReportScreen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index bfe27910c943..2e2d7251de6f 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -418,7 +418,7 @@ function ReportScreen({ !onyxReportID && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && (report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED || (!report.statusNum && !prevReport.parentReportID && prevReport.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM))) || - ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport)) && _.isEmpty(report)) + ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport) || ReportUtils.isPolicyExpenseChat(prevReport)) && _.isEmpty(report)) ) { Navigation.dismissModal(); if (Navigation.getTopmostReportId() === prevOnyxReportID) { @@ -643,7 +643,7 @@ export default compose( key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : 0}`, selector: (parentReportActions, props) => { const parentReportActionID = lodashGet(props, 'report.parentReportActionID'); - if (!parentReportActionID) { + if (!parentReportActionID || !parentReportActions) { return {}; } return lodashGet(parentReportActions, parentReportActionID); From 5f89ad6cf8fdcc0a4a5522a35588a36c40670f70 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Thu, 8 Feb 2024 17:16:50 +0530 Subject: [PATCH 012/202] merge main, lint fixed and prettified code --- src/libs/PersonalDetailsUtils.ts | 2 +- src/pages/EnablePayments/OnfidoPrivacy.tsx | 2 +- src/pages/EnablePayments/TermsStep.tsx | 2 +- src/types/onyx/Form.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index aa9a7f79e582..69b0f386a76c 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -1,11 +1,11 @@ import Str from 'expensify-common/lib/str'; import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; +import type {CurrentUserPersonalDetails} from '@components/withCurrentUserPersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {CurrentUserPersonalDetails} from '@components/withCurrentUserPersonalDetails'; import * as LocalePhoneNumber from './LocalePhoneNumber'; import * as Localize from './Localize'; import * as UserUtils from './UserUtils'; diff --git a/src/pages/EnablePayments/OnfidoPrivacy.tsx b/src/pages/EnablePayments/OnfidoPrivacy.tsx index 80fa08c009ca..5d8cdc751e87 100644 --- a/src/pages/EnablePayments/OnfidoPrivacy.tsx +++ b/src/pages/EnablePayments/OnfidoPrivacy.tsx @@ -46,7 +46,7 @@ function OnfidoPrivacy({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoPr BankAccounts.openOnfidoFlow(); }; - let onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData ?? {}) || ''; + let onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData ?? {}) ?? ''; const onfidoFixableErrors = walletOnfidoData?.fixableErrors ?? []; onfidoError += !isEmptyObject(onfidoFixableErrors) ? `\n${onfidoFixableErrors.join('\n')}` : ''; diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index fe463f88792d..4836feae9f9b 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -33,7 +33,7 @@ function TermsStep(props: TermsStepProps) { const [error, setError] = useState(false); const {translate} = useLocalize(); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) || ''; + const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) ?? ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts index bb78487892bf..7043449ae6cf 100644 --- a/src/types/onyx/Form.ts +++ b/src/types/onyx/Form.ts @@ -82,7 +82,7 @@ type AdditionalDetailStepForm = Form<{ dob: string; ssn: string; addressState: string; -}> +}>; type RoomNameForm = Form<{ roomName: string; From ed7c4d21e101a1aeede28c6eaeb20e81101938d7 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Fri, 9 Feb 2024 20:05:31 +0530 Subject: [PATCH 013/202] fix: lint --- src/pages/EnablePayments/OnfidoPrivacy.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EnablePayments/OnfidoPrivacy.tsx b/src/pages/EnablePayments/OnfidoPrivacy.tsx index 8618499397dc..03f8df3ad82a 100644 --- a/src/pages/EnablePayments/OnfidoPrivacy.tsx +++ b/src/pages/EnablePayments/OnfidoPrivacy.tsx @@ -46,8 +46,8 @@ function OnfidoPrivacy({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoPr BankAccounts.openOnfidoFlow(); }; - const onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData) || ''; - const onfidoFixableErrors = walletOnfidoData?.fixableErrors??[]; + const onfidoError = ErrorUtils.getLatestErrorMessage(walletOnfidoData) ?? ''; + const onfidoFixableErrors = walletOnfidoData?.fixableErrors ?? []; if (Array.isArray(onfidoError)) { onfidoError[0] += !isEmptyObject(onfidoFixableErrors) ? `\n${onfidoFixableErrors.join('\n')}` : ''; } From e6df088475612cd7578a3c3036bd21036a9701ff Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Sat, 10 Feb 2024 13:11:13 +0530 Subject: [PATCH 014/202] updated key from ADDITIONAL_DETAILS_FORM to WALLET_ADDITIONAL_DETAILS --- src/ONYXKEYS.ts | 8 ++++---- src/libs/actions/Wallet.ts | 9 +++++---- src/pages/EnablePayments/AdditionalDetailsStep.tsx | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 90a6860fb1de..b14f0985bfed 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -369,8 +369,8 @@ const ONYXKEYS = { PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', IDOLOGY_QUESTIONS_FORM: 'idologyQuestions', IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsDraft', - ADDITIONAL_DETAILS_FORM: 'additionalDetailStep', - ADDITIONAL_DETAILS_FORM_DRAFT: 'additionalDetailStepDraft', + WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetailsForm', + WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsFormDraft', }, } as const; @@ -562,8 +562,8 @@ type OnyxValues = { [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_DRAFT]: OnyxTypes.PersonalBankAccount; [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM]: OnyxTypes.IdologyQuestionsForm; [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM_DRAFT]: OnyxTypes.IdologyQuestionsForm; - [ONYXKEYS.FORMS.ADDITIONAL_DETAILS_FORM]: OnyxTypes.AdditionalDetailStepForm; - [ONYXKEYS.FORMS.ADDITIONAL_DETAILS_FORM_DRAFT]: OnyxTypes.AdditionalDetailStepForm; + [ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS]: OnyxTypes.AdditionalDetailStepForm; + [ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS_DRAFT]: OnyxTypes.AdditionalDetailStepForm; }; type OnyxKeyValue = OnyxEntry; diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index b03b5e8f6d3d..4d0ba7a67fd1 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -75,11 +75,12 @@ function setKYCWallSource(source?: ValueOf, chatRe /** * Validates a user's provided details against a series of checks */ + function updatePersonalDetails(personalDetails: UpdatePersonalDetailsForWalletParams) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: true, errors: null, @@ -91,7 +92,7 @@ function updatePersonalDetails(personalDetails: UpdatePersonalDetailsForWalletPa const finallyData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: false, }, @@ -232,7 +233,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: true, }, @@ -242,7 +243,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const finallyData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: false, }, diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index ad802a74c050..c9b557a197e8 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -60,7 +60,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO const maxDate = subYears(currentDate, CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); const shouldAskForFullSSN = walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN; - const validate = (values: OnyxFormValuesFields) => { + const validate = (values: OnyxFormValuesFields) => { const requiredFields = ['legalFirstName', 'legalLastName', 'addressStreet', 'addressCity', 'addressZipCode', 'phoneNumber', 'dob', 'ssn', 'addressState']; const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); @@ -97,7 +97,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO return errors; }; - const activateWallet = (values: OnyxFormValuesFields) => { + const activateWallet = (values: OnyxFormValuesFields) => { const personalDetails = { phoneNumber: (values.phoneNumber && parsePhoneNumber(values.phoneNumber, {regionCode: CONST.COUNTRY.US}).number?.significant) ?? '', legalFirstName: values.legalFirstName ?? '', @@ -147,7 +147,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO Date: Mon, 12 Feb 2024 12:58:28 +0530 Subject: [PATCH 015/202] rearranged import for GetPhysicalCardForm --- 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 ca3abbca28b9..c9742595272f 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -16,8 +16,8 @@ import type { CloseAccountForm, DateOfBirthForm, DisplayNameForm, - IdologyQuestionsForm, GetPhysicalCardForm, + IdologyQuestionsForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, From ee76e50335a44ed6053292ee8deb78423a3edacf Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 12 Feb 2024 20:17:11 +0530 Subject: [PATCH 016/202] updated IDOLOGY_QUESTIONS_FORM key name --- src/ONYXKEYS.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index f19adfbeedd3..29a2955facfa 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -367,8 +367,8 @@ const ONYXKEYS = { REIMBURSEMENT_ACCOUNT_FORM_DRAFT: 'reimbursementAccountDraft', PERSONAL_BANK_ACCOUNT: 'personalBankAccountForm', PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', - IDOLOGY_QUESTIONS_FORM: 'idologyQuestions', - IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsDraft', + IDOLOGY_QUESTIONS_FORM: 'idologyQuestionsForm', + IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsFormDraft', WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetailsForm', WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsFormDraft', }, From 2c34dbf214c8511caa8357cfc186aacec0b0fef1 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Fri, 16 Feb 2024 14:39:23 +0530 Subject: [PATCH 017/202] fixed additional details step and idology questions types errors --- src/ONYXKEYS.ts | 2 ++ .../EnablePayments/AdditionalDetailsStep.tsx | 24 +++++++++++++------ src/pages/EnablePayments/IdologyQuestions.tsx | 4 ++-- src/types/form/index.ts | 2 ++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index d94f65954a98..05f064d90d5f 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -429,6 +429,8 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM]: FormTypes.ReimbursementAccountForm; [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT]: FormTypes.PersonalBankAccountForm; [ONYXKEYS.FORMS.WORKSPACE_DESCRIPTION_FORM]: FormTypes.WorkspaceDescriptionForm; + [ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS]: FormTypes.AdditionalDetailStepForm; + [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM]: FormTypes.IdologyQuestionsForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index c9b557a197e8..b347c93e296e 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -6,7 +6,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import DatePicker from '@components/DatePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; -import type {OnyxFormValuesFields} from '@components/Form/types'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -25,6 +25,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {WalletAdditionalDetails} from '@src/types/onyx'; import IdologyQuestions from './IdologyQuestions'; +import INPUT_IDS from '@src/types/form/AdditionalDetailStepForm'; const DEFAULT_WALLET_ADDITIONAL_DETAILS = { errorFields: {}, @@ -51,7 +52,16 @@ const fieldNameTranslationKeys = { ssn: 'common.ssnLast4', ssnFull9: 'common.ssnFull9', } as const; - +const STEP_FIELDS = [ + INPUT_IDS.LEGAL_FIRST_NAME, + INPUT_IDS.LEGAL_LAST_NAME, + INPUT_IDS.ADDRESS_STREET, + INPUT_IDS.ADDRESS_CITY, + INPUT_IDS.PHONE_NUMBER, + INPUT_IDS.DOB, + INPUT_IDS.ADDRESS_STATE, + INPUT_IDS.SSN +]; function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIONAL_DETAILS, currentUserPersonalDetails}: AdditionalDetailsStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -60,9 +70,9 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO const maxDate = subYears(currentDate, CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); const shouldAskForFullSSN = walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN; - const validate = (values: OnyxFormValuesFields) => { + const validate = (values: FormOnyxValues): FormInputErrors => { const requiredFields = ['legalFirstName', 'legalLastName', 'addressStreet', 'addressCity', 'addressZipCode', 'phoneNumber', 'dob', 'ssn', 'addressState']; - const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields); + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); if (values.dob) { if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { @@ -97,7 +107,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO return errors; }; - const activateWallet = (values: OnyxFormValuesFields) => { + const activateWallet = (values: FormOnyxValues) => { const personalDetails = { phoneNumber: (values.phoneNumber && parsePhoneNumber(values.phoneNumber, {regionCode: CONST.COUNTRY.US}).number?.significant) ?? '', legalFirstName: values.legalFirstName ?? '', @@ -197,10 +207,10 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO placeholder={translate('common.phoneNumberPlaceholder')} shouldSaveDraft /> - InputComponent={DatePicker} inputID="dob" - // @ts-expect-error TODO: Remove this once DatePicker (https://github.com/Expensify/App/issues/25148) is migrated to TypeScript. containerStyles={[styles.mt4]} label={translate(fieldNameTranslationKeys.dob)} placeholder={translate('common.dob')} diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index 4a5ef72019c0..f54f5a7cccba 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -3,7 +3,7 @@ import {View} from 'react-native'; import type {WalletAdditionalQuestionDetails} from 'src/types/onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; -import type {OnyxFormValuesFields} from '@components/Form/types'; +import type {FormOnyxValues,FormInputErrors} from '@components/Form/types'; import type {Choice} from '@components/RadioButtons'; import SingleChoiceQuestion from '@components/SingleChoiceQuestion'; import Text from '@components/Text'; @@ -91,7 +91,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { } }; - const validate = (values: OnyxFormValuesFields) => { + const validate = (values: FormOnyxValues) => { const errors: Errors = {}; if (!values.answer) { errors.answer = translate('additionalDetailsStep.selectAnswer'); diff --git a/src/types/form/index.ts b/src/types/form/index.ts index d9263991023c..9e457f83ace6 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -34,4 +34,6 @@ export type {WorkspaceRateAndUnitForm} from './WorkspaceRateAndUnitForm'; export type {WorkspaceSettingsForm} from './WorkspaceSettingsForm'; export type {WorkspaceDescriptionForm} from './WorkspaceDescriptionForm'; export type {WorkspaceProfileDescriptionForm} from './WorkspaceProfileDescriptionForm'; +export type {AdditionalDetailStepForm} from './AdditionalDetailStepForm'; +export type {IdologyQuestionsForm} from './IdologyQuestionsForm'; export type {default as Form} from './Form'; From 98ef6936cc57af1d9b20a24e1053eb8b7dad7a04 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Fri, 16 Feb 2024 14:46:29 +0530 Subject: [PATCH 018/202] code prettified & lint fixed --- .../EnablePayments/AdditionalDetailsStep.tsx | 5 ++--- src/pages/EnablePayments/IdologyQuestions.tsx | 4 ++-- src/types/form/AdditionalDetailStepForm.ts | 2 +- src/types/form/IdologyQuestionsForm.ts | 2 +- src/types/onyx/index.ts | 18 +----------------- 5 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index b347c93e296e..97041a5b021a 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -23,9 +23,9 @@ import AddressForm from '@pages/ReimbursementAccount/AddressForm'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import INPUT_IDS from '@src/types/form/AdditionalDetailStepForm'; import type {WalletAdditionalDetails} from '@src/types/onyx'; import IdologyQuestions from './IdologyQuestions'; -import INPUT_IDS from '@src/types/form/AdditionalDetailStepForm'; const DEFAULT_WALLET_ADDITIONAL_DETAILS = { errorFields: {}, @@ -60,7 +60,7 @@ const STEP_FIELDS = [ INPUT_IDS.PHONE_NUMBER, INPUT_IDS.DOB, INPUT_IDS.ADDRESS_STATE, - INPUT_IDS.SSN + INPUT_IDS.SSN, ]; function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIONAL_DETAILS, currentUserPersonalDetails}: AdditionalDetailsStepProps) { const {translate} = useLocalize(); @@ -71,7 +71,6 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO const shouldAskForFullSSN = walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN; const validate = (values: FormOnyxValues): FormInputErrors => { - const requiredFields = ['legalFirstName', 'legalLastName', 'addressStreet', 'addressCity', 'addressZipCode', 'phoneNumber', 'dob', 'ssn', 'addressState']; const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); if (values.dob) { diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index f54f5a7cccba..cadb7092f0c4 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -3,7 +3,7 @@ import {View} from 'react-native'; import type {WalletAdditionalQuestionDetails} from 'src/types/onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; -import type {FormOnyxValues,FormInputErrors} from '@components/Form/types'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import type {Choice} from '@components/RadioButtons'; import SingleChoiceQuestion from '@components/SingleChoiceQuestion'; import Text from '@components/Text'; @@ -91,7 +91,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { } }; - const validate = (values: FormOnyxValues) => { + const validate = (values: FormOnyxValues): FormInputErrors => { const errors: Errors = {}; if (!values.answer) { errors.answer = translate('additionalDetailsStep.selectAnswer'); diff --git a/src/types/form/AdditionalDetailStepForm.ts b/src/types/form/AdditionalDetailStepForm.ts index b432ae87e2cf..f102d03679ba 100644 --- a/src/types/form/AdditionalDetailStepForm.ts +++ b/src/types/form/AdditionalDetailStepForm.ts @@ -25,4 +25,4 @@ type AdditionalDetailStepForm = Form<{ }>; export type {AdditionalDetailStepForm}; -export default INPUT_IDS; \ No newline at end of file +export default INPUT_IDS; diff --git a/src/types/form/IdologyQuestionsForm.ts b/src/types/form/IdologyQuestionsForm.ts index eb48b9027541..5b8d50c68abf 100644 --- a/src/types/form/IdologyQuestionsForm.ts +++ b/src/types/form/IdologyQuestionsForm.ts @@ -9,4 +9,4 @@ type IdologyQuestionsForm = Form<{ }>; export type {IdologyQuestionsForm}; -export default INPUT_IDS; \ No newline at end of file +export default INPUT_IDS; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index e116aa99e95a..de9e96d8590b 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -11,23 +11,7 @@ import type Credentials from './Credentials'; import type Currency from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; -import type { - AddDebitCardForm, - AdditionalDetailStepForm, - CloseAccountForm, - DateOfBirthForm, - DisplayNameForm, - GetPhysicalCardForm, - IdologyQuestionsForm, - IKnowATeacherForm, - IntroSchoolPrincipalForm, - NewRoomForm, - PrivateNotesForm, - ReportFieldEditForm, - RoomNameForm, - WorkspaceSettingsForm, -} from './Form'; -import type Form from './Form'; +import type {AdditionalDetailStepForm, IdologyQuestionsForm, PrivateNotesForm, ReportFieldEditForm, RoomNameForm} from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; import type Fund from './Fund'; From 24fb379d31f4fa6647a12795ff7308be4cdd8f47 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Wed, 21 Feb 2024 19:48:37 +0530 Subject: [PATCH 019/202] fix loading issue for idology questions and fixed onValueChange for SingleChoiceQuestion --- src/libs/actions/Wallet.ts | 4 ++-- src/pages/EnablePayments/IdologyQuestions.tsx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 9cb4b28bef20..ffc68c562c4c 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -233,7 +233,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM, value: { isLoading: true, }, @@ -243,7 +243,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const finallyData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, + key: ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM, value: { isLoading: false, }, diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index cadb7092f0c4..b00010671518 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -126,9 +126,10 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { prompt={currentQuestion.prompt} possibleAnswers={possibleAnswers} currentQuestionIndex={currentQuestionIndex} - onInputChange={chooseAnswer} - // NOTEME: check the PR where this was added - // onValueChange={chooseAnswer} + onValueChange={(value) => { + chooseAnswer(String(value)); + }} + onInputChange={() => {}} /> From 708e818589c46508701cf0c6bfc0c93bbef437c8 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Wed, 21 Feb 2024 20:46:53 +0530 Subject: [PATCH 020/202] extracted URLs to CONST and deleted unused files --- src/CONST.ts | 4 ++++ .../EnablePayments/AdditionalDetailsStep.tsx | 2 +- src/pages/EnablePayments/IdologyQuestions.tsx | 3 ++- src/pages/EnablePayments/OnfidoPrivacy.tsx | 7 ++++--- src/pages/EnablePayments/TermsStep.tsx | 8 ++++--- .../walletAdditionalDetailsDraftPropTypes.js | 13 ------------ .../walletOnfidoDataPropTypes.js | 21 ------------------- .../ReimbursementAccount/BankAccountStep.js | 2 +- .../substeps/ConfirmAgreements.tsx | 3 ++- 9 files changed, 19 insertions(+), 44 deletions(-) delete mode 100644 src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js delete mode 100644 src/pages/EnablePayments/walletOnfidoDataPropTypes.js diff --git a/src/CONST.ts b/src/CONST.ts index ac8533c620b9..228f8bb97953 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -505,6 +505,10 @@ const CONST = { TERMS_URL: `${USE_EXPENSIFY_URL}/terms`, PRIVACY_URL: `${USE_EXPENSIFY_URL}/privacy`, LICENSES_URL: `${USE_EXPENSIFY_URL}/licenses`, + ACH_TERMS_URL: `${USE_EXPENSIFY_URL}/achterms`, + WALLET_AGREEMENT_URL: `${USE_EXPENSIFY_URL}/walletagreement`, + HELP_LINK_URL: `${USE_EXPENSIFY_URL}/usa-patriot-act`, + ELECTRONIC_DISCLOSURES_URL: `${USE_EXPENSIFY_URL}/esignagreement`, GITHUB_RELEASE_URL: 'https://api.github.com/repos/expensify/app/releases/latest', ADD_SECONDARY_LOGIN_URL: encodeURI('settings?param={"section":"account","openModal":"secondaryLogin"}'), MANAGE_CARDS_URL: 'domain_companycards', diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index 97041a5b021a..cdf166536c5f 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -150,7 +150,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO {translate('additionalDetailsStep.helpText')} {translate('additionalDetailsStep.helpLink')} diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index b00010671518..13c71f7005a9 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -11,6 +11,7 @@ import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as BankAccounts from '@userActions/BankAccounts'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Errors} from '@src/types/onyx/OnyxCommon'; @@ -105,7 +106,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { {translate('additionalDetailsStep.helpTextIdologyQuestions')} {translate('additionalDetailsStep.helpLink')} diff --git a/src/pages/EnablePayments/OnfidoPrivacy.tsx b/src/pages/EnablePayments/OnfidoPrivacy.tsx index 03f8df3ad82a..99117e3f1e99 100644 --- a/src/pages/EnablePayments/OnfidoPrivacy.tsx +++ b/src/pages/EnablePayments/OnfidoPrivacy.tsx @@ -13,6 +13,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {WalletOnfido} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -60,11 +61,11 @@ function OnfidoPrivacy({walletOnfidoData = DEFAULT_WALLET_ONFIDO_DATA}: OnfidoPr {translate('onfidoStep.acceptTerms')} - {translate('onfidoStep.facialScan')} + {translate('onfidoStep.facialScan')} {', '} - {translate('common.privacy')} + {translate('common.privacy')} {` ${translate('common.and')} `} - {translate('common.termsOfService')}. + {translate('common.termsOfService')}. diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index 4836feae9f9b..ecb636e854f0 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as BankAccounts from '@userActions/BankAccounts'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {UserWallet, WalletTerms} from '@src/types/onyx'; import LongTermsForm from './TermsPage/LongTermsForm'; @@ -69,7 +70,8 @@ function TermsStep(props: TermsStepProps) { LabelComponent={() => ( {`${translate('termsStep.haveReadAndAgree')}`} - {`${translate('termsStep.electronicDisclosures')}.`} + + {`${translate('termsStep.electronicDisclosures')}.`} )} /> @@ -80,11 +82,11 @@ function TermsStep(props: TermsStepProps) { {`${translate('termsStep.agreeToThe')} `} - {`${translate('common.privacy')} `} + {`${translate('common.privacy')} `} {`${translate('common.and')} `} - {`${translate('termsStep.walletAgreement')}.`} + {`${translate('termsStep.walletAgreement')}.`} )} /> diff --git a/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js b/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js deleted file mode 100644 index 747fa82f9fa3..000000000000 --- a/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js +++ /dev/null @@ -1,13 +0,0 @@ -import PropTypes from 'prop-types'; - -export default PropTypes.shape({ - legalFirstName: PropTypes.string, - legalLastName: PropTypes.string, - addressStreet: PropTypes.string, - addressCity: PropTypes.string, - addressState: PropTypes.string, - addressZip: PropTypes.string, - phoneNumber: PropTypes.string, - dob: PropTypes.string, - ssn: PropTypes.string, -}); diff --git a/src/pages/EnablePayments/walletOnfidoDataPropTypes.js b/src/pages/EnablePayments/walletOnfidoDataPropTypes.js deleted file mode 100644 index cedc1f2777b5..000000000000 --- a/src/pages/EnablePayments/walletOnfidoDataPropTypes.js +++ /dev/null @@ -1,21 +0,0 @@ -import PropTypes from 'prop-types'; - -export default PropTypes.shape({ - /** Unique identifier returned from openOnfidoFlow then re-sent to ActivateWallet with Onfido response data */ - applicantID: PropTypes.string, - - /** Token used to initialize the Onfido SDK token */ - sdkToken: PropTypes.string, - - /** Loading state to provide feedback when we are waiting for a request to finish */ - loading: PropTypes.bool, - - /** Error message to inform the user of any problem that might occur */ - error: PropTypes.string, - - /** A list of Onfido errors that the user can fix in order to attempt the Onfido flow again */ - fixableErrors: PropTypes.arrayOf(PropTypes.string), - - /** Whether the user has accepted the privacy policy of Onfido or not */ - hasAcceptedPrivacyPolicy: PropTypes.bool, -}); diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index 278036430dbf..2c40c5a2ed2f 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -179,7 +179,7 @@ function BankAccountStep(props) { )} - {props.translate('common.privacy')} + {props.translate('common.privacy')} Link.openExternalLink('https://community.expensify.com/discussion/5677/deep-dive-how-expensify-protects-your-information/')} style={[styles.flexRow, styles.alignItemsCenter]} diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx index aa554ca87eb2..fae7702053b7 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx +++ b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx @@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ValidationUtils from '@libs/ValidationUtils'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; import type {ReimbursementAccount} from '@src/types/onyx'; @@ -90,7 +91,7 @@ function ConfirmAgreements({onNext, reimbursementAccount}: ConfirmAgreementsProp LabelComponent={() => ( {translate('common.iAcceptThe')} - {`${translate('completeVerificationStep.termsAndConditions')}`} + {`${translate('completeVerificationStep.termsAndConditions')}`} )} defaultValue={defaultValues.acceptTermsAndConditions} From a78c3f8f66403c475c9468cdeafc460352f174ad Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 24 Feb 2024 13:51:28 +0700 Subject: [PATCH 021/202] remove redundant change --- src/pages/home/ReportScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 7f923b20864e..fe5ed9bb1150 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -648,7 +648,7 @@ export default compose( key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : 0}`, selector: (parentReportActions, props) => { const parentReportActionID = lodashGet(props, 'report.parentReportActionID'); - if (!parentReportActionID || !parentReportActions) { + if (!parentReportActionID) { return {}; } return lodashGet(parentReportActions, parentReportActionID, {}); From 229e1561643f0df80486d414a8f9136cf5584007 Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 24 Feb 2024 14:44:40 +0700 Subject: [PATCH 022/202] fix: infinite loading in policy expense chat when changing from auditor to employee --- src/pages/home/ReportScreen.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index fe5ed9bb1150..997989c97aa4 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -137,6 +137,17 @@ function getReportID(route) { return String(lodashGet(route, 'params.reportID') || 0); } +/** + * Check is the report is deleted. + * We currently use useMemo to memorize every properties of the report + * so we can't check using isEmpty. + * + * @param {Object} report + */ +function isDeletedReport(report) { + return _.every(report, _.isUndefined); +} + function ReportScreen({ betas, route, @@ -421,7 +432,7 @@ function ReportScreen({ !onyxReportID && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && (report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED || (!report.statusNum && !prevReport.parentReportID && prevReport.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM))) || - ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport) || ReportUtils.isPolicyExpenseChat(prevReport)) && _.isEmpty(report)) + ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport) || ReportUtils.isPolicyExpenseChat(prevReport)) && isDeletedReport(report)) ) { Navigation.dismissModal(); if (Navigation.getTopmostReportId() === prevOnyxReportID) { From feeceae1bcbd1d11ef2d8d0f94c1815f8fbcc810 Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 24 Feb 2024 15:38:10 +0700 Subject: [PATCH 023/202] fix lint --- src/pages/home/ReportScreen.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 997989c97aa4..9c3d31fda9e7 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -143,6 +143,7 @@ function getReportID(route) { * so we can't check using isEmpty. * * @param {Object} report + * @returns {Boolean} */ function isDeletedReport(report) { return _.every(report, _.isUndefined); From 60ea1a16422b9452a62464600f73d89da28b8beb Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 26 Feb 2024 16:03:36 +0500 Subject: [PATCH 024/202] perf: remove redundant translations --- src/CONST.ts | 1 + src/libs/PersonalDetailsUtils.ts | 9 +++++++-- src/libs/ReportUtils.ts | 23 +++++++++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 8abd4c087b16..bb167bb5d8d8 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -41,6 +41,7 @@ const KEYBOARD_SHORTCUT_NAVIGATION_TYPE = 'NAVIGATION_SHORTCUT'; const cardActiveStates: number[] = [2, 3, 4, 7]; const CONST = { + MERGED_ACCOUNT_PREFIX: 'MERGED_', ANDROID_PACKAGE_NAME, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 55aee10e611a..7cd6ac5bdedd 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -24,9 +24,14 @@ Onyx.connect({ }, }); +const hiddenText = Localize.translateLocal('common.hidden'); +const substringStartIndex = 8; function getDisplayNameOrDefault(passedPersonalDetails?: Partial | null, defaultValue = '', shouldFallbackToHidden = true): string { - const displayName = passedPersonalDetails?.displayName ? passedPersonalDetails.displayName.replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, '') : ''; - const fallbackValue = shouldFallbackToHidden ? Localize.translateLocal('common.hidden') : ''; + let displayName = passedPersonalDetails?.displayName ?? ''; + if (displayName.startsWith(CONST.MERGED_ACCOUNT_PREFIX)) { + displayName = displayName.substring(substringStartIndex); + } + const fallbackValue = shouldFallbackToHidden ? hiddenText : ''; return displayName || defaultValue || fallbackValue; } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 8813501e2b3f..adfefec932e5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -575,17 +575,18 @@ function getPolicyType(report: OnyxEntry, policies: OnyxCollection | undefined | EmptyObject, returnEmptyIfNotFound = false, policy: OnyxEntry | undefined = undefined): string { - const noPolicyFound = returnEmptyIfNotFound ? '' : Localize.translateLocal('workspace.common.unavailable'); + const noPolicyFound = returnEmptyIfNotFound ? '' : unavailableWorkspaceText; if (isEmptyObject(report)) { return noPolicyFound; } if ((!allPolicies || Object.keys(allPolicies).length === 0) && !report?.policyName) { - return Localize.translateLocal('workspace.common.unavailable'); + return unavailableWorkspaceText; } const finalPolicy = policy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]; @@ -773,11 +774,12 @@ function isAnnounceRoom(report: OnyxEntry): boolean { return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE; } +const chatTypes = [CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, CONST.REPORT.CHAT_TYPE.DOMAIN_ALL]; /** * Whether the provided report is a default room */ function isDefaultRoom(report: OnyxEntry): boolean { - return [CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, CONST.REPORT.CHAT_TYPE.DOMAIN_ALL].some((type) => type === getChatType(report)); + return chatTypes.some((type) => type === getChatType(report)); } /** @@ -1625,6 +1627,7 @@ function getPersonalDetailsForAccountID(accountID: number): Partial, policy: OnyxEntry = nu } if (parentReportAction?.message?.[0]?.isDeletedParentAction) { - return Localize.translateLocal('parentReportAction.deletedMessage'); + return deletedMessageText; } const isAttachment = ReportActionsUtils.isReportActionAttachment(!isEmptyObject(parentReportAction) ? parentReportAction : null); const parentReportActionMessage = (parentReportAction?.message?.[0]?.text ?? '').replace(/(\r\n|\n|\r)/gm, ' '); if (isAttachment && parentReportActionMessage) { - return `[${Localize.translateLocal('common.attachment')}]`; + return `[${attachmentText}]`; } if ( parentReportAction?.message?.[0]?.moderationDecision?.decision === CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE || @@ -2529,7 +2536,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) { - return Localize.translateLocal('parentReportAction.deletedTask'); + return deletedTaskText; } if (isChatRoom(report) || isTaskReport(report)) { @@ -2545,7 +2552,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isArchivedRoom(report)) { - formattedName += ` (${Localize.translateLocal('common.archived')})`; + formattedName += ` (${archivedText})`; } if (formattedName) { From 22f0ffa46f75a5828e6edbf6774c0b53e688fbda Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 26 Feb 2024 16:29:41 +0500 Subject: [PATCH 025/202] perf: only parse the number if it matches the pattern --- src/CONST.ts | 1 + src/libs/LocalePhoneNumber.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index bb167bb5d8d8..fce096a9957a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -42,6 +42,7 @@ const cardActiveStates: number[] = [2, 3, 4, 7]; const CONST = { MERGED_ACCOUNT_PREFIX: 'MERGED_', + SMS_DOMAIN_PATTERN: 'expensify.sms', ANDROID_PACKAGE_NAME, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index 933aa7937560..4fc13322b0cf 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -1,5 +1,6 @@ import Str from 'expensify-common/lib/str'; import Onyx from 'react-native-onyx'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {parsePhoneNumber} from './PhoneNumber'; @@ -18,6 +19,10 @@ function formatPhoneNumber(number: string): string { return ''; } + // do not parse the string, if it's not a phone number + if (number.indexOf(CONST.SMS_DOMAIN_PATTERN) === -1) { + return number; + } const numberWithoutSMSDomain = Str.removeSMSDomain(number); const parsedPhoneNumber = parsePhoneNumber(numberWithoutSMSDomain); From f7ec94a46916c897df9c29ff34151db2a4d5f45a Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 26 Feb 2024 19:01:09 +0700 Subject: [PATCH 026/202] change function name --- src/pages/home/ReportScreen.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 9c3d31fda9e7..157be9118c6c 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -145,7 +145,7 @@ function getReportID(route) { * @param {Object} report * @returns {Boolean} */ -function isDeletedReport(report) { +function isEmpty(report) { return _.every(report, _.isUndefined); } @@ -433,7 +433,7 @@ function ReportScreen({ !onyxReportID && prevReport.statusNum === CONST.REPORT.STATUS_NUM.OPEN && (report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED || (!report.statusNum && !prevReport.parentReportID && prevReport.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ROOM))) || - ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport) || ReportUtils.isPolicyExpenseChat(prevReport)) && isDeletedReport(report)) + ((ReportUtils.isMoneyRequest(prevReport) || ReportUtils.isMoneyRequestReport(prevReport) || ReportUtils.isPolicyExpenseChat(prevReport)) && isEmpty(report)) ) { Navigation.dismissModal(); if (Navigation.getTopmostReportId() === prevOnyxReportID) { From 643c7e150cd9e7f42f559c5df0e384182c7a0c0d Mon Sep 17 00:00:00 2001 From: hurali97 Date: Tue, 27 Feb 2024 12:44:01 +0500 Subject: [PATCH 027/202] perf: return early if displayName exists --- src/libs/PersonalDetailsUtils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 7cd6ac5bdedd..912e9aba36aa 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -25,14 +25,22 @@ Onyx.connect({ }); const hiddenText = Localize.translateLocal('common.hidden'); -const substringStartIndex = 8; +const substringStartIndex = CONST.MERGED_ACCOUNT_PREFIX.length; function getDisplayNameOrDefault(passedPersonalDetails?: Partial | null, defaultValue = '', shouldFallbackToHidden = true): string { let displayName = passedPersonalDetails?.displayName ?? ''; if (displayName.startsWith(CONST.MERGED_ACCOUNT_PREFIX)) { displayName = displayName.substring(substringStartIndex); } + + /** + * If displayName exists, return it early so we don't have to allocate + * memory for the fallback string. + */ + if (displayName) { + return displayName; + } const fallbackValue = shouldFallbackToHidden ? hiddenText : ''; - return displayName || defaultValue || fallbackValue; + return defaultValue || fallbackValue; } /** From c683db7392b2ad06320785a78661bf56c5c2bc4e Mon Sep 17 00:00:00 2001 From: hurali97 Date: Tue, 27 Feb 2024 13:10:35 +0500 Subject: [PATCH 028/202] test: fix failing test for formatPhoneNumber --- src/libs/LocalePhoneNumber.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index 4fc13322b0cf..ec704ec4d44b 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -10,6 +10,28 @@ Onyx.connect({ callback: (val) => (countryCodeByIP = val ?? 1), }); +/** + * Checks whether the given string contains any numbers. + * It uses indexOf instead of regex and includes for performance reasons. + * + * @param text + * @returns boolean + */ +function containsNumbers(text: string) { + return ( + text.indexOf('0') !== -1 || + text.indexOf('1') !== -1 || + text.indexOf('2') !== -1 || + text.indexOf('3') !== -1 || + text.indexOf('4') !== -1 || + text.indexOf('5') !== -1 || + text.indexOf('6') !== -1 || + text.indexOf('7') !== -1 || + text.indexOf('8') !== -1 || + text.indexOf('9') !== -1 + ); +} + /** * 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 @@ -20,7 +42,7 @@ function formatPhoneNumber(number: string): string { } // do not parse the string, if it's not a phone number - if (number.indexOf(CONST.SMS_DOMAIN_PATTERN) === -1) { + if (number.indexOf(CONST.SMS_DOMAIN_PATTERN) === -1 && !containsNumbers(number)) { return number; } const numberWithoutSMSDomain = Str.removeSMSDomain(number); From 454a9b258fee05e310d2378b5bfd2cdaf915b251 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Tue, 27 Feb 2024 15:24:10 +0500 Subject: [PATCH 029/202] refactor: move translations to utils --- src/libs/CommonTranslationUtils.ts | 49 ++++++++++++++++++++++++++++++ src/libs/PersonalDetailsUtils.ts | 11 +++++-- src/libs/ReportUtils.ts | 21 +++++-------- 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 src/libs/CommonTranslationUtils.ts diff --git a/src/libs/CommonTranslationUtils.ts b/src/libs/CommonTranslationUtils.ts new file mode 100644 index 000000000000..80a06e51ce9f --- /dev/null +++ b/src/libs/CommonTranslationUtils.ts @@ -0,0 +1,49 @@ +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; +import * as Localize from './Localize'; + +/** + * This file contains common translations that are used in multiple places in the app. + * This is done to avoid duplicate translations and to keep the translations consistent. + * This also allows us to not repeatedly translate the same string which may happen due + * to translations being done for eg, in a loop. + * + * This was identified as part of a performance audit. + * details: https://github.com/Expensify/App/issues/35234#issuecomment-1926911643 + */ + +let deletedTaskText = ''; +let deletedMessageText = ''; +let attachmentText = ''; +let archivedText = ''; +let hiddenText = ''; +let unavailableWorkspaceText = ''; + +function isTranslationAvailable() { + return deletedTaskText && deletedMessageText && attachmentText && archivedText && hiddenText && unavailableWorkspaceText; +} + +Onyx.connect({ + key: ONYXKEYS.NVP_PREFERRED_LOCALE, + callback: (val) => { + if (!val && isTranslationAvailable()) { + return; + } + + deletedTaskText = Localize.translateLocal('parentReportAction.deletedTask'); + deletedMessageText = Localize.translateLocal('parentReportAction.deletedMessage'); + attachmentText = Localize.translateLocal('common.attachment'); + archivedText = Localize.translateLocal('common.archived'); + hiddenText = Localize.translateLocal('common.hidden'); + unavailableWorkspaceText = Localize.translateLocal('workspace.common.unavailable'); + }, +}); + +export default { + deletedTaskText: () => deletedTaskText, + deletedMessageText: () => deletedMessageText, + attachmentText: () => attachmentText, + archivedText: () => archivedText, + hiddenText: () => hiddenText, + unavailableWorkspaceText: () => unavailableWorkspaceText, +}; diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 912e9aba36aa..7a9b3fe96598 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -5,6 +5,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx'; import type {OnyxData} from '@src/types/onyx/Request'; +import CommonTranslationUtils from './CommonTranslationUtils'; import * as LocalePhoneNumber from './LocalePhoneNumber'; import * as Localize from './Localize'; import * as UserUtils from './UserUtils'; @@ -24,10 +25,16 @@ Onyx.connect({ }, }); -const hiddenText = Localize.translateLocal('common.hidden'); +/** + * Index for the substring method to remove the merged account prefix. + */ const substringStartIndex = CONST.MERGED_ACCOUNT_PREFIX.length; + function getDisplayNameOrDefault(passedPersonalDetails?: Partial | null, defaultValue = '', shouldFallbackToHidden = true): string { let displayName = passedPersonalDetails?.displayName ?? ''; + /** + * If the displayName starts with the merged account prefix, remove it. + */ if (displayName.startsWith(CONST.MERGED_ACCOUNT_PREFIX)) { displayName = displayName.substring(substringStartIndex); } @@ -39,7 +46,7 @@ function getDisplayNameOrDefault(passedPersonalDetails?: Partial, policies: OnyxCollection | undefined | EmptyObject, returnEmptyIfNotFound = false, policy: OnyxEntry | undefined = undefined): string { - const noPolicyFound = returnEmptyIfNotFound ? '' : unavailableWorkspaceText; + const noPolicyFound = returnEmptyIfNotFound ? '' : CommonTranslationUtils.unavailableWorkspaceText(); if (isEmptyObject(report)) { return noPolicyFound; } if ((!allPolicies || Object.keys(allPolicies).length === 0) && !report?.policyName) { - return unavailableWorkspaceText; + return CommonTranslationUtils.unavailableWorkspaceText(); } const finalPolicy = policy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]; @@ -1627,7 +1627,6 @@ function getPersonalDetailsForAccountID(accountID: number): Partial, policy: OnyxEntry = nu } if (parentReportAction?.message?.[0]?.isDeletedParentAction) { - return deletedMessageText; + return CommonTranslationUtils.deletedMessageText(); } const isAttachment = ReportActionsUtils.isReportActionAttachment(!isEmptyObject(parentReportAction) ? parentReportAction : null); const parentReportActionMessage = (parentReportAction?.message?.[0]?.text ?? '').replace(/(\r\n|\n|\r)/gm, ' '); if (isAttachment && parentReportActionMessage) { - return `[${attachmentText}]`; + return `[${CommonTranslationUtils.attachmentText()}]`; } if ( parentReportAction?.message?.[0]?.moderationDecision?.decision === CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE || @@ -2536,7 +2531,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) { - return deletedTaskText; + return CommonTranslationUtils.deletedTaskText(); } if (isChatRoom(report) || isTaskReport(report)) { @@ -2552,7 +2547,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isArchivedRoom(report)) { - formattedName += ` (${archivedText})`; + formattedName += ` (${CommonTranslationUtils.archivedText()})`; } if (formattedName) { From eb8f26ccb2fabb54fbb7f6c054e13dd53127c9ee Mon Sep 17 00:00:00 2001 From: hurali97 Date: Tue, 27 Feb 2024 15:24:28 +0500 Subject: [PATCH 030/202] fix: linting --- src/libs/LocalePhoneNumber.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index ec704ec4d44b..798e0a50c43e 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -13,7 +13,7 @@ Onyx.connect({ /** * Checks whether the given string contains any numbers. * It uses indexOf instead of regex and includes for performance reasons. - * + * * @param text * @returns boolean */ From 34cd2e8402fe6fab0135e503114b7d514360a76b Mon Sep 17 00:00:00 2001 From: hurali97 Date: Wed, 28 Feb 2024 13:03:14 +0500 Subject: [PATCH 031/202] refactor: use regex and dedicated const for sms domain --- src/CONST.ts | 1 - src/libs/LocalePhoneNumber.ts | 26 ++------------------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index fce096a9957a..bb167bb5d8d8 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -42,7 +42,6 @@ const cardActiveStates: number[] = [2, 3, 4, 7]; const CONST = { MERGED_ACCOUNT_PREFIX: 'MERGED_', - SMS_DOMAIN_PATTERN: 'expensify.sms', ANDROID_PACKAGE_NAME, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, diff --git a/src/libs/LocalePhoneNumber.ts b/src/libs/LocalePhoneNumber.ts index 798e0a50c43e..460d5fc0fe9f 100644 --- a/src/libs/LocalePhoneNumber.ts +++ b/src/libs/LocalePhoneNumber.ts @@ -10,28 +10,6 @@ Onyx.connect({ callback: (val) => (countryCodeByIP = val ?? 1), }); -/** - * Checks whether the given string contains any numbers. - * It uses indexOf instead of regex and includes for performance reasons. - * - * @param text - * @returns boolean - */ -function containsNumbers(text: string) { - return ( - text.indexOf('0') !== -1 || - text.indexOf('1') !== -1 || - text.indexOf('2') !== -1 || - text.indexOf('3') !== -1 || - text.indexOf('4') !== -1 || - text.indexOf('5') !== -1 || - text.indexOf('6') !== -1 || - text.indexOf('7') !== -1 || - text.indexOf('8') !== -1 || - text.indexOf('9') !== -1 - ); -} - /** * 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 @@ -41,8 +19,8 @@ function formatPhoneNumber(number: string): string { return ''; } - // do not parse the string, if it's not a phone number - if (number.indexOf(CONST.SMS_DOMAIN_PATTERN) === -1 && !containsNumbers(number)) { + // do not parse the string, if it doesn't contain the SMS domain and it's not a phone number + if (number.indexOf(CONST.SMS.DOMAIN) === -1 && !CONST.REGEX.DIGITS_AND_PLUS.test(number)) { return number; } const numberWithoutSMSDomain = Str.removeSMSDomain(number); From 707f56c7f913dcf6e7e764933c7e3b7f78021294 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Wed, 28 Feb 2024 13:03:42 +0500 Subject: [PATCH 032/202] refactor: remove allocating a variable and return the evaluated expresssion --- src/libs/PersonalDetailsUtils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 7a9b3fe96598..d5946feb2f74 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -46,8 +46,7 @@ function getDisplayNameOrDefault(passedPersonalDetails?: Partial Date: Wed, 28 Feb 2024 19:25:41 +0530 Subject: [PATCH 033/202] fix: updated IdologyQuestionsForm and AdditionalDetailStepForm values usage of the updated Form --- src/pages/EnablePayments/TermsStep.tsx | 2 -- src/types/form/AdditionalDetailStepForm.ts | 28 +++++++++++++--------- src/types/form/IdologyQuestionsForm.ts | 12 +++++++--- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index 7a4fc76d87c5..df9b14cffca4 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -7,8 +7,6 @@ import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; - -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; diff --git a/src/types/form/AdditionalDetailStepForm.ts b/src/types/form/AdditionalDetailStepForm.ts index f102d03679ba..0d2c96487392 100644 --- a/src/types/form/AdditionalDetailStepForm.ts +++ b/src/types/form/AdditionalDetailStepForm.ts @@ -1,3 +1,4 @@ +import type {ValueOf} from 'type-fest'; import type Form from './Form'; const INPUT_IDS = { @@ -12,17 +13,22 @@ const INPUT_IDS = { SSN: 'ssn', } as const; -type AdditionalDetailStepForm = Form<{ - [INPUT_IDS.LEGAL_FIRST_NAME]: string; - [INPUT_IDS.LEGAL_LAST_NAME]: string; - [INPUT_IDS.PHONE_NUMBER]: string; - [INPUT_IDS.ADDRESS_STREET]: string; - [INPUT_IDS.ADDRESS_CITY]: string; - [INPUT_IDS.ADDRESS_ZIP_CODE]: string; - [INPUT_IDS.ADDRESS_STATE]: string; - [INPUT_IDS.DOB]: string; - [INPUT_IDS.SSN]: string; -}>; +type InputID = ValueOf; + +type AdditionalDetailStepForm = Form< + InputID, + { + [INPUT_IDS.LEGAL_FIRST_NAME]: string; + [INPUT_IDS.LEGAL_LAST_NAME]: string; + [INPUT_IDS.PHONE_NUMBER]: string; + [INPUT_IDS.ADDRESS_STREET]: string; + [INPUT_IDS.ADDRESS_CITY]: string; + [INPUT_IDS.ADDRESS_ZIP_CODE]: string; + [INPUT_IDS.ADDRESS_STATE]: string; + [INPUT_IDS.DOB]: string; + [INPUT_IDS.SSN]: string; + } +>; export type {AdditionalDetailStepForm}; export default INPUT_IDS; diff --git a/src/types/form/IdologyQuestionsForm.ts b/src/types/form/IdologyQuestionsForm.ts index 5b8d50c68abf..250e8c6f7766 100644 --- a/src/types/form/IdologyQuestionsForm.ts +++ b/src/types/form/IdologyQuestionsForm.ts @@ -1,12 +1,18 @@ +import type {ValueOf} from 'type-fest'; import type Form from './Form'; const INPUT_IDS = { ANSWER: 'answer', } as const; -type IdologyQuestionsForm = Form<{ - [INPUT_IDS.ANSWER]: string; -}>; +type InputID = ValueOf; + +type IdologyQuestionsForm = Form< + InputID, + { + [INPUT_IDS.ANSWER]: string; + } +>; export type {IdologyQuestionsForm}; export default INPUT_IDS; From f36550f1001bba5e995b1ef682dc22da19b28605 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Thu, 29 Feb 2024 13:00:44 +0500 Subject: [PATCH 034/202] refactor: use single-line comments --- src/libs/PersonalDetailsUtils.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index d5946feb2f74..97e2dc91492b 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -25,24 +25,19 @@ Onyx.connect({ }, }); -/** - * Index for the substring method to remove the merged account prefix. - */ +// Index for the substring method to remove the merged account prefix. const substringStartIndex = CONST.MERGED_ACCOUNT_PREFIX.length; function getDisplayNameOrDefault(passedPersonalDetails?: Partial | null, defaultValue = '', shouldFallbackToHidden = true): string { let displayName = passedPersonalDetails?.displayName ?? ''; - /** - * If the displayName starts with the merged account prefix, remove it. - */ + + // If the displayName starts with the merged account prefix, remove it. if (displayName.startsWith(CONST.MERGED_ACCOUNT_PREFIX)) { displayName = displayName.substring(substringStartIndex); } - /** - * If displayName exists, return it early so we don't have to allocate - * memory for the fallback string. - */ + // If displayName exists, return it early so we don't have to allocate + // memory for the fallback string. if (displayName) { return displayName; } From ce048d53cf21d17eb4ae0ce7ca4031ef9f16e699 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Sat, 2 Mar 2024 12:06:35 +0530 Subject: [PATCH 035/202] revert the WALLET_ADDITIONAL_DETAILS key name --- src/ONYXKEYS.ts | 4 ++-- src/pages/EnablePayments/AdditionalDetailsStep.tsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index afcbd059a9f8..389c270f7510 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -399,8 +399,8 @@ const ONYXKEYS = { EXIT_SURVEY_RESPONSE_FORM_DRAFT: 'exitSurveyResponseFormDraft', IDOLOGY_QUESTIONS_FORM: 'idologyQuestionsForm', IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsFormDraft', - WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetailsForm', - WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsFormDraft', + WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetails', + WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsDraft', }, } as const; diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index cdf166536c5f..0b663261865f 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -237,6 +237,7 @@ AdditionalDetailsStep.displayName = 'AdditionalDetailsStep'; export default withCurrentUserPersonalDetails( withOnyx({ + // @ts-expect-error: ONYXKEYS.WALLET_ADDITIONAL_DETAILS is conflicting with ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS walletAdditionalDetails: { key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, }, From e02b55a5f95fe10e4f22a28b16f20aaf75977c5f Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 13:02:21 +0500 Subject: [PATCH 036/202] refactor: use default policy room chat types from CONST --- src/CONST.ts | 17 ++++++++++------- src/libs/ReportUtils.ts | 3 +-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index bb167bb5d8d8..78c562ea2cde 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -37,11 +37,20 @@ const keyInputRightArrow = KeyCommand?.constants?.keyInputRightArrow ?? 'keyInpu // describes if a shortcut key can cause navigation const KEYBOARD_SHORTCUT_NAVIGATION_TYPE = 'NAVIGATION_SHORTCUT'; +const chatTypes = { + POLICY_ANNOUNCE: 'policyAnnounce', + POLICY_ADMINS: 'policyAdmins', + DOMAIN_ALL: 'domainAll', + POLICY_ROOM: 'policyRoom', + POLICY_EXPENSE_CHAT: 'policyExpenseChat', +} as const; + // Explicit type annotation is required const cardActiveStates: number[] = [2, 3, 4, 7]; const CONST = { MERGED_ACCOUNT_PREFIX: 'MERGED_', + DEFAULT_POLICY_ROOM_CHAT_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL], ANDROID_PACKAGE_NAME, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, @@ -684,13 +693,7 @@ const CONST = { IOU: 'iou', TASK: 'task', }, - CHAT_TYPE: { - POLICY_ANNOUNCE: 'policyAnnounce', - POLICY_ADMINS: 'policyAdmins', - DOMAIN_ALL: 'domainAll', - POLICY_ROOM: 'policyRoom', - POLICY_EXPENSE_CHAT: 'policyExpenseChat', - }, + CHAT_TYPE: chatTypes, WORKSPACE_CHAT_ROOMS: { ANNOUNCE: '#announce', ADMINS: '#admins', diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 37fee63780fb..93d2fd5da37d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -774,12 +774,11 @@ function isAnnounceRoom(report: OnyxEntry): boolean { return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE; } -const chatTypes = [CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, CONST.REPORT.CHAT_TYPE.DOMAIN_ALL]; /** * Whether the provided report is a default room */ function isDefaultRoom(report: OnyxEntry): boolean { - return chatTypes.some((type) => type === getChatType(report)); + return CONST.DEFAULT_POLICY_ROOM_CHAT_TYPES.some((type) => type === getChatType(report)); } /** From 7cbca08a4bd4b93ec49f6277df41f476744a33e7 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 15:55:46 +0500 Subject: [PATCH 037/202] revert: bring back localize.translateLocal --- src/libs/PersonalDetailsUtils.ts | 2 +- src/libs/ReportUtils.ts | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 97e2dc91492b..5a3de690d8f8 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -41,7 +41,7 @@ function getDisplayNameOrDefault(passedPersonalDetails?: Partial, policies: OnyxCollection | undefined | EmptyObject, returnEmptyIfNotFound = false, policy: OnyxEntry | undefined = undefined): string { - const noPolicyFound = returnEmptyIfNotFound ? '' : CommonTranslationUtils.unavailableWorkspaceText(); + const noPolicyFound = returnEmptyIfNotFound ? '' : Localize.translateLocal('workspace.common.unavailable'); if (isEmptyObject(report)) { return noPolicyFound; } if ((!allPolicies || Object.keys(allPolicies).length === 0) && !report?.policyName) { - return CommonTranslationUtils.unavailableWorkspaceText(); + return Localize.translateLocal('workspace.common.unavailable'); } const finalPolicy = policy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]; @@ -1647,7 +1647,7 @@ function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = f const longName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails, formattedLogin, shouldFallbackToHidden); // If the user's personal details (first name) should be hidden, make sure we return "hidden" instead of the short name - if (shouldFallbackToHidden && longName === CommonTranslationUtils.hiddenText()) { + if (shouldFallbackToHidden && longName === Localize.translateLocal('common.hidden')) { return longName; } @@ -2508,13 +2508,13 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (parentReportAction?.message?.[0]?.isDeletedParentAction) { - return CommonTranslationUtils.deletedMessageText(); + return Localize.translateLocal('parentReportAction.deletedMessage'); } const isAttachment = ReportActionsUtils.isReportActionAttachment(!isEmptyObject(parentReportAction) ? parentReportAction : null); const parentReportActionMessage = (parentReportAction?.message?.[0]?.text ?? '').replace(/(\r\n|\n|\r)/gm, ' '); if (isAttachment && parentReportActionMessage) { - return `[${CommonTranslationUtils.attachmentText()}]`; + return `[${Localize.translateLocal('common.attachment')}]`; } if ( parentReportAction?.message?.[0]?.moderationDecision?.decision === CONST.MODERATION.MODERATOR_DECISION_PENDING_HIDE || @@ -2530,7 +2530,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isTaskReport(report) && isCanceledTaskReport(report, parentReportAction)) { - return CommonTranslationUtils.deletedTaskText(); + return Localize.translateLocal('parentReportAction.deletedTask'); } if (isChatRoom(report) || isTaskReport(report)) { @@ -2546,7 +2546,7 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } if (isArchivedRoom(report)) { - formattedName += ` (${CommonTranslationUtils.archivedText()})`; + formattedName += ` (${Localize.translateLocal('common.archived')})`; } if (formattedName) { From 4df1d3da5dd9f6cb7862c8c62b105688cbbe9274 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 16:51:30 +0500 Subject: [PATCH 038/202] feat: add cache for translated values in Localize --- src/libs/Localize/index.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index 64d07897aa8a..9cadc352ca9a 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -93,11 +93,42 @@ function translate(desiredLanguage: 'en' | 'es' | throw new Error(`${phraseKey} was not found in the default language`); } +/** + * Map to store translated values for each locale + * This is used to avoid translating the same phrase multiple times. + * + * The data is stored in the following format: + * + * { + * "name_en": "Name", + * "name_es": "Nombre", + * } + * + * Note: We are not storing any translated values for phrases with variables, + * as they have higher chance of being unique, so we'll end up wasting space + * in our cache. + */ +const translatedValues = new Map(); + /** * Uses the locale in this file updated by the Onyx subscriber. */ function translateLocal(phrase: TKey, ...variables: PhraseParameters>) { - return translate(BaseLocaleListener.getPreferredLocale(), phrase, ...variables); + const preferredLocale = BaseLocaleListener.getPreferredLocale(); + const key = `${phrase}_${preferredLocale}`; + const isVariablesEmpty = variables.length === 0; + + // If the phrase is already translated and there are no variables, return the translated value + if (translatedValues.has(key) && isVariablesEmpty) { + return translatedValues.get(key) as string; + } + const translatedText = translate(preferredLocale, phrase, ...variables); + + // We don't want to store translated values for phrases with variables + if (isVariablesEmpty) { + translatedValues.set(key, translatedText); + } + return translatedText; } /** From 55eb5d2f765099561de1a8720e2cb1345ca013e3 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 17:13:32 +0500 Subject: [PATCH 039/202] refactor: delete common translation utils --- src/libs/CommonTranslationUtils.ts | 49 ------------------------------ 1 file changed, 49 deletions(-) delete mode 100644 src/libs/CommonTranslationUtils.ts diff --git a/src/libs/CommonTranslationUtils.ts b/src/libs/CommonTranslationUtils.ts deleted file mode 100644 index 80a06e51ce9f..000000000000 --- a/src/libs/CommonTranslationUtils.ts +++ /dev/null @@ -1,49 +0,0 @@ -import Onyx from 'react-native-onyx'; -import ONYXKEYS from '@src/ONYXKEYS'; -import * as Localize from './Localize'; - -/** - * This file contains common translations that are used in multiple places in the app. - * This is done to avoid duplicate translations and to keep the translations consistent. - * This also allows us to not repeatedly translate the same string which may happen due - * to translations being done for eg, in a loop. - * - * This was identified as part of a performance audit. - * details: https://github.com/Expensify/App/issues/35234#issuecomment-1926911643 - */ - -let deletedTaskText = ''; -let deletedMessageText = ''; -let attachmentText = ''; -let archivedText = ''; -let hiddenText = ''; -let unavailableWorkspaceText = ''; - -function isTranslationAvailable() { - return deletedTaskText && deletedMessageText && attachmentText && archivedText && hiddenText && unavailableWorkspaceText; -} - -Onyx.connect({ - key: ONYXKEYS.NVP_PREFERRED_LOCALE, - callback: (val) => { - if (!val && isTranslationAvailable()) { - return; - } - - deletedTaskText = Localize.translateLocal('parentReportAction.deletedTask'); - deletedMessageText = Localize.translateLocal('parentReportAction.deletedMessage'); - attachmentText = Localize.translateLocal('common.attachment'); - archivedText = Localize.translateLocal('common.archived'); - hiddenText = Localize.translateLocal('common.hidden'); - unavailableWorkspaceText = Localize.translateLocal('workspace.common.unavailable'); - }, -}); - -export default { - deletedTaskText: () => deletedTaskText, - deletedMessageText: () => deletedMessageText, - attachmentText: () => attachmentText, - archivedText: () => archivedText, - hiddenText: () => hiddenText, - unavailableWorkspaceText: () => unavailableWorkspaceText, -}; From e643960c7ef54a8e2451f052c926ab664be127a4 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 17:43:24 +0500 Subject: [PATCH 040/202] refactor: avoid multiple cache lookups --- src/libs/Localize/index.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index 9cadc352ca9a..ad5e93af24ee 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -118,9 +118,13 @@ function translateLocal(phrase: TKey, ...variable const key = `${phrase}_${preferredLocale}`; const isVariablesEmpty = variables.length === 0; - // If the phrase is already translated and there are no variables, return the translated value - if (translatedValues.has(key) && isVariablesEmpty) { - return translatedValues.get(key) as string; + // Directly access and assign the translated value from the cache, instead of + // going through map.has() and map.get() to avoid multiple lookups. + const valueFromCache = translatedValues.get(key); + + // If the phrase is already translated, return the translated value + if (valueFromCache) { + return valueFromCache; } const translatedText = translate(preferredLocale, phrase, ...variables); From f3d6f1f73255fe186eea218f6600365dbfe06e41 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 4 Mar 2024 17:43:39 +0500 Subject: [PATCH 041/202] fix: lint --- src/libs/PersonalDetailsUtils.ts | 1 - src/libs/ReportUtils.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index c5de7456629d..391cabef0790 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -5,7 +5,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx'; import type {OnyxData} from '@src/types/onyx/Request'; -import CommonTranslationUtils from './CommonTranslationUtils'; import * as LocalePhoneNumber from './LocalePhoneNumber'; import * as Localize from './Localize'; import * as UserUtils from './UserUtils'; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 1c64deff881e..f7d49389e200 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -51,7 +51,6 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import * as CollectionUtils from './CollectionUtils'; -import CommonTranslationUtils from './CommonTranslationUtils'; import * as CurrencyUtils from './CurrencyUtils'; import DateUtils from './DateUtils'; import isReportMessageAttachment from './isReportMessageAttachment'; From 0f1fb25ffd036dc02b3e7aba1730a2ee46baeb44 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 4 Mar 2024 20:17:26 +0530 Subject: [PATCH 042/202] removed unused onyx/Form --- src/types/onyx/Form.ts | 140 ---------------------------------------- src/types/onyx/index.ts | 6 -- 2 files changed, 146 deletions(-) delete mode 100644 src/types/onyx/Form.ts diff --git a/src/types/onyx/Form.ts b/src/types/onyx/Form.ts deleted file mode 100644 index 3743468b39b0..000000000000 --- a/src/types/onyx/Form.ts +++ /dev/null @@ -1,140 +0,0 @@ -import type * as OnyxCommon from './OnyxCommon'; -import type PersonalBankAccount from './PersonalBankAccount'; - -type FormValueType = string | boolean | Date | OnyxCommon.Errors; - -type BaseForm = { - /** Controls the loading state of the form */ - isLoading?: boolean; - - /** Server side errors keyed by microtime */ - errors?: OnyxCommon.Errors | null; - - /** Field-specific server side errors keyed by microtime */ - errorFields?: OnyxCommon.ErrorFields | null; -}; - -type Form = Record> = TFormValues & BaseForm; - -type AddDebitCardForm = Form<{ - /** Whether the form has been submitted */ - setupComplete: boolean; -}>; - -type DateOfBirthForm = Form<{ - /** Date of birth */ - dob?: string; -}>; - -type DisplayNameForm = Form<{ - firstName: string; - lastName: string; -}>; - -type NewRoomForm = Form<{ - roomName?: string; - reportDescription?: string; - policyID?: string; - writeCapability?: string; - visibility?: string; -}>; - -type IKnowATeacherForm = Form<{ - firstName: string; - lastName: string; - partnerUserID: string; -}>; - -type IntroSchoolPrincipalForm = Form<{ - firstName: string; - lastName: string; - partnerUserID: string; -}>; - -type PrivateNotesForm = Form<{ - privateNotes: string; -}>; - -type GetPhysicalCardForm = Form<{ - /** Address line 1 for delivery */ - addressLine1?: string; - - /** Address line 2 for delivery */ - addressLine2?: string; - - /** City for delivery */ - city?: string; - - /** Country for delivery */ - country?: string; - - /** First name for delivery */ - legalFirstName?: string; - - /** Last name for delivery */ - legalLastName?: string; - - /** Phone number for delivery */ - phoneNumber?: string; - - /** State for delivery */ - state?: string; - - /** Zip code for delivery */ - zipPostCode?: string; -}>; - -type PersonalBankAccountForm = Form; - -type WorkspaceSettingsForm = Form<{ - name: string; -}>; - -type ReportFieldEditForm = Form>; - -type CloseAccountForm = Form<{ - reasonForLeaving: string; - phoneOrEmail: string; -}>; - -type IdologyQuestionsForm = Form<{ - answer: string; -}>; - -type AdditionalDetailStepForm = Form<{ - legalFirstName: string; - legalLastName: string; - addressStreet: string; - addressCity: string; - addressZipCode: string; - phoneNumber: string; - dob: string; - ssn: string; - addressState: string; -}>; - -type RoomNameForm = Form<{ - roomName: string; -}>; - -export default Form; - -export type { - AddDebitCardForm, - DateOfBirthForm, - PrivateNotesForm, - DisplayNameForm, - FormValueType, - GetPhysicalCardForm, - NewRoomForm, - BaseForm, - IKnowATeacherForm, - IntroSchoolPrincipalForm, - PersonalBankAccountForm, - WorkspaceSettingsForm, - ReportFieldEditForm, - CloseAccountForm, - IdologyQuestionsForm, - AdditionalDetailStepForm, - RoomNameForm, -}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 277011602a17..6846fc302639 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -12,7 +12,6 @@ import type Currency from './Currency'; import type {CurrencyList} from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; -import type {AdditionalDetailStepForm, IdologyQuestionsForm, PrivateNotesForm, ReportFieldEditForm, RoomNameForm} from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; import type Fund from './Fund'; @@ -154,10 +153,5 @@ export type { RecentlyUsedReportFields, LastPaymentMethod, InvitedEmailsToAccountIDs, - PrivateNotesForm, - ReportFieldEditForm, - IdologyQuestionsForm, - AdditionalDetailStepForm, - RoomNameForm, Log, }; From 8a2b943aa3ab57c38d487f7de31307dadd0b28ca Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Mon, 4 Mar 2024 22:09:08 +0530 Subject: [PATCH 043/202] removed IdologyQuestionsForm instead used AdditionalDetailStepForm --- src/ONYXKEYS.ts | 3 --- src/libs/actions/Wallet.ts | 4 ++-- src/pages/EnablePayments/IdologyQuestions.tsx | 4 ++-- src/types/form/AdditionalDetailStepForm.ts | 2 ++ src/types/form/IdologyQuestionsForm.ts | 18 ------------------ src/types/form/index.ts | 1 - 6 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 src/types/form/IdologyQuestionsForm.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 389c270f7510..6834fcaa13ce 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -397,8 +397,6 @@ const ONYXKEYS = { EXIT_SURVEY_REASON_FORM_DRAFT: 'exitSurveyReasonFormDraft', EXIT_SURVEY_RESPONSE_FORM: 'exitSurveyResponseForm', EXIT_SURVEY_RESPONSE_FORM_DRAFT: 'exitSurveyResponseFormDraft', - IDOLOGY_QUESTIONS_FORM: 'idologyQuestionsForm', - IDOLOGY_QUESTIONS_FORM_DRAFT: 'idologyQuestionsFormDraft', WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetails', WALLET_ADDITIONAL_DETAILS_DRAFT: 'walletAdditionalDetailsDraft', }, @@ -446,7 +444,6 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT]: FormTypes.PersonalBankAccountForm; [ONYXKEYS.FORMS.WORKSPACE_DESCRIPTION_FORM]: FormTypes.WorkspaceDescriptionForm; [ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS]: FormTypes.AdditionalDetailStepForm; - [ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM]: FormTypes.IdologyQuestionsForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index ffc68c562c4c..9cb4b28bef20 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -233,7 +233,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: true, }, @@ -243,7 +243,7 @@ function answerQuestionsForWallet(answers: WalletQuestionAnswer[], idNumber: str const finallyData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.IDOLOGY_QUESTIONS_FORM, + key: ONYXKEYS.FORMS.WALLET_ADDITIONAL_DETAILS, value: { isLoading: false, }, diff --git a/src/pages/EnablePayments/IdologyQuestions.tsx b/src/pages/EnablePayments/IdologyQuestions.tsx index 13c71f7005a9..6baea2158613 100644 --- a/src/pages/EnablePayments/IdologyQuestions.tsx +++ b/src/pages/EnablePayments/IdologyQuestions.tsx @@ -92,7 +92,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { } }; - const validate = (values: FormOnyxValues): FormInputErrors => { + const validate = (values: FormOnyxValues): FormInputErrors => { const errors: Errors = {}; if (!values.answer) { errors.answer = translate('additionalDetailsStep.selectAnswer'); @@ -112,7 +112,7 @@ function IdologyQuestions({questions, idNumber}: IdologyQuestionsProps) { ; @@ -27,6 +28,7 @@ type AdditionalDetailStepForm = Form< [INPUT_IDS.ADDRESS_STATE]: string; [INPUT_IDS.DOB]: string; [INPUT_IDS.SSN]: string; + [INPUT_IDS.ANSWER]: string; } >; diff --git a/src/types/form/IdologyQuestionsForm.ts b/src/types/form/IdologyQuestionsForm.ts deleted file mode 100644 index 250e8c6f7766..000000000000 --- a/src/types/form/IdologyQuestionsForm.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import type Form from './Form'; - -const INPUT_IDS = { - ANSWER: 'answer', -} as const; - -type InputID = ValueOf; - -type IdologyQuestionsForm = Form< - InputID, - { - [INPUT_IDS.ANSWER]: string; - } ->; - -export type {IdologyQuestionsForm}; -export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index 498265848e37..0ab53ba9ec0e 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -38,5 +38,4 @@ export type {WorkspaceSettingsForm} from './WorkspaceSettingsForm'; export type {ReportPhysicalCardForm} from './ReportPhysicalCardForm'; export type {WorkspaceDescriptionForm} from './WorkspaceDescriptionForm'; export type {AdditionalDetailStepForm} from './AdditionalDetailStepForm'; -export type {IdologyQuestionsForm} from './IdologyQuestionsForm'; export type {default as Form} from './Form'; From 018516241e2691db789e7e7ff67f171950c2dcb6 Mon Sep 17 00:00:00 2001 From: tienifr Date: Tue, 5 Mar 2024 19:37:54 +0700 Subject: [PATCH 044/202] fix: image shrinks while loading in carousel --- src/components/Lightbox/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Lightbox/index.tsx b/src/components/Lightbox/index.tsx index a7ed6946fb28..1a69e1f8958b 100644 --- a/src/components/Lightbox/index.tsx +++ b/src/components/Lightbox/index.tsx @@ -137,7 +137,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan const [isFallbackImageLoaded, setFallbackImageLoaded] = useState(false); const fallbackSize = useMemo(() => { if (!hasSiblingCarouselItems || !contentSize || isCanvasLoading) { - return DEFAULT_IMAGE_DIMENSION; + return undefined; } const {minScale} = getCanvasFitScale({canvasSize, contentSize}); @@ -217,7 +217,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan > setFallbackImageLoaded(true)} From e9140e1aafc1e0e9cb836c34294a7fdbcfa9b14d Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Tue, 5 Mar 2024 22:02:32 +0530 Subject: [PATCH 045/202] updated setAdditionalDetailsQuestions prop to handle null and added missed addressZipCode INPUT_ID to STEP_FIELDS --- src/libs/actions/Wallet.ts | 3 +-- src/pages/EnablePayments/AdditionalDetailsStep.tsx | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index 9cb4b28bef20..097d9ee0419a 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -52,7 +52,7 @@ function openOnfidoFlow() { API.read(READ_COMMANDS.OPEN_ONFIDO_FLOW, {}, {optimisticData, finallyData}); } -function setAdditionalDetailsQuestions(questions: WalletAdditionalQuestionDetails[], idNumber: string) { +function setAdditionalDetailsQuestions(questions: WalletAdditionalQuestionDetails[] | null, idNumber?: string) { Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {questions, idNumber}); } @@ -75,7 +75,6 @@ function setKYCWallSource(source?: ValueOf, chatRe /** * Validates a user's provided details against a series of checks */ - function updatePersonalDetails(personalDetails: UpdatePersonalDetailsForWalletParams) { const optimisticData: OnyxUpdate[] = [ { diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index 0b663261865f..57b9c7c6ade4 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -57,6 +57,7 @@ const STEP_FIELDS = [ INPUT_IDS.LEGAL_LAST_NAME, INPUT_IDS.ADDRESS_STREET, INPUT_IDS.ADDRESS_CITY, + INPUT_IDS.ADDRESS_ZIP_CODE, INPUT_IDS.PHONE_NUMBER, INPUT_IDS.DOB, INPUT_IDS.ADDRESS_STATE, @@ -132,7 +133,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO > Wallet.setAdditionalDetailsQuestions([], walletAdditionalDetails?.idNumber ?? '')} + onBackButtonPress={() => Wallet.setAdditionalDetailsQuestions(null)} /> Date: Wed, 6 Mar 2024 14:20:49 +0500 Subject: [PATCH 046/202] refactor: use dedicated map for each locale --- src/libs/Localize/index.ts | 39 +++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index ad5e93af24ee..f64d39d5e24a 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -12,6 +12,7 @@ import type {Locale} from '@src/types/onyx'; import type {ReceiptError} from '@src/types/onyx/Transaction'; import LocaleListener from './LocaleListener'; import BaseLocaleListener from './LocaleListener/BaseLocaleListener'; +import type BaseLocale from './LocaleListener/types'; // Current user mail is needed for handling missing translations let userEmail = ''; @@ -94,33 +95,55 @@ function translate(desiredLanguage: 'en' | 'es' | } /** - * Map to store translated values for each locale + * Map to store translated values for each locale. * This is used to avoid translating the same phrase multiple times. * * The data is stored in the following format: * * { - * "name_en": "Name", - * "name_es": "Nombre", + * "name": "Name", * } * * Note: We are not storing any translated values for phrases with variables, * as they have higher chance of being unique, so we'll end up wasting space * in our cache. */ -const translatedValues = new Map(); +const TRANSLATED_VALUES_EN = new Map(); +const TRANSLATED_VALUES_ES = new Map(); +const TRANSLATED_VALUES_ES_ES = new Map(); +const TRANSLATED_VALUES_ES_ONFIDO = new Map(); + +/** + * Returns the map for the given locale. + */ +function getTranslatedValuesMap(locale: BaseLocale) { + switch (locale) { + case CONST.LOCALES.ES_ES: + return TRANSLATED_VALUES_ES_ES; + case CONST.LOCALES.ES_ES_ONFIDO: + return TRANSLATED_VALUES_ES_ONFIDO; + case CONST.LOCALES.ES: + return TRANSLATED_VALUES_ES; + case CONST.LOCALES.DEFAULT: + default: + return TRANSLATED_VALUES_EN; + } +} /** * Uses the locale in this file updated by the Onyx subscriber. */ function translateLocal(phrase: TKey, ...variables: PhraseParameters>) { const preferredLocale = BaseLocaleListener.getPreferredLocale(); - const key = `${phrase}_${preferredLocale}`; + const key = `${phrase}`; const isVariablesEmpty = variables.length === 0; + // Get the map for the preferred locale + const map = getTranslatedValuesMap(preferredLocale); + // Directly access and assign the translated value from the cache, instead of // going through map.has() and map.get() to avoid multiple lookups. - const valueFromCache = translatedValues.get(key); + const valueFromCache = map.get(key); // If the phrase is already translated, return the translated value if (valueFromCache) { @@ -130,7 +153,9 @@ function translateLocal(phrase: TKey, ...variable // We don't want to store translated values for phrases with variables if (isVariablesEmpty) { - translatedValues.set(key, translatedText); + // We set the translated value in the cache in the next iteration + // of the event loop to make this operation asynchronous. + setImmediate(() => map.set(key, translatedText)); } return translatedText; } From 99dd34cfdf973681a713100ea345ced47911e206 Mon Sep 17 00:00:00 2001 From: hurali97 Date: Wed, 6 Mar 2024 14:32:23 +0500 Subject: [PATCH 047/202] refactor: remove setImmediate --- src/libs/Localize/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/Localize/index.ts b/src/libs/Localize/index.ts index f64d39d5e24a..72bb4dd89bb1 100644 --- a/src/libs/Localize/index.ts +++ b/src/libs/Localize/index.ts @@ -153,9 +153,8 @@ function translateLocal(phrase: TKey, ...variable // We don't want to store translated values for phrases with variables if (isVariablesEmpty) { - // We set the translated value in the cache in the next iteration - // of the event loop to make this operation asynchronous. - setImmediate(() => map.set(key, translatedText)); + // We set the translated value in the cache + map.set(key, translatedText); } return translatedText; } From 01ca51592899313913c58ad31e5fa072615b0083 Mon Sep 17 00:00:00 2001 From: Jayesh Mangwani Date: Wed, 6 Mar 2024 21:54:40 +0530 Subject: [PATCH 048/202] deleted unused walletTermsPropTypes --- .../EnablePayments/walletTermsPropTypes.js | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/pages/EnablePayments/walletTermsPropTypes.js diff --git a/src/pages/EnablePayments/walletTermsPropTypes.js b/src/pages/EnablePayments/walletTermsPropTypes.js deleted file mode 100644 index 4420a2dd0861..000000000000 --- a/src/pages/EnablePayments/walletTermsPropTypes.js +++ /dev/null @@ -1,18 +0,0 @@ -import PropTypes from 'prop-types'; -import _ from 'underscore'; -import CONST from '@src/CONST'; - -/** Prop types related to the Terms step of KYC flow */ -export default PropTypes.shape({ - /** Any error message to show */ - errors: PropTypes.objectOf(PropTypes.string), - - /** The source that triggered the KYC wall */ - source: PropTypes.oneOf(_.values(CONST.KYC_WALL_SOURCE)), - - /** When the user accepts the Wallet's terms in order to pay an IOU, this is the ID of the chatReport the IOU is linked to */ - chatReportID: PropTypes.string, - - /** Boolean to indicate whether the submission of wallet terms is being processed */ - isLoading: PropTypes.bool, -}); From b7cdc1b51d9ae04112c81c7c468de55dd29fe372 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:26:24 +0100 Subject: [PATCH 049/202] add initial new tax page --- src/CONST.ts | 4 + src/ONYXKEYS.ts | 2 + src/ROUTES.ts | 4 + src/SCREENS.ts | 1 + src/languages/en.ts | 2 + .../AppNavigator/ModalStackNavigators.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 3 + src/libs/Navigation/types.ts | 3 + .../workspace/taxes/WorkspaceNewTaxPage.tsx | 96 +++++++++++++++++++ .../workspace/taxes/WorkspaceTaxesPage.tsx | 6 +- src/types/form/WorkspaceNewTaxForm.ts | 22 +++++ src/types/form/index.ts | 1 + src/types/onyx/Policy.ts | 2 +- 13 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/pages/workspace/taxes/WorkspaceNewTaxPage.tsx create mode 100644 src/types/form/WorkspaceNewTaxForm.ts diff --git a/src/CONST.ts b/src/CONST.ts index 6861fe174ffe..b981d10e5be3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4021,6 +4021,10 @@ const CONST = { SESSION_STORAGE_KEYS: { INITIAL_URL: 'INITIAL_URL', }, + + TAX_RATES: { + NAME_MAX_LENGTH: 50, + }, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 188ab5646d30..05b1e1bec1f9 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -404,6 +404,7 @@ const ONYXKEYS = { EXIT_SURVEY_REASON_FORM_DRAFT: 'exitSurveyReasonFormDraft', EXIT_SURVEY_RESPONSE_FORM: 'exitSurveyResponseForm', EXIT_SURVEY_RESPONSE_FORM_DRAFT: 'exitSurveyResponseFormDraft', + WORKSPACE_NEW_TAX_FORM: 'workspaceNewTaxForm', }, } as const; @@ -449,6 +450,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM]: FormTypes.ReimbursementAccountForm; [ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT]: FormTypes.PersonalBankAccountForm; [ONYXKEYS.FORMS.WORKSPACE_DESCRIPTION_FORM]: FormTypes.WorkspaceDescriptionForm; + [ONYXKEYS.FORMS.WORKSPACE_NEW_TAX_FORM]: FormTypes.WorkspaceNewTaxForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 9704bf047315..f0f6fed658f9 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -558,6 +558,10 @@ const ROUTES = { route: 'workspace/:policyID/taxes', getRoute: (policyID: string) => `workspace/${policyID}/taxes` as const, }, + WORKSPACE_TAXES_NEW: { + route: 'workspace/:policyID/taxes/new', + getRoute: (policyID: string) => `workspace/${policyID}/taxes/new` as const, + }, // Referral program promotion REFERRAL_DETAILS_MODAL: { route: 'referral/:contentType', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 27909319b724..d48cc9c19b83 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -216,6 +216,7 @@ const SCREENS = { CATEGORIES: 'Workspace_Categories', TAGS: 'Workspace_Tags', TAXES: 'Workspace_Taxes', + TAXES_NEW: 'Workspace_Taxes_New', CURRENCY: 'Workspace_Profile_Currency', WORKFLOWS: 'Workspace_Workflows', WORKFLOWS_APPROVER: 'Workspace_Workflows_Approver', diff --git a/src/languages/en.ts b/src/languages/en.ts index 715640bbb200..56c983ace282 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1787,6 +1787,8 @@ export default { }, taxes: { subtitle: 'Add tax names, rates, and set defaults.', + value: 'Value', + name: 'Name', }, emptyWorkspace: { title: 'Create a workspace', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index cee9e31cedea..001891805bb2 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -262,6 +262,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/settings/ExitSurvey/ExitSurveyConfirmPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default as React.ComponentType, + [SCREENS.WORKSPACE.TAXES_NEW]: () => require('../../../pages/workspace/taxes/WorkspaceNewTaxPage').default as React.ComponentType, }); const EnablePaymentsStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 0cae5e34e958..76f605c648b8 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -309,6 +309,9 @@ const config: LinkingOptions['config'] = { [SCREENS.SETTINGS.EXIT_SURVEY.CONFIRM]: { path: ROUTES.SETTINGS_EXIT_SURVEY_CONFIRM.route, }, + [SCREENS.WORKSPACE.TAXES_NEW]: { + path: ROUTES.WORKSPACE_TAXES_NEW.route, + }, }, }, [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 5c64dd62fd43..fcd69c49a135 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -225,6 +225,9 @@ type SettingsNavigatorParamList = { [SCREENS.SETTINGS.EXIT_SURVEY.CONFIRM]: { backTo: Routes; }; + [SCREENS.WORKSPACE.TAXES_NEW]: { + policyID: string; + }; } & ReimbursementAccountNavigatorParamList; type NewChatNavigatorParamList = { diff --git a/src/pages/workspace/taxes/WorkspaceNewTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceNewTaxPage.tsx new file mode 100644 index 000000000000..a23b8d3061de --- /dev/null +++ b/src/pages/workspace/taxes/WorkspaceNewTaxPage.tsx @@ -0,0 +1,96 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import AmountPicker from '@components/AmountPicker'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormOnyxValues} from '@components/Form/types'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextPicker from '@components/TextPicker'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {createWorkspaceTax} from '@libs/actions/TaxRate'; +import Navigation from '@libs/Navigation/Navigation'; +import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; +import INPUT_IDS from '@src/types/form/WorkspaceNewTaxForm'; +import type {TaxRate} from '@src/types/onyx'; + +type WorkspaceNewTaxPageProps = StackScreenProps; + +function WorkspaceNewTaxPage({ + route: { + params: {policyID}, + }, +}: WorkspaceNewTaxPageProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const validate = useCallback((values: FormOnyxValues): Partial> => { + const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.VALUE, INPUT_IDS.NAME]); + + const value = Number(values[INPUT_IDS.VALUE]); + if (value > 100 || value < 0) { + errors[INPUT_IDS.VALUE] = 'workspace.taxes.errors.value.percentageRange'; + } + + return errors; + }, []); + + const submitForm = useCallback( + (values: FormOnyxValues) => { + // TODO: Add proper code generation + const taxRate = { + ...values, + code: `tax_${Date.now()}`, + } satisfies TaxRate; + createWorkspaceTax({policyID, taxRate}); + Navigation.goBack(); + }, + [policyID], + ); + + return ( + + + + + + + + + + ); +} + +WorkspaceNewTaxPage.displayName = 'WorkspaceNewTaxPage'; + +export default WorkspaceNewTaxPage; diff --git a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx index b19a69adebe2..0f4340b97eb8 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx @@ -15,12 +15,14 @@ import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import Navigation from '@libs/Navigation/Navigation'; import type {CentralPaneNavigatorParamList} from '@navigation/types'; import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper'; import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper'; import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading'; import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; -import type SCREENS from '@src/SCREENS'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; type WorkspaceTaxesPageProps = WithPolicyAndFullscreenLoadingProps & StackScreenProps; @@ -83,7 +85,7 @@ function WorkspaceTaxesPage({policy}: WorkspaceTaxesPageProps) {