diff --git a/src/hooks/usePrivateIsArchivedMap.ts b/src/hooks/usePrivateIsArchivedMap.ts new file mode 100644 index 000000000000..2a325ad474ca --- /dev/null +++ b/src/hooks/usePrivateIsArchivedMap.ts @@ -0,0 +1,20 @@ +import type {PrivateIsArchivedMap} from '@selectors/ReportNameValuePairs'; +import {privateIsArchivedMapSelector} from '@selectors/ReportNameValuePairs'; +import ONYXKEYS from '@src/ONYXKEYS'; +import {getEmptyObject} from '@src/types/utils/EmptyObject'; +import useDeepCompareRef from './useDeepCompareRef'; +import useOnyx from './useOnyx'; + +/** + * Hook that returns a map of report IDs to their private_isArchived values + */ +function usePrivateIsArchivedMap(): PrivateIsArchivedMap { + const [privateIsArchivedMap = getEmptyObject()] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS, { + canBeMissing: true, + selector: privateIsArchivedMapSelector, + }); + + return useDeepCompareRef(privateIsArchivedMap) ?? {}; +} + +export default usePrivateIsArchivedMap; diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 0ecf0307e652..dd33a0ec2f2f 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -235,12 +235,12 @@ Onyx.connect({ }, }); -let allReportNameValuePairs: OnyxCollection; +let allReportNameValuePairsOnyxConnect: OnyxCollection; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS, waitForCollectionCallback: true, callback: (value) => { - allReportNameValuePairs = value; + allReportNameValuePairsOnyxConnect = value; }, }); @@ -286,7 +286,7 @@ Onyx.connect({ lastReportActions[reportID] = firstReportAction; } - const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]; + const reportNameValuePairs = allReportNameValuePairsOnyxConnect?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]; const isReportArchived = !!reportNameValuePairs?.private_isArchived; const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived); const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]; @@ -872,6 +872,7 @@ function createOption( report: OnyxInputOrEntry, config?: PreviewConfig, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], + privateIsArchived?: string, ): SearchOptionData { const {showChatPreviewLine = false, forcePolicyNamePreview = false, showPersonalDetails = false, selected, isSelected, isDisabled} = config ?? {}; @@ -930,10 +931,10 @@ function createOption( result.participantsList = personalDetailList; if (report) { - const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]; + const reportNameValuePairsForReport = allReportNameValuePairsOnyxConnect?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]; // Set properties that are used in SearchOption context - result.private_isArchived = reportNameValuePairs?.private_isArchived; + result.private_isArchived = privateIsArchived ?? reportNameValuePairsForReport?.private_isArchived; result.keyForList = String(report.reportID); // Type/category flags already set in initialization above, but update brickRoadIndicator @@ -954,7 +955,17 @@ function createOption( : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, !!result.private_isArchived, lastActorDetails); const personalDetailsForCompute: PersonalDetailsList | undefined = personalDetails ?? undefined; - const computedReportName = computeReportName(report, allReports, allPolicies, undefined, allReportNameValuePairs, personalDetailsForCompute, allReportActions, currentUserAccountID); + const computedReportName = computeReportName( + report, + allReports, + allPolicies, + undefined, + undefined, + personalDetailsForCompute, + allReportActions, + currentUserAccountID, + result.private_isArchived, + ); reportName = showPersonalDetails ? getDisplayNameForParticipant({accountID: accountIDs.at(0), formatPhoneNumber: formatPhoneNumberPhoneUtils}) || formatPhoneNumberPhoneUtils(personalDetail?.login ?? '') : computedReportName; @@ -998,6 +1009,7 @@ function createOption( */ function getReportOption( participant: Participant, + privateIsArchived: string | undefined, policy: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], reportDrafts?: OnyxCollection, @@ -1014,6 +1026,7 @@ function getReportOption( forcePolicyNamePreview: false, }, reportAttributesDerived, + privateIsArchived, ); // Update text & alternateText because createOption returns workspace name only if report is owned by the user @@ -1021,7 +1034,7 @@ function getReportOption( // eslint-disable-next-line @typescript-eslint/no-deprecated option.alternateText = translateLocal('reportActionsView.yourSpace'); } else if (option.isInvoiceRoom) { - option.text = computeReportName(report, undefined, undefined, undefined, allReportNameValuePairs, allPersonalDetails, undefined, currentUserAccountID); + option.text = computeReportName(report, undefined, undefined, undefined, undefined, allPersonalDetails, undefined, currentUserAccountID, privateIsArchived); // eslint-disable-next-line @typescript-eslint/no-deprecated option.alternateText = translateLocal('workspace.common.invoices'); } else { @@ -1050,7 +1063,12 @@ function getReportOption( /** * Get the display option for a given report. */ -function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports']): OptionData { +function getReportDisplayOption( + report: OnyxEntry, + unknownUserDetails: OnyxEntry, + privateIsArchived: string | undefined, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +): OptionData { const visibleParticipantAccountIDs = getParticipantsAccountIDsForDisplay(report, true); const option = createOption( @@ -1062,6 +1080,7 @@ function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: O forcePolicyNamePreview: false, }, reportAttributesDerived, + privateIsArchived, ); // Update text & alternateText because createOption returns workspace name only if report is owned by the user @@ -1069,7 +1088,7 @@ function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: O // eslint-disable-next-line @typescript-eslint/no-deprecated option.alternateText = translateLocal('reportActionsView.yourSpace'); } else if (option.isInvoiceRoom) { - option.text = computeReportName(report, undefined, undefined, undefined, allReportNameValuePairs, allPersonalDetails, undefined, currentUserAccountID); + option.text = computeReportName(report, undefined, undefined, undefined, undefined, allPersonalDetails, undefined, currentUserAccountID, privateIsArchived); // eslint-disable-next-line @typescript-eslint/no-deprecated option.alternateText = translateLocal('workspace.common.invoices'); } else if (unknownUserDetails) { diff --git a/src/libs/ReportNameUtils.ts b/src/libs/ReportNameUtils.ts index 3352e3e68bc0..d864cd7de7c2 100644 --- a/src/libs/ReportNameUtils.ts +++ b/src/libs/ReportNameUtils.ts @@ -551,8 +551,8 @@ function computeReportNameBasedOnReportAction( function computeChatThreadReportName( translate: LocalizedTranslate, + isArchived: boolean, report: Report, - reportNameValuePairs: ReportNameValuePairs, reports: OnyxCollection, parentReportAction?: ReportAction, ): string | undefined { @@ -564,7 +564,7 @@ function computeChatThreadReportName( } const parentReportActionMessage = getReportActionMessageFromActionsUtils(parentReportAction); - const isArchivedNonExpense = isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived); + const isArchivedNonExpense = isArchivedNonExpenseReport(report, isArchived); if (!isEmptyObject(parentReportAction) && isTransactionThread(parentReportAction)) { let formattedName = getTransactionReportName({reportAction: parentReportAction}); @@ -642,15 +642,16 @@ function computeReportName( personalDetailsList?: PersonalDetailsList, reportActions?: OnyxCollection, currentUserAccountID?: number, + privateIsArchived?: string, ): string { if (!report || !report.reportID) { return ''; } - const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]; + const privateIsArchivedValue = privateIsArchived ?? allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]?.private_isArchived; const reportPolicy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]; - const isArchivedNonExpense = isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived); + const isArchivedNonExpense = isArchivedNonExpenseReport(report, !!privateIsArchivedValue); const parentReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`]; const parentReportAction = isThread(report) ? reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`]?.[report.parentReportActionID] : undefined; @@ -667,7 +668,7 @@ function computeReportName( } // eslint-disable-next-line @typescript-eslint/no-deprecated - const chatThreadReportName = computeChatThreadReportName(translateLocal, report, reportNameValuePairs ?? {}, reports ?? {}, parentReportAction); + const chatThreadReportName = computeChatThreadReportName(translateLocal, !!privateIsArchivedValue, report, reports ?? {}, parentReportAction); if (chatThreadReportName) { return chatThreadReportName; } diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 7baeb24c263a..569ae81c63d3 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -18,6 +18,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap'; import useThemeStyles from '@hooks/useThemeStyles'; import {addAttachmentWithComment, addComment, openReport} from '@libs/actions/Report'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; @@ -61,8 +62,13 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const [errorMessage, setErrorMessage] = useState(undefined); const report: OnyxEntry = getReportOrDraftReport(reportOrAccountID); + const privateIsArchivedMap = usePrivateIsArchivedMap(); + const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`]; const ancestors = useAncestors(report); - const displayReport = useMemo(() => getReportDisplayOption(report, unknownUserDetails, reportAttributesDerived), [report, unknownUserDetails, reportAttributesDerived]); + const displayReport = useMemo( + () => getReportDisplayOption(report, unknownUserDetails, privateIsArchived, reportAttributesDerived), + [report, unknownUserDetails, privateIsArchived, reportAttributesDerived], + ); const shouldShowAttachment = !isTextShared; const fileSource = shouldUsePreValidatedFile ? (validatedFile?.uri ?? '') : (currentAttachment?.content ?? ''); diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index cec6bab7efff..3705b202264d 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -13,6 +13,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePersonalPolicy from '@hooks/usePersonalPolicy'; +import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useThemeStyles from '@hooks/useThemeStyles'; import type {GpsPoint} from '@libs/actions/IOU'; @@ -56,6 +57,7 @@ function SubmitDetailsPage({ const [lastLocationPermissionPrompt] = useOnyx(ONYXKEYS.NVP_LAST_LOCATION_PERMISSION_PROMPT, {canBeMissing: false}); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); + const privateIsArchivedMap = usePrivateIsArchivedMap(); const [currentDate] = useOnyx(ONYXKEYS.CURRENT_DATE, {canBeMissing: true}); const [validFilesToUpload] = useOnyx(ONYXKEYS.VALIDATED_FILE_OBJECT, {canBeMissing: true}); const [policyRecentlyUsedCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: true}); @@ -107,9 +109,10 @@ function SubmitDetailsPage({ }, [reportOrAccountID, policy, personalPolicy, report, parentReport, currentDate, currentUserPersonalDetails, hasOnlyPersonalPolicies]); const selectedParticipants = unknownUserDetails ? [unknownUserDetails] : getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); - const participants = selectedParticipants.map((participant) => - participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived), - ); + const participants = selectedParticipants.map((participant) => { + const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`]; + return participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, privateIsArchived, policy, reportAttributesDerived); + }); const trimmedComment = transaction?.comment?.comment?.trim() ?? ''; const transactionAmount = transaction?.amount ?? 0; const transactionTaxAmount = transaction?.taxAmount ?? 0; diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index dd7e1e326314..108ba977497b 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePersonalPolicy from '@hooks/usePersonalPolicy'; +import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; import {setTransactionReport} from '@libs/actions/Transaction'; @@ -98,6 +99,7 @@ function IOURequestStepAmount({ const personalPolicy = usePersonalPolicy(); const {duplicateTransactions, duplicateTransactionViolations} = useDuplicateTransactionsAndViolations(transactionID ? [transactionID] : []); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); + const privateIsArchivedMap = usePrivateIsArchivedMap(); const isEditing = action === CONST.IOU.ACTION.EDIT; const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; const isCreateAction = action === CONST.IOU.ACTION.CREATE; @@ -209,7 +211,8 @@ function IOURequestStepAmount({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`]; + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, privateIsArchived, policy, 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 818df51c68e3..06f0a32e9d38 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -14,7 +14,6 @@ import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationLi import {usePersonalDetails, usePolicyCategories} from '@components/OnyxListItemProvider'; import PrevNextButtons from '@components/PrevNextButtons'; import ScreenWrapper from '@components/ScreenWrapper'; -import useArchivedReportsIdSet from '@hooks/useArchivedReportsIdSet'; import useConfirmModal from '@hooks/useConfirmModal'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDeepCompareRef from '@hooks/useDeepCompareRef'; @@ -29,6 +28,7 @@ import useParentReportAction from '@hooks/useParentReportAction'; import useParticipantsInvoiceReport from '@hooks/useParticipantsInvoiceReport'; import usePermissions from '@hooks/usePermissions'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; +import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {completeTestDriveTask} from '@libs/actions/Task'; @@ -261,7 +261,7 @@ function IOURequestStepConfirmation({ isOnboardingTaskParentReportArchived: isViewTourTaskParentReportArchived, hasOutstandingChildTask, } = useOnboardingTaskInformation(CONST.ONBOARDING_TASK_TYPE.VIEW_TOUR); - const archivedReportsIdSet = useArchivedReportsIdSet(); + const privateIsArchivedMap = usePrivateIsArchivedMap(); const parentReportAction = useParentReportAction(viewTourTaskReport); const receiptFilename = transaction?.receipt?.filename; @@ -306,9 +306,12 @@ function IOURequestStepConfirmation({ if (participant.isSender && iouType === CONST.IOU.TYPE.INVOICE) { return participant; } - return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived, reportDrafts); + const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`]; + return participant.accountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, privateIsArchived, policy, reportAttributesDerived, reportDrafts); }) ?? [], - [transaction?.participants, iouType, personalDetails, reportAttributesDerived, reportDrafts, policy], + [transaction?.participants, iouType, personalDetails, reportAttributesDerived, reportDrafts, privateIsArchivedMap, policy], ); const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]); const shouldGenerateTransactionThreadReport = !isBetaEnabled(CONST.BETAS.NO_OPTIMISTIC_TRANSACTION_THREADS); @@ -565,7 +568,7 @@ function IOURequestStepConfirmation({ const isTestReceipt = receipt?.isTestReceipt ?? false; const isTestDriveReceipt = receipt?.isTestDriveReceipt ?? false; const isLinkedTrackedExpenseReportArchived = - !!item.linkedTrackedExpenseReportID && archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${item.linkedTrackedExpenseReportID}`); + !!item.linkedTrackedExpenseReportID && !!privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${item.linkedTrackedExpenseReportID}`]; if (isTestDriveReceipt) { completeTestDriveTask( @@ -643,7 +646,7 @@ function IOURequestStepConfirmation({ [ transactions, receiptFiles, - archivedReportsIdSet, + privateIsArchivedMap, report, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, @@ -747,7 +750,7 @@ function IOURequestStepConfirmation({ } for (const [index, item] of transactions.entries()) { const isLinkedTrackedExpenseReportArchived = - !!item.linkedTrackedExpenseReportID && archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${item.linkedTrackedExpenseReportID}`); + !!item.linkedTrackedExpenseReportID && !!privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${item.linkedTrackedExpenseReportID}`]; const itemDistance = isManualDistanceRequest || isOdometerDistanceRequest ? (item.comment?.customUnit?.quantity ?? undefined) : undefined; trackExpenseIOUActions({ @@ -818,7 +821,7 @@ function IOURequestStepConfirmation({ isDraftPolicy, isManualDistanceRequest, isOdometerDistanceRequest, - archivedReportsIdSet, + privateIsArchivedMap, isASAPSubmitBetaEnabled, introSelected, activePolicyID, diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index d9e084c1356b..9907f1001fc2 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -87,6 +87,7 @@ function IOURequestStepDistance({ const {isBetaEnabled} = usePermissions(); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); @@ -203,12 +204,8 @@ function IOURequestStepDistance({ return false; } - return ( - iouType !== CONST.IOU.TYPE.SPLIT && - !isArchivedReport(reportNameValuePairs) && - !(isPolicyExpenseChatUtil(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))) - ); - }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, reportNameValuePairs, iouType]); + return iouType !== CONST.IOU.TYPE.SPLIT && !isArchived && !(isPolicyExpenseChatUtil(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); + }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, isArchived, iouType]); let buttonText = !isCreatingNewRequest ? translate('common.save') : translate('common.next'); if (shouldSkipConfirmation) { if (iouType === CONST.IOU.TYPE.SPLIT) { @@ -322,11 +319,13 @@ function IOURequestStepDistance({ // In this case, the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirm step. // If the user started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. - if (report?.reportID && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (report?.reportID && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { @@ -439,7 +438,7 @@ function IOURequestStepDistance({ transaction, backTo, report, - reportNameValuePairs, + isArchived, iouType, defaultExpensePolicy, currentUserPersonalDetails.accountID, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 0d06f11741c9..2f1b76877764 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -79,6 +79,7 @@ function IOURequestStepDistanceManual({ const [formError, setFormError] = useState(''); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const [selectedTab, selectedTabResult] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.DISTANCE_REQUEST_TYPE}`, {canBeMissing: true}); const isLoadingSelectedTab = isLoadingOnyxValue(selectedTabResult); const policy = usePolicy(report?.policyID); @@ -129,8 +130,8 @@ function IOURequestStepDistanceManual({ return false; } - return !(isArchivedReport(reportNameValuePairs) || isPolicyExpenseChatUtils(report)); - }, [report, skipConfirmation, reportNameValuePairs]); + return !(isArchived || isPolicyExpenseChatUtils(report)); + }, [report, skipConfirmation, isArchived]); useFocusEffect( useCallback(() => { @@ -196,11 +197,13 @@ function IOURequestStepDistanceManual({ return; } - if (report?.reportID && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (report?.reportID && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserAccountIDParam); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, reportAttributesDerived); }); if (shouldSkipConfirmation) { setMoneyRequestPendingFields(transactionID, {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); @@ -308,7 +311,7 @@ function IOURequestStepDistanceManual({ action, backTo, report, - reportNameValuePairs, + isArchived, iouType, shouldUseDefaultExpensePolicy, distance, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 9ac0b5b2cb1a..e487f854869f 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -88,6 +88,7 @@ function IOURequestStepDistanceMap({ const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [transactionBackup] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_BACKUP}${transactionID}`, {canBeMissing: true}); @@ -204,12 +205,8 @@ function IOURequestStepDistanceMap({ return false; } - return ( - iouType !== CONST.IOU.TYPE.SPLIT && - !isArchivedReport(reportNameValuePairs) && - !(isPolicyExpenseChatUtil(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))) - ); - }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, reportNameValuePairs, iouType]); + return iouType !== CONST.IOU.TYPE.SPLIT && !isArchived && !(isPolicyExpenseChatUtil(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); + }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, isArchived, iouType]); let buttonText = !isCreatingNewRequest ? translate('common.save') : translate('common.next'); if (shouldSkipConfirmation) { if (iouType === CONST.IOU.TYPE.SPLIT) { @@ -323,11 +320,13 @@ function IOURequestStepDistanceMap({ // In this case, the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirm step. // If the user started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. - if (report?.reportID && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (report?.reportID && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserAccountIDParam); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { @@ -440,7 +439,7 @@ function IOURequestStepDistanceMap({ transaction, backTo, report, - reportNameValuePairs, + isArchived, iouType, defaultExpensePolicy, currentUserAccountIDParam, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index 6e35e3f5505f..def2a1136f45 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -94,6 +94,7 @@ function IOURequestStepDistanceOdometer({ const endReadingRef = useRef(''); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); @@ -129,7 +130,7 @@ function IOURequestStepDistanceOdometer({ const unit = DistanceRequestUtils.getRate({transaction, policy: shouldUseDefaultExpensePolicy ? defaultExpensePolicy : policy}).unit; - const shouldSkipConfirmation: boolean = !skipConfirmation || !report?.reportID ? false : !(isArchivedReport(reportNameValuePairs) || isPolicyExpenseChatUtils(report)); + const shouldSkipConfirmation: boolean = !skipConfirmation || !report?.reportID ? false : !(isArchived || isPolicyExpenseChatUtils(report)); const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID, backToReport); @@ -357,12 +358,14 @@ function IOURequestStepDistanceOdometer({ // If a reportID exists in the report object, use it to set participants and navigate to confirmation // Following Manual tab pattern - if (report?.reportID && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (report?.reportID && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const derivedReports = (reportAttributesDerived as ReportAttributesDerivedValue | undefined)?.reports; const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, derivedReports); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, derivedReports); }); if (shouldSkipConfirmation) { diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 60bb28a873ca..d467d063903e 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -116,6 +116,7 @@ function IOURequestStepScan({ const [startLocationPermissionFlow, setStartLocationPermissionFlow] = useState(false); const [receiptFiles, setReceiptFiles] = useState([]); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const policy = usePolicy(report?.policyID); const personalPolicy = usePersonalPolicy(); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); @@ -178,8 +179,8 @@ function IOURequestStepScan({ return false; } - return !isArchivedReport(reportNameValuePairs) && !(isPolicyExpenseChat(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); - }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, reportNameValuePairs]); + return !isArchived && !(isPolicyExpenseChat(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); + }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, isArchived]); const {translate} = useLocalize(); @@ -428,11 +429,13 @@ function IOURequestStepScan({ // the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirmation step. // If the user is started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. - if (!initialTransaction?.isFromGlobalCreate && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (!initialTransaction?.isFromGlobalCreate && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -543,7 +546,7 @@ function IOURequestStepScan({ initialTransaction?.currency, initialTransaction?.participants, initialTransaction?.reportID, - reportNameValuePairs, + isArchived, iouType, defaultExpensePolicy, report, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index b544b57b54ca..522a6c5cd800 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -118,6 +118,7 @@ function IOURequestStepScan({ const getScreenshotTimeoutRef = useRef(null); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const isArchived = isArchivedReport(reportNameValuePairs); const policy = usePolicy(report?.policyID); const personalPolicy = usePersonalPolicy(); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); @@ -181,8 +182,8 @@ function IOURequestStepScan({ return false; } - return !isArchivedReport(reportNameValuePairs) && !(isPolicyExpenseChat(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); - }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, reportNameValuePairs]); + return !isArchived && !(isPolicyExpenseChat(report) && ((policy?.requiresCategory ?? false) || (policy?.requiresTag ?? false))); + }, [report, skipConfirmation, policy?.requiresCategory, policy?.requiresTag, isArchived]); /** * On phones that have ultra-wide lens, react-webcam uses ultra-wide by default. @@ -485,11 +486,13 @@ function IOURequestStepScan({ // the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirmation step. // If the user is started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. - if (!initialTransaction?.isFromGlobalCreate && !isArchivedReport(reportNameValuePairs) && iouType !== CONST.IOU.TYPE.CREATE) { + if (!initialTransaction?.isFromGlobalCreate && !isArchived && iouType !== CONST.IOU.TYPE.CREATE) { const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, reportNameValuePairs?.private_isArchived, policy, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -599,7 +602,7 @@ function IOURequestStepScan({ initialTransaction?.currency, initialTransaction?.participants, initialTransaction?.reportID, - reportNameValuePairs, + isArchived, iouType, defaultExpensePolicy, report, diff --git a/src/selectors/ReportNameValuePairs.ts b/src/selectors/ReportNameValuePairs.ts index 774309ae8cf4..a33ccc389313 100644 --- a/src/selectors/ReportNameValuePairs.ts +++ b/src/selectors/ReportNameValuePairs.ts @@ -26,4 +26,22 @@ const archivedReportsIdSetSelector = (all: OnyxCollection) return ids; }; -export {createReportNameValuePairsSelector, archivedReportsIdSetSelector}; +type PrivateIsArchivedMap = Record; + +/** + * Selector that creates a map of report IDs to their private_isArchived values + */ +const privateIsArchivedMapSelector = (all: OnyxCollection): PrivateIsArchivedMap => { + const map: PrivateIsArchivedMap = {}; + if (!all) { + return map; + } + + for (const [key, value] of Object.entries(all)) { + map[key] = value?.private_isArchived; + } + return map; +}; + +export {createReportNameValuePairsSelector, archivedReportsIdSetSelector, privateIsArchivedMapSelector}; +export type {PrivateIsArchivedMap}; diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 679a3a3f462c..8f19732d5683 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {render, renderHook} from '@testing-library/react-native'; import {View} from 'react-native'; -import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import ComposeProviders from '@components/ComposeProviders'; import {LocaleContextProvider} from '@components/LocaleContextProvider'; @@ -25,6 +25,7 @@ import { getLastMessageTextForReport, getMemberInviteOptions, getPersonalDetailSearchTerms, + getReportDisplayOption, getReportOption, getSearchOptions, getSearchValueForPhoneOrEmail, @@ -54,7 +55,8 @@ import initOnyxDerivedValues from '@userActions/OnyxDerived'; import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetails, Policy, Report, ReportAction, Transaction} from '@src/types/onyx'; +import type {PersonalDetails, Policy, Report, ReportAction, ReportNameValuePairs, Transaction} from '@src/types/onyx'; +import type {Participant} from '@src/types/onyx/IOU'; import createRandomReportAction from '../utils/collections/reportActions'; import {createRandomReport, createRegularChat} from '../utils/collections/reports'; import createRandomTransaction from '../utils/collections/transaction'; @@ -2999,7 +3001,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant, policy); + const option = getReportOption(participant, undefined, policy); expect(option.text).toBe('Test Workspace'); expect(option.alternateText).toBe(translateLocal('workspace.common.workspace')); @@ -3054,7 +3056,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant, policy); + const option = getReportOption(participant, undefined, policy); expect(option.text).toBe('Test Workspace with Submit'); // The submitsTo logic may or may not apply depending on complex approval rules @@ -3077,7 +3079,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, POLICY); expect(option.isDisabled).toBe(true); }); @@ -3113,7 +3115,7 @@ describe('OptionsListUtils', () => { isSelfDM: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, POLICY); // The option.isSelfDM is set by createOption based on the report type // Just verify the alternateText is correct for self DM @@ -3148,12 +3150,211 @@ describe('OptionsListUtils', () => { isInvoiceRoom: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, POLICY); expect(option.isInvoiceRoom).toBe(true); expect(option.alternateText).toBe(translateLocal('workspace.common.invoices')); }); + it('should return option with correct text for workspace chat', async () => { + const workspaceReport: Report = { + lastReadTime: '2021-01-14 11:25:39.302', + lastVisibleActionCreated: '2022-11-22 03:26:02.022', + isPinned: false, + reportID: '18', + participants: { + 2: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + }, + reportName: '', + policyID, + policyName: POLICY.name, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + isOwnPolicyExpenseChat: true, + type: CONST.REPORT.TYPE.CHAT, + }; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}18`, workspaceReport); + await waitForBatchedUpdates(); + + const participant: Participant = { + reportID: '18', + selected: false, + }; + + let reportNameValuePair: OnyxEntry; + Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`, + waitForCollectionCallback: false, + callback: (value) => { + reportNameValuePair = value; + }, + }); + await waitForBatchedUpdates(); + + const option = getReportOption(participant, reportNameValuePair?.private_isArchived, POLICY); + + expect(option.text).toBe(POLICY.name); + expect(option.alternateText).toBeTruthy(); + expect(option.alternateText === translateLocal('workspace.common.workspace') || option.alternateText?.includes('Submits to')).toBe(true); + }); + + it('should handle draft reports', async () => { + const draftReport: Report = { + lastReadTime: '2021-01-14 11:25:39.302', + lastVisibleActionCreated: '2022-11-22 03:26:02.022', + isPinned: false, + reportID: '19', + participants: { + 2: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + 3: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + }, + reportName: 'Draft Report', + type: CONST.REPORT.TYPE.CHAT, + writeCapability: CONST.REPORT.WRITE_CAPABILITIES.ADMINS, + }; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}19`, draftReport); + await waitForBatchedUpdates(); + + const draftReports = { + '19': draftReport, + }; + + const participant: Participant = { + reportID: '19', + selected: false, + }; + + let reportNameValuePair: OnyxEntry; + Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`, + waitForCollectionCallback: false, + callback: (value) => { + reportNameValuePair = value; + }, + }); + await waitForBatchedUpdates(); + + const option = getReportOption(participant, reportNameValuePair?.private_isArchived, POLICY, undefined, draftReports); + + expect(option.isDisabled).toBe(true); + }); + }); + + describe('getReportDisplayOption', () => { + it('should use reportNameValuePair parameter for archived reports', async () => { + const reportID = '23'; + const report: Report = { + ...createRegularChat(Number(reportID), [2, 7]), + reportID, + lastVisibleActionCreated: '2022-11-22 03:26:02.001', + }; + + const reportNameValuePair: ReportNameValuePairs = { + private_isArchived: DateUtils.getDBTime(), + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); + await waitForBatchedUpdates(); + + const option = getReportDisplayOption(report, undefined, reportNameValuePair?.private_isArchived); + + expect(option).toBeDefined(); + expect(option.reportID).toBe(reportID); + expect(option.private_isArchived).toBeDefined(); + expect(option.private_isArchived).toBe(reportNameValuePair.private_isArchived); + expect(option.isDisabled).toBe(true); + expect(option.isSelected).toBe(false); + }); + + it('should use reportNameValuePair parameter for non-archived reports', async () => { + const reportID = '24'; + const report: Report = { + ...createRegularChat(Number(reportID), [2, 7]), + reportID, + lastVisibleActionCreated: '2022-11-22 03:26:02.001', + }; + + const reportNameValuePair: ReportNameValuePairs = {}; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); + await waitForBatchedUpdates(); + + const option = getReportDisplayOption(report, undefined, reportNameValuePair?.private_isArchived); + + expect(option).toBeDefined(); + expect(option.reportID).toBe(reportID); + expect(option.private_isArchived).toBeUndefined(); + expect(option.isDisabled).toBe(true); + expect(option.isSelected).toBe(false); + }); + + it('should handle undefined reportNameValuePair', async () => { + const reportID = '25'; + const report: Report = { + ...createRegularChat(Number(reportID), [2, 7]), + reportID, + lastVisibleActionCreated: '2022-11-22 03:26:02.001', + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); + await waitForBatchedUpdates(); + + const option = getReportDisplayOption(report, undefined, undefined); + + expect(option).toBeDefined(); + expect(option.reportID).toBe(reportID); + expect(option.isDisabled).toBe(true); + expect(option.isSelected).toBe(false); + }); + + it('should use reportNameValuePair for invoice room reports', async () => { + const reportID = '26'; + const report: Report = { + ...createRegularChat(Number(reportID), [2, 7]), + reportID, + chatType: CONST.REPORT.CHAT_TYPE.INVOICE, + lastVisibleActionCreated: '2022-11-22 03:26:02.001', + }; + + const reportNameValuePair: ReportNameValuePairs = { + private_isArchived: DateUtils.getDBTime(), + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); + await waitForBatchedUpdates(); + + const option = getReportDisplayOption(report, undefined, reportNameValuePair?.private_isArchived); + + expect(option).toBeDefined(); + expect(option.reportID).toBe(reportID); + expect(option.isInvoiceRoom).toBe(true); + expect(option.private_isArchived).toBeDefined(); + expect(option.private_isArchived).toBe(reportNameValuePair.private_isArchived); + }); + + it('should use reportNameValuePair for self DM reports', async () => { + const reportID = '27'; + const report: Report = { + ...createRegularChat(Number(reportID), [2]), + reportID, + chatType: CONST.REPORT.CHAT_TYPE.SELF_DM, + ownerAccountID: 2, + lastVisibleActionCreated: '2022-11-22 03:26:02.001', + }; + + const reportNameValuePair: ReportNameValuePairs = {}; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); + await waitForBatchedUpdates(); + + const option = getReportDisplayOption(report, undefined, reportNameValuePair?.private_isArchived); + + expect(option).toBeDefined(); + expect(option.reportID).toBe(reportID); + expect(option.isSelfDM).toBe(true); + }); + it('should preserve selected state from participant', async () => { const reportID = '106'; const report: Report = { @@ -3170,7 +3371,7 @@ describe('OptionsListUtils', () => { selected: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, POLICY); expect(option.isSelected).toBe(true); expect(option.selected).toBe(true); @@ -3191,7 +3392,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, undefined); expect(option).toBeDefined(); expect(option.text).toBeDefined(); @@ -3213,7 +3414,7 @@ describe('OptionsListUtils', () => { }; // Test that the function works with reportAttributesDerived parameter (optional) - const option = getReportOption(participant, undefined, undefined); + const option = getReportOption(participant, undefined, POLICY); expect(option).toBeDefined(); });