@@ -10,6 +10,7 @@ import DragAndDropConsumer from '@components/DragAndDrop/Consumer';
1010import DragAndDropProvider from '@components/DragAndDrop/Provider' ;
1111import DropZoneUI from '@components/DropZone/DropZoneUI' ;
1212import HoldOrRejectEducationalModal from '@components/HoldOrRejectEducationalModal' ;
13+ import HoldSubmitterEducationalModal from '@components/HoldSubmitterEducationalModal' ;
1314import * as Expensicons from '@components/Icon/Expensicons' ;
1415import type { PaymentMethodType } from '@components/KYCWall/types' ;
1516import type { PopoverMenuItem } from '@components/PopoverMenu' ;
@@ -54,6 +55,7 @@ import {
5455 unholdMoneyRequestOnSearch ,
5556} from '@libs/actions/Search' ;
5657import { setTransactionReport } from '@libs/actions/Transaction' ;
58+ import { setNameValuePair } from '@libs/actions/User' ;
5759import { navigateToParticipantPage } from '@libs/IOUUtils' ;
5860import Navigation from '@libs/Navigation/Navigation' ;
5961import type { PlatformStackScreenProps } from '@libs/Navigation/PlatformStackNavigation/types' ;
@@ -66,6 +68,7 @@ import {
6668 getPolicyExpenseChat ,
6769 getReportOrDraftReport ,
6870 isBusinessInvoiceRoom ,
71+ isCurrentUserSubmitter ,
6972 isExpenseReport as isExpenseReportUtil ,
7073 isInvoiceReport ,
7174 isIOUReport as isIOUReportUtil ,
@@ -82,7 +85,7 @@ import CONST from '@src/CONST';
8285import ONYXKEYS from '@src/ONYXKEYS' ;
8386import ROUTES from '@src/ROUTES' ;
8487import type SCREENS from '@src/SCREENS' ;
85- import type { SearchResults , Transaction } from '@src/types/onyx' ;
88+ import type { Report , SearchResults , Transaction } from '@src/types/onyx' ;
8689import type { FileObject } from '@src/types/utils/Attachment' ;
8790import SearchPageNarrow from './SearchPageNarrow' ;
8891import SearchPageWide from './SearchPageWide' ;
@@ -119,13 +122,12 @@ function SearchPage({route}: SearchPageProps) {
119122 const [ isExportWithTemplateModalVisible , setIsExportWithTemplateModalVisible ] = useState ( false ) ;
120123 const [ searchRequestResponseStatusCode , setSearchRequestResponseStatusCode ] = useState < number | null > ( null ) ;
121124 const [ isDEWModalVisible , setIsDEWModalVisible ] = useState ( false ) ;
125+ const [ isHoldEducationalModalVisible , setIsHoldEducationalModalVisible ] = useState ( false ) ;
126+ const [ rejectModalAction , setRejectModalAction ] = useState < ValueOf <
127+ typeof CONST . REPORT . TRANSACTION_SECONDARY_ACTIONS . HOLD | typeof CONST . REPORT . TRANSACTION_SECONDARY_ACTIONS . REJECT
128+ > | null > ( null ) ;
122129 const [ dismissedRejectUseExplanation ] = useOnyx ( ONYXKEYS . NVP_DISMISSED_REJECT_USE_EXPLANATION , { canBeMissing : true } ) ;
123- const [ isRejectEducationalModalVisible , setIsRejectEducationalModalVisible ] = useState ( false ) ;
124- const dismissModalAndUpdateUseReject = ( ) => {
125- setIsRejectEducationalModalVisible ( false ) ;
126- dismissRejectUseExplanation ( ) ;
127- Navigation . navigate ( ROUTES . SEARCH_REJECT_REASON_RHP ) ;
128- } ;
130+ const [ dismissedHoldUseExplanation ] = useOnyx ( ONYXKEYS . NVP_DISMISSED_HOLD_USE_EXPLANATION , { canBeMissing : true } ) ;
129131 const queryJSON = useMemo ( ( ) => buildSearchQueryJSON ( route . params . q , route . params . rawQuery ) , [ route . params . q , route . params . rawQuery ] ) ;
130132 const { saveScrollOffset} = useContext ( ScrollOffsetContext ) ;
131133 const activeAdminPolicies = getActiveAdminWorkspaces ( policies , currentUserPersonalDetails ?. accountID . toString ( ) ) . sort ( ( a , b ) => localeCompare ( a . name || '' , b . name || '' ) ) ;
@@ -376,6 +378,28 @@ function SearchPage({route}: SearchPageProps) {
376378 [ clearSelectedTransactions , hash , isOffline , lastPaymentMethods , selectedReports , selectedTransactions , policies , formatPhoneNumber ] ,
377379 ) ;
378380
381+ // Check if all selected transactions are from the submitter
382+ const areAllTransactionsFromSubmitter = useMemo ( ( ) => {
383+ if ( ! currentUserPersonalDetails ?. accountID ) {
384+ return false ;
385+ }
386+
387+ const searchData = currentSearchResults ?. data ;
388+ const reports : Report [ ] = searchData
389+ ? Object . keys ( searchData )
390+ . filter ( ( key ) => key . startsWith ( ONYXKEYS . COLLECTION . REPORT ) )
391+ . map ( ( key ) => searchData [ key as keyof typeof searchData ] as Report )
392+ . filter ( ( report ) : report is Report => report != null && 'reportID' in report )
393+ : [ ] ;
394+
395+ return (
396+ selectedTransactionReportIDs . length > 0 &&
397+ selectedTransactionReportIDs . every ( ( id ) => {
398+ return isCurrentUserSubmitter ( getReportOrDraftReport ( id , reports ) ) ;
399+ } )
400+ ) ;
401+ } , [ selectedTransactionReportIDs , currentUserPersonalDetails ?. accountID , currentSearchResults ?. data ] ) ;
402+
379403 const headerButtonsOptions = useMemo ( ( ) => {
380404 if ( selectedTransactionsKeys . length === 0 || status == null || ! hash ) {
381405 return CONST . EMPTY_ARRAY as unknown as Array < DropdownOption < SearchHeaderOptionValue > > ;
@@ -564,7 +588,7 @@ function SearchPage({route}: SearchPageProps) {
564588 if ( dismissedRejectUseExplanation ) {
565589 Navigation . navigate ( ROUTES . SEARCH_REJECT_REASON_RHP ) ;
566590 } else {
567- setIsRejectEducationalModalVisible ( true ) ;
591+ setRejectModalAction ( CONST . REPORT . TRANSACTION_SECONDARY_ACTIONS . REJECT ) ;
568592 }
569593 } ,
570594 } ) ;
@@ -634,7 +658,15 @@ function SearchPage({route}: SearchPageProps) {
634658 return ;
635659 }
636660
637- Navigation . navigate ( ROUTES . TRANSACTION_HOLD_REASON_RHP ) ;
661+ const isDismissed = areAllTransactionsFromSubmitter ? dismissedHoldUseExplanation : dismissedRejectUseExplanation ;
662+
663+ if ( isDismissed ) {
664+ Navigation . navigate ( ROUTES . TRANSACTION_HOLD_REASON_RHP ) ;
665+ } else if ( areAllTransactionsFromSubmitter ) {
666+ setIsHoldEducationalModalVisible ( true ) ;
667+ } else {
668+ setRejectModalAction ( CONST . REPORT . TRANSACTION_SECONDARY_ACTIONS . HOLD ) ;
669+ }
638670 } ,
639671 } ) ;
640672 }
@@ -761,6 +793,9 @@ function SearchPage({route}: SearchPageProps) {
761793 styles . fontWeightNormal ,
762794 styles . textWrap ,
763795 expensifyIcons ,
796+ dismissedHoldUseExplanation ,
797+ dismissedRejectUseExplanation ,
798+ areAllTransactionsFromSubmitter ,
764799 bulkRejectHydrationStatus ,
765800 ] ) ;
766801
@@ -982,6 +1017,27 @@ function SearchPage({route}: SearchPageProps) {
9821017 setIsDownloadExportModalVisible ?.( false ) ;
9831018 } , [ setIsDownloadExportModalVisible ] ) ;
9841019
1020+ const dismissModalAndUpdateUseHold = useCallback ( ( ) => {
1021+ setIsHoldEducationalModalVisible ( false ) ;
1022+ setNameValuePair ( ONYXKEYS . NVP_DISMISSED_HOLD_USE_EXPLANATION , true , false , ! isOffline ) ;
1023+ if ( hash && selectedTransactionsKeys . length > 0 ) {
1024+ Navigation . navigate ( ROUTES . TRANSACTION_HOLD_REASON_RHP ) ;
1025+ }
1026+ } , [ hash , selectedTransactionsKeys . length , isOffline ] ) ;
1027+
1028+ const dismissRejectModalBasedOnAction = useCallback ( ( ) => {
1029+ if ( rejectModalAction === CONST . REPORT . TRANSACTION_SECONDARY_ACTIONS . HOLD ) {
1030+ dismissRejectUseExplanation ( ) ;
1031+ if ( hash && selectedTransactionsKeys . length > 0 ) {
1032+ Navigation . navigate ( ROUTES . TRANSACTION_HOLD_REASON_RHP ) ;
1033+ }
1034+ } else {
1035+ dismissRejectUseExplanation ( ) ;
1036+ Navigation . navigate ( ROUTES . SEARCH_REJECT_REASON_RHP ) ;
1037+ }
1038+ setRejectModalAction ( null ) ;
1039+ } , [ rejectModalAction , hash , selectedTransactionsKeys . length ] ) ;
1040+
9851041 return (
9861042 < >
9871043 < Animated . View style = { [ styles . flex1 ] } >
@@ -1094,10 +1150,16 @@ function SearchPage({route}: SearchPageProps) {
10941150 cancelText = { translate ( 'common.cancel' ) }
10951151 />
10961152 ) }
1097- { ! ! isRejectEducationalModalVisible && (
1153+ { ! ! rejectModalAction && (
10981154 < HoldOrRejectEducationalModal
1099- onClose = { dismissModalAndUpdateUseReject }
1100- onConfirm = { dismissModalAndUpdateUseReject }
1155+ onClose = { dismissRejectModalBasedOnAction }
1156+ onConfirm = { dismissRejectModalBasedOnAction }
1157+ />
1158+ ) }
1159+ { ! ! isHoldEducationalModalVisible && (
1160+ < HoldSubmitterEducationalModal
1161+ onClose = { dismissModalAndUpdateUseHold }
1162+ onConfirm = { dismissModalAndUpdateUseHold }
11011163 />
11021164 ) }
11031165 </ View >
0 commit comments