Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Expense - Not here page shows up briefly when deleting the expense #52740

Open
wants to merge 50 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7d69e66
Change behavior, navigate before transaction delete to resolve [delet…
wildan-m Oct 5, 2024
b32c78b
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Oct 6, 2024
bc8f8ed
fix incorrect reportIDToNavigateBack
wildan-m Oct 6, 2024
f6781e6
actually delete the transaction after ReportDetailsPage unmounted
wildan-m Oct 6, 2024
5b205e6
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Oct 7, 2024
0bd45cc
Refactor, remove unnecessary code
wildan-m Oct 7, 2024
eb051bb
Add NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL to show loading transact…
wildan-m Oct 7, 2024
c2cecdc
prettier
wildan-m Oct 7, 2024
7e8d4f4
Refactor
wildan-m Oct 7, 2024
66e3de8
Partially DeleteTransactionThread to prevent not found page briefly a…
wildan-m Oct 7, 2024
9ec0a26
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Oct 23, 2024
9bce4f0
decouple urlToNavigateBack functions
wildan-m Oct 23, 2024
e2cd642
actually delete transaction after reportdetailspage unmounted
wildan-m Oct 23, 2024
980e8e5
Resolve cyclic dependency
wildan-m Oct 23, 2024
0288efb
extract navagateUrl from prepareToCleanUpMoneyRequest
wildan-m Oct 24, 2024
aef7070
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Oct 24, 2024
5d982cc
Implement NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL
wildan-m Oct 24, 2024
4447344
change delete money request and track expense to merge instead of fas…
wildan-m Oct 24, 2024
71c3d41
show skeleton when deleting processed
wildan-m Oct 24, 2024
82668c5
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 14, 2024
390d357
remove unnecessary code
wildan-m Nov 14, 2024
576e194
prettier
wildan-m Nov 14, 2024
7145f31
lint & prettier
wildan-m Nov 14, 2024
1256e03
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 15, 2024
a343297
Ensure report skeleton hide after interaction and update completed
wildan-m Nov 15, 2024
e41e182
Remove unused import
wildan-m Nov 15, 2024
7123b2f
Move navigateToTargetUrl to onModalHide, fix potential bug, remove un…
wildan-m Nov 15, 2024
19dccb4
lint
wildan-m Nov 15, 2024
6c96672
Refactor for more accurate function name
wildan-m Nov 15, 2024
38a7323
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 19, 2024
964626b
fix lint
wildan-m Nov 19, 2024
67eb827
Remove unnecessary code
wildan-m Nov 19, 2024
62aaa28
remove unnecessary export
wildan-m Nov 19, 2024
051d3cc
Adjust tests after change deleting approach from set to merge
wildan-m Nov 19, 2024
0887779
Adjust more test
wildan-m Nov 19, 2024
78f8f71
Update src/ONYXKEYS.ts
wildan-m Nov 22, 2024
df0100f
Refactor name
wildan-m Nov 22, 2024
0ea2bba
remove unnecessary code
wildan-m Nov 22, 2024
9c0c5d1
Merge branch 'wildan/fix/45576-fix-not-found-decouple-2' of https://g…
wildan-m Nov 22, 2024
9cedf92
Update src/pages/ReportDetailsPage.tsx
wildan-m Nov 22, 2024
65199e2
Update src/pages/ReportDetailsPage.tsx
wildan-m Nov 22, 2024
213fe69
Refactor
wildan-m Nov 22, 2024
fee7dc7
Merge branch 'wildan/fix/45576-fix-not-found-decouple-2' of https://g…
wildan-m Nov 22, 2024
1f6a99d
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 22, 2024
51daaa0
resolve typecheck error
wildan-m Nov 22, 2024
6b0b5a6
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 23, 2024
5e5026d
Add comment why use merge instead of set when deleting report
wildan-m Nov 23, 2024
5ddba66
prettier
wildan-m Nov 23, 2024
71728f6
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 26, 2024
fd39c99
Merge branch 'main' of https://github.com/wildan-m/App into wildan/fi…
wildan-m Nov 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ const ONYXKEYS = {
/** The NVP containing all information related to educational tooltip in workspace chat */
NVP_WORKSPACE_TOOLTIP: 'workspaceTooltip',

/** The NVP containing the target url to navigate to when deleting a transaction */
NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL: 'nvp_deleteTransactionNavigateBackURL',

/** Whether to show save search rename tooltip */
SHOULD_SHOW_SAVED_SEARCH_RENAME_TOOLTIP: 'shouldShowSavedSearchRenameTooltip',

Expand Down Expand Up @@ -1012,6 +1015,7 @@ type OnyxValuesMapping = {
[ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: number;
[ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END]: number;
[ONYXKEYS.NVP_WORKSPACE_TOOLTIP]: OnyxTypes.WorkspaceTooltip;
[ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL]: string | undefined;
[ONYXKEYS.NVP_SHOULD_HIDE_GBR_TOOLTIP]: boolean;
[ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[];
[ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string;
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
isVisible={isDeleteRequestModalVisible}
onConfirm={deleteTransaction}
onCancel={() => setIsDeleteRequestModalVisible(false)}
onModalHide={() => ReportUtils.navigateBackAfterDeleteTransaction(navigateBackToAfterDelete.current)}
onModalHide={() => ReportUtils.navigateBackOnDeleteTransaction(navigateBackToAfterDelete.current)}
prompt={translate('iou.deleteConfirmation', {count: 1})}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
Expand Down
4 changes: 2 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4200,7 +4200,7 @@ function goBackToDetailsPage(report: OnyxEntry<Report>, backTo?: string) {
Navigation.goBack(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? '-1', backTo));
}

function navigateBackAfterDeleteTransaction(backRoute: Route | undefined, isFromRHP?: boolean) {
function navigateBackOnDeleteTransaction(backRoute: Route | undefined, isFromRHP?: boolean) {
if (!backRoute) {
return;
}
Expand Down Expand Up @@ -8712,7 +8712,7 @@ export {
canWriteInReport,
navigateToDetailsPage,
navigateToPrivateNotes,
navigateBackAfterDeleteTransaction,
navigateBackOnDeleteTransaction,
parseReportRouteParams,
parseReportActionHtmlToText,
requiresAttentionFromCurrentUser,
Expand Down
147 changes: 117 additions & 30 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import type {IOUAction, IOUType} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Route} from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {Attendee, Participant, Split} from '@src/types/onyx/IOU';
import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon';
Expand Down Expand Up @@ -1784,10 +1785,21 @@ function getDeleteTrackExpenseInformation(

if (shouldDeleteTransactionThread) {
optimisticData.push(
// Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear.
// The remaining parts of the report object will be removed after the API call is successful.
{
onyxMethod: Onyx.METHOD.SET,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
value: null,
value: {
reportID: null,
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
participants: {
[userAccountID]: {
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
},
},
Comment on lines +1793 to +1802
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing this? When the transaction is deleted we should delete the transaction thread, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luacmartins We switched from using SET to MERGE to prevent the appearance of the not found page due to platforms updating the value too quickly. This change has already been made for leaveRoom and leaveGroupChat to address a similar issue #49468.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying. I think that makes sense, it just feels a bit odd to do that. Let's add a comment explaining why we're doing it so people don't try to revert this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},
{
onyxMethod: Onyx.METHOD.SET,
Expand Down Expand Up @@ -1827,6 +1839,19 @@ function getDeleteTrackExpenseInformation(
},
];

// Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response.
// This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function.
if (shouldDeleteTransactionThread && transactionThread) {
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
value: Object.keys(transactionThread).reduce<Record<string, null>>((acc, key) => {
acc[key] = null;
return acc;
}, {}),
});
}

Comment on lines +1844 to +1854
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luacmartins Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response. This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function. #50846 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, let's add a comment about it. We should add a comment for all instances to make sure people don't revert this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const failureData: OnyxUpdate[] = [];

if (shouldDeleteTransactionFromOnyx) {
Expand Down Expand Up @@ -5393,10 +5418,9 @@ function updateMoneyRequestAmountAndCurrency({
*
* @param transactionID - The transactionID of IOU
* @param reportAction - The reportAction of the transaction in the IOU report
* @param isSingleTransactionView - whether we are in the transaction thread report
* @return the url to navigate back once the money request is deleted
*/
function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false) {
function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction) {
// STEP 1: Get all collections we're updating
const allReports = ReportConnection.getAllReports();
const iouReportID = ReportActionsUtils.isMoneyRequestAction(reportAction) ? ReportActionsUtils.getOriginalMessage(reportAction)?.IOUReportID : '-1';
Expand Down Expand Up @@ -5497,19 +5521,6 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT
updatedReportPreviewAction.childMoneyRequestCount = reportPreviewAction.childMoneyRequestCount - 1;
}

// STEP 5: Calculate the url that the user will be navigated back to
// This depends on which page they are on and which resources were deleted
let reportIDToNavigateBack: string | undefined;
if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) {
reportIDToNavigateBack = iouReport.reportID;
}

if (iouReport?.chatReportID && shouldDeleteIOUReport) {
reportIDToNavigateBack = iouReport.chatReportID;
}

const urlToNavigateBack = reportIDToNavigateBack ? ROUTES.REPORT_WITH_ID.getRoute(reportIDToNavigateBack) : undefined;

return {
shouldDeleteTransactionThread,
shouldDeleteIOUReport,
Expand All @@ -5523,10 +5534,59 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT
transactionViolations,
reportPreviewAction,
iouReport,
urlToNavigateBack,
};
}

/**
* Calculate the URL to navigate to after a money request deletion
* @param transactionID - The ID of the money request being deleted
* @param reportAction - The report action associated with the money request
* @param isSingleTransactionView - whether we are in the transaction thread report
* @returns The URL to navigate to
*/
function getNavigationUrlOnMoneyRequestDelete(transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false): Route | undefined {
const {shouldDeleteTransactionThread, shouldDeleteIOUReport, iouReport} = prepareToCleanUpMoneyRequest(transactionID, reportAction);

// Determine which report to navigate back to
if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) {
return ROUTES.REPORT_WITH_ID.getRoute(iouReport.reportID);
}

if (iouReport?.chatReportID && shouldDeleteIOUReport) {
return ROUTES.REPORT_WITH_ID.getRoute(iouReport.chatReportID);
}

return undefined;
}

/**
* Calculate the URL to navigate to after a track expense deletion
* @param chatReportID - The ID of the chat report containing the track expense
* @param transactionID - The ID of the track expense being deleted
* @param reportAction - The report action associated with the track expense
* @param isSingleTransactionView - Whether we're in single transaction view
* @returns The URL to navigate to
*/
function getNavigationUrlAfterTrackExpenseDelete(chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false): Route | undefined {
const chatReport = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] ?? null;

// If not a self DM, handle it as a regular money request
if (!ReportUtils.isSelfDM(chatReport)) {
return getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView);
}

const transactionThreadID = reportAction.childReportID;
const shouldDeleteTransactionThread = transactionThreadID ? (reportAction?.childVisibleActionCount ?? 0) === 0 : false;

// Only navigate if in single transaction view and the thread will be deleted
if (isSingleTransactionView && shouldDeleteTransactionThread && chatReport?.reportID) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
return ROUTES.REPORT_WITH_ID.getRoute(chatReport.reportID);
}

return undefined;
}

/**
*
* @param transactionID - The transactionID of IOU
Expand All @@ -5545,9 +5605,9 @@ function cleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repo
chatReport,
iouReport,
reportPreviewAction,
urlToNavigateBack,
} = prepareToCleanUpMoneyRequest(transactionID, reportAction, isSingleTransactionView);
} = prepareToCleanUpMoneyRequest(transactionID, reportAction);

const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView);
// build Onyx data

// Onyx operations to delete the transaction, update the IOU report action and chat report action
Expand Down Expand Up @@ -5691,8 +5751,9 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
transactionViolations,
iouReport,
reportPreviewAction,
urlToNavigateBack,
} = prepareToCleanUpMoneyRequest(transactionID, reportAction, isSingleTransactionView);
} = prepareToCleanUpMoneyRequest(transactionID, reportAction);

const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView);

// STEP 2: Build Onyx data
// The logic mostly resembles the cleanUpMoneyRequest function
Expand All @@ -5712,10 +5773,21 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor

if (shouldDeleteTransactionThread) {
optimisticData.push(
// Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear.
// The remaining parts of the report object will be removed after the API call is successful.
{
onyxMethod: Onyx.METHOD.SET,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
value: null,
value: {
reportID: null,
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
participants: {
[userAccountID]: {
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
},
},
},
Comment on lines +5781 to +5790
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},
{
onyxMethod: Onyx.METHOD.SET,
Expand Down Expand Up @@ -5813,6 +5885,19 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
},
];

// Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response.
// This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function.
if (shouldDeleteTransactionThread && transactionThread) {
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
value: Object.keys(transactionThread).reduce<Record<string, null>>((acc, key) => {
acc[key] = null;
return acc;
}, {}),
});
}

Comment on lines +5890 to +5900
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if (shouldDeleteIOUReport) {
successData.push({
onyxMethod: Onyx.METHOD.SET,
Expand Down Expand Up @@ -5916,15 +6001,18 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
}

function deleteTrackExpense(chatReportID: string, transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false) {
const urlToNavigateBack = getNavigationUrlAfterTrackExpenseDelete(chatReportID, transactionID, reportAction, isSingleTransactionView);

// STEP 1: Get all collections we're updating
const chatReport = ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] ?? null;
if (!ReportUtils.isSelfDM(chatReport)) {
return deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView);
deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView);
return urlToNavigateBack;
}

const whisperAction = ReportActionsUtils.getTrackExpenseActionableWhisper(transactionID, chatReportID);
const actionableWhisperReportActionID = whisperAction?.reportActionID;
const {parameters, optimisticData, successData, failureData, shouldDeleteTransactionThread} = getDeleteTrackExpenseInformation(
const {parameters, optimisticData, successData, failureData} = getDeleteTrackExpenseInformation(
chatReportID,
transactionID,
reportAction,
Expand All @@ -5939,10 +6027,7 @@ function deleteTrackExpense(chatReportID: string, transactionID: string, reportA
CachedPDFPaths.clearByKey(transactionID);

// STEP 7: Navigate the user depending on which page they are on and which resources were deleted
if (isSingleTransactionView && shouldDeleteTransactionThread) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
return ROUTES.REPORT_WITH_ID.getRoute(chatReport?.reportID ?? '-1');
}
return urlToNavigateBack;
}

/**
Expand Down Expand Up @@ -8488,5 +8573,7 @@ export {
updateLastLocationPermissionPrompt,
resolveDuplicates,
getIOUReportActionToApproveOrPay,
getNavigationUrlOnMoneyRequestDelete,
getNavigationUrlAfterTrackExpenseDelete,
};
export type {GPSPoint as GpsPoint, IOURequestType};
12 changes: 12 additions & 0 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2916,6 +2916,8 @@ function leaveGroupChat(reportID: string) {
});
}

// Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response.
// This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function.
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -4346,6 +4348,14 @@ function exportReportToCSV({reportID, transactionIDList}: ExportReportCSVParams,
fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_CSV}), 'Expensify.csv', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed);
}

function setDeleteTransactionNavigateBackUrl(url: string) {
Onyx.set(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, url);
}

function clearDeleteTransactionNavigateBackUrl() {
Onyx.merge(ONYXKEYS.NVP_DELETE_TRANSACTION_NAVIGATE_BACK_URL, null);
}

export type {Video};

export {
Expand Down Expand Up @@ -4435,4 +4445,6 @@ export {
updateReportName,
updateRoomVisibility,
updateWriteCapability,
setDeleteTransactionNavigateBackUrl,
clearDeleteTransactionNavigateBackUrl,
};
42 changes: 34 additions & 8 deletions src/libs/actions/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,36 @@ function getParentReport(report: OnyxEntry<OnyxTypes.Report>): OnyxEntry<OnyxTyp
return ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`];
}

/**
* Calculate the URL to navigate to after a task deletion
* @param report - The task report being deleted
* @returns The URL to navigate to
*/
function getNavigationUrlOnTaskDelete(report: OnyxEntry<OnyxTypes.Report>): string | undefined {
if (!report) {
return undefined;
}

const shouldDeleteTaskReport = !ReportActionsUtils.doesReportHaveVisibleActions(report.reportID ?? '-1');
if (!shouldDeleteTaskReport) {
return undefined;
}

// First try to navigate to parent report
const parentReport = getParentReport(report);
if (parentReport?.reportID) {
return ROUTES.REPORT_WITH_ID.getRoute(parentReport.reportID);
}

// If no parent report, try to navigate to most recent report
const mostRecentReportID = Report.getMostRecentReportID(report);
if (mostRecentReportID) {
return ROUTES.REPORT_WITH_ID.getRoute(mostRecentReportID);
}

return undefined;
}

/**
* Cancels a task by setting the report state to SUBMITTED and status to CLOSED
*/
Expand Down Expand Up @@ -1121,15 +1151,10 @@ function deleteTask(report: OnyxEntry<OnyxTypes.Report>) {
API.write(WRITE_COMMANDS.CANCEL_TASK, parameters, {optimisticData, successData, failureData});
Report.notifyNewAction(report.reportID, currentUserAccountID);

if (shouldDeleteTaskReport) {
const urlToNavigateBack = getNavigationUrlOnTaskDelete(report);
if (urlToNavigateBack) {
Navigation.goBack();
if (parentReport?.reportID) {
return ROUTES.REPORT_WITH_ID.getRoute(parentReport.reportID);
}
const mostRecentReportID = Report.getMostRecentReportID(report);
if (mostRecentReportID) {
return ROUTES.REPORT_WITH_ID.getRoute(mostRecentReportID);
}
return urlToNavigateBack;
}
}

Expand Down Expand Up @@ -1243,6 +1268,7 @@ export {
canModifyTask,
canActionTask,
setNewOptimisticAssignee,
getNavigationUrlOnTaskDelete,
};

export type {PolicyValue, Assignee, ShareDestination};
Loading