diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index 9eef3e2b12ab..4ca8e24444f8 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -56,12 +56,12 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const hasInitialData = useMemo(() => Object.keys(personalDetails ?? {}).length > 0, [personalDetails]); const loadOptions = useCallback(() => { - const optionLists = createOptionList(personalDetails, reports); + const optionLists = createOptionList(personalDetails, reports, reportAttributes?.reports); setOptions({ reports: optionLists.reports, personalDetails: optionLists.personalDetails, }); - }, [personalDetails, reports]); + }, [personalDetails, reports, reportAttributes?.reports]); /** * This effect is responsible for generating the options list when their data is not yet initialized @@ -116,7 +116,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { changedReportKeys.forEach((reportKey) => { const report = changedReportsEntries[reportKey]; const reportID = reportKey.replace(ONYXKEYS.COLLECTION.REPORT, ''); - const {reportOption} = processReport(report, personalDetails); + const {reportOption} = processReport(report, personalDetails, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -130,7 +130,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportsEntries, personalDetails]); + }, [changedReportsEntries, personalDetails, reportAttributes?.reports]); useEffect(() => { if (!changedReportActions || !areOptionsInitialized.current) { @@ -150,7 +150,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); - const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails); + const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -162,7 +162,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportActions, personalDetails]); + }, [changedReportActions, personalDetails, reportAttributes?.reports]); /** * This effect is used to update the options list when personal details change. @@ -180,7 +180,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { // Handle initial personal details load. This initialization is required here specifically to prevent // UI freezing that occurs when resetting the app from the troubleshooting page. if (!prevPersonalDetails) { - const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, reports); + const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, reports, reportAttributes?.reports); setOptions((prevOptions) => ({ ...prevOptions, personalDetails: newPersonalDetailsOptions, @@ -208,7 +208,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { if (!report) { return; } - const newReportOption = createOptionFromReport(report, personalDetails); + const newReportOption = createOptionFromReport(report, personalDetails, reportAttributes?.reports); const replaceIndex = options.reports.findIndex((option) => option.reportID === report.reportID); newReportOptions.push({ newReportOption, @@ -218,7 +218,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { }); // since personal details are not a collection, we need to recreate the whole list from scratch - const newPersonalDetailsOptions = createOptionList(personalDetails).personalDetails; + const newPersonalDetailsOptions = createOptionList(personalDetails, reports, reportAttributes?.reports).personalDetails; setOptions((prevOptions) => { const newOptions = {...prevOptions}; @@ -229,7 +229,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { // This effect is used to update the options list when personal details change so we ignore all dependencies except personalDetails // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, [personalDetails]); + }, [personalDetails, reportAttributes?.reports]); const initializeOptions = useCallback(() => { loadOptions(); diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 58c096255fdd..10521d992e9e 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -47,17 +47,18 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const [selectedReportIDs, setSelectedReportIDs] = useState(initialReportIDs); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]); const selectedOptions = useMemo(() => { return selectedReportIDs.map((id) => { - const report = getSelectedOptionData(createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails)); + const report = getSelectedOptionData(createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportAttributesDerived)); const alternateText = getAlternateText(report, {}); return {...report, alternateText}; }); - }, [personalDetails, reports, selectedReportIDs]); + }, [personalDetails, reportAttributesDerived, reports, selectedReportIDs]); const defaultOptions = useMemo(() => { if (!areOptionsInitialized || !isScreenTransitionEnd) { @@ -79,7 +80,16 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen return {sections: [], headerMessage: undefined}; } - const formattedResults = formatSectionsFromSearchTerm(cleanSearchTerm, selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, personalDetails, false); + const formattedResults = formatSectionsFromSearchTerm( + cleanSearchTerm, + selectedOptions, + chatOptions.recentReports, + chatOptions.personalDetails, + personalDetails, + false, + undefined, + reportAttributesDerived, + ); newSections.push(formattedResults.section); @@ -107,6 +117,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen cleanSearchTerm, didScreenTransitionEnd, personalDetails, + reportAttributesDerived, selectedOptions, selectedReportIDs, translate, diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index ea26d2134a9a..04affea2924a 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -44,6 +44,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {canBeMissing: false, initWithStoredValues: false}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const [selectedOptions, setSelectedOptions] = useState([]); const [searchTerm, setSearchTerm] = useState(''); const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]); @@ -80,7 +81,16 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: return {sections: [], headerMessage: undefined}; } - const formattedResults = formatSectionsFromSearchTerm(cleanSearchTerm, selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, personalDetails, true); + const formattedResults = formatSectionsFromSearchTerm( + cleanSearchTerm, + selectedOptions, + chatOptions.recentReports, + chatOptions.personalDetails, + personalDetails, + true, + undefined, + reportAttributesDerived, + ); const selectedCurrentUser = formattedResults.section.data.find((option) => option.accountID === chatOptions.currentUserOption?.accountID); @@ -119,7 +129,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: sections: newSections, headerMessage: message, }; - }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, translate]); + }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, reportAttributesDerived, translate]); const resetChanges = useCallback(() => { setSelectedOptions([]); diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 7001c9fbcd6c..8b1a15798769 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -458,12 +458,6 @@ Onyx.connect({ callback: (value) => (nvpDismissedProductTraining = value), }); -let reportAttributesDerivedValue: ReportAttributesDerivedValue['reports'] | undefined; -Onyx.connect({ - key: ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, - callback: (value) => (reportAttributesDerivedValue = value?.reports), -}); - /** * @param defaultValues {login: accountID} In workspace invite page, when new user is added we pass available data to opt in * @returns Returns avatar data for a list of user accountIDs @@ -899,7 +893,13 @@ function getLastMessageTextForReport(report: OnyxEntry, lastActorDetails /** * Creates a report list option */ -function createOption(accountIDs: number[], personalDetails: OnyxInputOrEntry, report: OnyxInputOrEntry, config?: PreviewConfig): OptionData { +function createOption( + accountIDs: number[], + personalDetails: OnyxInputOrEntry, + report: OnyxInputOrEntry, + config?: PreviewConfig, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +): OptionData { const {showChatPreviewLine = false, forcePolicyNamePreview = false, showPersonalDetails = false, selected, isSelected, isDisabled} = config ?? {}; const result: OptionData = { text: undefined, @@ -959,7 +959,7 @@ function createOption(accountIDs: number[], personalDetails: OnyxInputOrEntry, unknownUserDetails: OnyxEntry): OptionData { +function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports']): OptionData { const visibleParticipantAccountIDs = getParticipantsAccountIDsForDisplay(report, true); - const option = createOption(visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, { - showChatPreviewLine: false, - forcePolicyNamePreview: false, - }); + const option = createOption( + visibleParticipantAccountIDs, + allPersonalDetails ?? {}, + !isEmptyObject(report) ? report : undefined, + { + showChatPreviewLine: false, + forcePolicyNamePreview: false, + }, + reportAttributesDerived, + ); // Update text & alternateText because createOption returns workspace name only if report is owned by the user if (option.isSelfDM) { @@ -1108,17 +1120,23 @@ function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: O /** * Get the option for a policy expense report. */ -function getPolicyExpenseReportOption(participant: Participant | OptionData): OptionData { +function getPolicyExpenseReportOption(participant: Participant | OptionData, reportAttributesDerived?: ReportAttributesDerivedValue['reports']): OptionData { const expenseReport = reportUtilsIsPolicyExpenseChat(participant) ? getReportOrDraftReport(participant.reportID) : null; const visibleParticipantAccountIDs = Object.entries(expenseReport?.participants ?? {}) .filter(([, reportParticipant]) => reportParticipant && !isHiddenForCurrentUser(reportParticipant.notificationPreference)) .map(([accountID]) => Number(accountID)); - const option = createOption(visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(expenseReport) ? expenseReport : null, { - showChatPreviewLine: false, - forcePolicyNamePreview: false, - }); + const option = createOption( + visibleParticipantAccountIDs, + allPersonalDetails ?? {}, + !isEmptyObject(expenseReport) ? expenseReport : null, + { + showChatPreviewLine: false, + forcePolicyNamePreview: false, + }, + reportAttributesDerived, + ); // Update text & alternateText because createOption returns workspace name only if report is owned by the user option.text = getPolicyName({report: expenseReport}); @@ -1224,6 +1242,7 @@ function isReportSelected(reportOption: OptionData, selectedOptions: Array, personalDetails: OnyxEntry, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): { reportMapEntry?: [number, Report]; // The entry to add to reportMapForAccountIDs if applicable reportOption: SearchOption | null; // The report option to add to allReportOptions if applicable @@ -1247,18 +1266,18 @@ function processReport( reportMapEntry, reportOption: { item: report, - ...createOption(accountIDs, personalDetails, report), + ...createOption(accountIDs, personalDetails, report, undefined, reportAttributesDerived), }, }; } -function createOptionList(personalDetails: OnyxEntry, reports?: OnyxCollection) { +function createOptionList(personalDetails: OnyxEntry, reports?: OnyxCollection, reportAttributesDerived?: ReportAttributesDerivedValue['reports']) { const reportMapForAccountIDs: Record = {}; const allReportOptions: Array> = []; if (reports) { Object.values(reports).forEach((report) => { - const {reportMapEntry, reportOption} = processReport(report, personalDetails); + const {reportMapEntry, reportOption} = processReport(report, personalDetails, reportAttributesDerived); if (reportMapEntry) { const [accountID, reportValue] = reportMapEntry; @@ -1273,9 +1292,15 @@ function createOptionList(personalDetails: OnyxEntry, repor const allPersonalDetailsOptions = Object.values(personalDetails ?? {}).map((personalDetail) => ({ item: personalDetail, - ...createOption([personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], personalDetails, reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], { - showPersonalDetails: true, - }), + ...createOption( + [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + personalDetails, + reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + { + showPersonalDetails: true, + }, + reportAttributesDerived, + ), })); return { @@ -1284,12 +1309,12 @@ function createOptionList(personalDetails: OnyxEntry, repor }; } -function createOptionFromReport(report: Report, personalDetails: OnyxEntry) { +function createOptionFromReport(report: Report, personalDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports']) { const accountIDs = getParticipantsAccountIDsForDisplay(report); return { item: report, - ...createOption(accountIDs, personalDetails, report), + ...createOption(accountIDs, personalDetails, report, undefined, reportAttributesDerived), }; } @@ -2268,6 +2293,7 @@ function formatSectionsFromSearchTerm( personalDetails: OnyxEntry = {}, shouldGetOptionDetails = false, filteredWorkspaceChats: OptionData[] = [], + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): SectionForSearchTerm { // We show the selected participants at the top of the list when there is no search term or maximum number of participants has already been selected // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results @@ -2279,7 +2305,7 @@ function formatSectionsFromSearchTerm( data: shouldGetOptionDetails ? selectedOptions.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; - return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedOptions, shouldShow: selectedOptions.length > 0, @@ -2305,7 +2331,7 @@ function formatSectionsFromSearchTerm( data: shouldGetOptionDetails ? selectedParticipantsWithoutDetails.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; - return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedParticipantsWithoutDetails, shouldShow: selectedParticipantsWithoutDetails.length > 0, diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 06b83b0d9e5b..5e5f7abe42b0 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -152,6 +152,7 @@ function NewChatPage(_: unknown, ref: React.Ref) { const personalData = useCurrentUserPersonalDetails(); const {top} = useSafeAreaInsets(); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const selectionListRef = useRef(null); useImperativeHandle(ref, () => ({ @@ -165,7 +166,16 @@ function NewChatPage(_: unknown, ref: React.Ref) { const sectionsList: Section[] = []; let firstKey = ''; - const formatResults = formatSectionsFromSearchTerm(debouncedSearchTerm, selectedOptions as OptionData[], recentReports, personalDetails); + const formatResults = formatSectionsFromSearchTerm( + debouncedSearchTerm, + selectedOptions as OptionData[], + recentReports, + personalDetails, + undefined, + undefined, + undefined, + reportAttributesDerived, + ); sectionsList.push(formatResults.section); if (!firstKey) { @@ -202,7 +212,7 @@ function NewChatPage(_: unknown, ref: React.Ref) { } return [sectionsList, firstKey]; - }, [debouncedSearchTerm, selectedOptions, recentReports, personalDetails, translate, userToInvite]); + }, [debouncedSearchTerm, selectedOptions, recentReports, personalDetails, reportAttributesDerived, translate, userToInvite]); /** * Removes a selected option from list if already selected. If not already selected add this option to the list. diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 0b23660cb11c..9781b4ea3ac7 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -47,13 +47,14 @@ function ShareDetailsPage({ const {translate} = useLocalize(); const [unknownUserDetails] = useOnyx(ONYXKEYS.SHARE_UNKNOWN_USER_DETAILS, {canBeMissing: true}); const [currentAttachment] = useOnyx(ONYXKEYS.SHARE_TEMP_FILE, {canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const isTextShared = currentAttachment?.mimeType === 'txt'; const [message, setMessage] = useState(isTextShared ? (currentAttachment?.content ?? '') : ''); const [errorTitle, setErrorTitle] = useState(undefined); const [errorMessage, setErrorMessage] = useState(undefined); const report: OnyxEntry = getReportOrDraftReport(reportOrAccountID); - const displayReport = useMemo(() => getReportDisplayOption(report, unknownUserDetails), [report, unknownUserDetails]); + const displayReport = useMemo(() => getReportDisplayOption(report, unknownUserDetails, reportAttributesDerived), [report, unknownUserDetails, reportAttributesDerived]); useEffect(() => { if (!currentAttachment?.content || errorTitle) { diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index a6464f012c9a..b3814d41635f 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -48,6 +48,7 @@ function SubmitDetailsPage({ const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: false}); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: false}); const [lastLocationPermissionPrompt] = useOnyx(ONYXKEYS.NVP_LAST_LOCATION_PERMISSION_PROMPT, {canBeMissing: false}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const [startLocationPermissionFlow, setStartLocationPermissionFlow] = useState(false); @@ -72,7 +73,9 @@ function SubmitDetailsPage({ }, [reportOrAccountID, policy]); const selectedParticipants = unknownUserDetails ? [unknownUserDetails] : getMoneyRequestParticipantsFromReport(report); - const participants = selectedParticipants.map((participant) => (participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant))); + const participants = selectedParticipants.map((participant) => + participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived), + ); const trimmedComment = transaction?.comment?.comment?.trim() ?? ''; const transactionAmount = transaction?.amount ?? 0; const transactionTaxAmount = transaction?.taxAmount ?? 0; diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index da670147d7d3..7bc9241a990b 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -48,6 +48,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${IOUTransactionID}`, {canBeMissing: true}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true}); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); // In case this is workspace split expense, we manually add the workspace as the second participant of the split expense // because we don't save any accountID in the report action's originalMessage other than the payee's accountID @@ -55,7 +56,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag if (isPolicyExpenseChat(report)) { participants = [ getParticipantsOption({accountID: participantAccountIDs.at(0), selected: true, reportID: ''}, personalDetails), - getPolicyExpenseReportOption({...report, selected: true, reportID}), + getPolicyExpenseReportOption({...report, selected: true, reportID}, reportAttributesDerived), ]; } else { participants = participantAccountIDs.map((accountID) => getParticipantsOption({accountID, selected: true, reportID: ''}, personalDetails)); diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index 107a2de8a306..83a1f0013f93 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -56,6 +56,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType shouldInitialize: didScreenTransitionEnd, }); const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); useEffect(() => { searchInServer(debouncedSearchTerm.trim()); @@ -115,7 +116,16 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType const restOfRecents = [...chatOptions.recentReports].slice(5); const contactsWithRestOfRecents = [...restOfRecents, ...chatOptions.personalDetails]; - const formatResults = formatSectionsFromSearchTerm(debouncedSearchTerm, [], chatOptions.recentReports, chatOptions.personalDetails, personalDetails, true); + const formatResults = formatSectionsFromSearchTerm( + debouncedSearchTerm, + [], + chatOptions.recentReports, + chatOptions.personalDetails, + personalDetails, + true, + undefined, + reportAttributesDerived, + ); newSections.push(formatResults.section); newSections.push({ @@ -138,7 +148,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); @@ -151,7 +161,17 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType ); return [newSections, headerMessage]; - }, [areOptionsInitialized, didScreenTransitionEnd, debouncedSearchTerm, chatOptions.recentReports, chatOptions.personalDetails, chatOptions.userToInvite, personalDetails, translate]); + }, [ + areOptionsInitialized, + didScreenTransitionEnd, + chatOptions.recentReports, + chatOptions.personalDetails, + chatOptions.userToInvite, + debouncedSearchTerm, + personalDetails, + translate, + reportAttributesDerived, + ]); const selectAccountant = useCallback( (option: Accountant) => { diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index 30c42dac5538..4fb7a21cfff1 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -71,6 +71,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde const {options, areOptionsInitialized} = useOptionsList({ shouldInitialize: didScreenTransitionEnd, }); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]); const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; @@ -148,6 +149,8 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde chatOptions.personalDetails, personalDetails, true, + undefined, + reportAttributesDerived, ); newSections.push(formatResults.section); @@ -171,7 +174,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); @@ -188,13 +191,14 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde }, [ areOptionsInitialized, didScreenTransitionEnd, - attendees, chatOptions.recentReports, chatOptions.personalDetails, chatOptions.userToInvite, + cleanSearchTerm, + attendees, personalDetails, translate, - cleanSearchTerm, + reportAttributesDerived, ]); const addAttendeeToSelection = useCallback( diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 9783c6423e4a..0d74444cefa9 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -119,6 +119,7 @@ function MoneyRequestParticipantsSelector( const {options, areOptionsInitialized, initializeOptions} = useOptionsList({ shouldInitialize: didScreenTransitionEnd, }); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const [contacts, setContacts] = useState>>([]); const [textInputAutoFocus, setTextInputAutoFocus] = useState(!isNative); const selectionListRef = useRef(null); @@ -280,6 +281,8 @@ function MoneyRequestParticipantsSelector( chatOptions.personalDetails, personalDetails, true, + undefined, + reportAttributesDerived, ); newSections.push(formatResults.section); @@ -321,7 +324,7 @@ function MoneyRequestParticipantsSelector( title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); @@ -340,14 +343,15 @@ function MoneyRequestParticipantsSelector( participants, chatOptions.recentReports, chatOptions.personalDetails, - chatOptions.selfDMChat, chatOptions.workspaceChats, + chatOptions.selfDMChat, chatOptions.userToInvite, personalDetails, translate, + isPerDiemRequest, showImportContacts, + reportAttributesDerived, inputHelperText, - isPerDiemRequest, ]); /** diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 35b393ec40e0..f3126fb44da3 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -81,6 +81,7 @@ function IOURequestStepAmount({ const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`, {canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const isEditing = action === CONST.IOU.ACTION.EDIT; const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; @@ -177,7 +178,7 @@ function IOURequestStepAmount({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); }); const backendAmount = convertToBackendAmount(Number.parseFloat(amount)); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index f795ae547b0d..9cfa10193dd4 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -129,6 +129,7 @@ function IOURequestStepConfirmation({ const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${draftPolicyID}`, {canBeMissing: true}); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${realPolicyID}`, {canBeMissing: true}); const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION, {canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); /* * We want to use a report from the transaction if it exists @@ -211,9 +212,9 @@ function IOURequestStepConfirmation({ if (participant.isSender && iouType === CONST.IOU.TYPE.INVOICE) { return participant; } - return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant); + return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); }) ?? [], - [transaction?.participants, personalDetails, iouType], + [transaction?.participants, iouType, personalDetails, reportAttributesDerived], ); const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]); const formHasBeenSubmitted = useRef(false); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index eb610d00a840..57f2c37d213b 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -96,6 +96,7 @@ function IOURequestStepDistance({ }, [optimisticWaypoints, transaction], ); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const backupWaypoints = transactionBackup?.pendingFields?.waypoints ? transactionBackup?.comment?.waypoints : undefined; // When online, fetch the backup route to ensure the map is populated even if the user does not save the transaction. @@ -304,7 +305,7 @@ function IOURequestStepDistance({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { @@ -390,7 +391,6 @@ function IOURequestStepDistance({ transaction, backTo, report, - reportID, reportNameValuePairs, iouType, activePolicy, @@ -398,6 +398,7 @@ function IOURequestStepDistance({ shouldSkipConfirmation, transactionID, personalDetails, + reportAttributesDerived, translate, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, @@ -406,6 +407,7 @@ function IOURequestStepDistance({ backToReport, customUnitRateID, navigateToConfirmationPage, + reportID, ]); const getError = () => { diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 53268458251f..30d77306866b 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -109,6 +109,7 @@ function IOURequestStepScan({ const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: false}); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`, {canBeMissing: true}); const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const platform = getPlatform(true); const [mutedPlatforms = getEmptyObject>>()] = useOnyx(ONYXKEYS.NVP_MUTED_PLATFORMS, {canBeMissing: true}); const isPlatformMuted = mutedPlatforms[platform]; @@ -384,7 +385,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -489,6 +490,7 @@ function IOURequestStepScan({ navigateToConfirmationPage, shouldSkipConfirmation, personalDetails, + reportAttributesDerived, createTransaction, currentUserPersonalDetails?.login, currentUserPersonalDetails.accountID, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index b631abf8ade7..e2768ad9d846 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -115,6 +115,7 @@ function IOURequestStepScan({ const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: false}); const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`, {canBeMissing: true}); const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: (val) => val?.reports}); const isEditing = action === CONST.IOU.ACTION.EDIT; const canUseMultiScan = !isEditing && iouType !== CONST.IOU.TYPE.SPLIT && !backTo && !backToReport; const isReplacingReceipt = (isEditing && hasReceipt(initialTransaction)) || (!!initialTransaction?.receipt && !!backTo); @@ -440,7 +441,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -539,18 +540,19 @@ function IOURequestStepScan({ report, reportNameValuePairs, iouType, - initialTransaction?.participants, - initialTransaction?.currency, - initialTransaction?.reportID, activePolicy, initialTransactionID, navigateToConfirmationPage, shouldSkipConfirmation, personalDetails, + reportAttributesDerived, createTransaction, currentUserPersonalDetails?.login, currentUserPersonalDetails.accountID, reportID, + initialTransaction?.currency, + initialTransaction?.participants, + initialTransaction?.reportID, transactionTaxCode, transactionTaxAmount, policy,