diff --git a/src/components/AddressSearch/types.ts b/src/components/AddressSearch/types.ts index e115d4f697b2..e4735e9d0020 100644 --- a/src/components/AddressSearch/types.ts +++ b/src/components/AddressSearch/types.ts @@ -79,7 +79,7 @@ type AddressSearchProps = { predefinedPlaces?: Place[] | null; /** A map of inputID key names */ - renamedInputKeys: RenamedInputKeysProps; + renamedInputKeys?: RenamedInputKeysProps; /** Maximum number of characters allowed in search input */ maxInputLength?: number; diff --git a/src/languages/types.ts b/src/languages/types.ts index 410c8e1c2085..bb56d5c38cd3 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -157,7 +157,7 @@ type EnterMagicCodeParams = {contactMethod: string}; type TransferParams = {amount: string}; -type InstantSummaryParams = {rate: number; minAmount: number}; +type InstantSummaryParams = {rate: string; minAmount: string}; type NotYouParams = {user: string}; diff --git a/src/libs/GetPhysicalCardUtils.ts b/src/libs/GetPhysicalCardUtils.ts index 3f8a7d191f4b..48c537f0f14c 100644 --- a/src/libs/GetPhysicalCardUtils.ts +++ b/src/libs/GetPhysicalCardUtils.ts @@ -54,24 +54,20 @@ function setCurrentRoute(currentRoute: string, domain: string, privatePersonalDe * @param privatePersonalDetails * @returns */ -function getUpdatedDraftValues( - draftValues: OnyxEntry, - privatePersonalDetails: OnyxEntry, - loginList: OnyxEntry, -): Partial { +function getUpdatedDraftValues(draftValues: OnyxEntry, privatePersonalDetails: OnyxEntry, loginList: OnyxEntry): GetPhysicalCardForm { const {address, legalFirstName, legalLastName, phoneNumber} = privatePersonalDetails ?? {}; return { /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ // we do not need to use nullish coalescing here because we want to allow empty strings - legalFirstName: draftValues?.legalFirstName || legalFirstName, - legalLastName: draftValues?.legalLastName || legalLastName, - addressLine1: draftValues?.addressLine1 || address?.street.split('\n')[0], + legalFirstName: draftValues?.legalFirstName || legalFirstName || '', + legalLastName: draftValues?.legalLastName || legalLastName || '', + addressLine1: draftValues?.addressLine1 || address?.street.split('\n')[0] || '', addressLine2: draftValues?.addressLine2 || address?.street.split('\n')[1] || '', - city: draftValues?.city || address?.city, - country: draftValues?.country || address?.country, + city: draftValues?.city || address?.city || '', + country: draftValues?.country || address?.country || '', phoneNumber: draftValues?.phoneNumber || phoneNumber || UserUtils.getSecondaryPhoneLogin(loginList) || '', - state: draftValues?.state || address?.state, + state: draftValues?.state || address?.state || '', zipPostCode: draftValues?.zipPostCode || address?.zip || '', /* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ }; diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index f02bb3bd2aca..765ab76fd638 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -502,6 +502,7 @@ type PublicScreensParamList = { shortLivedAuthToken?: string; shortLivedToken?: string; exitTo?: Routes | HybridAppRoute; + domain?: Routes; }; [SCREENS.VALIDATE_LOGIN]: { accountID: string; diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 2cc32616562d..756ef902d913 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -178,3 +178,4 @@ function revealVirtualCardDetails(cardID: number): Promise { } export {requestReplacementExpensifyCard, activatePhysicalExpensifyCard, clearCardListErrors, reportVirtualExpensifyCardFraud, revealVirtualCardDetails}; +export type {ReplacementReason}; diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx similarity index 76% rename from src/pages/settings/Wallet/ActivatePhysicalCardPage.js rename to src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx index 24156a7c74fc..4edf637618ea 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -1,14 +1,14 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import type {StackScreenProps} from '@react-navigation/stack'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import BigNumberPad from '@components/BigNumberPad'; import Button from '@components/Button'; import IllustratedHeaderPageLayout from '@components/IllustratedHeaderPageLayout'; import LottieAnimations from '@components/LottieAnimations'; import MagicCodeInput from '@components/MagicCodeInput'; +import type {MagicCodeInputHandle} from '@components/MagicCodeInput'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -19,32 +19,22 @@ import * as CardUtils from '@libs/CardUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import type {PublicScreensParamList} from '@libs/Navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as CardSettings from '@userActions/Card'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; -import assignedCardPropTypes from './assignedCardPropTypes'; +import type {Card} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; -const propTypes = { - /* Onyx Props */ - - /** The details about the Expensify cards */ - cardList: PropTypes.objectOf(assignedCardPropTypes), - - /** Navigation route context info provided by react navigation */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** domain passed via route /settings/wallet/card/:domain */ - domain: PropTypes.string, - }), - }).isRequired, +type ActivatePhysicalCardPageOnyxProps = { + /** Card list propTypes */ + cardList: OnyxEntry>; }; -const defaultProps = { - cardList: {}, -}; +type ActivatePhysicalCardPageProps = ActivatePhysicalCardPageOnyxProps & StackScreenProps; const LAST_FOUR_DIGITS_LENGTH = 4; const MAGIC_INPUT_MIN_HEIGHT = 86; @@ -52,9 +42,9 @@ const MAGIC_INPUT_MIN_HEIGHT = 86; function ActivatePhysicalCardPage({ cardList, route: { - params: {domain}, + params: {domain = ''}, }, -}) { +}: ActivatePhysicalCardPageProps) { const theme = useTheme(); const styles = useThemeStyles(); const {isExtraSmallScreenHeight} = useWindowDimensions(); @@ -65,23 +55,24 @@ function ActivatePhysicalCardPage({ const [lastFourDigits, setLastFourDigits] = useState(''); const [lastPressedDigit, setLastPressedDigit] = useState(''); - const domainCards = CardUtils.getDomainCards(cardList)[domain]; - const physicalCard = _.find(domainCards, (card) => !card.isVirtual) || {}; - const cardID = lodashGet(physicalCard, 'cardID', 0); - const cardError = ErrorUtils.getLatestErrorMessage(physicalCard); + const domainCards = CardUtils.getDomainCards(cardList)[domain] ?? []; + const physicalCard = domainCards.find((card) => !card.isVirtual); + const cardID = physicalCard?.cardID ?? 0; + const cardError = ErrorUtils.getLatestErrorMessage(physicalCard ?? {}); - const activateCardCodeInputRef = useRef(null); + const activateCardCodeInputRef = useRef(null); /** * If state of the card is CONST.EXPENSIFY_CARD.STATE.OPEN, navigate to card details screen. */ useEffect(() => { - if (physicalCard.isLoading || lodashGet(cardList, `${cardID}.state`, 0) !== CONST.EXPENSIFY_CARD.STATE.OPEN) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + if (physicalCard?.isLoading || cardList?.[cardID]?.state !== CONST.EXPENSIFY_CARD.STATE.OPEN) { return; } Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain)); - }, [cardID, cardList, domain, physicalCard.isLoading]); + }, [cardID, cardList, domain, physicalCard?.isLoading]); useEffect( () => () => { @@ -95,17 +86,13 @@ function ActivatePhysicalCardPage({ * * NOTE: If the same digit is pressed twice in a row, append it to the end of the string * so that useEffect inside MagicCodeInput will be triggered by artificial change of the value. - * - * @param {String} key */ - const updateLastPressedDigit = useCallback((key) => setLastPressedDigit(lastPressedDigit === key ? lastPressedDigit + key : key), [lastPressedDigit]); + const updateLastPressedDigit = useCallback((key: string) => setLastPressedDigit(lastPressedDigit === key ? lastPressedDigit + key : key), [lastPressedDigit]); /** * Handle card activation code input - * - * @param {String} text */ - const onCodeInput = (text) => { + const onCodeInput = (text: string) => { setFormError(''); if (cardError) { @@ -116,7 +103,7 @@ function ActivatePhysicalCardPage({ }; const submitAndNavigateToNextPage = useCallback(() => { - activateCardCodeInputRef.current.blur(); + activateCardCodeInputRef.current?.blur(); if (lastFourDigits.replace(CONST.MAGIC_CODE_EMPTY_CHAR, '').length !== LAST_FOUR_DIGITS_LENGTH) { setFormError('activateCardPage.error.thatDidntMatch'); @@ -126,7 +113,7 @@ function ActivatePhysicalCardPage({ CardSettings.activatePhysicalExpensifyCard(lastFourDigits, cardID); }, [lastFourDigits, cardID]); - if (_.isEmpty(physicalCard)) { + if (isEmptyObject(physicalCard)) { return ; } @@ -161,7 +148,7 @@ function ActivatePhysicalCardPage({