Skip to content
Closed
Changes from all commits
Commits
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
128 changes: 64 additions & 64 deletions src/pages/home/report/ReportActionsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,72 +155,11 @@ function ReportActionsView({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [route, isLoadingInitialReportActions, reportActionID]);

// When we are offline before opening an IOU/Expense report,
// the total of the report and sometimes the expense aren't displayed because these actions aren't returned until `OpenReport` API is complete.
// We generate a fake created action here if it doesn't exist to display the total whenever possible because the total just depends on report data
// and we also generate an expense action if the number of expenses in allReportActions is less than the total number of expenses
// to display at least one expense action to match the total data.
const reportActionsToDisplay = useMemo(() => {
if (!ReportUtils.isMoneyRequestReport(report) || !allReportActions.length) {
return allReportActions;
}

const actions = [...allReportActions];
const lastAction = allReportActions[allReportActions.length - 1];

if (!ReportActionsUtils.isCreatedAction(lastAction)) {
const optimisticCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(String(report?.ownerAccountID), DateUtils.subtractMillisecondsFromDateTime(lastAction.created, 1));
optimisticCreatedAction.pendingAction = null;
actions.push(optimisticCreatedAction);
}

const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(report.chatReportID ?? '', report.reportID);
const moneyRequestActions = allReportActions.filter((action) => {
const originalMessage = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) : undefined;
return (
ReportActionsUtils.isMoneyRequestAction(action) &&
originalMessage &&
(originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE ||
!!(originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && originalMessage?.IOUDetails) ||
originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.TRACK)
);
});

if (report.total && moneyRequestActions.length < (reportPreviewAction?.childMoneyRequestCount ?? 0) && isEmptyObject(transactionThreadReport)) {
const optimisticIOUAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
0,
CONST.CURRENCY.USD,
'',
[],
NumberUtils.rand64(),
undefined,
report.reportID,
false,
false,
{},
false,
DateUtils.subtractMillisecondsFromDateTime(actions[actions.length - 1].created, 1),
) as OnyxTypes.ReportAction;
moneyRequestActions.push(optimisticIOUAction);
actions.splice(actions.length - 1, 0, optimisticIOUAction);
}

// Update pending action of created action if we have some requests that are pending
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const createdAction = actions.pop()!;
if (moneyRequestActions.filter((action) => !!action.pendingAction).length > 0) {
createdAction.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE;
}

return [...actions, createdAction];
}, [allReportActions, report, transactionThreadReport]);

// Get a sorted array of reportActions for both the current report and the transaction thread report associated with this report (if there is one)
// so that we display transaction-level and report-level report actions in order in the one-transaction view
const combinedReportActions = useMemo(
() => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions),
[reportActionsToDisplay, transactionThreadReportActions, transactionThreadReportID],
() => ReportActionsUtils.getCombinedReportActions(allReportActions, transactionThreadReportID ?? null, transactionThreadReportActions),
[allReportActions, transactionThreadReportActions, transactionThreadReportID],
);

const parentReportActionForTransactionThread = useMemo(
Expand Down Expand Up @@ -491,6 +430,67 @@ function ReportActionsView({
};
}, [isTheFirstReportActionIsLinked]);

// When we are offline before opening an IOU/Expense report,
// the total of the report and sometimes the expense aren't displayed because these actions aren't returned until `OpenReport` API is complete.
// We generate a fake created action here if it doesn't exist to display the total whenever possible because the total just depends on report data
// and we also generate an expense action if the number of expenses in reportActions is less than the total number of expenses
// to display at least one expense action to match the total data.
const reportActionsToDisplay = useMemo(() => {
if (!ReportUtils.isMoneyRequestReport(report) || !reportActions.length) {
return reportActions;
}

const actions = [...reportActions];
const lastAction = reportActions[reportActions.length - 1];

if (!ReportActionsUtils.isCreatedAction(lastAction)) {
const optimisticCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(String(report?.ownerAccountID), DateUtils.subtractMillisecondsFromDateTime(lastAction.created, 1));
optimisticCreatedAction.pendingAction = null;
actions.push(optimisticCreatedAction);
}

const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(report.chatReportID ?? '-1', report.reportID);
const moneyRequestActions = reportActions.filter((action) => {
const originalMessage = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) : undefined;
return (
ReportActionsUtils.isMoneyRequestAction(action) &&
originalMessage &&
(originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE ||
!!(originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && originalMessage?.IOUDetails) ||
originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.TRACK)
);
});

if (report.total && moneyRequestActions.length < (reportPreviewAction?.childMoneyRequestCount ?? 0) && isEmptyObject(transactionThreadReport)) {
const optimisticIOUAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
0,
CONST.CURRENCY.USD,
'',
[],
NumberUtils.rand64(),
undefined,
report.reportID,
false,
false,
{},
false,
DateUtils.subtractMillisecondsFromDateTime(actions[actions.length - 1].created, 1),
) as OnyxTypes.ReportAction;
moneyRequestActions.push(optimisticIOUAction);
actions.splice(actions.length - 1, 0, optimisticIOUAction);
}

// Update pending action of created action if we have some requests that are pending
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const createdAction = actions.pop()!;
if (moneyRequestActions.filter((action) => !!action.pendingAction).length > 0) {
createdAction.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE;
}

return [...actions, createdAction];
}, [reportActions, report, transactionThreadReport]);

// Comments have not loaded at all yet do nothing
if (!reportActions.length) {
return null;
Expand All @@ -506,7 +506,7 @@ function ReportActionsView({
parentReportAction={parentReportAction}
parentReportActionForTransactionThread={parentReportActionForTransactionThread}
onLayout={recordTimeToMeasureItemLayout}
sortedReportActions={reportActions}
sortedReportActions={reportActionsToDisplay}
mostRecentIOUReportActionID={mostRecentIOUReportActionID}
loadOlderChats={loadOlderChats}
loadNewerChats={loadNewerChats}
Expand Down