diff --git a/.eslintrc.changed.js b/.eslintrc.changed.js index b2c9a46df078..d0a7f9a27d21 100644 --- a/.eslintrc.changed.js +++ b/.eslintrc.changed.js @@ -21,13 +21,7 @@ module.exports = { }, overrides: [ { - files: [ - 'src/libs/actions/IOU.ts', - 'src/libs/actions/Report.ts', - 'src/pages/workspace/WorkspaceInitialPage.tsx', - 'src/pages/home/report/PureReportActionItem.tsx', - 'src/libs/SidebarUtils.ts', - ], + files: ['src/libs/actions/IOU.ts', 'src/pages/workspace/WorkspaceInitialPage.tsx', 'src/pages/home/report/PureReportActionItem.tsx', 'src/libs/SidebarUtils.ts'], rules: { 'rulesdir/no-default-id-values': 'off', }, diff --git a/src/ROUTES.ts b/src/ROUTES.ts index d6251dd1ff85..5c0d0b4b376f 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -749,7 +749,12 @@ const ROUTES = { WORKSPACE_NEW_ROOM: 'workspace/new-room', WORKSPACE_INITIAL: { route: 'settings/workspaces/:policyID', - getRoute: (policyID: string, backTo?: string) => `${getUrlWithBackToParam(`settings/workspaces/${policyID}`, backTo)}` as const, + getRoute: (policyID: string | undefined, backTo?: string) => { + if (!policyID) { + Log.warn('Invalid policyID while building route WORKSPACE_INITIAL'); + } + return `${getUrlWithBackToParam(`settings/workspaces/${policyID}`, backTo)}` as const; + }, }, WORKSPACE_INVITE: { route: 'settings/workspaces/:policyID/invite', @@ -983,7 +988,12 @@ const ROUTES = { }, WORKSPACE_MEMBERS: { route: 'settings/workspaces/:policyID/members', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/members` as const, + getRoute: (policyID: string | undefined) => { + if (!policyID) { + Log.warn('Invalid policyID while building route WORKSPACE_MEMBERS'); + } + return `settings/workspaces/${policyID}/members` as const; + }, }, WORKSPACE_MEMBERS_IMPORT: { route: 'settings/workspaces/:policyID/members/import', @@ -995,7 +1005,10 @@ const ROUTES = { }, POLICY_ACCOUNTING: { route: 'settings/workspaces/:policyID/accounting', - getRoute: (policyID: string, newConnectionName?: ConnectionName, integrationToDisconnect?: ConnectionName, shouldDisconnectIntegrationBeforeConnecting?: boolean) => { + getRoute: (policyID: string | undefined, newConnectionName?: ConnectionName, integrationToDisconnect?: ConnectionName, shouldDisconnectIntegrationBeforeConnecting?: boolean) => { + if (!policyID) { + Log.warn('Invalid policyID while building route POLICY_ACCOUNTING'); + } let queryParams = ''; if (newConnectionName) { queryParams += `?newConnectionName=${newConnectionName}`; @@ -1033,7 +1046,12 @@ const ROUTES = { }, WORKSPACE_CATEGORIES: { route: 'settings/workspaces/:policyID/categories', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories` as const, + getRoute: (policyID: string | undefined) => { + if (!policyID) { + Log.warn('Invalid policyID while building route WORKSPACE_CATEGORIES'); + } + return `settings/workspaces/${policyID}/categories` as const; + }, }, WORKSPACE_CATEGORY_SETTINGS: { route: 'settings/workspaces/:policyID/category/:categoryName', @@ -1098,7 +1116,12 @@ const ROUTES = { }, WORKSPACE_MORE_FEATURES: { route: 'settings/workspaces/:policyID/more-features', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/more-features` as const, + getRoute: (policyID: string | undefined) => { + if (!policyID) { + Log.warn('Invalid policyID while building route WORKSPACE_MORE_FEATURES'); + } + return `settings/workspaces/${policyID}/more-features` as const; + }, }, WORKSPACE_TAGS: { route: 'settings/workspaces/:policyID/tags', diff --git a/src/libs/API/parameters/SearchForRoomsToMentionParams.ts b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts index 6a4efe7aed6b..adc2bdd2e4eb 100644 --- a/src/libs/API/parameters/SearchForRoomsToMentionParams.ts +++ b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts @@ -1,6 +1,6 @@ type SearchForRoomsToMentionParams = { query: string; - policyID: string; + policyID?: string; }; export default SearchForRoomsToMentionParams; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f5a1e71cea78..4db7d5ff9358 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -10,7 +10,7 @@ import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {SvgProps} from 'react-native-svg'; import type {OriginalMessageIOU, OriginalMessageModifiedExpense} from 'src/types/onyx/OriginalMessage'; -import type {TupleToUnion, ValueOf} from 'type-fest'; +import type {SetRequired, TupleToUnion, ValueOf} from 'type-fest'; import type {FileObject} from '@components/AttachmentModal'; import {FallbackAvatar, IntacctSquare, NetSuiteSquare, QBOSquare, XeroSquare} from '@components/Icon/Expensicons'; import * as defaultGroupAvatars from '@components/Icon/GroupDefaultAvatars'; @@ -513,22 +513,25 @@ type OptimisticModifiedExpenseReportAction = Pick< | 'delegateAccountID' > & {reportID?: string}; -type OptimisticTaskReport = Pick< - Report, - | 'reportID' - | 'reportName' - | 'description' - | 'ownerAccountID' - | 'participants' - | 'managerID' - | 'type' - | 'parentReportID' - | 'policyID' - | 'stateNum' - | 'statusNum' - | 'parentReportActionID' - | 'lastVisibleActionCreated' - | 'hasParentAccess' +type OptimisticTaskReport = SetRequired< + Pick< + Report, + | 'reportID' + | 'reportName' + | 'description' + | 'ownerAccountID' + | 'participants' + | 'managerID' + | 'type' + | 'parentReportID' + | 'policyID' + | 'stateNum' + | 'statusNum' + | 'parentReportActionID' + | 'lastVisibleActionCreated' + | 'hasParentAccess' + >, + 'parentReportID' >; type TransactionDetails = { @@ -6350,8 +6353,8 @@ function buildOptimisticWorkspaceChats(policyID: string, policyName: string, exp function buildOptimisticTaskReport( ownerAccountID: number, + parentReportID: string, assigneeAccountID = 0, - parentReportID?: string, title?: string, description?: string, policyID: string = CONST.POLICY.OWNER_EMAIL_FAKE, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index a469af82dd1c..f0d2d2a08ac9 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -193,7 +193,7 @@ type TaskForParameters = taskReportID: string; parentReportID: string; parentReportActionID: string; - assigneeChatReportID: string; + assigneeChatReportID?: string; createdTaskReportActionID: string; completedTaskReportActionID?: string; title: string; @@ -844,7 +844,7 @@ function openReport( reportActionID?: string, participantLoginList: string[] = [], newReportObject?: OptimisticChatReport, - parentReportActionID = '-1', + parentReportActionID?: string, isFromDeepLink = false, participantAccountIDList: number[] = [], avatar?: File | CustomRNImageManipulatorResult, @@ -934,19 +934,21 @@ function openReport( const onboardingData = prepareOnboardingOptimisticData(choice, onboardingMessage); - optimisticData.push(...onboardingData.optimisticData, { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.NVP_INTRO_SELECTED, - value: { - isInviteOnboardingComplete: true, - }, - }); + if (onboardingData) { + optimisticData.push(...onboardingData.optimisticData, { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.NVP_INTRO_SELECTED, + value: { + isInviteOnboardingComplete: true, + }, + }); - successData.push(...onboardingData.successData); + successData.push(...onboardingData.successData); - failureData.push(...onboardingData.failureData); + failureData.push(...onboardingData.failureData); - parameters.guidedSetupData = JSON.stringify(onboardingData.guidedSetupData); + parameters.guidedSetupData = JSON.stringify(onboardingData.guidedSetupData); + } } } @@ -1100,7 +1102,7 @@ function openReport( failureData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${newReportObject.parentReportID}`, - value: {[parentReportActionID]: {childReportID: '-1', childType: ''}}, + value: {[parentReportActionID]: {childType: ''}}, }); } } @@ -1177,12 +1179,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 ?? '-1'), actionType); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID), actionType); } } @@ -1200,7 +1202,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); } @@ -1211,8 +1213,8 @@ function navigateToAndOpenReportWithAccountIDs(participantAccountIDs: number[]) * @param parentReportAction the parent comment of a thread * @param parentReportID The reportID of the parent */ -function navigateToAndOpenChildReport(childReportID = '-1', parentReportAction: Partial = {}, parentReportID = '0') { - if (childReportID !== '-1' && childReportID !== '0') { +function navigateToAndOpenChildReport(childReportID: string | undefined, parentReportAction: Partial = {}, parentReportID?: string) { + if (childReportID) { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(childReportID)); } else { const participantAccountIDs = [...new Set([currentUserAccountID, Number(parentReportAction.actorAccountID)])]; @@ -1506,36 +1508,38 @@ function handleReportChanged(report: OnyxEntry) { return; } + const {reportID, preexistingReportID, parentReportID, parentReportActionID} = report; + // Handle cleanup of stale optimistic IOU report and its report preview separately - if (report?.reportID && report.preexistingReportID && isMoneyRequestReport(report) && report?.parentReportActionID) { - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, { - [report.parentReportActionID]: null, + if (reportID && preexistingReportID && isMoneyRequestReport(report) && parentReportActionID) { + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, { + [parentReportActionID]: null, }); - Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, null); + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null); return; } // It is possible that we optimistically created a DM/group-DM for a set of users for which a report already exists. // In this case, the API will let us know by returning a preexistingReportID. // We should clear out the optimistically created report and re-route the user to the preexisting report. - if (report?.reportID && report.preexistingReportID) { + if (reportID && preexistingReportID) { let callback = () => { - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, null); - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.preexistingReportID}`, {...report, reportID: report.preexistingReportID, preexistingReportID: null}); - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, null); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${preexistingReportID}`, {...report, reportID: preexistingReportID, preexistingReportID: null}); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, null); }; // Only re-route them if they are still looking at the optimistically created report - if (Navigation.getActiveRoute().includes(`/r/${report.reportID}`)) { + if (Navigation.getActiveRoute().includes(`/r/${reportID}`)) { const currCallback = callback; callback = () => { currCallback(); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.preexistingReportID ?? '-1'), CONST.NAVIGATION.TYPE.UP); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(preexistingReportID), CONST.NAVIGATION.TYPE.UP); }; // The report screen will listen to this event and transfer the draft comment to the existing report // This will allow the newest draft comment to be transferred to the existing report - DeviceEventEmitter.emit(`switchToPreExistingReport_${report.reportID}`, { - preexistingReportID: report.preexistingReportID, + DeviceEventEmitter.emit(`switchToPreExistingReport_${reportID}`, { + preexistingReportID, callback, }); @@ -1544,20 +1548,20 @@ function handleReportChanged(report: OnyxEntry) { // In case the user is not on the report screen, we will transfer the report draft comment directly to the existing report // after that clear the optimistically created report - const draftReportComment = allReportDraftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`]; + const draftReportComment = allReportDraftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`]; if (!draftReportComment) { callback(); return; } - saveReportDraftComment(report.preexistingReportID ?? '-1', draftReportComment, callback); + saveReportDraftComment(preexistingReportID, draftReportComment, callback); return; } - if (report?.reportID) { + if (reportID) { if (isConciergeChatReport(report)) { - conciergeChatReportID = report.reportID; + conciergeChatReportID = reportID; } } } @@ -1972,10 +1976,15 @@ function updateRoomVisibility(reportID: string, previousValue: RoomVisibility | * @param parentReportID The reportID of the parent * @param prevNotificationPreference The previous notification preference for the child report */ -function toggleSubscribeToChildReport(childReportID = '-1', parentReportAction: Partial = {}, parentReportID = '-1', prevNotificationPreference?: NotificationPreference) { - if (childReportID !== '-1') { +function toggleSubscribeToChildReport( + childReportID: string | undefined, + parentReportAction: Partial = {}, + parentReportID?: string, + prevNotificationPreference?: NotificationPreference, +) { + if (childReportID) { openReport(childReportID); - const parentReportActionID = parentReportAction?.reportActionID ?? '-1'; + const parentReportActionID = parentReportAction?.reportActionID; if (!prevNotificationPreference || isHiddenForCurrentUser(prevNotificationPreference)) { updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, parentReportID, parentReportActionID); } else { @@ -2946,7 +2955,7 @@ function navigateToMostRecentReport(currentReport: OnyxEntry) { const lastAccessedReportID = findLastAccessedReport(false, false, undefined, currentReport?.reportID)?.reportID; if (lastAccessedReportID) { - const lastAccessedReportRoute = ROUTES.REPORT_WITH_ID.getRoute(lastAccessedReportID ?? '-1'); + const lastAccessedReportRoute = ROUTES.REPORT_WITH_ID.getRoute(lastAccessedReportID); Navigation.goBack(lastAccessedReportRoute); } else { const isChatThread = isChatThreadReportUtils(currentReport); @@ -3121,7 +3130,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, value: { [report.parentReportActionID]: { - childReportNotificationPreference: report?.participants?.[currentUserAccountID ?? -1]?.notificationPreference ?? getDefaultNotificationPreferenceForReport(report), + childReportNotificationPreference: report?.participants?.[currentUserAccountID]?.notificationPreference ?? getDefaultNotificationPreferenceForReport(report), }, }, }); @@ -3613,10 +3622,16 @@ function prepareOnboardingOptimisticData( // Guides are assigned and tasks are posted in the #admins room for the MANAGE_TEAM onboarding action, except for emails that have a '+'. const shouldPostTasksInAdminsRoom = engagementChoice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM && !currentUserEmail?.includes('+'); - const integrationName = userReportedIntegration ? CONST.ONBOARDING_ACCOUNTING_MAPPING[userReportedIntegration] : ''; const adminsChatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`]; const targetChatReport = shouldPostTasksInAdminsRoom ? adminsChatReport : getChatByParticipants([CONST.ACCOUNT_ID.CONCIERGE, currentUserAccountID]); - const {reportID: targetChatReportID = '', policyID: targetChatPolicyID = ''} = targetChatReport ?? {}; + const {reportID: targetChatReportID, policyID: targetChatPolicyID} = targetChatReport ?? {}; + + if (!targetChatReportID) { + Log.warn('Missing reportID for onboarding optimistic data'); + return; + } + + const integrationName = userReportedIntegration ? CONST.ONBOARDING_ACCOUNTING_MAPPING[userReportedIntegration] : ''; const assignedGuideEmail = getPolicy(targetChatPolicyID)?.assignedGuide?.email ?? 'Setup Specialist'; const assignedGuidePersonalDetail = Object.values(allPersonalDetails ?? {}).find((personalDetail) => personalDetail?.login === assignedGuideEmail); let assignedGuideAccountID: number; @@ -3668,14 +3683,14 @@ function prepareOnboardingOptimisticData( const taskDescription = typeof task.description === 'function' ? task.description({ - adminsRoomLink: `${environmentURL}/${ROUTES.REPORT_WITH_ID.getRoute(adminsChatReportID ?? '-1')}`, - workspaceCategoriesLink: `${environmentURL}/${ROUTES.WORKSPACE_CATEGORIES.getRoute(onboardingPolicyID ?? '-1')}`, - workspaceMembersLink: `${environmentURL}/${ROUTES.WORKSPACE_MEMBERS.getRoute(onboardingPolicyID ?? '-1')}`, - workspaceMoreFeaturesLink: `${environmentURL}/${ROUTES.WORKSPACE_MORE_FEATURES.getRoute(onboardingPolicyID ?? '-1')}`, + adminsRoomLink: `${environmentURL}/${ROUTES.REPORT_WITH_ID.getRoute(adminsChatReportID)}`, + workspaceCategoriesLink: `${environmentURL}/${ROUTES.WORKSPACE_CATEGORIES.getRoute(onboardingPolicyID)}`, + workspaceMembersLink: `${environmentURL}/${ROUTES.WORKSPACE_MEMBERS.getRoute(onboardingPolicyID)}`, + workspaceMoreFeaturesLink: `${environmentURL}/${ROUTES.WORKSPACE_MORE_FEATURES.getRoute(onboardingPolicyID)}`, navatticURL: getNavatticURL(environment, engagementChoice), integrationName, - workspaceAccountingLink: `${environmentURL}/${ROUTES.POLICY_ACCOUNTING.getRoute(onboardingPolicyID ?? '-1')}`, - workspaceSettingsLink: `${environmentURL}/${ROUTES.WORKSPACE_INITIAL.getRoute(onboardingPolicyID ?? '-1')}`, + workspaceAccountingLink: `${environmentURL}/${ROUTES.POLICY_ACCOUNTING.getRoute(onboardingPolicyID)}`, + workspaceSettingsLink: `${environmentURL}/${ROUTES.WORKSPACE_INITIAL.getRoute(onboardingPolicyID)}`, }) : task.description; const taskTitle = @@ -3686,8 +3701,8 @@ function prepareOnboardingOptimisticData( : task.title; const currentTask = buildOptimisticTaskReport( actorAccountID, - currentUserAccountID, targetChatReportID, + currentUserAccountID, taskTitle, taskDescription, targetChatPolicyID, @@ -3726,11 +3741,10 @@ function prepareOnboardingOptimisticData( type: 'task', task: task.type, taskReportID: currentTask.reportID, - parentReportID: currentTask.parentReportID ?? '-1', + parentReportID: currentTask.parentReportID, parentReportActionID: taskReportAction.reportAction.reportActionID, - assigneeChatReportID: '', createdTaskReportActionID: taskCreatedAction.reportActionID, - completedTaskReportActionID: completedTaskReportAction?.reportActionID ?? undefined, + completedTaskReportActionID: completedTaskReportAction?.reportActionID, title: currentTask.reportName ?? '', description: taskDescription ?? '', })); @@ -4165,14 +4179,12 @@ function completeOnboarding( userReportedIntegration?: OnboardingAccounting, wasInvited?: boolean, ) { - const {optimisticData, successData, failureData, guidedSetupData, actorAccountID, selfDMParameters} = prepareOnboardingOptimisticData( - engagementChoice, - data, - adminsChatReportID, - onboardingPolicyID, - userReportedIntegration, - wasInvited, - ); + const onboardingData = prepareOnboardingOptimisticData(engagementChoice, data, adminsChatReportID, onboardingPolicyID, userReportedIntegration, wasInvited); + if (!onboardingData) { + return; + } + + const {optimisticData, successData, failureData, guidedSetupData, actorAccountID, selfDMParameters} = onboardingData; const parameters: CompleteGuidedSetupParams = { engagementChoice, @@ -4248,7 +4260,7 @@ function searchForReports(searchInput: string, policyID?: string) { }, ]; - const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {query: searchInput, policyID: policyID ?? '-1'}; + const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {query: searchInput, policyID}; const searchForReportsParams: SearchForReportsParams = {searchInput, canCancel: true}; // We want to cancel all pending SearchForReports API calls before making another one diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 2a13ff69b769..e67ad4831d40 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -123,7 +123,7 @@ function createTaskAndNavigate( policyID: string = CONST.POLICY.OWNER_EMAIL_FAKE, isCreatedUsingMarkdown = false, ) { - const optimisticTaskReport = ReportUtils.buildOptimisticTaskReport(currentUserAccountID, assigneeAccountID, parentReportID, title, description, policyID); + const optimisticTaskReport = ReportUtils.buildOptimisticTaskReport(currentUserAccountID, parentReportID, assigneeAccountID, title, description, policyID); const assigneeChatReportID = assigneeChatReport?.reportID; const taskReportID = optimisticTaskReport.reportID; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index fe9e1a5b6cee..91481cd30754 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -311,7 +311,7 @@ const ContextMenuActions: ContextMenuAction[] = [ onPress: (closePopover, {reportID, reportAction, draftMessage}) => { if (isMoneyRequestAction(reportAction)) { hideContextMenu(false); - const childReportID = `${reportAction?.childReportID ?? CONST.DEFAULT_NUMBER_ID}`; + const childReportID = reportAction?.childReportID; openReport(childReportID); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(childReportID)); return;