diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 2a25178f26a6..b72a1e8ee54d 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -222,6 +222,7 @@ type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: bo type FilterOptionsConfig = Pick & { preferChatroomsOverThreads?: boolean; preferPolicyExpenseChat?: boolean; + preferRecentExpenseReports?: boolean; }; /** @@ -1573,7 +1574,11 @@ function createOptionFromReport(report: Report, personalDetails: OnyxEntry option?.lastIOUCreationDate ?? '' : '', + preferRecentExpenseReports ? (option) => option?.isPolicyExpenseChat : 0, ], - ['asc'], + ['asc', 'desc', 'desc'], ); } @@ -1923,6 +1937,8 @@ function getOptions( let recentReportOptions = []; let personalDetailsOptions: ReportUtils.OptionData[] = []; + const preferRecentExpenseReports = action === CONST.IOU.ACTION.CREATE; + if (includeRecentReports) { for (const reportOption of allReportOptions) { /** @@ -1983,6 +1999,22 @@ function getOptions( recentReportOptions.push(reportOption); } + // Add a field to sort the recent reports by the time of last IOU request for create actions + if (preferRecentExpenseReports) { + const reportPreviewAction = allSortedReportActions[reportOption.reportID]?.find((reportAction) => + ReportActionUtils.isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW), + ); + + if (reportPreviewAction) { + const iouReportID = ReportActionUtils.getIOUReportIDFromReportActionPreview(reportPreviewAction); + const iouReportActions = allSortedReportActions[iouReportID] ?? []; + const lastIOUAction = iouReportActions.find((iouAction) => iouAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU); + if (lastIOUAction) { + reportOption.lastIOUCreationDate = lastIOUAction.lastModified; + } + } + } + // Add this login to the exclude list so it won't appear when we process the personal details if (reportOption.login) { optionsToExclude.push({login: reportOption.login}); @@ -2031,7 +2063,11 @@ function getOptions( recentReportOptions.push(...personalDetailsOptions); personalDetailsOptions = []; } - recentReportOptions = orderOptions(recentReportOptions, searchValue, {preferChatroomsOverThreads: true, preferPolicyExpenseChat: !!action}); + recentReportOptions = orderOptions(recentReportOptions, searchValue, { + preferChatroomsOverThreads: true, + preferPolicyExpenseChat: !!action, + preferRecentExpenseReports, + }); } return { @@ -2395,6 +2431,7 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt excludeLogins = [], preferChatroomsOverThreads = false, preferPolicyExpenseChat = false, + preferRecentExpenseReports = false, } = config ?? {}; if (searchInputValue.trim() === '' && maxRecentReportsToShow > 0) { return {...options, recentReports: options.recentReports.slice(0, maxRecentReportsToShow)}; @@ -2476,7 +2513,7 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt return { personalDetails, - recentReports: orderOptions(recentReports, searchValue, {preferChatroomsOverThreads, preferPolicyExpenseChat}), + recentReports: orderOptions(recentReports, searchValue, {preferChatroomsOverThreads, preferPolicyExpenseChat, preferRecentExpenseReports}), userToInvite, currentUserOption: matchResults.currentUserOption, categoryOptions: [], diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 719f9971f907..584d5d09b682 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -459,6 +459,7 @@ type OptionData = { tabIndex?: 0 | -1; isConciergeChat?: boolean; isBold?: boolean; + lastIOUCreationDate?: string; } & Report; type OnyxDataTaskAssigneeChat = { diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index e44a59baf7eb..69c4402e959b 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -694,6 +694,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro const lastRoute = usePrevious(route); const lastReportActionIDFromRoute = usePrevious(reportActionIDFromRoute); + // Define here because reportActions are recalculated before mount, allowing data to display faster than useEffect can trigger. // If we have cached reportActions, they will be shown immediately. // We aim to display a loader first, then fetch relevant reportActions, and finally show them. diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index a83819afdfb4..0168133154ee 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -169,9 +169,10 @@ function MoneyRequestParticipantsSelector({participants = CONST.EMPTY_ARRAY, onF excludeLogins: CONST.EXPENSIFY_EMAILS, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, preferPolicyExpenseChat: isPaidGroupPolicy, + preferRecentExpenseReports: action === CONST.IOU.ACTION.CREATE, }); return newOptions; - }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, participants, isPaidGroupPolicy, canUseP2PDistanceRequests, iouRequestType, isCategorizeOrShareAction]); + }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, participants, isPaidGroupPolicy, canUseP2PDistanceRequests, iouRequestType, isCategorizeOrShareAction, action]); /** * Returns the sections needed for the OptionsSelector