diff --git a/src/components/AddPaymentMethodMenu.tsx b/src/components/AddPaymentMethodMenu.tsx index 734e8affa9ea..325bab091bec 100644 --- a/src/components/AddPaymentMethodMenu.tsx +++ b/src/components/AddPaymentMethodMenu.tsx @@ -11,7 +11,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {AnchorPosition} from '@src/styles'; import type {Report, Session} from '@src/types/onyx'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import * as Expensicons from './Icon/Expensicons'; import type {PaymentMethod} from './KYCWall/types'; import PopoverMenu from './PopoverMenu'; @@ -32,7 +31,7 @@ type AddPaymentMethodMenuProps = AddPaymentMethodMenuOnyxProps & { onItemSelected: (paymentMethod: PaymentMethod) => void; /** The IOU/Expense report we are paying */ - iouReport?: OnyxEntry | EmptyObject; + iouReport?: OnyxEntry; /** Anchor position for the AddPaymentMenu. */ anchorPosition: AnchorPosition; @@ -65,9 +64,9 @@ function AddPaymentMethodMenu({ // Users can choose to pay with business bank account in case of Expense reports or in case of P2P IOU report // which then starts a bottom up flow and creates a Collect workspace where the payer is an admin and payee is an employee. - const isIOUReport = ReportUtils.isIOUReport(iouReport ?? {}); + const isIOUReport = ReportUtils.isIOUReport(iouReport); const canUseBusinessBankAccount = - ReportUtils.isExpenseReport(iouReport ?? {}) || (isIOUReport && !ReportActionsUtils.hasRequestFromCurrentAccount(iouReport?.reportID ?? '-1', session?.accountID ?? -1)); + ReportUtils.isExpenseReport(iouReport) || (isIOUReport && !ReportActionsUtils.hasRequestFromCurrentAccount(iouReport?.reportID ?? '-1', session?.accountID ?? -1)); const canUsePersonalBankAccount = shouldShowPersonalBankAccountOption || isIOUReport; diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 19bad0fbdf5a..df027ed6edb4 100644 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -26,7 +26,6 @@ import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type ModalType from '@src/types/utils/ModalType'; import AttachmentCarousel from './Attachments/AttachmentCarousel'; @@ -99,7 +98,7 @@ type AttachmentModalProps = AttachmentModalOnyxProps & { headerTitle?: string; /** The report that has this attachment */ - report?: OnyxEntry | EmptyObject; + report?: OnyxEntry; /** The type of the attachment */ type?: ValueOf; diff --git a/src/components/ConnectionLayout.tsx b/src/components/ConnectionLayout.tsx index 1d10a3b48d55..7e29da7763c5 100644 --- a/src/components/ConnectionLayout.tsx +++ b/src/components/ConnectionLayout.tsx @@ -94,8 +94,8 @@ function ConnectionLayout({ }: ConnectionLayoutProps) { const {translate} = useLocalize(); - const policy = PolicyUtils.getPolicy(policyID ?? ''); - const isConnectionEmpty = isEmpty(policy.connections?.[connectionName]); + const policy = PolicyUtils.getPolicy(policyID); + const isConnectionEmpty = isEmpty(policy?.connections?.[connectionName]); const renderSelectionContent = useMemo( () => ( diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx index 49850d73e2d7..66e297e50734 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx @@ -15,7 +15,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Report} from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type MentionReportOnyxProps = { @@ -27,7 +26,7 @@ type MentionReportRendererProps = MentionReportOnyxProps & CustomRendererProps value.replace(CONST.UNICODE.LTR, '').replace('#', ''); -const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEntry | EmptyObject, reports: OnyxCollection, tnode: TText | TPhrasing) => { +const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEntry, reports: OnyxCollection, tnode: TText | TPhrasing) => { let reportID: string | undefined; let mentionDisplayText: string; diff --git a/src/components/KYCWall/types.ts b/src/components/KYCWall/types.ts index 53ed00e04143..568f2a15903f 100644 --- a/src/components/KYCWall/types.ts +++ b/src/components/KYCWall/types.ts @@ -7,7 +7,6 @@ import type {Route} from '@src/ROUTES'; import type {Report} from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; type Source = ValueOf; @@ -45,7 +44,7 @@ type KYCWallProps = { chatReportID?: string; /** The IOU/Expense report we are paying */ - iouReport?: OnyxEntry | EmptyObject; + iouReport?: OnyxEntry; /** Where the popover should be positioned relative to the anchor points. */ anchorAlignment?: AnchorAlignment; diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index efd67d6c6b50..2cc931303a30 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -133,7 +133,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio if (ReportActionsUtils.isMoneyRequestAction(lastReportAction)) { lastReportActionTransactionID = ReportActionsUtils.getOriginalMessage(lastReportAction)?.IOUTransactionID ?? '-1'; } - const lastReportActionTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${lastReportActionTransactionID}`] ?? {}; + const lastReportActionTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${lastReportActionTransactionID}`]; return ( ; @@ -58,7 +57,7 @@ type OptionRowLHNDataProps = { transaction: OnyxEntry; /** The transaction linked to the report's last action */ - lastReportActionTransaction?: OnyxEntry; + lastReportActionTransaction?: OnyxEntry; /** Whether a report contains a draft */ hasDraftComment: boolean; diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index e0e30d14d2a2..322a68ffe32a 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -72,7 +72,7 @@ const LocaleContext = createContext({ preferredLocale: CONST.LOCALES.DEFAULT, }); -function LocaleContextProvider({preferredLocale, currentUserPersonalDetails = {}, children}: LocaleContextProviderProps) { +function LocaleContextProvider({preferredLocale, currentUserPersonalDetails, children}: LocaleContextProviderProps) { const locale = preferredLocale ?? CONST.LOCALES.DEFAULT; const selectedTimezone = useMemo(() => currentUserPersonalDetails?.timezone?.selected, [currentUserPersonalDetails]); diff --git a/src/components/PopoverProvider/index.native.tsx b/src/components/PopoverProvider/index.native.tsx index b13909945bef..d58322fafe63 100644 --- a/src/components/PopoverProvider/index.native.tsx +++ b/src/components/PopoverProvider/index.native.tsx @@ -3,7 +3,7 @@ import type {PopoverContextProps, PopoverContextValue} from './types'; const PopoverContext = React.createContext({ onOpen: () => {}, - popover: {}, + popover: null, close: () => {}, isOpen: false, }); @@ -13,7 +13,7 @@ function PopoverContextProvider(props: PopoverContextProps) { () => ({ onOpen: () => {}, close: () => {}, - popover: {}, + popover: null, isOpen: false, }), [], diff --git a/src/components/PopoverProvider/index.tsx b/src/components/PopoverProvider/index.tsx index cc6c84477525..82f3c6c7d61a 100644 --- a/src/components/PopoverProvider/index.tsx +++ b/src/components/PopoverProvider/index.tsx @@ -6,7 +6,7 @@ import type {AnchorRef, PopoverContextProps, PopoverContextValue} from './types' const PopoverContext = createContext({ onOpen: () => {}, - popover: {}, + popover: null, close: () => {}, isOpen: false, }); diff --git a/src/components/PopoverProvider/types.ts b/src/components/PopoverProvider/types.ts index 5022aee0f843..b3d21e9ed5d9 100644 --- a/src/components/PopoverProvider/types.ts +++ b/src/components/PopoverProvider/types.ts @@ -8,7 +8,7 @@ type PopoverContextProps = { type PopoverContextValue = { onOpen?: (popoverParams: AnchorRef) => void; - popover?: AnchorRef | Record | null; + popover?: AnchorRef | null; close: (anchorRef?: RefObject) => void; isOpen: boolean; }; diff --git a/src/components/Reactions/ReactionTooltipContent.tsx b/src/components/Reactions/ReactionTooltipContent.tsx index 198eba1f969c..8f469b01272c 100644 --- a/src/components/Reactions/ReactionTooltipContent.tsx +++ b/src/components/Reactions/ReactionTooltipContent.tsx @@ -23,7 +23,7 @@ type ReactionTooltipContentProps = Pick PersonalDetailsUtils.getPersonalDetailsByIDs(accountIDs, currentUserPersonalDetails.accountID, true), [currentUserPersonalDetails.accountID, accountIDs]); diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index bdb9d52a67b7..9e31dc110579 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -4,6 +4,7 @@ import truncate from 'lodash/truncate'; import React, {useMemo} from 'react'; import {View} from 'react-native'; import type {GestureResponderEvent} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import Button from '@components/Button'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -42,7 +43,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; import type {OriginalMessageIOU} from '@src/types/onyx/OriginalMessage'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {MoneyRequestPreviewProps, PendingMessageProps} from './types'; @@ -247,10 +247,8 @@ function MoneyRequestPreviewContent({ }; const getDisplayDeleteAmountText = (): string => { - const iouOriginalMessage: OriginalMessageIOU | EmptyObject = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) ?? {} : {}; - const {amount = 0, currency = CONST.CURRENCY.USD} = iouOriginalMessage; - - return CurrencyUtils.convertToDisplayString(amount, currency); + const iouOriginalMessage: OnyxEntry = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) ?? undefined : undefined; + return CurrencyUtils.convertToDisplayString(iouOriginalMessage?.amount, iouOriginalMessage?.currency); }; const displayAmount = isDeleted ? getDisplayDeleteAmountText() : getDisplayAmountText(); diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 06083365bc96..c796a267fd01 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -199,7 +199,7 @@ function ReportPreview({ if (ReportUtils.hasHeldExpenses(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else { - IOU.approveMoneyRequest(iouReport ?? {}, true); + IOU.approveMoneyRequest(iouReport, true); } }; diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index 20bc30f1d937..3b5265685050 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -80,8 +80,8 @@ function SelectionScreen({ }: SelectionScreenProps) { const {translate} = useLocalize(); - const policy = PolicyUtils.getPolicy(policyID ?? ''); - const isConnectionEmpty = isEmpty(policy.connections?.[connectionName]); + const policy = PolicyUtils.getPolicy(policyID); + const isConnectionEmpty = isEmpty(policy?.connections?.[connectionName]); return ( | EmptyObject; + iouReport?: OnyxEntry; /** Should we show the payment options? */ shouldHidePaymentOptions?: boolean; @@ -121,9 +120,9 @@ function SettlementButton({ chatReportID = '', currency = CONST.CURRENCY.USD, enablePaymentsRoute, - // The "iouReport" and "nvpLastPaymentMethod" objects needs to be stable to prevent the "useMemo" - // hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT - iouReport = CONST.EMPTY_OBJECT, + iouReport, + // The "nvpLastPaymentMethod" object needs to be stable to prevent the "useMemo" + // hook from being recreated unnecessarily, hence the use of CONST.EMPTY_OBJECT nvpLastPaymentMethod = CONST.EMPTY_OBJECT, isDisabled = false, isLoading = false, @@ -148,7 +147,7 @@ function SettlementButton({ const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || -1}`); const isInvoiceReport = (!isEmptyObject(iouReport) && ReportUtils.isInvoiceReport(iouReport)) || false; const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport); - const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry)); + const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport)); const shouldShowPayElsewhereOption = (!isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) && !isInvoiceReport; const paymentButtonOptions = useMemo(() => { const buttonOptions = []; @@ -238,7 +237,7 @@ function SettlementButton({ if (confirmApproval) { confirmApproval(); } else { - IOU.approveMoneyRequest(iouReport ?? {}); + IOU.approveMoneyRequest(iouReport); } return; } diff --git a/src/components/withCurrentUserPersonalDetails.tsx b/src/components/withCurrentUserPersonalDetails.tsx index 8bbaf1c9305c..91fd388eabf1 100644 --- a/src/components/withCurrentUserPersonalDetails.tsx +++ b/src/components/withCurrentUserPersonalDetails.tsx @@ -4,10 +4,8 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import getComponentDisplayName from '@libs/getComponentDisplayName'; import type {PersonalDetails} from '@src/types/onyx'; -type CurrentUserPersonalDetails = PersonalDetails | Record; - type HOCProps = { - currentUserPersonalDetails: CurrentUserPersonalDetails; + currentUserPersonalDetails: PersonalDetails; }; type WithCurrentUserPersonalDetailsProps = HOCProps; @@ -32,4 +30,4 @@ export default function ; - function useCurrentUserPersonalDetails() { const session = useSession(); - const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; + const personalDetails = usePersonalDetails(); const accountID = session?.accountID ?? -1; const accountPersonalDetails = personalDetails?.[accountID]; - const currentUserPersonalDetails: CurrentUserPersonalDetails = useMemo( - () => (accountPersonalDetails ? {...accountPersonalDetails, accountID} : {}) as CurrentUserPersonalDetails, - [accountPersonalDetails, accountID], - ); + const currentUserPersonalDetails: PersonalDetails = useMemo(() => ({...accountPersonalDetails, accountID}), [accountPersonalDetails, accountID]); return currentUserPersonalDetails; } diff --git a/src/hooks/useKeyboardShortcut.ts b/src/hooks/useKeyboardShortcut.ts index 6bf8b2c52bc3..1c5bbc426ef2 100644 --- a/src/hooks/useKeyboardShortcut.ts +++ b/src/hooks/useKeyboardShortcut.ts @@ -26,7 +26,7 @@ type KeyboardShortcutConfig = { * Register a keyboard shortcut handler. * Recommendation: To ensure stability, wrap the `callback` function with the useCallback hook before using it with this hook. */ -export default function useKeyboardShortcut(shortcut: Shortcut, callback: (e?: GestureResponderEvent | KeyboardEvent) => void, config: KeyboardShortcutConfig | Record = {}) { +export default function useKeyboardShortcut(shortcut: Shortcut, callback: (e?: GestureResponderEvent | KeyboardEvent) => void, config: KeyboardShortcutConfig = {}) { const { captureOnInputs = true, shouldBubble = false, diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index d381fe0646d5..f94ba0c54978 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -1,6 +1,5 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import type * as Parameters from './parameters'; import type SignInUserParams from './parameters/SignInUserParams'; import type UpdateBeneficialOwnersForBankAccountParams from './parameters/UpdateBeneficialOwnersForBankAccountParams'; @@ -263,7 +262,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_AUTOMATIC_TIMEZONE]: Parameters.UpdateAutomaticTimezoneParams; [WRITE_COMMANDS.UPDATE_SELECTED_TIMEZONE]: Parameters.UpdateSelectedTimezoneParams; [WRITE_COMMANDS.UPDATE_USER_AVATAR]: Parameters.UpdateUserAvatarParams; - [WRITE_COMMANDS.DELETE_USER_AVATAR]: EmptyObject; + [WRITE_COMMANDS.DELETE_USER_AVATAR]: null; [WRITE_COMMANDS.REFER_TEACHERS_UNITE_VOLUNTEER]: Parameters.ReferTeachersUniteVolunteerParams; [WRITE_COMMANDS.ADD_SCHOOL_PRINCIPAL]: Parameters.AddSchoolPrincipalParams; [WRITE_COMMANDS.CLOSE_ACCOUNT]: Parameters.CloseAccountParams; @@ -279,7 +278,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.SET_CONTACT_METHOD_AS_DEFAULT]: Parameters.SetContactMethodAsDefaultParams; [WRITE_COMMANDS.UPDATE_THEME]: Parameters.UpdateThemeParams; [WRITE_COMMANDS.UPDATE_STATUS]: Parameters.UpdateStatusParams; - [WRITE_COMMANDS.CLEAR_STATUS]: EmptyObject; + [WRITE_COMMANDS.CLEAR_STATUS]: null; [WRITE_COMMANDS.UPDATE_PERSONAL_DETAILS_FOR_WALLET]: Parameters.UpdatePersonalDetailsForWalletParams; [WRITE_COMMANDS.VERIFY_IDENTITY]: Parameters.VerifyIdentityParams; [WRITE_COMMANDS.ACCEPT_WALLET_TERMS]: Parameters.AcceptWalletTermsParams; @@ -294,8 +293,8 @@ type WriteCommandParameters = { [WRITE_COMMANDS.SIGN_IN_USER_WITH_LINK]: Parameters.SignInUserWithLinkParams; [WRITE_COMMANDS.REQUEST_UNLINK_VALIDATION_LINK]: Parameters.RequestUnlinkValidationLinkParams; [WRITE_COMMANDS.UNLINK_LOGIN]: Parameters.UnlinkLoginParams; - [WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH]: EmptyObject; - [WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH]: EmptyObject; + [WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH]: null; + [WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH]: null; [WRITE_COMMANDS.TWO_FACTOR_AUTH_VALIDATE]: Parameters.ValidateTwoFactorAuthParams; [WRITE_COMMANDS.ADD_COMMENT]: Parameters.AddCommentOrAttachementParams; [WRITE_COMMANDS.ADD_ATTACHMENT]: Parameters.AddCommentOrAttachementParams; @@ -446,7 +445,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.SHARE_TRACKED_EXPENSE]: Parameters.ShareTrackedExpenseParams; [WRITE_COMMANDS.LEAVE_POLICY]: Parameters.LeavePolicyParams; [WRITE_COMMANDS.DISMISS_VIOLATION]: Parameters.DismissViolationParams; - [WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS]: EmptyObject; + [WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; [WRITE_COMMANDS.SEND_INVOICE]: Parameters.SendInvoiceParams; [WRITE_COMMANDS.PAY_INVOICE]: Parameters.PayInvoiceParams; [WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams; @@ -518,9 +517,9 @@ type ReadCommandParameters = { [READ_COMMANDS.SYNC_POLICY_TO_XERO]: Parameters.SyncPolicyToXeroParams; [READ_COMMANDS.OPEN_REIMBURSEMENT_ACCOUNT_PAGE]: Parameters.OpenReimbursementAccountPageParams; [READ_COMMANDS.OPEN_WORKSPACE_VIEW]: Parameters.OpenWorkspaceViewParams; - [READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN]: EmptyObject; - [READ_COMMANDS.OPEN_PAYMENTS_PAGE]: EmptyObject; - [READ_COMMANDS.OPEN_PERSONAL_DETAILS]: EmptyObject; + [READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN]: null; + [READ_COMMANDS.OPEN_PAYMENTS_PAGE]: null; + [READ_COMMANDS.OPEN_PERSONAL_DETAILS]: null; [READ_COMMANDS.OPEN_PUBLIC_PROFILE_PAGE]: Parameters.OpenPublicProfilePageParams; [READ_COMMANDS.OPEN_PLAID_BANK_LOGIN]: Parameters.OpenPlaidBankLoginParams; [READ_COMMANDS.OPEN_PLAID_BANK_ACCOUNT_SELECTOR]: Parameters.OpenPlaidBankAccountSelectorParams; @@ -535,9 +534,9 @@ type ReadCommandParameters = { [READ_COMMANDS.GET_ROUTE]: Parameters.GetRouteParams; [READ_COMMANDS.GET_ROUTE_FOR_DRAFT]: Parameters.GetRouteParams; [READ_COMMANDS.GET_STATEMENT_PDF]: Parameters.GetStatementPDFParams; - [READ_COMMANDS.OPEN_ONFIDO_FLOW]: EmptyObject; - [READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE]: EmptyObject; - [READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE]: EmptyObject; + [READ_COMMANDS.OPEN_ONFIDO_FLOW]: null; + [READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE]: null; + [READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE]: null; [READ_COMMANDS.BEGIN_SIGNIN]: Parameters.BeginSignInParams; [READ_COMMANDS.SIGN_IN_WITH_SHORT_LIVED_AUTH_TOKEN]: Parameters.SignInWithShortLivedAuthTokenParams; [READ_COMMANDS.SIGN_IN_WITH_SUPPORT_AUTH_TOKEN]: Parameters.SignInWithSupportAuthTokenParams; @@ -583,7 +582,7 @@ type SideEffectRequestCommandParameters = { [SIDE_EFFECT_REQUEST_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; [SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; [SIDE_EFFECT_REQUEST_COMMANDS.GENERATE_SPOTNANA_TOKEN]: Parameters.GenerateSpotnanaTokenParams; - [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: EmptyObject; + [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: null; }; type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index 17a933766a69..dda5427e9c9f 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -7,7 +7,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {LastSelectedDistanceRates, OnyxInputOrEntry, Report} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import type Policy from '@src/types/onyx/Policy'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import * as CurrencyUtils from './CurrencyUtils'; import * as PolicyUtils from './PolicyUtils'; @@ -78,7 +77,7 @@ function getMileageRates(policy: OnyxInputOrEntry, includeDisabledRates * @returns [currency] - The currency associated with the rate. * @returns [unit] - The unit of measurement for the distance. */ -function getDefaultMileageRate(policy: OnyxInputOrEntry | EmptyObject): MileageRate | undefined { +function getDefaultMileageRate(policy: OnyxInputOrEntry): MileageRate | undefined { if (isEmptyObject(policy) || !policy?.customUnits) { return undefined; } diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index d10511a325ed..5a7182405681 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -1,7 +1,7 @@ import {findFocusedRoute} from '@react-navigation/core'; import type {EventArg, NavigationContainerEventMap} from '@react-navigation/native'; import {CommonActions, getPathFromState, StackActions} from '@react-navigation/native'; -import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import Log from '@libs/Log'; import isCentralPaneName from '@libs/NavigationUtils'; @@ -13,7 +13,6 @@ import type {HybridAppRoute, Route} from '@src/ROUTES'; import ROUTES, {HYBRID_APP_ROUTES} from '@src/ROUTES'; import {PROTECTED_SCREENS} from '@src/SCREENS'; import type {Report} from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import originalCloseRHPFlow from './closeRHPFlow'; import originalDismissModal from './dismissModal'; import originalDismissModalWithReport from './dismissModalWithReport'; @@ -79,7 +78,7 @@ const closeRHPFlow = (ref = navigationRef) => originalCloseRHPFlow(ref); // Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies. // This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet. // Then we can pass the report as a param without getting it from the Onyx. -const dismissModalWithReport = (report: Report | EmptyObject, ref = navigationRef) => originalDismissModalWithReport(report, ref); +const dismissModalWithReport = (report: OnyxEntry, ref = navigationRef) => originalDismissModalWithReport(report, ref); /** Method for finding on which index in stack we are. */ function getActiveRouteIndex(stateOrRoute: StateOrRoute, index?: number): number | undefined { diff --git a/src/libs/Navigation/dismissModalWithReport.ts b/src/libs/Navigation/dismissModalWithReport.ts index 6e1f360a4f58..1bb939f5230f 100644 --- a/src/libs/Navigation/dismissModalWithReport.ts +++ b/src/libs/Navigation/dismissModalWithReport.ts @@ -2,6 +2,7 @@ import {getActionFromState} from '@react-navigation/core'; import type {NavigationContainerRef} from '@react-navigation/native'; import {StackActions} from '@react-navigation/native'; import {findLastIndex} from 'lodash'; +import type {OnyxEntry} from 'react-native-onyx'; import Log from '@libs/Log'; import isCentralPaneName from '@libs/NavigationUtils'; import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; @@ -10,7 +11,6 @@ import NAVIGATORS from '@src/NAVIGATORS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type {Report} from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import getPolicyIDFromState from './getPolicyIDFromState'; import getStateFromPath from './getStateFromPath'; @@ -26,7 +26,7 @@ import type {RootStackParamList, StackNavigationAction, State} from './types'; * * @param targetReportID - The reportID to navigate to after dismissing the modal */ -function dismissModalWithReport(targetReport: Report | EmptyObject, navigationRef: NavigationContainerRef) { +function dismissModalWithReport(targetReport: OnyxEntry, navigationRef: NavigationContainerRef) { if (!navigationRef.isReady()) { return; } @@ -45,8 +45,8 @@ function dismissModalWithReport(targetReport: Report | EmptyObject, navigationRe case SCREENS.REPORT_AVATAR: case SCREENS.CONCIERGE: // If we are not in the target report, we need to navigate to it after dismissing the modal - if (targetReport.reportID !== getTopmostReportId(state)) { - const reportState = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReport.reportID)); + if (targetReport?.reportID !== getTopmostReportId(state)) { + const reportState = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReport?.reportID ?? '-1')); const policyID = getPolicyIDFromState(state as State); const policyMemberAccountIDs = getPolicyEmployeeAccountIDs(policyID); const shouldOpenAllWorkspace = isEmptyObject(targetReport) ? true : !doesReportBelongToWorkspace(targetReport, policyMemberAccountIDs, policyID); diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 484104ebb881..0ac2878b6857 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -1,14 +1,13 @@ import {format, lastDayOfMonth, setDate} from 'date-fns'; import {Str} from 'expensify-common'; import Onyx from 'react-native-onyx'; -import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report, ReportNextStep} from '@src/types/onyx'; import type {Message} from '@src/types/onyx/ReportNextStep'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import DateUtils from './DateUtils'; import EmailUtils from './EmailUtils'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; @@ -73,16 +72,12 @@ type BuildNextStepParameters = { * @param parameters.isPaidWithExpensify - Whether a report has been paid with Expensify or outside * @returns nextStep */ -function buildNextStep( - report: Report | EmptyObject, - predictedNextStatus: ValueOf, - {isPaidWithExpensify}: BuildNextStepParameters = {}, -): ReportNextStep | null { +function buildNextStep(report: OnyxEntry, predictedNextStatus: ValueOf, {isPaidWithExpensify}: BuildNextStepParameters = {}): ReportNextStep | null { if (!ReportUtils.isExpenseReport(report)) { return null; } - const {policyID = '', ownerAccountID = -1, managerID = -1} = report; + const {policyID = '', ownerAccountID = -1, managerID = -1} = report ?? {}; const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? ({} as Policy); const {harvesting, preventSelfApproval, autoReportingFrequency, autoReportingOffset} = policy; const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, ownerAccountID); @@ -282,7 +277,7 @@ function buildNextStep( accountID: currentUserAccountID, email: currentUserEmail, }, - report as Report, + report, ) ) { optimisticNextStep = { diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 077fb5b72102..b85d93bf0d33 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -36,7 +36,6 @@ import type { import type {Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import times from '@src/utils/times'; import Timing from './actions/Timing'; @@ -2139,23 +2138,23 @@ function getShareLogOptions(options: OptionList, searchValue = '', betas: Beta[] /** * Build the IOUConfirmation options for showing the payee personalDetail */ -function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: PersonalDetails | EmptyObject, amountText?: string): PayeePersonalDetails { - const formattedLogin = LocalePhoneNumber.formatPhoneNumber(personalDetail.login ?? ''); +function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: OnyxEntry, amountText?: string): PayeePersonalDetails { + const formattedLogin = LocalePhoneNumber.formatPhoneNumber(personalDetail?.login ?? ''); return { text: PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, formattedLogin), alternateText: formattedLogin || PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, '', false), icons: [ { - source: personalDetail.avatar ?? FallbackAvatar, - name: personalDetail.login ?? '', + source: personalDetail?.avatar ?? FallbackAvatar, + name: personalDetail?.login ?? '', type: CONST.ICON_TYPE_AVATAR, - id: personalDetail.accountID, + id: personalDetail?.accountID, }, ], descriptiveText: amountText ?? '', - login: personalDetail.login ?? '', - accountID: personalDetail.accountID, - keyForList: String(personalDetail.accountID), + login: personalDetail?.login ?? '', + accountID: personalDetail?.accountID ?? -1, + keyForList: String(personalDetail?.accountID ?? -1), }; } diff --git a/src/libs/PersonalDetailsUtils.ts b/src/libs/PersonalDetailsUtils.ts index 9a35dfc41b72..8ba468e87ed0 100644 --- a/src/libs/PersonalDetailsUtils.ts +++ b/src/libs/PersonalDetailsUtils.ts @@ -1,7 +1,6 @@ import {Str} from 'expensify-common'; 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 {OnyxInputOrEntry, PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx'; @@ -272,7 +271,7 @@ function createDisplayName(login: string, passedPersonalDetails: Pick /** * Retrieves the distance custom unit object for the given policy */ -function getCustomUnit(policy: OnyxEntry | EmptyObject) { +function getCustomUnit(policy: OnyxEntry): CustomUnit | undefined { return Object.values(policy?.customUnits ?? {}).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE); } /** * Retrieves custom unit rate object from the given customUnitRateID */ -function getCustomUnitRate(policy: OnyxEntry | EmptyObject, customUnitRateID: string): Rate | EmptyObject { +function getCustomUnitRate(policy: OnyxEntry, customUnitRateID: string): Rate | undefined { const distanceUnit = getCustomUnit(policy); - return distanceUnit?.rates[customUnitRateID] ?? {}; + return distanceUnit?.rates[customUnitRateID]; } function getRateDisplayValue(value: number, toLocaleDigit: (arg: string) => string): string { @@ -150,26 +149,26 @@ function isExpensifyTeam(email: string | undefined): boolean { /** * Checks if the current user is an admin of the policy. */ -const isPolicyAdmin = (policy: OnyxInputOrEntry | EmptyObject, currentUserLogin?: string): boolean => +const isPolicyAdmin = (policy: OnyxInputOrEntry, currentUserLogin?: string): boolean => (policy?.role ?? (currentUserLogin && policy?.employeeList?.[currentUserLogin]?.role)) === CONST.POLICY.ROLE.ADMIN; /** * Checks if the current user is an user of the policy. */ -const isPolicyUser = (policy: OnyxInputOrEntry | EmptyObject, currentUserLogin?: string): boolean => +const isPolicyUser = (policy: OnyxInputOrEntry, currentUserLogin?: string): boolean => (policy?.role ?? (currentUserLogin && policy?.employeeList?.[currentUserLogin]?.role)) === CONST.POLICY.ROLE.USER; /** * Checks if the policy is a free group policy. */ -const isFreeGroupPolicy = (policy: OnyxEntry | EmptyObject): boolean => policy?.type === CONST.POLICY.TYPE.FREE; +const isFreeGroupPolicy = (policy: OnyxEntry): boolean => policy?.type === CONST.POLICY.TYPE.FREE; const isPolicyEmployee = (policyID: string, policies: OnyxCollection): boolean => Object.values(policies ?? {}).some((policy) => policy?.id === policyID); /** * Checks if the current user is an owner (creator) of the policy. */ -const isPolicyOwner = (policy: OnyxInputOrEntry | EmptyObject, currentUserAccountID: number): boolean => policy?.ownerAccountID === currentUserAccountID; +const isPolicyOwner = (policy: OnyxInputOrEntry, currentUserAccountID: number): boolean => policy?.ownerAccountID === currentUserAccountID; /** * Create an object mapping member emails to their accountIDs. Filter for members without errors if includeMemberWithErrors is false, and get the login email from the personalDetail object using the accountID. @@ -294,7 +293,7 @@ function isPendingDeletePolicy(policy: OnyxEntry): boolean { return policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; } -function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { +function isPaidGroupPolicy(policy: OnyxEntry): boolean { return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE; } @@ -311,14 +310,14 @@ function isTaxTrackingEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry | EmptyObject): boolean { +function isInstantSubmitEnabled(policy: OnyxInputOrEntry): boolean { return policy?.type === CONST.POLICY.TYPE.FREE || (policy?.autoReporting === true && policy?.autoReportingFrequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT); } /** * Checks if policy's approval mode is "optional", a.k.a. "Submit & Close" */ -function isSubmitAndClose(policy: OnyxInputOrEntry | EmptyObject): boolean { +function isSubmitAndClose(policy: OnyxInputOrEntry): boolean { return policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.OPTIONAL; } @@ -361,7 +360,7 @@ function canEditTaxRate(policy: Policy, taxID: string): boolean { return policy.taxRates?.defaultExternalID !== taxID; } -function isPolicyFeatureEnabled(policy: OnyxEntry | EmptyObject, featureName: PolicyFeatureName): boolean { +function isPolicyFeatureEnabled(policy: OnyxEntry, featureName: PolicyFeatureName): boolean { if (featureName === CONST.POLICY.MORE_FEATURES.ARE_TAXES_ENABLED) { return !!policy?.tax?.trackingEnabled; } @@ -369,7 +368,7 @@ function isPolicyFeatureEnabled(policy: OnyxEntry | EmptyObject, feature return !!policy?.[featureName]; } -function getApprovalWorkflow(policy: OnyxEntry | EmptyObject): ValueOf { +function getApprovalWorkflow(policy: OnyxEntry): ValueOf { if (policy?.type === CONST.POLICY.TYPE.PERSONAL) { return CONST.POLICY.APPROVAL_MODE.OPTIONAL; } @@ -377,14 +376,14 @@ function getApprovalWorkflow(policy: OnyxEntry | EmptyObject): ValueOf | EmptyObject): string { +function getDefaultApprover(policy: OnyxEntry): string { return policy?.approver ?? policy?.owner ?? ''; } /** * Returns the accountID to whom the given employeeAccountID submits reports to in the given Policy. */ -function getSubmitToAccountID(policy: OnyxEntry | EmptyObject, employeeAccountID: number): number { +function getSubmitToAccountID(policy: OnyxEntry, employeeAccountID: number): number { const employeeLogin = getLoginsByAccountIDs([employeeAccountID])[0]; const defaultApprover = getDefaultApprover(policy); @@ -412,11 +411,11 @@ function getAdminEmployees(policy: OnyxEntry): PolicyEmployee[] { /** * Returns the policy of the report */ -function getPolicy(policyID: string | undefined): Policy | EmptyObject { +function getPolicy(policyID: string | undefined): OnyxEntry { if (!allPolicies || !policyID) { - return {}; + return undefined; } - return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? {}; + return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; } /** Return active policies where current user is an admin */ diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index f21dd187f466..352a75bf9255 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -13,7 +13,6 @@ import type Report from '@src/types/onyx/Report'; import type {Message, OriginalMessage, ReportActions} from '@src/types/onyx/ReportAction'; import type ReportAction from '@src/types/onyx/ReportAction'; import type ReportActionName from '@src/types/onyx/ReportActionName'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DateUtils from './DateUtils'; import * as Environment from './Environment/Environment'; @@ -122,7 +121,7 @@ function isReversedTransaction(reportAction: OnyxInputOrEntry 0; } -function isPendingRemove(reportAction: OnyxInputOrEntry | EmptyObject): boolean { +function isPendingRemove(reportAction: OnyxInputOrEntry): boolean { if (isEmptyObject(reportAction)) { return false; } @@ -277,11 +276,11 @@ function isThreadParentMessage(reportAction: OnyxEntry, reportID: * * @deprecated Use Onyx.connect() or withOnyx() instead */ -function getParentReportAction(report: OnyxInputOrEntry | EmptyObject): ReportAction | EmptyObject { +function getParentReportAction(report: OnyxInputOrEntry): OnyxEntry { if (!report?.parentReportID || !report.parentReportActionID) { - return {}; + return undefined; } - return allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`]?.[report.parentReportActionID] ?? {}; + return allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`]?.[report.parentReportActionID]; } /** @@ -299,7 +298,7 @@ function isSentMoneyReportAction(reportAction: OnyxEntry | EmptyObject): boolean { +function isTransactionThread(parentReportAction: OnyxInputOrEntry): boolean { if (isEmptyObject(parentReportAction) || !isMoneyRequestAction(parentReportAction)) { return false; } @@ -1288,9 +1287,9 @@ function isReportActionUnread(reportAction: OnyxEntry, lastReadTim * Check whether the current report action of the report is unread or not * */ -function isCurrentActionUnread(report: Report | EmptyObject, reportAction: ReportAction): boolean { - const lastReadTime = report.lastReadTime ?? ''; - const sortedReportActions = getSortedReportActions(Object.values(getAllReportActions(report.reportID))); +function isCurrentActionUnread(report: OnyxEntry, reportAction: ReportAction): boolean { + const lastReadTime = report?.lastReadTime ?? ''; + const sortedReportActions = getSortedReportActions(Object.values(getAllReportActions(report?.reportID ?? '-1'))); const currentActionIndex = sortedReportActions.findIndex((action) => action.reportActionID === reportAction.reportActionID); if (currentActionIndex === -1) { return false; @@ -1319,14 +1318,14 @@ function isActionableJoinRequestPending(reportID: string): boolean { return !!findPendingRequest; } -function isApprovedOrSubmittedReportAction(action: OnyxEntry | EmptyObject) { +function isApprovedOrSubmittedReportAction(action: OnyxEntry) { return [CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.SUBMITTED].some((type) => type === action?.actionName); } /** * Gets the text version of the message in a report action */ -function getReportActionMessageText(reportAction: OnyxEntry | EmptyObject): string { +function getReportActionMessageText(reportAction: OnyxEntry): string { if (!Array.isArray(reportAction?.message)) { return getReportActionText(reportAction); } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7a3b2d1d0869..a696b73cd270 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -45,7 +45,6 @@ import type {Status} from '@src/types/onyx/PersonalDetails'; import type {NotificationPreference, Participants, PendingChatMember, Participant as ReportParticipant} from '@src/types/onyx/Report'; import type {Message, ReportActions} from '@src/types/onyx/ReportAction'; import type {Comment, Receipt, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import AccountUtils from './AccountUtils'; @@ -577,7 +576,7 @@ function getCurrentUserDisplayNameOrEmail(): string | undefined { return currentUserPersonalDetails?.displayName ?? currentUserEmail; } -function getChatType(report: OnyxInputOrEntry | Participant | EmptyObject): ValueOf | undefined { +function getChatType(report: OnyxInputOrEntry | Participant): ValueOf | undefined { return report?.chatType; } @@ -607,20 +606,20 @@ function isDraftReport(reportID: string | undefined): boolean { /** * Returns the parentReport if the given report is a thread */ -function getParentReport(report: OnyxEntry | EmptyObject): OnyxEntry | EmptyObject { +function getParentReport(report: OnyxEntry): OnyxEntry { if (!report?.parentReportID) { - return {}; + return undefined; } - return allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`] ?? {}; + return allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]; } /** * Returns the root parentReport if the given report is nested. * Uses recursion to iterate any depth of nested reports. */ -function getRootParentReport(report: OnyxEntry | undefined | EmptyObject): OnyxEntry | EmptyObject { +function getRootParentReport(report: OnyxEntry): OnyxEntry { if (!report) { - return {}; + return undefined; } // Returns the current report as the root report, because it does not have a parentReportID @@ -637,11 +636,11 @@ function getRootParentReport(report: OnyxEntry | undefined | EmptyObject /** * Returns the policy of the report */ -function getPolicy(policyID: string | undefined): Policy | EmptyObject { +function getPolicy(policyID: string | undefined): OnyxEntry { if (!allPolicies || !policyID) { - return {}; + return undefined; } - return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? {}; + return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; } /** @@ -655,7 +654,7 @@ function getPolicyType(report: OnyxInputOrEntry, policies: OnyxCollectio /** * Get the policy name from a given report */ -function getPolicyName(report: OnyxInputOrEntry | undefined | EmptyObject, returnEmptyIfNotFound = false, policy?: OnyxInputOrEntry): string { +function getPolicyName(report: OnyxInputOrEntry, returnEmptyIfNotFound = false, policy?: OnyxInputOrEntry): string { const noPolicyFound = returnEmptyIfNotFound ? '' : Localize.translateLocal('workspace.common.unavailable'); if (isEmptyObject(report)) { return noPolicyFound; @@ -687,25 +686,25 @@ function getReportParticipantsTitle(accountIDs: number[]): string { /** * Checks if a report is a chat report. */ -function isChatReport(report: OnyxEntry | EmptyObject): boolean { +function isChatReport(report: OnyxEntry): boolean { return report?.type === CONST.REPORT.TYPE.CHAT; } -function isInvoiceReport(report: OnyxInputOrEntry | EmptyObject): boolean { +function isInvoiceReport(report: OnyxInputOrEntry): boolean { return report?.type === CONST.REPORT.TYPE.INVOICE; } /** * Checks if a report is an Expense report. */ -function isExpenseReport(report: OnyxInputOrEntry | EmptyObject): boolean { +function isExpenseReport(report: OnyxInputOrEntry): boolean { return report?.type === CONST.REPORT.TYPE.EXPENSE; } /** * Checks if a report is an IOU report using report or reportID */ -function isIOUReport(reportOrID: OnyxInputOrEntry | string | EmptyObject): boolean { +function isIOUReport(reportOrID: OnyxInputOrEntry | string): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; return report?.type === CONST.REPORT.TYPE.IOU; } @@ -713,7 +712,7 @@ function isIOUReport(reportOrID: OnyxInputOrEntry | string | EmptyObject /** * Checks if a report is an IOU report using report */ -function isIOUReportUsingReport(report: OnyxEntry | EmptyObject): report is Report { +function isIOUReportUsingReport(report: OnyxEntry): report is Report { return report?.type === CONST.REPORT.TYPE.IOU; } /** @@ -730,7 +729,7 @@ function isTaskReport(report: OnyxInputOrEntry): boolean { * There's another situation where you don't have access to the parentReportAction (because it was created in a chat you don't have access to) * In this case, we have added the key to the report itself */ -function isCanceledTaskReport(report: OnyxInputOrEntry | EmptyObject = {}, parentReportAction: OnyxInputOrEntry | EmptyObject = {}): boolean { +function isCanceledTaskReport(report: OnyxInputOrEntry, parentReportAction: OnyxInputOrEntry = null): boolean { if (!isEmptyObject(parentReportAction) && (ReportActionsUtils.getReportActionMessage(parentReportAction)?.isDeletedParentAction ?? false)) { return true; } @@ -747,7 +746,7 @@ function isCanceledTaskReport(report: OnyxInputOrEntry | EmptyObject = { * * @param parentReportAction - The parent report action of the report (Used to check if the task has been canceled) */ -function isOpenTaskReport(report: OnyxInputOrEntry, parentReportAction: OnyxInputOrEntry | EmptyObject = {}): boolean { +function isOpenTaskReport(report: OnyxInputOrEntry, parentReportAction: OnyxInputOrEntry = null): boolean { return ( isTaskReport(report) && !isCanceledTaskReport(report, parentReportAction) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN ); @@ -770,7 +769,7 @@ function isReportManager(report: OnyxEntry): boolean { /** * Checks if the supplied report has been approved */ -function isReportApproved(reportOrID: OnyxInputOrEntry | string | EmptyObject, parentReportAction: OnyxEntry = undefined): boolean { +function isReportApproved(reportOrID: OnyxInputOrEntry | string, parentReportAction: OnyxEntry = undefined): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; if (!report) { return parentReportAction?.childStateNum === CONST.REPORT.STATE_NUM.APPROVED && parentReportAction?.childStatusNum === CONST.REPORT.STATUS_NUM.APPROVED; @@ -781,7 +780,7 @@ function isReportApproved(reportOrID: OnyxInputOrEntry | string | EmptyO /** * Checks if the supplied report is an expense report in Open state and status. */ -function isOpenExpenseReport(report: OnyxInputOrEntry | EmptyObject): boolean { +function isOpenExpenseReport(report: OnyxInputOrEntry): boolean { return isExpenseReport(report) && report?.stateNum === CONST.REPORT.STATE_NUM.OPEN && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN; } @@ -811,7 +810,7 @@ function isSettled(reportID: string | undefined): boolean { if (!allReports || !reportID) { return false; } - const report: Report | EmptyObject = allReports[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? {}; + const report = allReports[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; if (isEmptyObject(report) || report.isWaitingOnBankAccount) { return false; } @@ -881,11 +880,11 @@ function isUserCreatedPolicyRoom(report: OnyxEntry): boolean { /** * Whether the provided report is a Policy Expense chat. */ -function isPolicyExpenseChat(report: OnyxInputOrEntry | Participant | EmptyObject): boolean { +function isPolicyExpenseChat(report: OnyxInputOrEntry | Participant): boolean { return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT || (report?.isPolicyExpenseChat ?? false); } -function isInvoiceRoom(report: OnyxEntry | EmptyObject): boolean { +function isInvoiceRoom(report: OnyxEntry): boolean { return getChatType(report) === CONST.REPORT.CHAT_TYPE.INVOICE; } @@ -964,7 +963,7 @@ function isPaidGroupPolicyExpenseReport(report: OnyxEntry): boolean { /** * Checks if the supplied report is an invoice report in Open state and status. */ -function isOpenInvoiceReport(report: OnyxEntry | EmptyObject): boolean { +function isOpenInvoiceReport(report: OnyxEntry): boolean { return isInvoiceReport(report) && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN; } @@ -1102,7 +1101,7 @@ function sortReportsByLastRead(reports: Array>, reportMetadata /** * Returns true if report is still being processed */ -function isProcessingReport(report: OnyxEntry | EmptyObject): boolean { +function isProcessingReport(report: OnyxEntry): boolean { return report?.stateNum === CONST.REPORT.STATE_NUM.SUBMITTED && report?.statusNum === CONST.REPORT.STATUS_NUM.SUBMITTED; } @@ -1182,7 +1181,7 @@ function findLastAccessedReport( let sortedReports = sortReportsByLastRead(reportsValues, reportMetadata); - let adminReport: OnyxEntry | undefined; + let adminReport: OnyxEntry; if (openOnAdminRoom) { adminReport = sortedReports.find((report) => { const chatType = getChatType(report); @@ -1236,7 +1235,7 @@ function isClosedExpenseReportWithNoExpenses(report: OnyxEntry): boolean /** * Whether the provided report is an archived room */ -function isArchivedRoom(report: OnyxInputOrEntry | EmptyObject, reportNameValuePairs?: OnyxInputOrEntry | EmptyObject): boolean { +function isArchivedRoom(report: OnyxInputOrEntry, reportNameValuePairs?: OnyxInputOrEntry): boolean { if (reportNameValuePairs) { return reportNameValuePairs.isArchived; } @@ -1256,7 +1255,7 @@ function isArchivedRoomWithID(reportID?: string) { /** * Whether the provided report is a closed report */ -function isClosedReport(report: OnyxEntry | EmptyObject): boolean { +function isClosedReport(report: OnyxEntry): boolean { return report?.statusNum === CONST.REPORT.STATUS_NUM.CLOSED; } @@ -1272,7 +1271,7 @@ function isJoinRequestInAdminRoom(report: OnyxEntry): boolean { // since they are not a part of the company, and should not action it on their behalf. if (report.policyID) { const policy = getPolicy(report.policyID); - if (!PolicyUtils.isExpensifyTeam(policy.owner) && PolicyUtils.isExpensifyTeam(currentUserPersonalDetails?.login)) { + if (!PolicyUtils.isExpensifyTeam(policy?.owner) && PolicyUtils.isExpensifyTeam(currentUserPersonalDetails?.login)) { return false; } } @@ -1423,7 +1422,7 @@ function isMoneyRequest(reportOrID: OnyxEntry | string): boolean { /** * Checks if a report is an IOU or expense report. */ -function isMoneyRequestReport(reportOrID: OnyxInputOrEntry | EmptyObject | string): boolean { +function isMoneyRequestReport(reportOrID: OnyxInputOrEntry | string): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID; return isIOUReport(report) || isExpenseReport(report); } @@ -1949,11 +1948,11 @@ function getIcons( const parentReportAction = ReportActionsUtils.getParentReportAction(report); const workspaceIcon = getWorkspaceIcon(report, policy); const memberIcon = { - source: personalDetails?.[parentReportAction.actorAccountID ?? -1]?.avatar ?? FallbackAvatar, - id: parentReportAction.actorAccountID, + source: personalDetails?.[parentReportAction?.actorAccountID ?? -1]?.avatar ?? FallbackAvatar, + id: parentReportAction?.actorAccountID, type: CONST.ICON_TYPE_AVATAR, - name: personalDetails?.[parentReportAction.actorAccountID ?? -1]?.displayName ?? '', - fallbackIcon: personalDetails?.[parentReportAction.actorAccountID ?? -1]?.fallbackIcon, + name: personalDetails?.[parentReportAction?.actorAccountID ?? -1]?.displayName ?? '', + fallbackIcon: personalDetails?.[parentReportAction?.actorAccountID ?? -1]?.fallbackIcon, }; return [memberIcon, workspaceIcon]; @@ -1961,14 +1960,14 @@ function getIcons( if (isChatThread(report)) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const actorAccountID = parentReportAction.actorAccountID; + const actorAccountID = parentReportAction?.actorAccountID; const actorDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(allPersonalDetails?.[actorAccountID ?? -1], '', false); const actorIcon = { id: actorAccountID, source: personalDetails?.[actorAccountID ?? -1]?.avatar ?? FallbackAvatar, name: actorDisplayName, type: CONST.ICON_TYPE_AVATAR, - fallbackIcon: personalDetails?.[parentReportAction.actorAccountID ?? -1]?.fallbackIcon, + fallbackIcon: personalDetails?.[parentReportAction?.actorAccountID ?? -1]?.fallbackIcon, }; if (isWorkspaceThread(report)) { @@ -2197,7 +2196,7 @@ function getReimbursementQueuedActionMessage( */ function getReimbursementDeQueuedActionMessage( reportAction: OnyxEntry>, - reportOrID: OnyxEntry | EmptyObject | string, + reportOrID: OnyxEntry | string, isLHNPreview = false, ): string { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] : reportOrID; @@ -2279,7 +2278,7 @@ function getLastVisibleMessage(reportID: string | undefined, actionsToMerge: Rep * * @param [parentReportAction] - The parent report action of the report (Used to check if the task has been canceled) */ -function isWaitingForAssigneeToCompleteTask(report: OnyxEntry, parentReportAction: OnyxEntry | EmptyObject = {}): boolean { +function isWaitingForAssigneeToCompleteTask(report: OnyxEntry, parentReportAction: OnyxEntry): boolean { return isTaskReport(report) && isReportManager(report) && isOpenTaskReport(report, parentReportAction); } @@ -2303,7 +2302,7 @@ function isUnreadWithMention(reportOrOption: OnyxEntry | OptionData): bo * @param option (report or optionItem) * @param parentReportAction (the report action the current report is a thread of) */ -function requiresAttentionFromCurrentUser(optionOrReport: OnyxEntry | OptionData, parentReportAction: EmptyObject | OnyxEntry = {}) { +function requiresAttentionFromCurrentUser(optionOrReport: OnyxEntry | OptionData, parentReportAction?: OnyxEntry) { if (!optionOrReport) { return false; } @@ -2653,7 +2652,7 @@ function canEditMoneyRequest(reportAction: OnyxInputOrEntry if ((fieldToEdit === CONST.EDIT_REQUEST_FIELD.AMOUNT || fieldToEdit === CONST.EDIT_REQUEST_FIELD.CURRENCY) && TransactionUtils.isDistanceRequest(transaction)) { const policy = getPolicy(moneyRequestReport?.reportID ?? '-1'); - const isAdmin = isExpenseReport(moneyRequestReport) && policy.role === CONST.POLICY.ROLE.ADMIN; + const isAdmin = isExpenseReport(moneyRequestReport) && policy?.role === CONST.POLICY.ROLE.ADMIN; const isManager = isExpenseReport(moneyRequestReport) && currentUserAccountID === moneyRequestReport?.managerID; return isAdmin || isManager; @@ -2843,14 +2842,14 @@ function areAllRequestsBeingSmartScanned(iouReportID: string, reportPreviewActio * * NOTE: This method is only meant to be used inside this action file. Do not export and use it elsewhere. Use withOnyx or Onyx.connect() instead. */ -function getLinkedTransaction(reportAction: OnyxEntry): Transaction | EmptyObject { +function getLinkedTransaction(reportAction: OnyxEntry): OnyxEntry { let transactionID = ''; if (ReportActionsUtils.isMoneyRequestAction(reportAction)) { transactionID = ReportActionsUtils.getOriginalMessage(reportAction)?.IOUTransactionID ?? '-1'; } - return allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? {}; + return allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; } /** @@ -2933,13 +2932,13 @@ function getTransactionReportName(reportAction: OnyxEntry | EmptyObject | string, - iouReportAction: OnyxInputOrEntry | EmptyObject = {}, + reportOrID: OnyxInputOrEntry | string, + iouReportAction: OnyxInputOrEntry = null, shouldConsiderScanningReceiptOrPendingRoute = false, isPreviewMessageForParentChatReport = false, policy?: OnyxInputOrEntry, isForListPreview = false, - originalReportAction: OnyxInputOrEntry | EmptyObject = iouReportAction, + originalReportAction: OnyxInputOrEntry = iouReportAction, ): string { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] : reportOrID; const reportActionMessage = ReportActionsUtils.getReportActionHtml(iouReportAction); @@ -3173,7 +3172,7 @@ function isChangeLogObject(originalMessage?: OriginalMessageChangeLog): Original * @param parentReportAction * @param parentReportActionMessage */ -function getAdminRoomInvitedParticipants(parentReportAction: ReportAction | EmptyObject, parentReportActionMessage: string) { +function getAdminRoomInvitedParticipants(parentReportAction: OnyxEntry, parentReportActionMessage: string) { if (isEmptyObject(parentReportAction)) { return parentReportActionMessage || Localize.translateLocal('parentReportAction.deletedMessage'); } @@ -3273,7 +3272,7 @@ function parseReportActionHtmlToText(reportAction: OnyxEntry, repo /** * Get the report action message for a report action. */ -function getReportActionMessage(reportAction: ReportAction | EmptyObject, reportID?: string, childReportID?: string) { +function getReportActionMessage(reportAction: OnyxEntry, reportID?: string, childReportID?: string) { if (isEmptyObject(reportAction)) { return ''; } @@ -3858,7 +3857,7 @@ function getHumanReadableStatus(statusNum: number): string { * If after all replacements the formula is empty, the original formula is returned. * See {@link https://help.expensify.com/articles/expensify-classic/insights-and-custom-reporting/Custom-Templates} */ -function populateOptimisticReportFormula(formula: string, report: OptimisticExpenseReport, policy: Policy | EmptyObject): string { +function populateOptimisticReportFormula(formula: string, report: OptimisticExpenseReport, policy: OnyxEntry): string { const createdDate = report.lastVisibleActionCreated ? new Date(report.lastVisibleActionCreated) : undefined; const result = formula // We don't translate because the server response is always in English @@ -3866,7 +3865,7 @@ function populateOptimisticReportFormula(formula: string, report: OptimisticExpe .replaceAll('{report:startdate}', createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '') .replaceAll('{report:total}', report.total !== undefined ? CurrencyUtils.convertToDisplayString(Math.abs(report.total), report.currency).toString() : '') .replaceAll('{report:currency}', report.currency ?? '') - .replaceAll('{report:policyname}', policy.name ?? '') + .replaceAll('{report:policyname}', policy?.name ?? '') .replaceAll('{report:created}', createdDate ? format(createdDate, CONST.DATE.FNS_DATE_TIME_FORMAT_STRING) : '') .replaceAll('{report:created:yyyy-MM-dd}', createdDate ? format(createdDate, CONST.DATE.FNS_FORMAT_STRING) : '') .replaceAll('{report:status}', report.statusNum !== undefined ? getHumanReadableStatus(report.statusNum) : '') @@ -3957,7 +3956,7 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa function getIOUSubmittedMessage(report: OnyxEntry) { const policy = getPolicy(report?.policyID); - if (report?.ownerAccountID !== currentUserAccountID && policy.role === CONST.POLICY.ROLE.ADMIN) { + if (report?.ownerAccountID !== currentUserAccountID && policy?.role === CONST.POLICY.ROLE.ADMIN) { const ownerPersonalDetail = getPersonalDetailsForAccountID(report?.ownerAccountID ?? -1); const ownerDisplayName = `${ownerPersonalDetail.displayName ?? ''}${ownerPersonalDetail.displayName !== ownerPersonalDetail.login ? ` (${ownerPersonalDetail.login})` : ''}`; @@ -4123,7 +4122,7 @@ function buildOptimisticIOUReportAction( receipt: Receipt = {}, isOwnPolicyExpenseChat = false, created = DateUtils.getDBTime(), - linkedExpenseReportAction: ReportAction | EmptyObject = {}, + linkedExpenseReportAction?: OnyxEntry, ): OptimisticIOUReportAction { const IOUReportID = iouReportID || generateReportID(); @@ -5180,7 +5179,7 @@ function buildOptimisticMoneyRequestEntities( isPersonalTrackingExpense?: boolean, existingTransactionThreadReportID?: string, linkedTrackedExpenseReportAction?: ReportAction, -): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport, OptimisticCreatedReportAction | EmptyObject] { +): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport, OptimisticCreatedReportAction | null] { const createdActionForChat = buildOptimisticCreatedReportAction(payeeEmail); // The `CREATED` action must be optimistically generated before the IOU action so that it won't appear after the IOU action in the chat. @@ -5206,7 +5205,7 @@ function buildOptimisticMoneyRequestEntities( // Create optimistic transactionThread and the `CREATED` action for it, if existingTransactionThreadReportID is undefined const transactionThread = buildTransactionThread(iouAction, iouReport, existingTransactionThreadReportID); - const createdActionForTransactionThread = existingTransactionThreadReportID ? {} : buildOptimisticCreatedReportAction(payeeEmail); + const createdActionForTransactionThread = existingTransactionThreadReportID ? null : buildOptimisticCreatedReportAction(payeeEmail); // The IOU action and the transactionThread are co-dependent as parent-child, so we need to link them together iouAction.childReportID = existingTransactionThreadReportID ?? transactionThread.reportID; @@ -5588,7 +5587,7 @@ function getAllPolicyReports(policyID: string): Array> { /** * Returns true if Chronos is one of the chat participants (1:1) */ -function chatIncludesChronos(report: OnyxInputOrEntry | EmptyObject): boolean { +function chatIncludesChronos(report: OnyxInputOrEntry): boolean { const participantAccountIDs = Object.keys(report?.participants ?? {}).map(Number); return participantAccountIDs.includes(CONST.ACCOUNT_ID.CHRONOS); } @@ -6088,7 +6087,7 @@ function getAddWorkspaceRoomOrChatReportErrors(report: OnyxEntry): Error /** * Return true if the expense report is marked for deletion. */ -function isMoneyRequestReportPendingDeletion(reportOrID: OnyxEntry | EmptyObject | string): boolean { +function isMoneyRequestReportPendingDeletion(reportOrID: OnyxEntry | string): boolean { const report = typeof reportOrID === 'string' ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] : reportOrID; if (!isMoneyRequestReport(report)) { return false; @@ -6463,7 +6462,7 @@ function shouldUseFullTitleToDisplay(report: OnyxEntry): boolean { ); } -function getRoom(type: ValueOf, policyID: string): OnyxEntry | undefined { +function getRoom(type: ValueOf, policyID: string): OnyxEntry { const room = Object.values(allReports ?? {}).find((report) => report?.policyID === policyID && report?.chatType === type && !isThread(report)); return room; } @@ -6471,7 +6470,7 @@ function getRoom(type: ValueOf, policyID: string) /** * We only want policy members who are members of the report to be able to modify the report description, but not in thread chat. */ -function canEditReportDescription(report: OnyxEntry, policy: OnyxEntry | undefined): boolean { +function canEditReportDescription(report: OnyxEntry, policy: OnyxEntry): boolean { return ( !isMoneyRequestReport(report) && !isArchivedRoom(report) && @@ -6539,7 +6538,7 @@ function navigateToPrivateNotes(report: OnyxEntry, session: OnyxEntry TransactionUtils.isOnHold(transaction)); } @@ -6652,7 +6651,7 @@ function getAllAncestorReportActions(report: Report | null | undefined): Ancesto break; } - const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport ?? {}, parentReportAction); + const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport, parentReportAction); allAncestors.push({ report: currentReport, reportAction: parentReportAction, @@ -6719,7 +6718,7 @@ function getAllAncestorReportActionIDs(report: Report | null | undefined, includ * @param lastVisibleActionCreated Last visible action created of the child report * @param type The type of action in the child report */ -function getOptimisticDataForParentReportAction(reportID: string, lastVisibleActionCreated: string, type: string): Array { +function getOptimisticDataForParentReportAction(reportID: string, lastVisibleActionCreated: string, type: string): Array { const report = getReportOrDraftReport(reportID); if (!report || isEmptyObject(report)) { @@ -6733,13 +6732,13 @@ function getOptimisticDataForParentReportAction(reportID: string, lastVisibleAct const ancestorReport = getReportOrDraftReport(ancestors.reportIDs[index]); if (!ancestorReport || isEmptyObject(ancestorReport)) { - return {} as EmptyObject; + return null; } const ancestorReportAction = ReportActionsUtils.getReportAction(ancestorReport.reportID, ancestors.reportActionsIDs[index]); if (!ancestorReportAction || isEmptyObject(ancestorReportAction)) { - return {} as EmptyObject; + return null; } return { @@ -6752,7 +6751,7 @@ function getOptimisticDataForParentReportAction(reportID: string, lastVisibleAct }); } -function canBeAutoReimbursed(report: OnyxInputOrEntry, policy: OnyxInputOrEntry | EmptyObject): boolean { +function canBeAutoReimbursed(report: OnyxInputOrEntry, policy: OnyxInputOrEntry): boolean { if (isEmptyObject(policy)) { return false; } @@ -6775,11 +6774,8 @@ function isReportOwner(report: OnyxInputOrEntry): boolean { function isAllowedToApproveExpenseReport(report: OnyxEntry, approverAccountID?: number): boolean { const policy = getPolicy(report?.policyID); - const {preventSelfApproval} = policy; - const isOwner = (approverAccountID ?? currentUserAccountID) === report?.ownerAccountID; - - return !(preventSelfApproval && isOwner); + return !(policy?.preventSelfApproval && isOwner); } function isAllowedToSubmitDraftExpenseReport(report: OnyxEntry): boolean { @@ -6982,7 +6978,7 @@ function createDraftTransactionAndNavigateToParticipantSelector(transactionID: s /** * @returns the object to update `report.hasOutstandingChildRequest` */ -function getOutstandingChildRequest(iouReport: OnyxInputOrEntry | EmptyObject): OutstandingChildRequest { +function getOutstandingChildRequest(iouReport: OnyxInputOrEntry): OutstandingChildRequest { if (!iouReport || isEmptyObject(iouReport)) { return {}; } @@ -7016,7 +7012,7 @@ function canReportBeMentionedWithinPolicy(report: OnyxEntry, policyID: s } function shouldShowMerchantColumn(transactions: Transaction[]) { - return transactions.some((transaction) => isExpenseReport(allReports?.[transaction.reportID] ?? {})); + return transactions.some((transaction) => isExpenseReport(allReports?.[transaction.reportID] ?? null)); } /** diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index b752328e2ccf..b28e5b782965 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -114,7 +114,7 @@ function buildOptimisticTransaction( source = '', originalTransactionID = '', merchant = '', - receipt: Receipt = {}, + receipt?: OnyxEntry, filename = '', existingTransactionID: string | null = null, category = '', @@ -749,7 +749,7 @@ function getRateID(transaction: OnyxInputOrEntry): string | undefin * If it is distance request, then returns the tax code corresponding to the custom unit rate * Else returns policy default tax rate if transaction is in policy default currency, otherwise foreign default tax rate */ -function getDefaultTaxCode(policy: OnyxEntry, transaction: OnyxEntry, currency?: string | undefined) { +function getDefaultTaxCode(policy: OnyxEntry, transaction: OnyxEntry, currency?: string | undefined): string | undefined { if (isDistanceRequest(transaction)) { const customUnitRateID = getRateID(transaction) ?? ''; const customUnitRate = getCustomUnitRate(policy, customUnitRateID); diff --git a/src/libs/WorkspacesSettingsUtils.ts b/src/libs/WorkspacesSettingsUtils.ts index 6c57c2a6f99d..62c034145d4b 100644 --- a/src/libs/WorkspacesSettingsUtils.ts +++ b/src/libs/WorkspacesSettingsUtils.ts @@ -4,7 +4,7 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy, ReimbursementAccount, Report, ReportActions} from '@src/types/onyx'; +import type {Policy, ReimbursementAccount, Report, ReportAction, ReportActions} from '@src/types/onyx'; import type {Unit} from '@src/types/onyx/Policy'; import * as CurrencyUtils from './CurrencyUtils'; import type {Phrase, PhraseParameters} from './Localize'; @@ -66,10 +66,10 @@ const getBrickRoadForPolicy = (report: Report, altReportActions?: OnyxCollection } // To determine if the report requires attention from the current user, we need to load the parent report action - let itemParentReportAction = {}; + let itemParentReportAction: OnyxEntry; if (report.parentReportID) { const itemParentReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`] ?? {}; - itemParentReportAction = report.parentReportActionID ? itemParentReportActions[report.parentReportActionID] : {}; + itemParentReportAction = report.parentReportActionID ? itemParentReportActions[report.parentReportActionID] : undefined; } const reportOption = {...report, isUnread: ReportUtils.isUnread(report), isUnreadWithMention: ReportUtils.isUnreadWithMention(report)}; const shouldShowGreenDotIndicator = ReportUtils.requiresAttentionFromCurrentUser(reportOption, itemParentReportAction); diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 911e1d3cf99e..6a9427e884ec 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -58,7 +58,6 @@ import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; import type {Comment, Receipt, ReceiptSource, Routes, SplitShares, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import * as CachedPDFPaths from './CachedPDFPaths'; import * as Category from './Policy/Category'; @@ -244,11 +243,11 @@ Onyx.connect({ }, }); -let currentUserPersonalDetails: OnyxTypes.PersonalDetails | EmptyObject = {}; +let currentUserPersonalDetails: OnyxEntry; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (value) => { - currentUserPersonalDetails = value?.[userAccountID] ?? {}; + currentUserPersonalDetails = value?.[userAccountID] ?? undefined; }, }); @@ -354,13 +353,13 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, amount: 0, comment, created, - currency: policy?.outputCurrency ?? currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD, + currency: policy?.outputCurrency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD, iouRequestType, reportID, transactionID: newTransactionID, isFromGlobalCreate, merchant: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, - splitPayerAccountIDs: [currentUserPersonalDetails.accountID], + splitPayerAccountIDs: currentUserPersonalDetails ? [currentUserPersonalDetails.accountID] : undefined, }); } @@ -464,7 +463,7 @@ function updateDistanceRequestRate(transactionID: string, rateID: string, policy } /** Helper function to get the receipt error for expenses, or the generic error if there's no receipt */ -function getReceiptError(receipt?: Receipt, filename?: string, isScanRequest = true, errorKey?: number): Errors | ErrorFields { +function getReceiptError(receipt: OnyxEntry, filename?: string, isScanRequest = true, errorKey?: number): Errors | ErrorFields { return isEmptyObject(receipt) || !isScanRequest ? ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage', errorKey) : ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source?.toString() ?? '', filename: filename ?? ''}, errorKey); @@ -483,8 +482,8 @@ function buildOnyxDataForMoneyRequest( optimisticPolicyRecentlyUsedCategories: string[], optimisticPolicyRecentlyUsedTags: OnyxTypes.RecentlyUsedTags, isNewChatReport: boolean, - transactionThreadReport: OptimisticChatReport | EmptyObject, - transactionThreadCreatedReportAction: OptimisticCreatedReportAction | EmptyObject, + transactionThreadReport: OptimisticChatReport | null, + transactionThreadCreatedReportAction: OptimisticCreatedReportAction | null, shouldCreateNewMoneyRequestReport: boolean, policy?: OnyxTypes.OnyxInputOrEntry, policyTagList?: OnyxTypes.OnyxInputOrEntry, @@ -573,7 +572,7 @@ function buildOnyxDataForMoneyRequest( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { ...transactionThreadReport, pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}, @@ -590,7 +589,7 @@ function buildOnyxDataForMoneyRequest( if (!isEmptyObject(transactionThreadCreatedReportAction)) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: transactionThreadCreatedReportAction, }, @@ -682,7 +681,7 @@ function buildOnyxDataForMoneyRequest( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { participants: redundantParticipants, pendingFields: null, @@ -739,7 +738,7 @@ function buildOnyxDataForMoneyRequest( if (!isEmptyObject(transactionThreadCreatedReportAction)) { successData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { pendingAction: null, @@ -781,7 +780,7 @@ function buildOnyxDataForMoneyRequest( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { pendingFields: null, errorFields: existingTransactionThreadReport @@ -830,7 +829,7 @@ function buildOnyxDataForMoneyRequest( if (!isEmptyObject(transactionThreadCreatedReportAction)) { failureData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), @@ -880,7 +879,7 @@ function buildOnyxDataForInvoice( optimisticPolicyRecentlyUsedTags: OnyxTypes.RecentlyUsedTags, isNewChatReport: boolean, transactionThreadReport: OptimisticChatReport, - transactionThreadCreatedReportAction: OptimisticCreatedReportAction | EmptyObject, + transactionThreadCreatedReportAction: OptimisticCreatedReportAction | null, policy?: OnyxEntry, policyTagList?: OnyxEntry, policyCategories?: OnyxEntry, @@ -937,7 +936,7 @@ function buildOnyxDataForInvoice( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { - [transactionThreadCreatedReportAction.reportActionID]: transactionThreadCreatedReportAction, + [transactionThreadCreatedReportAction?.reportActionID ?? '-1']: transactionThreadCreatedReportAction, }, }, // Remove the temporary transaction used during the creation flow @@ -1067,7 +1066,7 @@ function buildOnyxDataForInvoice( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { - [transactionThreadCreatedReportAction.reportActionID]: { + [transactionThreadCreatedReportAction?.reportActionID ?? '-1']: { pendingAction: null, errors: null, }, @@ -1154,7 +1153,7 @@ function buildOnyxDataForInvoice( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, value: { - [transactionThreadCreatedReportAction.reportActionID]: { + [transactionThreadCreatedReportAction?.reportActionID ?? '-1']: { errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateInvoiceFailureMessage', errorKey), }, }, @@ -1196,8 +1195,8 @@ function buildOnyxDataForTrackExpense( iouCreatedAction: OptimisticCreatedReportAction, iouAction: OptimisticIOUReportAction, reportPreviewAction: OnyxInputValue, - transactionThreadReport: OptimisticChatReport | EmptyObject, - transactionThreadCreatedReportAction: OptimisticCreatedReportAction | EmptyObject, + transactionThreadReport: OptimisticChatReport | null, + transactionThreadCreatedReportAction: OptimisticCreatedReportAction | null, shouldCreateNewMoneyRequestReport: boolean, policy?: OnyxInputValue, policyTagList?: OnyxInputValue, @@ -1331,7 +1330,7 @@ function buildOnyxDataForTrackExpense( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { ...transactionThreadReport, pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}, @@ -1348,7 +1347,7 @@ function buildOnyxDataForTrackExpense( if (!isEmptyObject(transactionThreadCreatedReportAction)) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: transactionThreadCreatedReportAction, }, @@ -1408,7 +1407,7 @@ function buildOnyxDataForTrackExpense( successData.push( { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { pendingFields: null, errorFields: null, @@ -1427,7 +1426,7 @@ function buildOnyxDataForTrackExpense( if (!isEmptyObject(transactionThreadCreatedReportAction)) { successData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { [transactionThreadCreatedReportAction.reportActionID]: { pendingAction: null, @@ -1506,7 +1505,7 @@ function buildOnyxDataForTrackExpense( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.reportID}`, value: { pendingFields: null, errorFields: existingTransactionThreadReport @@ -1528,9 +1527,9 @@ function buildOnyxDataForTrackExpense( }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`, value: { - [transactionThreadCreatedReportAction.reportActionID]: { + [transactionThreadCreatedReportAction?.reportActionID ?? '-1']: { errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, @@ -1883,7 +1882,7 @@ function getSendInvoiceInformation( * it creates optimistic versions of them and uses those instead */ function getMoneyRequestInformation( - parentChatReport: OnyxEntry | EmptyObject, + parentChatReport: OnyxEntry, participant: Participant, comment: string, amount: number, @@ -2066,7 +2065,7 @@ function getMoneyRequestInformation( optimisticPolicyRecentlyUsedTags, isNewChatReport, optimisticTransactionThread ?? {}, - optimisticCreatedActionForTransactionThread ?? {}, + optimisticCreatedActionForTransactionThread, shouldCreateNewMoneyRequestReport, policy, policyTagList, @@ -2099,14 +2098,14 @@ function getMoneyRequestInformation( * it creates optimistic versions of them and uses those instead */ function getTrackExpenseInformation( - parentChatReport: OnyxEntry | EmptyObject, + parentChatReport: OnyxEntry, participant: Participant, comment: string, amount: number, currency: string, created: string, merchant: string, - receipt: Receipt | undefined, + receipt: OnyxEntry, category: string | undefined, tag: string | undefined, taxCode: string | undefined, @@ -2120,7 +2119,7 @@ function getTrackExpenseInformation( moneyRequestReportID = '', linkedTrackedExpenseReportAction?: OnyxTypes.ReportAction, existingTransactionID?: string, -): TrackExpenseInformation | EmptyObject { +): TrackExpenseInformation | null { const optimisticData: OnyxUpdate[] = []; const successData: OnyxUpdate[] = []; const failureData: OnyxUpdate[] = []; @@ -2138,7 +2137,7 @@ function getTrackExpenseInformation( // If we still don't have a report, it likely doesn't exist, and we will early return here as it should not happen // Maybe later, we can build an optimistic selfDM chat. if (!chatReport) { - return {}; + return null; } // Check if the report is a draft @@ -2276,7 +2275,7 @@ function getTrackExpenseInformation( iouAction, reportPreviewAction, optimisticTransactionThread ?? {}, - (optimisticCreatedActionForTransactionThread as OptimisticCreatedReportAction) ?? {}, // Add type assertion here + optimisticCreatedActionForTransactionThread, shouldCreateNewMoneyRequestReport, policy, policyTagList, @@ -2295,7 +2294,7 @@ function getTrackExpenseInformation( createdIOUReportActionID: shouldCreateNewMoneyRequestReport ? optimisticCreatedActionForIOUReport.reportActionID : '-1', reportPreviewAction: reportPreviewAction ?? undefined, transactionThreadReportID: optimisticTransactionThread.reportID, - createdReportActionIDForThread: optimisticCreatedActionForTransactionThread.reportActionID, + createdReportActionIDForThread: optimisticCreatedActionForTransactionThread?.reportActionID ?? '-1', actionableWhisperReportActionIDParam: actionableTrackExpenseWhisper?.reportActionID ?? '', onyxData: { optimisticData: optimisticData.concat(trackExpenseOnyxData[0]), @@ -2576,9 +2575,9 @@ function getUpdateMoneyRequestParams( // Step 4: Compute the IOU total and update the report preview message (and report header) so LHN amount owed is correct. const diff = calculateDiffAmount(iouReport, updatedTransaction, transaction); - let updatedMoneyRequestReport: OnyxTypes.Report | EmptyObject; + let updatedMoneyRequestReport: OnyxTypes.OnyxInputOrEntry; if (!iouReport) { - updatedMoneyRequestReport = {}; + updatedMoneyRequestReport = null; } else if ((ReportUtils.isExpenseReport(iouReport) || ReportUtils.isInvoiceReport(iouReport)) && typeof iouReport.total === 'number') { // For expense report, the amount is negative, so we should subtract total from diff updatedMoneyRequestReport = { @@ -2592,7 +2591,9 @@ function getUpdateMoneyRequestParams( updatedMoneyRequestReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false, true); } - updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, transactionDetails?.currency); + if (updatedMoneyRequestReport) { + updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, transactionDetails?.currency); + } optimisticData.push( { @@ -3265,7 +3266,7 @@ function categorizeTrackedExpense( linkedTrackedExpenseReportID: string, transactionThreadReportID: string, reportPreviewReportActionID: string, - onyxData: OnyxData, + onyxData: OnyxData | undefined, amount: number, currency: string, comment: string, @@ -3279,7 +3280,7 @@ function categorizeTrackedExpense( receipt?: Receipt, createdWorkspaceParams?: CreateWorkspaceParams, ) { - const {optimisticData, successData, failureData} = onyxData; + const {optimisticData, successData, failureData} = onyxData ?? {}; const { optimisticData: moveTransactionOptimisticData, @@ -3342,7 +3343,7 @@ function shareTrackedExpense( linkedTrackedExpenseReportID: string, transactionThreadReportID: string, reportPreviewReportActionID: string, - onyxData: OnyxData, + onyxData: OnyxData | undefined, amount: number, currency: string, comment: string, @@ -3356,7 +3357,7 @@ function shareTrackedExpense( receipt?: Receipt, createdWorkspaceParams?: CreateWorkspaceParams, ) { - const {optimisticData, successData, failureData} = onyxData; + const {optimisticData, successData, failureData} = onyxData ?? {}; const { optimisticData: moveTransactionOptimisticData, @@ -3456,7 +3457,7 @@ function requestMoney( createdReportActionIDForThread, onyxData, } = getMoneyRequestInformation( - isMovingTransactionFromTrackExpense ? {} : currentChatReport, + isMovingTransactionFromTrackExpense ? undefined : currentChatReport, participant, comment, amount, @@ -3635,32 +3636,33 @@ function trackExpense( createdReportActionIDForThread, actionableWhisperReportActionIDParam, onyxData, - } = getTrackExpenseInformation( - currentChatReport, - participant, - comment, - amount, - currency, - created, - merchant, - receipt, - category, - tag, - taxCode, - taxAmount, - billable, - policy, - policyTagList, - policyCategories, - payeeEmail, - payeeAccountID, - moneyRequestReportID, - linkedTrackedExpenseReportAction, - isMovingTransactionFromTrackExpense && linkedTrackedExpenseReportAction && ReportActionsUtils.isMoneyRequestAction(linkedTrackedExpenseReportAction) - ? ReportActionsUtils.getOriginalMessage(linkedTrackedExpenseReportAction)?.IOUTransactionID - : undefined, - ); - const activeReportID = isMoneyRequestReport ? report.reportID : chatReport.reportID; + } = + getTrackExpenseInformation( + currentChatReport, + participant, + comment, + amount, + currency, + created, + merchant, + receipt, + category, + tag, + taxCode, + taxAmount, + billable, + policy, + policyTagList, + policyCategories, + payeeEmail, + payeeAccountID, + moneyRequestReportID, + linkedTrackedExpenseReportAction, + isMovingTransactionFromTrackExpense && linkedTrackedExpenseReportAction && ReportActionsUtils.isMoneyRequestAction(linkedTrackedExpenseReportAction) + ? ReportActionsUtils.getOriginalMessage(linkedTrackedExpenseReportAction)?.IOUTransactionID + : undefined, + ) ?? {}; + const activeReportID = isMoneyRequestReport ? report.reportID : chatReport?.reportID; switch (action) { case CONST.IOU.ACTION.CATEGORIZE: { @@ -3668,15 +3670,15 @@ function trackExpense( return; } categorizeTrackedExpense( - chatReport.policyID ?? '-1', - transaction.transactionID, - iouAction.reportActionID, + chatReport?.policyID ?? '-1', + transaction?.transactionID ?? '-1', + iouAction?.reportActionID ?? '-1', iouReport?.reportID ?? '-1', createdIOUReportActionID ?? '-1', actionableWhisperReportActionID, linkedTrackedExpenseReportAction, linkedTrackedExpenseReportID, - transactionThreadReportID, + transactionThreadReportID ?? '-1', reportPreviewAction?.reportActionID ?? '-1', onyxData, amount, @@ -3699,15 +3701,15 @@ function trackExpense( return; } shareTrackedExpense( - chatReport.policyID ?? '-1', - transaction.transactionID, - iouAction.reportActionID, + chatReport?.policyID ?? '-1', + transaction?.transactionID ?? '-1', + iouAction?.reportActionID ?? '-1', iouReport?.reportID ?? '-1', createdIOUReportActionID ?? '-1', actionableWhisperReportActionID, linkedTrackedExpenseReportAction, linkedTrackedExpenseReportID, - transactionThreadReportID, + transactionThreadReportID ?? '-1', reportPreviewAction?.reportActionID ?? '-1', onyxData, amount, @@ -3733,10 +3735,10 @@ function trackExpense( created, merchant, iouReportID: iouReport?.reportID, - chatReportID: chatReport.reportID, - transactionID: transaction.transactionID, - reportActionID: iouAction.reportActionID, - createdChatReportActionID, + chatReportID: chatReport?.reportID ?? '-1', + transactionID: transaction?.transactionID ?? '-1', + reportActionID: iouAction?.reportActionID ?? '-1', + createdChatReportActionID: createdChatReportActionID ?? '-1', createdIOUReportActionID, reportPreviewReportActionID: reportPreviewAction?.reportActionID, receipt, @@ -3748,8 +3750,8 @@ function trackExpense( billable, // This needs to be a string of JSON because of limitations with the fetch() API and nested objects receiptGpsPoints: gpsPoints ? JSON.stringify(gpsPoints) : undefined, - transactionThreadReportID, - createdReportActionIDForThread, + transactionThreadReportID: transactionThreadReportID ?? '-1', + createdReportActionIDForThread: createdReportActionIDForThread ?? '-1', waypoints: validWaypoints ? JSON.stringify(validWaypoints) : undefined, }; if (actionableWhisperReportActionIDParam) { @@ -3764,7 +3766,7 @@ function trackExpense( Navigation.navigate(ROUTES.ROOM_INVITE.getRoute(activeReportID ?? '-1', CONST.IOU.SHARE.ROLE.ACCOUNTANT)); } - Report.notifyNewAction(activeReportID, payeeAccountID); + Report.notifyNewAction(activeReportID ?? '', payeeAccountID); } function getOrCreateOptimisticSplitChatReport(existingSplitChatReportID: string, participants: Participant[], participantAccountIDs: number[], currentUserAccountID: number) { @@ -4188,7 +4190,7 @@ function createSplitsAndOnyxData( createdIOUReportActionID: oneOnOneCreatedActionForIOU.reportActionID, reportPreviewReportActionID: oneOnOneReportPreviewAction.reportActionID, transactionThreadReportID: optimisticTransactionThread.reportID, - createdReportActionIDForThread: optimisticCreatedActionForTransactionThread.reportActionID, + createdReportActionIDForThread: optimisticCreatedActionForTransactionThread?.reportActionID, taxAmount: splitTaxAmount, }; @@ -4787,7 +4789,7 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA // In case this is still the optimistic accountID saved in the splits array, return early as we cannot know // if there is an existing chat between the split creator and this participant // Instead, we will rely on Auth generating the report IDs and the user won't see any optimistic chats or reports created - const participantPersonalDetails: OnyxTypes.PersonalDetails | EmptyObject = allPersonalDetails[participant?.accountID ?? -1] ?? {}; + const participantPersonalDetails: OnyxTypes.PersonalDetails | null = allPersonalDetails[participant?.accountID ?? -1]; if (!participantPersonalDetails || participantPersonalDetails.isOptimisticPersonalDetail) { splits.push({ email: participant.email, @@ -4796,11 +4798,11 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA } } - let oneOnOneChatReport: OnyxTypes.Report | null; + let oneOnOneChatReport: OnyxEntry; let isNewOneOnOneChatReport = false; if (isPolicyExpenseChat) { // The workspace chat reportID is saved in the splits array when starting a split expense with a workspace - oneOnOneChatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${participant.chatReportID}`] ?? null; + oneOnOneChatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${participant.chatReportID}`]; } else { const existingChatReport = ReportUtils.getChatByParticipants(participant.accountID ? [participant.accountID, sessionAccountID] : []); isNewOneOnOneChatReport = !existingChatReport; @@ -4896,7 +4898,7 @@ function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportA createdIOUReportActionID: oneOnOneCreatedActionForIOU.reportActionID, reportPreviewReportActionID: oneOnOneReportPreviewAction.reportActionID, transactionThreadReportID: optimisticTransactionThread.reportID, - createdReportActionIDForThread: optimisticCreatedActionForTransactionThread.reportActionID, + createdReportActionIDForThread: optimisticCreatedActionForTransactionThread?.reportActionID, }); optimisticData.push(...oneOnOneOptimisticData); @@ -5315,7 +5317,7 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor iouReportLastMessageText.length === 0 && !ReportActionsUtils.isDeletedParentAction(lastVisibleAction) && (!transactionThreadID || shouldDeleteTransactionThread); // STEP 4: Update the iouReport and reportPreview with new totals and messages if it wasn't deleted - let updatedIOUReport: OnyxTypes.Report | null; + let updatedIOUReport: OnyxInputValue; const currency = TransactionUtils.getCurrency(transaction); const updatedReportPreviewAction: OnyxTypes.ReportAction = {...reportPreviewAction}; updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; @@ -5417,7 +5419,7 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor }, ); - if (!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0) { + if (!shouldDeleteIOUReport && updatedReportPreviewAction?.childMoneyRequestCount === 0) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`, @@ -5546,7 +5548,7 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor }); } - if (!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0) { + if (!shouldDeleteIOUReport && updatedReportPreviewAction?.childMoneyRequestCount === 0) { failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`, @@ -5602,7 +5604,7 @@ function deleteTrackExpense(chatReportID: string, transactionID: string, reportA * @param recipient - The user receiving the money */ function getSendMoneyParams( - report: OnyxEntry | EmptyObject, + report: OnyxEntry, amount: number, currency: string, comment: string, @@ -5721,14 +5723,14 @@ function getSendMoneyParams( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`, value: { - [optimisticCreatedActionForTransactionThread.reportActionID]: optimisticCreatedActionForTransactionThread, + [optimisticCreatedActionForTransactionThread?.reportActionID ?? '-1']: optimisticCreatedActionForTransactionThread, }, }; const successData: OnyxUpdate[] = []; // Add optimistic personal details for recipient - let optimisticPersonalDetailListData: OnyxUpdate | EmptyObject = {}; + let optimisticPersonalDetailListData: OnyxUpdate | null = null; const optimisticPersonalDetailListAction = isNewChat ? { [recipientAccountID]: { @@ -5806,7 +5808,7 @@ function getSendMoneyParams( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`, value: { - [optimisticCreatedActionForTransactionThread.reportActionID]: { + [optimisticCreatedActionForTransactionThread?.reportActionID ?? '-1']: { pendingAction: null, }, }, @@ -5834,7 +5836,7 @@ function getSendMoneyParams( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticTransactionThread.reportID}`, value: { - [optimisticCreatedActionForTransactionThread.reportActionID]: { + [optimisticCreatedActionForTransactionThread?.reportActionID ?? '-1']: { errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'), }, }, @@ -5912,7 +5914,7 @@ function getSendMoneyParams( reportPreviewReportActionID: reportPreviewAction.reportActionID, createdIOUReportActionID: optimisticCreatedActionForIOUReport.reportActionID, transactionThreadReportID: optimisticTransactionThread.reportID, - createdReportActionIDForThread: optimisticCreatedActionForTransactionThread.reportActionID, + createdReportActionIDForThread: optimisticCreatedActionForTransactionThread?.reportActionID ?? '-1', }, optimisticData, successData, @@ -6117,9 +6119,9 @@ function sendMoneyWithWallet(report: OnyxEntry, amount: number } function canApproveIOU( - iouReport: OnyxTypes.OnyxInputOrEntry | EmptyObject, - chatReport: OnyxTypes.OnyxInputOrEntry | EmptyObject, - policy: OnyxTypes.OnyxInputOrEntry | EmptyObject, + iouReport: OnyxTypes.OnyxInputOrEntry, + chatReport: OnyxTypes.OnyxInputOrEntry, + policy: OnyxTypes.OnyxInputOrEntry, ) { if (isEmptyObject(chatReport)) { return false; @@ -6148,9 +6150,9 @@ function canApproveIOU( } function canIOUBePaid( - iouReport: OnyxTypes.OnyxInputOrEntry | EmptyObject, - chatReport: OnyxTypes.OnyxInputOrEntry | EmptyObject, - policy: OnyxTypes.OnyxInputOrEntry | EmptyObject, + iouReport: OnyxTypes.OnyxInputOrEntry, + chatReport: OnyxTypes.OnyxInputOrEntry, + policy: OnyxTypes.OnyxInputOrEntry, ) { const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(chatReport); const isChatReportArchived = ReportUtils.isArchivedRoom(chatReport); @@ -6171,7 +6173,7 @@ function canIOUBePaid( if (chatReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) { return chatReport?.invoiceReceiver?.accountID === userAccountID; } - return PolicyUtils.getPolicy(chatReport?.invoiceReceiver?.policyID).role === CONST.POLICY.ROLE.ADMIN; + return PolicyUtils.getPolicy(chatReport?.invoiceReceiver?.policyID)?.role === CONST.POLICY.ROLE.ADMIN; } const isPayer = ReportUtils.isPayer( @@ -6193,7 +6195,7 @@ function canIOUBePaid( ); } -function hasIOUToApproveOrPay(chatReport: OnyxEntry | EmptyObject, excludedIOUReportID: string): boolean { +function hasIOUToApproveOrPay(chatReport: OnyxEntry, excludedIOUReportID: string): boolean { const chatReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`] ?? {}; return Object.values(chatReportActions).some((action) => { @@ -6204,20 +6206,20 @@ function hasIOUToApproveOrPay(chatReport: OnyxEntry | EmptyObj }); } -function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full?: boolean) { - const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null; - let total = expenseReport.total ?? 0; - const hasHeldExpenses = ReportUtils.hasHeldExpenses(expenseReport.reportID); - if (hasHeldExpenses && !full && !!expenseReport.unheldTotal) { - total = expenseReport.unheldTotal; +function approveMoneyRequest(expenseReport: OnyxEntry, full?: boolean) { + const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`] ?? null; + let total = expenseReport?.total ?? 0; + const hasHeldExpenses = ReportUtils.hasHeldExpenses(expenseReport?.reportID); + if (hasHeldExpenses && !full && !!expenseReport?.unheldTotal) { + total = expenseReport?.unheldTotal; } - const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(total, expenseReport.currency ?? '', expenseReport.reportID); + const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(total, expenseReport?.currency ?? '', expenseReport?.reportID ?? '-1'); const optimisticNextStep = NextStepUtils.buildNextStep(expenseReport, CONST.REPORT.STATUS_NUM.APPROVED); - const chatReport = getReportOrDraftReport(expenseReport.chatReportID); + const chatReport = getReportOrDraftReport(expenseReport?.chatReportID); const optimisticReportActionsData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { ...(optimisticApprovedReportAction as OnyxTypes.ReportAction), @@ -6227,7 +6229,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full }; const optimisticIOUReportData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport?.reportID}`, value: { ...expenseReport, lastMessageText: ReportActionsUtils.getReportActionText(optimisticApprovedReportAction), @@ -6250,7 +6252,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full const optimisticNextStepData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`, value: optimisticNextStep, }; const optimisticData: OnyxUpdate[] = [optimisticIOUReportData, optimisticReportActionsData, optimisticNextStepData, optimisticChatReportData]; @@ -6258,7 +6260,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { pendingAction: null, @@ -6267,7 +6269,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport?.reportID}`, value: { pendingFields: { partial: null, @@ -6279,7 +6281,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), @@ -6288,7 +6290,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.chatReportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport?.chatReportID}`, value: { hasOutstandingChildRequest: chatReport?.hasOutstandingChildRequest, pendingFields: { @@ -6298,14 +6300,14 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full }, { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`, value: currentNextStep, }, ]; // Clear hold reason of all transactions if we approve all requests if (full && hasHeldExpenses) { - const heldTransactions = ReportUtils.getAllHeldTransactions(expenseReport.reportID); + const heldTransactions = ReportUtils.getAllHeldTransactions(expenseReport?.reportID); heldTransactions.forEach((heldTransaction) => { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, @@ -6329,7 +6331,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject, full } const parameters: ApproveMoneyRequestParams = { - reportID: expenseReport.reportID, + reportID: expenseReport?.reportID ?? '-1', approvedReportActionID: optimisticApprovedReportAction.reportActionID, full, }; @@ -6341,9 +6343,9 @@ function submitReport(expenseReport: OnyxTypes.Report) { const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null; const parentReport = getReportOrDraftReport(expenseReport.parentReportID); const policy = PolicyUtils.getPolicy(expenseReport.policyID); - const isCurrentUserManager = currentUserPersonalDetails.accountID === expenseReport.managerID; + const isCurrentUserManager = currentUserPersonalDetails?.accountID === expenseReport.managerID; const isSubmitAndClosePolicy = PolicyUtils.isSubmitAndClose(policy); - const adminAccountID = policy.role === CONST.POLICY.ROLE.ADMIN ? currentUserPersonalDetails.accountID : undefined; + const adminAccountID = policy?.role === CONST.POLICY.ROLE.ADMIN ? currentUserPersonalDetails?.accountID : undefined; const optimisticSubmittedReportAction = ReportUtils.buildOptimisticSubmittedReportAction(expenseReport?.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID, adminAccountID); const optimisticNextStep = NextStepUtils.buildNextStep(expenseReport, isSubmitAndClosePolicy ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.SUBMITTED); @@ -6466,7 +6468,7 @@ function cancelPayment(expenseReport: OnyxTypes.Report, chatReport: OnyxTypes.Re const optimisticReportAction = ReportUtils.buildOptimisticCancelPaymentReportAction(expenseReport.reportID, -(expenseReport.total ?? 0), expenseReport.currency ?? ''); const policy = PolicyUtils.getPolicy(chatReport.policyID); const isFree = policy && policy.type === CONST.POLICY.TYPE.FREE; - const approvalMode = policy.approvalMode ?? CONST.POLICY.APPROVAL_MODE.BASIC; + const approvalMode = policy?.approvalMode ?? CONST.POLICY.APPROVAL_MODE.BASIC; let stateNum: ValueOf = CONST.REPORT.STATE_NUM.SUBMITTED; let statusNum: ValueOf = CONST.REPORT.STATUS_NUM.SUBMITTED; if (!isFree) { @@ -6672,7 +6674,7 @@ function replaceReceipt(transactionID: string, file: File, source: string) { function setMoneyRequestParticipantsFromReport(transactionID: string, report: OnyxEntry): Participant[] { // If the report is iou or expense report, we should get the chat report to set participant for request money const chatReport = ReportUtils.isMoneyRequestReport(report) ? getReportOrDraftReport(report?.chatReportID) : report; - const currentUserAccountID = currentUserPersonalDetails.accountID; + const currentUserAccountID = currentUserPersonalDetails?.accountID; const shouldAddAsReport = !isEmptyObject(chatReport) && ReportUtils.isSelfDM(chatReport); let participants: Participant[] = []; diff --git a/src/libs/actions/MapboxToken.ts b/src/libs/actions/MapboxToken.ts index 923f5590b2bd..4a52bbf4e4a6 100644 --- a/src/libs/actions/MapboxToken.ts +++ b/src/libs/actions/MapboxToken.ts @@ -39,7 +39,7 @@ const setExpirationTimer = () => { return; } console.debug(`[MapboxToken] Fetching a new token after waiting ${REFRESH_INTERVAL / 1000 / 60} minutes`); - API.read(READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN, {}, {}); + API.read(READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN, null, {}); }, REFRESH_INTERVAL); }; @@ -52,7 +52,7 @@ const clearToken = () => { }; const fetchToken = () => { - API.read(READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN, {}, {}); + API.read(READ_COMMANDS.GET_MAPBOX_ACCESS_TOKEN, null, {}); isCurrentlyFetchingToken = true; }; diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index c12f7a042659..6371c970379f 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -64,15 +64,11 @@ function openWalletPage() { }, ]; - return API.read( - READ_COMMANDS.OPEN_PAYMENTS_PAGE, - {}, - { - optimisticData, - successData, - failureData, - }, - ); + return API.read(READ_COMMANDS.OPEN_PAYMENTS_PAGE, null, { + optimisticData, + successData, + failureData, + }); } function getMakeDefaultPaymentOnyxData( diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index daeb4ad58802..5870d642d8cd 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -397,7 +397,7 @@ function deleteAvatar() { }, ]; - API.write(WRITE_COMMANDS.DELETE_USER_AVATAR, {}, {optimisticData, failureData}); + API.write(WRITE_COMMANDS.DELETE_USER_AVATAR, null, {optimisticData, failureData}); } /** diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index 7c87dd597d51..9874a175d0a2 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -22,7 +22,6 @@ import type {InvitedEmailsToAccountIDs, PersonalDetailsList, Policy, PolicyEmplo import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type {JoinWorkspaceResolution} from '@src/types/onyx/OriginalMessage'; import type {Attributes, Rate} from '@src/types/onyx/Policy'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import {createPolicyExpenseChats} from './Policy'; @@ -105,11 +104,11 @@ Onyx.connect({ /** * Returns the policy of the report */ -function getPolicy(policyID: string | undefined): Policy | EmptyObject { +function getPolicy(policyID: string | undefined): OnyxEntry { if (!allPolicies || !policyID) { - return {}; + return undefined; } - return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? {}; + return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; } /** @@ -229,9 +228,11 @@ function removeMembers(accountIDs: number[], policyID: string) { const workspaceChats = ReportUtils.getWorkspaceChats(policyID, accountIDs); const emailList = accountIDs.map((accountID) => allPersonalDetails?.[accountID]?.login).filter((login) => !!login) as string[]; - const optimisticClosedReportActions = workspaceChats.map(() => ReportUtils.buildOptimisticClosedReportAction(sessionEmail, policy.name, CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY)); + const optimisticClosedReportActions = workspaceChats.map(() => + ReportUtils.buildOptimisticClosedReportAction(sessionEmail, policy?.name ?? '', CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY), + ); - const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policy.id, policy.name, accountIDs); + const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policy?.id ?? '-1', policy?.name ?? '', accountIDs); const optimisticMembersState: OnyxCollectionInputValue = {}; const successMembersState: OnyxCollectionInputValue = {}; @@ -278,7 +279,7 @@ function removeMembers(accountIDs: number[], policyID: string) { value: { statusNum: CONST.REPORT.STATUS_NUM.CLOSED, stateNum: CONST.REPORT.STATE_NUM.APPROVED, - oldPolicyName: policy.name, + oldPolicyName: policy?.name, pendingChatMembers, }, }); @@ -314,7 +315,7 @@ function removeMembers(accountIDs: number[], policyID: string) { const remainingLogins = employeeListEmails.filter((email) => !emailList.includes(email)); const invitedPrimaryToSecondaryLogins: Record = {}; - if (policy.primaryLoginsInvited) { + if (policy?.primaryLoginsInvited) { Object.keys(policy.primaryLoginsInvited).forEach((key) => (invitedPrimaryToSecondaryLogins[policy.primaryLoginsInvited?.[key] ?? ''] = key)); } diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 88aae0dcb149..5945c09d67af 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -55,7 +55,6 @@ import type {InvitedEmailsToAccountIDs, PersonalDetailsList, Policy, PolicyCateg import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {Attributes, CompanyAddress, CustomUnit, Rate, TaxRate, Unit} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import {buildOptimisticPolicyCategories} from './Category'; @@ -174,11 +173,11 @@ function isCurrencySupportedForDirectReimbursement(currency: string) { /** * Returns the policy of the report */ -function getPolicy(policyID: string | undefined): Policy | EmptyObject { +function getPolicy(policyID: string | undefined): OnyxEntry { if (!allPolicies || !policyID) { - return {}; + return undefined; } - return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? {}; + return allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; } /** @@ -358,7 +357,7 @@ function setWorkspaceAutoReportingFrequency(policyID: string, frequency: ValueOf onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - autoReportingFrequency: policy.autoReportingFrequency ?? null, + autoReportingFrequency: policy?.autoReportingFrequency ?? null, pendingFields: {autoReportingFrequency: null}, errorFields: {autoReportingFrequency: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.autoReportingFrequencyErrorMessage')}, }, @@ -399,7 +398,7 @@ function setWorkspaceAutoReportingMonthlyOffset(policyID: string, autoReportingO onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - autoReportingOffset: policy.autoReportingOffset ?? null, + autoReportingOffset: policy?.autoReportingOffset ?? null, pendingFields: {autoReportingOffset: null}, errorFields: {autoReportingOffset: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.monthlyOffsetErrorMessage')}, }, @@ -444,8 +443,8 @@ function setWorkspaceApprovalMode(policyID: string, approver: string, approvalMo onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - approver: policy.approver ?? null, - approvalMode: policy.approvalMode ?? null, + approver: policy?.approver, + approvalMode: policy?.approvalMode, pendingFields: {approvalMode: null}, errorFields: {approvalMode: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsApprovalPage.genericErrorMessage')}, }, @@ -504,7 +503,7 @@ function setWorkspacePayer(policyID: string, reimburserEmail: string) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - achAccount: {reimburser: policy.achAccount?.reimburser ?? null}, + achAccount: {reimburser: policy?.achAccount?.reimburser ?? null}, errorFields: {reimburser: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsPayerPage.genericErrorMessage')}, pendingFields: {reimburser: null}, }, @@ -567,8 +566,8 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { isLoadingWorkspaceReimbursement: false, - reimbursementChoice: policy.reimbursementChoice ?? null, - achAccount: {reimburser: policy.achAccount?.reimburser ?? null}, + reimbursementChoice: policy?.reimbursementChoice ?? null, + achAccount: {reimburser: policy?.achAccount?.reimburser ?? null}, errorFields: {reimbursementChoice: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, pendingFields: {reimbursementChoice: null}, }, @@ -1976,7 +1975,7 @@ function dismissAddedWithPrimaryLoginMessages(policyID: string) { * * @returns policyID of the workspace we have created */ -function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string | undefined { +function createWorkspaceFromIOUPayment(iouReport: OnyxEntry): string | undefined { // This flow only works for IOU reports if (!ReportUtils.isIOUReportUsingReport(iouReport)) { return; @@ -2316,12 +2315,12 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[reportPreview.reportActionID]: null}, + value: {[reportPreview?.reportActionID ?? '-1']: null}, }); failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChatReportID}`, - value: {[reportPreview.reportActionID]: reportPreview}, + value: {[reportPreview?.reportActionID ?? '-1']: reportPreview}, }); // To optimistically remove the GBR from the DM we need to update the hasOutstandingChildRequest param to false @@ -2351,7 +2350,7 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string message: [ { type: CONST.REPORT.MESSAGE.TYPE.TEXT, - text: ReportUtils.getReportPreviewMessage(expenseReport, {}, false, false, newWorkspace), + text: ReportUtils.getReportPreviewMessage(expenseReport, null, false, false, newWorkspace), }, ], created: DateUtils.getDBTime(), @@ -2363,7 +2362,7 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${memberData.workspaceChatReportID}`, - value: {[reportPreview.reportActionID]: null}, + value: {[reportPreview?.reportActionID ?? '-1']: null}, }); // Create the MOVED report action and add it to the DM chat which indicates to the user where the report has been moved @@ -2683,10 +2682,10 @@ function enablePolicyWorkflows(policyID: string, enabled: boolean) { areWorkflowsEnabled: !enabled, ...(!enabled ? { - approvalMode: policy.approvalMode, - autoReporting: policy.autoReporting, - harvesting: policy.harvesting, - reimbursementChoice: policy.reimbursementChoice, + approvalMode: policy?.approvalMode, + autoReporting: policy?.autoReporting, + harvesting: policy?.harvesting, + reimbursementChoice: policy?.reimbursementChoice, } : {}), pendingFields: { @@ -2751,7 +2750,7 @@ function enableDistanceRequestTax(policyID: string, customUnitName: string, cust value: { customUnits: { [customUnitID]: { - attributes: policy.customUnits ? policy.customUnits[customUnitID].attributes : null, + attributes: policy?.customUnits ? policy?.customUnits[customUnitID].attributes : null, }, }, }, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index d6fb70ee177a..e528fde34ffe 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -97,7 +97,6 @@ import type {Decision} from '@src/types/onyx/OriginalMessage'; import type {NotificationPreference, Participants, Participant as ReportParticipant, RoomVisibility, WriteCapability} from '@src/types/onyx/Report'; import type Report from '@src/types/onyx/Report'; import type {Message, ReportActions} from '@src/types/onyx/ReportAction'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import * as CachedPDFPaths from './CachedPDFPaths'; import * as Modal from './Modal'; @@ -743,7 +742,7 @@ function openReport( reportID: string, reportActionID?: string, participantLoginList: string[] = [], - newReportObject: Partial = {}, + newReportObject?: ReportUtils.OptimisticChatReport, parentReportActionID = '-1', isFromDeepLink = false, participantAccountIDList: number[] = [], @@ -817,8 +816,8 @@ function openReport( if (ReportUtils.isGroupChat(newReportObject)) { parameters.chatType = CONST.REPORT.CHAT_TYPE.GROUP; parameters.groupChatAdminLogins = currentUserEmail; - parameters.optimisticAccountIDList = Object.keys(newReportObject.participants ?? {}).join(','); - parameters.reportName = newReportObject.reportName ?? ''; + parameters.optimisticAccountIDList = Object.keys(newReportObject?.participants ?? {}).join(','); + parameters.reportName = newReportObject?.reportName ?? ''; // If we have an avatar then include it with the parameters if (avatar) { @@ -966,8 +965,8 @@ function navigateToAndOpenReport( optimisticReportID?: string, isGroupChat = false, ) { - let newChat: ReportUtils.OptimisticChatReport | EmptyObject = {}; - let chat: OnyxEntry | EmptyObject = {}; + let newChat: ReportUtils.OptimisticChatReport | undefined; + let chat: OnyxEntry; const participantAccountIDs = PersonalDetailsUtils.getAccountIDsByLogins(userLogins); // If we are not creating a new Group Chat then we are creating a 1:1 DM and will look for an existing chat @@ -997,12 +996,12 @@ function navigateToAndOpenReport( const report = isEmptyObject(chat) ? newChat : chat; // We want to pass newChat here because if anything is passed in that param (even an existing chat), we will try to create a chat on the server - openReport(report.reportID, '', userLogins, newChat, undefined, undefined, undefined, avatarFile); + openReport(report?.reportID ?? '', '', userLogins, newChat, undefined, undefined, undefined, avatarFile); if (shouldDismissModal) { Navigation.dismissModalWithReport(report); } else { Navigation.navigateWithSwitchPolicyID({route: ROUTES.HOME}); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID)); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '-1')); } } @@ -1012,7 +1011,7 @@ function navigateToAndOpenReport( * @param participantAccountIDs of user logins to start a chat report with. */ function navigateToAndOpenReportWithAccountIDs(participantAccountIDs: number[]) { - let newChat: ReportUtils.OptimisticChatReport | EmptyObject = {}; + let newChat: ReportUtils.OptimisticChatReport | undefined; const chat = ReportUtils.getChatByParticipants([...participantAccountIDs, currentUserAccountID]); if (!chat) { newChat = ReportUtils.buildOptimisticChatReport([...participantAccountIDs, currentUserAccountID]); @@ -1020,7 +1019,7 @@ function navigateToAndOpenReportWithAccountIDs(participantAccountIDs: number[]) const report = chat ?? newChat; // We want to pass newChat here because if anything is passed in that param (even an existing chat), we will try to create a chat on the server - openReport(report.reportID, '', [], newChat, '0', false, participantAccountIDs); + openReport(report?.reportID ?? '', '', [], newChat, '0', false, participantAccountIDs); Navigation.dismissModalWithReport(report); } @@ -1617,7 +1616,7 @@ function updateNotificationPreference( navigate: boolean, parentReportID?: string, parentReportActionID?: string, - report: OnyxEntry | EmptyObject = {}, + report?: OnyxEntry, ) { if (previousValue === newValue) { if (navigate && !isEmptyObject(report) && report.reportID) { @@ -1663,7 +1662,7 @@ function updateNotificationPreference( } } -function updateRoomVisibility(reportID: string, previousValue: RoomVisibility | undefined, newValue: RoomVisibility, navigate: boolean, report: OnyxEntry | EmptyObject = {}) { +function updateRoomVisibility(reportID: string, previousValue: RoomVisibility | undefined, newValue: RoomVisibility, navigate: boolean, report?: OnyxEntry) { if (previousValue === newValue) { if (navigate && !isEmptyObject(report) && report.reportID) { ReportUtils.goBackToDetailsPage(report); @@ -2512,7 +2511,7 @@ function openReportFromDeepLink(url: string, shouldNavigate = true) { if (reportID && !isAuthenticated) { // Call the OpenReport command to check in the server if it's a public room. If so, we'll open it as an anonymous user - openReport(reportID, '', [], {}, '0', true); + openReport(reportID, '', [], undefined, '0', true); // Show the sign-in page if the app is offline if (networkStatus === CONST.NETWORK.NETWORK_STATUS.OFFLINE) { diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index bf94de9c52b2..ec45298c3910 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -48,7 +48,7 @@ function search({hash, query, policyIDs, offset, sortBy, sortOrder}: SearchParam * In that case, when users select the search result row, we need to create the transaction thread on the fly and update the search result with the new transactionThreadReport */ function createTransactionThread(hash: number, transactionID: string, reportID: string, moneyRequestReportActionID: string) { - Report.openReport(reportID, '', [currentUserEmail], {}, moneyRequestReportActionID); + Report.openReport(reportID, '', [currentUserEmail], undefined, moneyRequestReportActionID); const onyxUpdate: Record>> = { data: { diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index e85fdc9d1531..b3e77e9fe66e 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -901,7 +901,7 @@ function toggleTwoFactorAuth(enable: boolean) { }, ]; - API.write(enable ? WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH : WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH, {}, {optimisticData, successData, failureData}); + API.write(enable ? WRITE_COMMANDS.ENABLE_TWO_FACTOR_AUTH : WRITE_COMMANDS.DISABLE_TWO_FACTOR_AUTH, null, {optimisticData, successData, failureData}); } function validateTwoFactorAuth(twoFactorAuthCode: string) { diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 8dfbc152a3ea..15522a84da62 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -22,7 +22,6 @@ import type {Icon} from '@src/types/onyx/OnyxCommon'; import type {ReportActions} from '@src/types/onyx/ReportAction'; import type ReportAction from '@src/types/onyx/ReportAction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import * as Report from './Report'; type OptimisticReport = Pick; @@ -795,22 +794,22 @@ function getShareDestination(reportID: string, reports: OnyxCollection): ReportAction | Record { +function getParentReportAction(report: OnyxEntry): OnyxEntry { // If the report is not a thread report, then it won't have a parent and an empty object can be returned. if (!report?.parentReportID || !report.parentReportActionID) { - return {}; + return undefined; } - return allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`]?.[report.parentReportActionID] ?? {}; + return allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`]?.[report.parentReportActionID]; } /** * Returns the parentReport if the given report is a thread */ -function getParentReport(report: OnyxEntry | EmptyObject): OnyxEntry | EmptyObject { +function getParentReport(report: OnyxEntry): OnyxEntry { if (!report?.parentReportID) { - return {}; + return undefined; } - return allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`] ?? {}; + return allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]; } /** @@ -830,7 +829,7 @@ function deleteTask(report: OnyxEntry) { const shouldDeleteTaskReport = !ReportActionsUtils.doesReportHaveVisibleActions(report.reportID ?? '-1'); const optimisticReportAction: Partial = { pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, - previousMessage: parentReportAction.message, + previousMessage: parentReportAction?.message, message: [ { translationKey: '', @@ -845,7 +844,7 @@ function deleteTask(report: OnyxEntry) { linkMetadata: [], }; const optimisticReportActions = { - [parentReportAction.reportActionID]: optimisticReportAction, + [parentReportAction?.reportActionID ?? '-1']: optimisticReportAction, }; const optimisticData: OnyxUpdate[] = [ @@ -911,7 +910,7 @@ function deleteTask(report: OnyxEntry) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`, value: { - [parentReportAction.reportActionID]: { + [parentReportAction?.reportActionID ?? '-1']: { pendingAction: null, }, }, @@ -938,7 +937,7 @@ function deleteTask(report: OnyxEntry) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`, value: { - [parentReportAction.reportActionID]: { + [parentReportAction?.reportActionID ?? '-1']: { pendingAction: null, }, }, @@ -979,7 +978,7 @@ function getTaskAssigneeAccountID(taskReport: OnyxEntry): numb } const reportAction = getParentReportAction(taskReport); - return reportAction.childManagerAccountID; + return reportAction?.childManagerAccountID; } /** diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index f39102d46ef3..3166d0dfcb8f 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -4,7 +4,6 @@ import lodashClone from 'lodash/clone'; import lodashHas from 'lodash/has'; import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {CurrentUserPersonalDetails} from '@components/withCurrentUserPersonalDetails'; import * as API from '@libs/API'; import type {DismissViolationParams, GetRouteParams, MarkAsCashParams} from '@libs/API/parameters'; import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; @@ -289,7 +288,7 @@ function updateWaypoints(transactionID: string, waypoints: WaypointCollection, i * Dismisses the duplicate transaction violation for the provided transactionIDs * and updates the transaction to include the dismissed violation in the comment. */ -function dismissDuplicateTransactionViolation(transactionIDs: string[], dissmissedPersonalDetails: PersonalDetails | CurrentUserPersonalDetails) { +function dismissDuplicateTransactionViolation(transactionIDs: string[], dissmissedPersonalDetails: PersonalDetails) { const currentTransactionViolations = transactionIDs.map((id) => ({transactionID: id, violations: allTransactionViolation?.[id] ?? []})); const currentTransactions = transactionIDs.map((id) => allTransactions?.[id]); const transactionsReportActions = currentTransactions.map((transaction) => ReportActionsUtils.getIOUActionForReportID(transaction.reportID ?? '', transaction.transactionID ?? '')); diff --git a/src/libs/actions/Travel.ts b/src/libs/actions/Travel.ts index 38a8ce347b3f..e379139fccee 100644 --- a/src/libs/actions/Travel.ts +++ b/src/libs/actions/Travel.ts @@ -21,7 +21,7 @@ function acceptSpotnanaTerms() { asyncOpenURL( // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS, {}, {optimisticData}) + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS, null, {optimisticData}) .then((response) => (response?.spotnanaToken ? buildTravelDotURL(response.spotnanaToken) : buildTravelDotURL())) .catch(() => buildTravelDotURL()), (travelDotURL) => travelDotURL, diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 83a73033d204..fbeed3cd72e9 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -44,7 +44,6 @@ import type OnyxPersonalDetails from '@src/types/onyx/PersonalDetails'; import type {Status} from '@src/types/onyx/PersonalDetails'; import type ReportAction from '@src/types/onyx/ReportAction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import applyOnyxUpdatesReliably from './applyOnyxUpdatesReliably'; import * as Link from './Link'; import * as Report from './Report'; @@ -60,7 +59,7 @@ Onyx.connect({ }, }); -let myPersonalDetails: OnyxEntry | EmptyObject = {}; +let myPersonalDetails: OnyxEntry; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (value) => { @@ -68,7 +67,7 @@ Onyx.connect({ return; } - myPersonalDetails = value[currentUserAccountID] ?? {}; + myPersonalDetails = value[currentUserAccountID] ?? undefined; }, }); @@ -964,7 +963,7 @@ function clearCustomStatus() { }, }, ]; - API.write(WRITE_COMMANDS.CLEAR_STATUS, {}, {optimisticData}); + API.write(WRITE_COMMANDS.CLEAR_STATUS, null, {optimisticData}); } /** diff --git a/src/libs/actions/Wallet.ts b/src/libs/actions/Wallet.ts index c12c44c1ed74..7ba0fd8d474e 100644 --- a/src/libs/actions/Wallet.ts +++ b/src/libs/actions/Wallet.ts @@ -49,7 +49,7 @@ function openOnfidoFlow() { }, ]; - API.read(READ_COMMANDS.OPEN_ONFIDO_FLOW, {}, {optimisticData, finallyData}); + API.read(READ_COMMANDS.OPEN_ONFIDO_FLOW, null, {optimisticData, finallyData}); } function setAdditionalDetailsQuestions(questions: WalletAdditionalQuestionDetails[] | null, idNumber?: string) { @@ -208,14 +208,14 @@ function acceptWalletTerms(parameters: AcceptWalletTermsParams) { * Fetches data when the user opens the InitialSettingsPage */ function openInitialSettingsPage() { - API.read(READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE, {}); + API.read(READ_COMMANDS.OPEN_INITIAL_SETTINGS_PAGE, null); } /** * Fetches data when the user opens the EnablePaymentsPage */ function openEnablePaymentsPage() { - API.read(READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE, {}); + API.read(READ_COMMANDS.OPEN_ENABLE_PAYMENTS_PAGE, null); } function updateCurrentStep(currentStep: ValueOf | null) { diff --git a/src/libs/actions/Welcome.ts b/src/libs/actions/Welcome.ts index 3f70dc0d962d..82af0765e179 100644 --- a/src/libs/actions/Welcome.ts +++ b/src/libs/actions/Welcome.ts @@ -4,7 +4,6 @@ import type {OnboardingPurposeType} from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type Onboarding from '@src/types/onyx/Onboarding'; import type OnyxPolicy from '@src/types/onyx/Policy'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; let onboarding: Onboarding | [] | undefined; let isLoadingReportData = true; @@ -99,7 +98,7 @@ Onyx.connect({ }, }); -const allPolicies: OnyxCollection | EmptyObject = {}; +const allPolicies: OnyxCollection = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, callback: (val, key) => { diff --git a/src/libs/migrations/CheckForPreviousReportActionID.ts b/src/libs/migrations/CheckForPreviousReportActionID.ts index 7e4bbe9ffb3e..83658ff961c0 100644 --- a/src/libs/migrations/CheckForPreviousReportActionID.ts +++ b/src/libs/migrations/CheckForPreviousReportActionID.ts @@ -3,6 +3,7 @@ import Onyx from 'react-native-onyx'; import Log from '@libs/Log'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; +import type {ReportActionsCollectionDataSet} from '@src/types/onyx/ReportAction'; function getReportActionsFromOnyx(): Promise> { return new Promise((resolve) => { @@ -60,6 +61,6 @@ export default function (): Promise { onyxData[onyxKey] = {}; }); - return Onyx.multiSet(onyxData as Record<`${typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS}`, Record>); + return Onyx.multiSet(onyxData as ReportActionsCollectionDataSet); }); } diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index 4ddffa3d802b..f088de064cc7 100755 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -39,7 +39,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {PersonalDetails, Report} from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; type ProfilePageProps = StackScreenProps; @@ -47,7 +46,8 @@ type ProfilePageProps = StackScreenProps { +const getPhoneNumber = (details: OnyxEntry): string | undefined => { + const {login = '', displayName = ''} = details ?? {}; // If the user hasn't set a displayName, it is set to their phone number const parsedPhoneNumber = parsePhoneNumber(displayName); @@ -99,14 +99,14 @@ function ProfilePage({route}: ProfilePageProps) { const isValidAccountID = ValidationUtils.isValidAccountRoute(accountID); const loginParams = route.params?.login; - const details = useMemo((): PersonalDetails | EmptyObject => { + const details = useMemo((): OnyxEntry => { // Check if we have the personal details already in Onyx if (personalDetails?.[accountID]) { - return personalDetails?.[accountID] ?? {}; + return personalDetails?.[accountID] ?? undefined; } // Check if we have the login param if (!loginParams) { - return isValidAccountID ? {} : {accountID: 0}; + return isValidAccountID ? undefined : {accountID: 0}; } // Look up the personal details by login const foundDetails = Object.values(personalDetails ?? {}).find((personalDetail) => personalDetail?.login === loginParams?.toLowerCase()); @@ -139,7 +139,7 @@ function ProfilePage({route}: ProfilePageProps) { const phoneNumber = getPhoneNumber(details); const phoneOrEmail = isSMSLogin ? getPhoneNumber(details) : login; - const hasAvatar = !!details.avatar; + const hasAvatar = !!details?.avatar; const isLoading = !!personalDetailsMetadata?.[accountID]?.isLoading || isEmptyObject(details); const shouldShowBlockingView = (!isValidAccountID && !isLoading) || CONST.RESTRICTED_ACCOUNT_IDS.includes(accountID); @@ -196,7 +196,7 @@ function ProfilePage({route}: ProfilePageProps) { - + {isSMSLogin ? formatPhoneNumber(phoneNumber ?? '') : login} diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 32ed282f9331..8dcb5e199ba1 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -103,7 +103,7 @@ const willBlurTextInputOnTapOutside = willBlurTextInputOnTapOutsideFunc(); function ReportActionCompose({ blockedFromConcierge, - currentUserPersonalDetails = {}, + currentUserPersonalDetails, disabled = false, isComposerFullSize = false, onSubmit, diff --git a/src/pages/home/report/ReportActionItemSingle.tsx b/src/pages/home/report/ReportActionItemSingle.tsx index e5794148dc46..7b0db3e0d844 100644 --- a/src/pages/home/report/ReportActionItemSingle.tsx +++ b/src/pages/home/report/ReportActionItemSingle.tsx @@ -86,7 +86,7 @@ function ReportActionItemSingle({ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, ''); const displayAllActors = useMemo(() => action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW, [action?.actionName]); - const isInvoiceReport = ReportUtils.isInvoiceReport(iouReport ?? {}); + const isInvoiceReport = ReportUtils.isInvoiceReport(iouReport ?? null); const isWorkspaceActor = isInvoiceReport || (ReportUtils.isPolicyExpenseChat(report) && (!actorAccountID || displayAllActors)); const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID; let avatarSource = avatar; diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 239ab12f0d8f..9945eeb7fb4f 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -29,7 +29,6 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import FloatingMessageCounter from './FloatingMessageCounter'; import getInitialNumToRender from './getInitialNumReportActionsToRender'; import ListBoundaryLoader from './ListBoundaryLoader'; @@ -601,7 +600,7 @@ function ReportActionsList({ [isLoadingNewerReportActions, styles.chatContentScrollView, styles.chatContentScrollViewWithHeaderLoader, canShowHeader], ); - const lastReportAction: OnyxTypes.ReportAction | EmptyObject = useMemo(() => sortedReportActions.at(-1) ?? {}, [sortedReportActions]); + const lastReportAction: OnyxTypes.ReportAction | undefined = useMemo(() => sortedReportActions.at(-1) ?? undefined, [sortedReportActions]); const retryLoadOlderChatsError = useCallback(() => { loadOlderChats(true); @@ -622,12 +621,12 @@ function ReportActionsList({ type={CONST.LIST_COMPONENTS.FOOTER} isLoadingOlderReportActions={isLoadingOlderReportActions} isLoadingInitialReportActions={isLoadingInitialReportActions} - lastReportActionName={lastReportAction.actionName} + lastReportActionName={lastReportAction?.actionName} hasError={hasLoadingOlderReportActionsError} onRetry={retryLoadOlderChatsError} /> ); - }, [isLoadingInitialReportActions, isLoadingOlderReportActions, lastReportAction.actionName, isOffline, hasLoadingOlderReportActionsError, retryLoadOlderChatsError]); + }, [isLoadingInitialReportActions, isLoadingOlderReportActions, lastReportAction?.actionName, isOffline, hasLoadingOlderReportActionsError, retryLoadOlderChatsError]); const onLayoutInner = useCallback( (event: LayoutChangeEvent) => { diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 2fc13af7040c..3e8b7643bdef 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -26,7 +26,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import ReportActionCompose from './ReportActionCompose/ReportActionCompose'; import SystemChatReportFooterMessage from './SystemChatReportFooterMessage'; @@ -137,18 +136,18 @@ function ReportFooter({ const mention = match[1] ? match[1].trim() : undefined; const mentionWithDomain = ReportUtils.addDomainToShortMention(mention ?? '') ?? mention; - let assignee: OnyxTypes.PersonalDetails | EmptyObject = {}; + let assignee: OnyxEntry; let assigneeChatReport; if (mentionWithDomain) { - assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? {}; - if (!Object.keys(assignee).length) { + assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? undefined; + if (!Object.keys(assignee ?? {}).length) { const assigneeAccountID = UserUtils.generateAccountID(mentionWithDomain); const optimisticDataForNewAssignee = Task.setNewOptimisticAssignee(mentionWithDomain, assigneeAccountID); assignee = optimisticDataForNewAssignee.assignee; assigneeChatReport = optimisticDataForNewAssignee.assigneeReport; } } - Task.createTaskAndNavigate(report.reportID, title, '', assignee?.login ?? '', assignee.accountID, assigneeChatReport, report.policyID); + Task.createTaskAndNavigate(report.reportID, title, '', assignee?.login ?? '', assignee?.accountID, assigneeChatReport, report.policyID); return true; }, [allPersonalDetails, report.policyID, report.reportID], diff --git a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx index cd85939e8bec..9ffb8c227e7e 100644 --- a/src/pages/home/report/withReportAndReportActionOrNotFound.tsx +++ b/src/pages/home/report/withReportAndReportActionOrNotFound.tsx @@ -52,11 +52,11 @@ export default function > { function WithReportOrNotFound(props: TProps, ref: ForwardedRef) { const getReportAction = useCallback(() => { - let reportAction: OnyxTypes.ReportAction | Record | undefined = props.reportActions?.[`${props.route.params.reportActionID}`]; + let reportAction: OnyxEntry = props.reportActions?.[`${props.route.params.reportActionID}`]; // Handle threads if needed if (!reportAction?.reportActionID) { - reportAction = props?.parentReportAction ?? {}; + reportAction = props?.parentReportAction ?? undefined; } return reportAction; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index ea03c9ae3b06..53bbebec7b02 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -81,7 +81,7 @@ function IOURequestStepConfirmation({ const {translate} = useLocalize(); const {windowWidth} = useWindowDimensions(); const {isOffline} = useNetwork(); - const [receiptFile, setReceiptFile] = useState(); + const [receiptFile, setReceiptFile] = useState>(); const requestType = TransactionUtils.getRequestType(transaction); const isDistanceRequest = requestType === CONST.IOU.REQUEST_TYPE.DISTANCE; @@ -257,7 +257,7 @@ function IOURequestStepConfirmation({ ); const trackExpense = useCallback( - (selectedParticipants: Participant[], trimmedComment: string, receiptObj?: Receipt, gpsPoints?: IOU.GpsPoint) => { + (selectedParticipants: Participant[], trimmedComment: string, receiptObj?: OnyxEntry, gpsPoints?: IOU.GpsPoint) => { if (!report || !transaction) { return; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 0f2d0cc0da61..9399a2a65d9f 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -78,7 +78,7 @@ function IOURequestStepDistanceRate({ function selectDistanceRate(customUnitRateID: string) { if (shouldShowTax) { const policyCustomUnitRate = getCustomUnitRate(policy, customUnitRateID); - const taxRateExternalID = policyCustomUnitRate.attributes?.taxRateExternalID ?? '-1'; + const taxRateExternalID = policyCustomUnitRate?.attributes?.taxRateExternalID ?? '-1'; const taxableAmount = DistanceRequestUtils.getTaxableAmount(policy, customUnitRateID, TransactionUtils.getDistance(transaction)); const taxPercentage = TransactionUtils.getTaxValue(policy, transaction, taxRateExternalID) ?? ''; const taxAmount = CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, taxableAmount)); diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 4c5ed88e6898..ae252da6fff6 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -26,7 +26,7 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {LoginList, PersonalDetails, PrivatePersonalDetails} from '@src/types/onyx'; +import type {LoginList, PrivatePersonalDetails} from '@src/types/onyx'; type ProfilePageOnyxProps = { loginList: OnyxEntry; @@ -102,7 +102,7 @@ function ProfilePage({ ]; useEffect(() => { - App.openProfile(currentUserPersonalDetails as PersonalDetails); + App.openProfile(currentUserPersonalDetails); }, [currentUserPersonalDetails]); const privateOptions = [ diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 4762690db3c1..b7624539a86b 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -4,7 +4,6 @@ import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; import type ONYXKEYS from '@src/ONYXKEYS'; import type CollectionDataSet from '@src/types/utils/CollectionDataSet'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import type * as OnyxCommon from './OnyxCommon'; import type OriginalMessage from './OriginalMessage'; import type {Decision} from './OriginalMessage'; @@ -221,7 +220,7 @@ type ReportActionBase = OnyxCommon.OnyxValueWithOfflineFeedback<{ isFirstItem?: boolean; /** Informations about attachments of report action */ - attachmentInfo?: FileObject | EmptyObject; + attachmentInfo?: FileObject; /** Receipt tied to report action */ receipt?: Receipt; diff --git a/tests/unit/APITest.ts b/tests/unit/APITest.ts index 9688b0890c34..74be6c742f51 100644 --- a/tests/unit/APITest.ts +++ b/tests/unit/APITest.ts @@ -538,7 +538,7 @@ describe('APITests', () => { // WHEN we make a request that should be retried, one that should not, and another that should API.write('MockCommandOne' as WriteCommand, {}); - API.read('MockCommandTwo' as ReadCommand, {}); + API.read('MockCommandTwo' as ReadCommand, null); API.write('MockCommandThree' as WriteCommand, {}); // THEN the retryable requests should immediately be added to the persisted requests diff --git a/tests/unit/SidebarOrderTest.ts b/tests/unit/SidebarOrderTest.ts index 98120a53b6d4..0abfa2efd752 100644 --- a/tests/unit/SidebarOrderTest.ts +++ b/tests/unit/SidebarOrderTest.ts @@ -860,8 +860,6 @@ describe('Sidebar', () => { describe('in #focus mode', () => { it('alphabetizes chats', () => { - LHNTestUtils.getDefaultRenderedSidebarLinks(); - const report1 = {...LHNTestUtils.getFakeReport([1, 2], 3, true), lastMessageText: 'test'}; const report2 = {...LHNTestUtils.getFakeReport([3, 4], 2, true), lastMessageText: 'test'}; const report3 = {...LHNTestUtils.getFakeReport([5, 6], 1, true), lastMessageText: 'test'}; @@ -875,7 +873,7 @@ describe('Sidebar', () => { return ( waitForBatchedUpdates() - .then(() => LHNTestUtils.getDefaultRenderedSidebarLinks()) + .then(() => LHNTestUtils.getDefaultRenderedSidebarLinks('0')) // Given the sidebar is rendered in #focus mode (hides read chats) // with all reports having unread comments .then(() =>