Skip to content

Commit 664f743

Browse files
authored
Merge pull request #42896 from nkdengineer/fix/39335
Add confirmation prompt when approving held request via report preview
2 parents c4e2a04 + 083823d commit 664f743

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

src/components/MoneyReportHeader.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Icon from './Icon';
2727
import * as Expensicons from './Icon/Expensicons';
2828
import MoneyReportHeaderStatusBar from './MoneyReportHeaderStatusBar';
2929
import MoneyRequestHeaderStatusBar from './MoneyRequestHeaderStatusBar';
30+
import type {ActionHandledType} from './ProcessMoneyReportHoldMenu';
3031
import ProcessMoneyReportHoldMenu from './ProcessMoneyReportHoldMenu';
3132
import SettlementButton from './SettlementButton';
3233

@@ -79,7 +80,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
7980
isActionOwner && (ReportUtils.canAddOrDeleteTransactions(moneyRequestReport) || ReportUtils.isTrackExpenseReport(transactionThreadReport)) && !isDeletedParentAction;
8081
const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false);
8182
const [paymentType, setPaymentType] = useState<PaymentMethodType>();
82-
const [requestType, setRequestType] = useState<'pay' | 'approve'>();
83+
const [requestType, setRequestType] = useState<ActionHandledType>();
8384
const canAllowSettlement = ReportUtils.hasUpdatedTotal(moneyRequestReport, policy);
8485
const policyType = policy?.type;
8586
const isPayer = ReportUtils.isPayer(session, moneyRequestReport);
@@ -124,7 +125,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
124125
return;
125126
}
126127
setPaymentType(type);
127-
setRequestType('pay');
128+
setRequestType(CONST.IOU.REPORT_ACTION_TYPE.PAY);
128129
if (ReportUtils.hasHeldExpenses(moneyRequestReport.reportID)) {
129130
setIsHoldMenuVisible(true);
130131
} else if (ReportUtils.isInvoiceReport(moneyRequestReport)) {
@@ -135,7 +136,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
135136
};
136137

137138
const confirmApproval = () => {
138-
setRequestType('approve');
139+
setRequestType(CONST.IOU.REPORT_ACTION_TYPE.APPROVE);
139140
if (ReportUtils.hasHeldExpenses(moneyRequestReport.reportID)) {
140141
setIsHoldMenuVisible(true);
141142
} else {

src/components/ProcessMoneyReportHoldMenu.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ import useLocalize from '@hooks/useLocalize';
44
import Navigation from '@libs/Navigation/Navigation';
55
import {isLinkedTransactionHeld} from '@libs/ReportActionsUtils';
66
import * as IOU from '@userActions/IOU';
7+
import CONST from '@src/CONST';
78
import ROUTES from '@src/ROUTES';
89
import type * as OnyxTypes from '@src/types/onyx';
910
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
11+
import type DeepValueOf from '@src/types/utils/DeepValueOf';
1012
import DecisionModal from './DecisionModal';
1113

14+
type ActionHandledType = DeepValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE.PAY | typeof CONST.IOU.REPORT_ACTION_TYPE.APPROVE>;
15+
1216
type ProcessMoneyReportHoldMenuProps = {
1317
/** The chat report this report is linked to */
1418
chatReport: OnyxEntry<OnyxTypes.Report>;
@@ -35,7 +39,7 @@ type ProcessMoneyReportHoldMenuProps = {
3539
paymentType?: PaymentMethodType;
3640

3741
/** Type of action handled */
38-
requestType?: 'pay' | 'approve';
42+
requestType?: ActionHandledType;
3943
};
4044

4145
function ProcessMoneyReportHoldMenu({
@@ -50,7 +54,7 @@ function ProcessMoneyReportHoldMenu({
5054
moneyRequestReport,
5155
}: ProcessMoneyReportHoldMenuProps) {
5256
const {translate} = useLocalize();
53-
const isApprove = requestType === 'approve';
57+
const isApprove = requestType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE;
5458

5559
const onSubmit = (full: boolean) => {
5660
if (isApprove) {
@@ -82,3 +86,4 @@ function ProcessMoneyReportHoldMenu({
8286
ProcessMoneyReportHoldMenu.displayName = 'ProcessMoneyReportHoldMenu';
8387

8488
export default ProcessMoneyReportHoldMenu;
89+
export type {ActionHandledType};

src/components/ReportActionItem/ReportPreview.tsx

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import truncate from 'lodash/truncate';
2-
import React, {useMemo} from 'react';
2+
import React, {useMemo, useState} from 'react';
33
import type {StyleProp, ViewStyle} from 'react-native';
44
import {View} from 'react-native';
55
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
@@ -9,13 +9,16 @@ import Icon from '@components/Icon';
99
import * as Expensicons from '@components/Icon/Expensicons';
1010
import OfflineWithFeedback from '@components/OfflineWithFeedback';
1111
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
12+
import ProcessMoneyReportHoldMenu from '@components/ProcessMoneyReportHoldMenu';
13+
import type {ActionHandledType} from '@components/ProcessMoneyReportHoldMenu';
1214
import SettlementButton from '@components/SettlementButton';
1315
import {showContextMenuForReport} from '@components/ShowContextMenuContext';
1416
import Text from '@components/Text';
1517
import useLocalize from '@hooks/useLocalize';
1618
import usePermissions from '@hooks/usePermissions';
1719
import useTheme from '@hooks/useTheme';
1820
import useThemeStyles from '@hooks/useThemeStyles';
21+
import useWindowDimensions from '@hooks/useWindowDimensions';
1922
import ControlSelection from '@libs/ControlSelection';
2023
import * as CurrencyUtils from '@libs/CurrencyUtils';
2124
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
@@ -119,6 +122,12 @@ function ReportPreview({
119122
[transactions, iouReportID, action],
120123
);
121124

125+
const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false);
126+
const [requestType, setRequestType] = useState<ActionHandledType>();
127+
const [nonHeldAmount, fullAmount] = ReportUtils.getNonHeldAndFullAmount(iouReport, policy);
128+
const {isSmallScreenWidth} = useWindowDimensions();
129+
const [paymentType, setPaymentType] = useState<PaymentMethodType>();
130+
122131
const managerID = iouReport?.managerID ?? 0;
123132
const {totalDisplaySpend, reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport);
124133

@@ -164,6 +173,32 @@ function ReportPreview({
164173
[chatReport?.isOwnPolicyExpenseChat, policy?.harvesting?.enabled],
165174
);
166175

176+
const confirmPayment = (type: PaymentMethodType | undefined) => {
177+
if (!type) {
178+
return;
179+
}
180+
setPaymentType(type);
181+
setRequestType(CONST.IOU.REPORT_ACTION_TYPE.PAY);
182+
if (ReportUtils.hasHeldExpenses(iouReport?.reportID)) {
183+
setIsHoldMenuVisible(true);
184+
} else if (chatReport && iouReport) {
185+
if (ReportUtils.isInvoiceReport(iouReport)) {
186+
IOU.payInvoice(type, chatReport, iouReport);
187+
} else {
188+
IOU.payMoneyRequest(type, chatReport, iouReport);
189+
}
190+
}
191+
};
192+
193+
const confirmApproval = () => {
194+
setRequestType(CONST.IOU.REPORT_ACTION_TYPE.APPROVE);
195+
if (ReportUtils.hasHeldExpenses(iouReport?.reportID)) {
196+
setIsHoldMenuVisible(true);
197+
} else {
198+
IOU.approveMoneyRequest(iouReport ?? {}, true);
199+
}
200+
};
201+
167202
const getDisplayAmount = (): string => {
168203
if (totalDisplaySpend) {
169204
return CurrencyUtils.convertToDisplayString(totalDisplaySpend, iouReport?.currency);
@@ -282,17 +317,6 @@ function ReportPreview({
282317
};
283318
}, [formattedMerchant, formattedDescription, moneyRequestComment, translate, numberOfRequests, numberOfScanningReceipts, numberOfPendingRequests]);
284319

285-
const confirmPayment = (paymentMethodType?: PaymentMethodType) => {
286-
if (!paymentMethodType || !chatReport || !iouReport) {
287-
return;
288-
}
289-
if (ReportUtils.isInvoiceReport(iouReport)) {
290-
IOU.payInvoice(paymentMethodType, chatReport, iouReport);
291-
} else {
292-
IOU.payMoneyRequest(paymentMethodType, chatReport, iouReport);
293-
}
294-
};
295-
296320
return (
297321
<OfflineWithFeedback
298322
pendingAction={iouReport?.pendingFields?.preview}
@@ -383,6 +407,7 @@ function ReportPreview({
383407
chatReportID={chatReportID}
384408
iouReport={iouReport}
385409
onPress={confirmPayment}
410+
confirmApproval={confirmApproval}
386411
enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS}
387412
addBankAccountRoute={bankAccountRoute}
388413
shouldHidePaymentOptions={!shouldShowPayButton}
@@ -413,6 +438,19 @@ function ReportPreview({
413438
</View>
414439
</PressableWithoutFeedback>
415440
</View>
441+
{isHoldMenuVisible && iouReport && requestType !== undefined && (
442+
<ProcessMoneyReportHoldMenu
443+
nonHeldAmount={!ReportUtils.hasOnlyHeldExpenses(iouReport?.reportID ?? '') ? nonHeldAmount : undefined}
444+
requestType={requestType}
445+
fullAmount={fullAmount}
446+
isSmallScreenWidth={isSmallScreenWidth}
447+
onClose={() => setIsHoldMenuVisible(false)}
448+
isVisible={isHoldMenuVisible}
449+
paymentType={paymentType}
450+
chatReport={chatReport}
451+
moneyRequestReport={iouReport}
452+
/>
453+
)}
416454
</OfflineWithFeedback>
417455
);
418456
}

0 commit comments

Comments
 (0)