@@ -7,41 +7,45 @@ import useLocalize from '@hooks/useLocalize';
77import useNetwork from '@hooks/useNetwork' ;
88import usePaymentAnimations from '@hooks/usePaymentAnimations' ;
99import useResponsiveLayout from '@hooks/useResponsiveLayout' ;
10+ import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsActions' ;
1011import useTheme from '@hooks/useTheme' ;
1112import useThemeStyles from '@hooks/useThemeStyles' ;
12- import { exportReportToCSV } from '@libs/actions/Report' ;
13- import { convertToDisplayString } from '@libs/CurrencyUtils' ;
13+ import { getIOUReportPreviewButtonType , getTotalAmountForIOUReportPreviewButton } from '@libs/MoneyRequestReportUtils' ;
1414import Navigation from '@libs/Navigation/Navigation' ;
1515import { buildOptimisticNextStepForPreventSelfApprovalsEnabled } from '@libs/NextStepUtils' ;
1616import { getConnectedIntegration } from '@libs/PolicyUtils' ;
17- import { getIOUActionForTransactionID , getOriginalMessage , isDeletedAction , isMoneyRequestAction , isTrackExpenseAction } from '@libs/ReportActionsUtils' ;
17+ import { getOriginalMessage , isDeletedAction , isMoneyRequestAction , isTrackExpenseAction } from '@libs/ReportActionsUtils' ;
1818import {
1919 canBeExported ,
20- canDeleteCardTransactionByLiabilityType ,
2120 canDeleteTransaction ,
2221 getArchiveReason ,
2322 getBankAccountRoute ,
24- getMoneyRequestSpendBreakdown ,
2523 getNonHeldAndFullAmount ,
2624 getTransactionsWithReceipts ,
25+ hasActionsWithErrors ,
2726 hasHeldExpenses as hasHeldExpensesReportUtils ,
27+ hasMissingSmartscanFields ,
28+ hasNoticeTypeViolations ,
2829 hasOnlyHeldExpenses as hasOnlyHeldExpensesReportUtils ,
30+ hasReportViolations ,
2931 hasUpdatedTotal ,
32+ hasViolations ,
33+ hasWarningTypeViolations ,
3034 isAllowedToApproveExpenseReport ,
3135 isAllowedToSubmitDraftExpenseReport ,
3236 isArchivedReportWithID ,
3337 isInvoiceReport ,
3438 isProcessingReport ,
3539 isReportApproved ,
3640 isReportOwner ,
41+ isSettled ,
3742 isWaitingForSubmissionFromCurrentUser as isWaitingForSubmissionFromCurrentUserReportUtils ,
3843 navigateBackOnDeleteTransaction ,
3944 reportTransactionsSelector ,
4045} from '@libs/ReportUtils' ;
4146import {
4247 allHavePendingRTERViolation ,
4348 checkIfShouldShowMarkAsCashButton ,
44- getTransaction ,
4549 hasDuplicateTransactions ,
4650 isDuplicate as isDuplicateTransactionUtils ,
4751 isExpensifyCardTransaction ,
@@ -64,7 +68,6 @@ import {
6468 payInvoice ,
6569 payMoneyRequest ,
6670 submitReport ,
67- unholdRequest ,
6871} from '@userActions/IOU' ;
6972import { markAsCash as markAsCashAction } from '@userActions/Transaction' ;
7073import CONST from '@src/CONST' ;
@@ -123,12 +126,10 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
123126 // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
124127 const { shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout ( ) ;
125128 const route = useRoute ( ) ;
126- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
127129 const [ chatReport ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT } ${ moneyRequestReport ?. chatReportID } ` , { canBeMissing : true } ) ;
128- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
129130 const [ nextStep ] = useOnyx ( `${ ONYXKEYS . COLLECTION . NEXT_STEP } ${ moneyRequestReport ?. reportID } ` , { canBeMissing : true } ) ;
130131 const [ transactionThreadReport ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT } ${ transactionThreadReportID } ` , { canBeMissing : true } ) ;
131- const [ session ] = useOnyx ( ONYXKEYS . SESSION , { canBeMissing : true } ) ;
132+ const [ session ] = useOnyx ( ONYXKEYS . SESSION , { canBeMissing : false } ) ;
132133 const requestParentReportAction = useMemo ( ( ) => {
133134 if ( ! reportActions || ! transactionThreadReport ?. parentReportActionID ) {
134135 return null ;
@@ -152,7 +153,6 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
152153 const [ isDeleteRequestModalVisible , setIsDeleteRequestModalVisible ] = useState ( false ) ;
153154 const { translate} = useLocalize ( ) ;
154155 const { isOffline} = useNetwork ( ) ;
155- const { reimbursableSpend} = getMoneyRequestSpendBreakdown ( moneyRequestReport ) ;
156156 const isOnHold = isOnHoldTransactionUtils ( transaction ) ;
157157 const isDeletedParentAction = ! ! requestParentReportAction && isDeletedAction ( requestParentReportAction ) ;
158158 const isDuplicate = isDuplicateTransactionUtils ( transaction ?. transactionID ) && ( ! isReportApproved ( { report : moneyRequestReport } ) || isApprovedAnimationRunning ) ;
@@ -197,99 +197,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
197197
198198 const { selectedTransactionsID, setSelectedTransactionsID} = useMoneyRequestReportContext ( ) ;
199199
200- const selectedTransactionsOptions = useMemo ( ( ) => {
201- if ( ! selectedTransactionsID . length ) {
202- return [ ] ;
203- }
204- const options = [ ] ;
205- const selectedTransactions = selectedTransactionsID . map ( ( transactionID ) => getTransaction ( transactionID ) ) . filter ( ( t ) => ! ! t ) ;
206-
207- const anyTransactionOnHold = selectedTransactions . some ( isOnHoldTransactionUtils ) ;
208- const allTransactionOnHold = selectedTransactions . every ( isOnHoldTransactionUtils ) ;
209- const isReportReimbursed = moneyRequestReport ?. stateNum === CONST . REPORT . STATE_NUM . APPROVED && moneyRequestReport ?. statusNum === CONST . REPORT . STATUS_NUM . REIMBURSED ;
210-
211- if ( ! anyTransactionOnHold && selectedTransactions . length === 1 && ! isReportReimbursed ) {
212- options . push ( {
213- text : translate ( 'iou.hold' ) ,
214- icon : Expensicons . Stopwatch ,
215- value : CONST . REPORT . SECONDARY_ACTIONS . HOLD ,
216- onSelected : ( ) => {
217- if ( ! moneyRequestReport ?. reportID ) {
218- return ;
219- }
220- Navigation . navigate ( ROUTES . SEARCH_MONEY_REQUEST_REPORT_HOLD_TRANSACTIONS . getRoute ( { reportID : moneyRequestReport . reportID } ) ) ;
221- } ,
222- } ) ;
223- }
224-
225- if ( allTransactionOnHold && selectedTransactions . length === 1 ) {
226- options . push ( {
227- text : translate ( 'iou.unhold' ) ,
228- icon : Expensicons . Stopwatch ,
229- value : 'UNHOLD' ,
230- onSelected : ( ) => {
231- selectedTransactionsID . forEach ( ( transactionID ) => {
232- const action = getIOUActionForTransactionID ( reportActions , transactionID ) ;
233- if ( ! action ?. childReportID ) {
234- return ;
235- }
236- unholdRequest ( transactionID , action ?. childReportID ) ;
237- } ) ;
238- // it's needed in order to recalculate options
239- setSelectedTransactionsID ( [ ...selectedTransactionsID ] ) ;
240- } ,
241- } ) ;
242- }
243-
244- options . push ( {
245- value : CONST . REPORT . SECONDARY_ACTIONS . DOWNLOAD ,
246- text : translate ( 'common.download' ) ,
247- icon : Expensicons . Download ,
248- onSelected : ( ) => {
249- if ( ! moneyRequestReport ) {
250- return ;
251- }
252- exportReportToCSV ( { reportID : moneyRequestReport . reportID , transactionIDList : selectedTransactionsID } , ( ) => {
253- setIsDownloadErrorModalVisible ( true ) ;
254- } ) ;
255- } ,
256- } ) ;
257-
258- const canAllSelectedTransactionsBeRemoved = selectedTransactionsID . every ( ( transactionID ) => {
259- const canRemoveTransaction = canDeleteCardTransactionByLiabilityType ( transactionID ) ;
260- const action = getIOUActionForTransactionID ( reportActions , transactionID ) ;
261- const isActionDeleted = isDeletedAction ( action ) ;
262- const isIOUActionOwner = typeof action ?. actorAccountID === 'number' && typeof session ?. accountID === 'number' && action . actorAccountID === session ?. accountID ;
263-
264- return canRemoveTransaction && isIOUActionOwner && ! isActionDeleted ;
265- } ) ;
266-
267- const canRemoveReportTransaction = canDeleteTransaction ( moneyRequestReport ) ;
268-
269- if ( canRemoveReportTransaction && canAllSelectedTransactionsBeRemoved ) {
270- options . push ( {
271- text : translate ( 'common.delete' ) ,
272- icon : Expensicons . Trashcan ,
273- value : CONST . REPORT . SECONDARY_ACTIONS . DELETE ,
274- onSelected : ( ) => {
275- const iouActions = reportActions . filter ( ( action ) => isMoneyRequestAction ( action ) ) ;
276-
277- const transactionsWithActions = selectedTransactions . map ( ( t ) => ( {
278- transactionID : t ?. transactionID ,
279- action : iouActions . find ( ( action ) => {
280- const IOUTransactionID = ( getOriginalMessage ( action ) as OnyxTypes . OriginalMessageIOU ) ?. IOUTransactionID ;
281-
282- return t ?. transactionID === IOUTransactionID ;
283- } ) ,
284- } ) ) ;
285-
286- transactionsWithActions . forEach ( ( { transactionID, action} ) => action && deleteMoneyRequest ( transactionID , action ) ) ;
287- setSelectedTransactionsID ( [ ] ) ;
288- } ,
289- } ) ;
290- }
291- return options ;
292- } , [ moneyRequestReport , reportActions , selectedTransactionsID , session ?. accountID , setSelectedTransactionsID , translate ] ) ;
200+ const selectedTransactionsOptions = useSelectedTransactionsActions ( { report : moneyRequestReport , reportActions, session, onExportFailed : ( ) => setIsDownloadErrorModalVisible ( true ) } ) ;
293201
294202 const shouldShowSelectedTransactionsButton = ! ! selectedTransactionsOptions . length && ! transactionThreadReportID ;
295203
@@ -314,7 +222,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
314222 const filteredTransactions = transactions ?. filter ( ( t ) => t ) ?? [ ] ;
315223 const shouldShowSubmitButton = canSubmitReport ( moneyRequestReport , policy , filteredTransactions , violations ) ;
316224
317- const shouldShowExportIntegrationButton = ! shouldShowPayButton && ! shouldShowSubmitButton && connectedIntegration && isAdmin && canBeExported ( moneyRequestReport ) ;
225+ const shouldShowExportIntegrationButton = ! shouldShowPayButton && ! shouldShowSubmitButton && ! ! connectedIntegration && isAdmin && canBeExported ( moneyRequestReport ) ;
318226
319227 const shouldShowSettlementButton =
320228 ! shouldShowSelectedTransactionsButton &&
@@ -349,10 +257,8 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
349257 shouldShowMarkAsCashButton ||
350258 shouldShowExportIntegrationButton ;
351259 const bankAccountRoute = getBankAccountRoute ( chatReport ) ;
352- const formattedAmount = convertToDisplayString ( reimbursableSpend , moneyRequestReport ?. currency ) ;
353260 const { nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount ( moneyRequestReport , shouldShowPayButton ) ;
354261 const isAnyTransactionOnHold = hasHeldExpensesReportUtils ( moneyRequestReport ?. reportID ) ;
355- const displayedAmount = isAnyTransactionOnHold && canAllowSettlement && hasValidNonHeldAmount ? nonHeldAmount : formattedAmount ;
356262 const isMoreContentShown = shouldShowNextStep || shouldShowStatusBar || ( shouldShowAnyButton && shouldUseNarrowLayout ) ;
357263 const { isDelegateAccessRestricted} = useDelegateUserDetails ( ) ;
358264 const [ isNoDelegateAccessMenuVisible , setIsNoDelegateAccessMenuVisible ] = useState ( false ) ;
@@ -512,6 +418,29 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
512418
513419 const shouldShowBackButton = shouldDisplayBackButton || shouldUseNarrowLayout ;
514420
421+ const iouReportID = moneyRequestReport ?. reportID ;
422+
423+ const isIOUSettled = isSettled ( iouReportID ) || requestParentReportAction ?. childStatusNum === CONST . REPORT . STATUS_NUM . REIMBURSED ;
424+
425+ const shouldShowRBR =
426+ ( ( hasMissingSmartscanFields ( iouReportID ) && ! isIOUSettled ) ||
427+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
428+ hasViolations ( iouReportID , violations , true ) ||
429+ hasNoticeTypeViolations ( iouReportID , violations , true ) ||
430+ hasWarningTypeViolations ( iouReportID , violations , true ) ||
431+ ( isReportOwner ( moneyRequestReport ) && hasReportViolations ( iouReportID ) ) ||
432+ hasActionsWithErrors ( iouReportID ) ) &&
433+ ! isIOUSettled ;
434+
435+ const buttonType = getIOUReportPreviewButtonType ( {
436+ shouldShowPayButton,
437+ shouldShowApproveButton,
438+ shouldShowSubmitButton,
439+ shouldShowSettlementButton,
440+ shouldShowRBR,
441+ shouldShowExportIntegrationButton,
442+ } ) ;
443+
515444 return (
516445 < View style = { [ styles . pt0 , styles . borderBottom ] } >
517446 < HeaderWithBackButton
@@ -568,7 +497,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
568497 shouldShowApproveButton = { shouldShowApproveButton }
569498 shouldDisableApproveButton = { shouldDisableApproveButton }
570499 style = { [ styles . pv2 ] }
571- formattedAmount = { ! hasOnlyHeldExpenses ? displayedAmount : '' }
500+ formattedAmount = { getTotalAmountForIOUReportPreviewButton ( moneyRequestReport , policy , buttonType ) }
572501 isDisabled = { isOffline && ! canAllowSettlement }
573502 isLoading = { ! isOffline && ! canAllowSettlement }
574503 />
@@ -647,7 +576,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
647576 addBankAccountRoute = { bankAccountRoute }
648577 shouldHidePaymentOptions = { ! shouldShowPayButton }
649578 shouldShowApproveButton = { shouldShowApproveButton }
650- formattedAmount = { ! hasOnlyHeldExpenses ? displayedAmount : '' }
579+ formattedAmount = { getTotalAmountForIOUReportPreviewButton ( moneyRequestReport , policy , buttonType ) }
651580 shouldDisableApproveButton = { shouldDisableApproveButton }
652581 isDisabled = { isOffline && ! canAllowSettlement }
653582 isLoading = { ! isOffline && ! canAllowSettlement }
0 commit comments