Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CP Staging] Show delete option for requests on one transaction view #39449

Merged
merged 9 commits into from
Apr 2, 2024
73 changes: 71 additions & 2 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback, useMemo, useState} from 'react';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
Expand All @@ -8,13 +8,15 @@ import useWindowDimensions from '@hooks/useWindowDimensions';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as HeaderUtils from '@libs/HeaderUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as IOU from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import Button from './Button';
import ConfirmModal from './ConfirmModal';
import HeaderWithBackButton from './HeaderWithBackButton';
Expand All @@ -32,6 +34,9 @@ type MoneyReportHeaderOnyxProps = {

/** Session info for the currently logged in user. */
session: OnyxEntry<OnyxTypes.Session>;

/** The transaction thread report associated with the current report, if any */
transactionThreadReport: OnyxEntry<OnyxTypes.Report>;
};

type MoneyReportHeaderProps = MoneyReportHeaderOnyxProps & {
Expand All @@ -40,14 +45,35 @@ type MoneyReportHeaderProps = MoneyReportHeaderOnyxProps & {

/** The policy tied to the money request report */
policy: OnyxEntry<OnyxTypes.Policy>;

/** Array of report actions for the report */
reportActions: OnyxTypes.ReportAction[];

/** The reportID of the transaction thread report associated with this current report, if any */
// eslint-disable-next-line react/no-unused-prop-types
transactionThreadReportID?: string | null;
};

function MoneyReportHeader({session, policy, chatReport, nextStep, report: moneyRequestReport}: MoneyReportHeaderProps) {
function MoneyReportHeader({session, policy, chatReport, nextStep, report: moneyRequestReport, transactionThreadReport, reportActions}: MoneyReportHeaderProps) {
const styles = useThemeStyles();
const [isDeleteRequestModalVisible, setIsDeleteRequestModalVisible] = useState(false);
const {translate} = useLocalize();
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();
const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(moneyRequestReport);
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const requestParentReportAction = useMemo(() => {
if (!reportActions || !transactionThreadReport?.parentReportActionID) {
return null;
}
return reportActions.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID);
}, [reportActions, transactionThreadReport?.parentReportActionID]);
const isDeletedParentAction = ReportActionsUtils.isDeletedAction(requestParentReportAction as OnyxTypes.ReportAction);

// Only the requestor can delete the request, admins can only edit it.
const isActionOwner =
typeof requestParentReportAction?.actorAccountID === 'number' && typeof session?.accountID === 'number' && requestParentReportAction.actorAccountID === session?.accountID;
const canDeleteRequest =
isActionOwner && (ReportUtils.canAddOrDeleteTransactions(moneyRequestReport) || ReportUtils.isTrackExpenseReport(transactionThreadReport)) && !isDeletedParentAction;
const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false);
const [paymentType, setPaymentType] = useState<PaymentMethodType>();
const [requestType, setRequestType] = useState<'pay' | 'approve'>();
Expand Down Expand Up @@ -106,6 +132,19 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
}
};

const deleteTransaction = useCallback(() => {
if (requestParentReportAction) {
const iouTransactionID = requestParentReportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? requestParentReportAction.originalMessage?.IOUTransactionID ?? '' : '';
if (ReportActionsUtils.isTrackExpenseAction(requestParentReportAction)) {
IOU.deleteTrackExpense(moneyRequestReport?.reportID ?? '', iouTransactionID, requestParentReportAction, true);
return;
}
IOU.deleteMoneyRequest(iouTransactionID, requestParentReportAction, true);
}

setIsDeleteRequestModalVisible(false);
}, [moneyRequestReport?.reportID, requestParentReportAction, setIsDeleteRequestModalVisible]);

// The submit button should be success green colour only if the user is submitter and the policy does not have Scheduled Submit turned on
const isWaitingForSubmissionFromCurrentUser = useMemo(
() => chatReport?.isOwnPolicyExpenseChat && !policy?.harvesting?.enabled,
Expand All @@ -121,6 +160,23 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
});
}

// If the report supports adding transactions to it, then it also supports deleting transactions from it.
if (canDeleteRequest && !isEmptyObject(transactionThreadReport)) {
threeDotsMenuItems.push({
icon: Expensicons.Trashcan,
text: translate('reportActionContextMenu.deleteAction', {action: requestParentReportAction}),
onSelected: () => setIsDeleteRequestModalVisible(true),
});
}

useEffect(() => {
if (canDeleteRequest) {
return;
}

setIsDeleteRequestModalVisible(false);
}, [canDeleteRequest]);

return (
<View style={[styles.pt0]}>
<HeaderWithBackButton
Expand Down Expand Up @@ -231,6 +287,16 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
cancelText={translate('common.dismiss')}
danger
/>
<ConfirmModal
title={translate('iou.deleteRequest')}
isVisible={isDeleteRequestModalVisible}
onConfirm={deleteTransaction}
onCancel={() => setIsDeleteRequestModalVisible(false)}
prompt={translate('iou.deleteConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
/>
</View>
);
}
Expand All @@ -244,6 +310,9 @@ export default withOnyx<MoneyReportHeaderProps, MoneyReportHeaderOnyxProps>({
nextStep: {
key: ({report}) => `${ONYXKEYS.COLLECTION.NEXT_STEP}${report.reportID}`,
},
transactionThreadReport: {
key: ({transactionThreadReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`,
},
session: {
key: ONYXKEYS.SESSION,
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ const MoneyRequestHeaderWithTransaction = withOnyx<MoneyRequestHeaderProps, Pick
transaction: {
key: ({report, parentReportActions}) => {
const parentReportAction = (report.parentReportActionID && parentReportActions ? parentReportActions[report.parentReportActionID] : {}) as ReportAction & OriginalMessageIOU;
return `${ONYXKEYS.COLLECTION.TRANSACTION}${parentReportAction.originalMessage.IOUTransactionID ?? 0}`;
return `${ONYXKEYS.COLLECTION.TRANSACTION}${parentReportAction?.originalMessage?.IOUTransactionID ?? 0}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting this is to avoid undefined crash

},
},
shownHoldUseExplanation: {
Expand Down
5 changes: 4 additions & 1 deletion src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,14 @@ function ReportScreen({
);
}

const transactionThreadReportID = useMemo(() => ReportActionsUtils.getOneTransactionThreadReportID(reportActions ?? []), [reportActions]);
if (ReportUtils.isMoneyRequestReport(report)) {
headerView = (
<MoneyReportHeader
report={report}
policy={policy}
transactionThreadReportID={transactionThreadReportID}
reportActions={reportActions}
/>
);
}
Expand Down Expand Up @@ -659,7 +662,7 @@ function ReportScreen({
isLoadingNewerReportActions={reportMetadata?.isLoadingNewerReportActions}
isLoadingOlderReportActions={reportMetadata?.isLoadingOlderReportActions}
isReadyForCommentLinking={!shouldShowSkeleton}
transactionThreadReportID={ReportActionsUtils.getOneTransactionThreadReportID(reportActions ?? [])}
transactionThreadReportID={transactionThreadReportID}
/>
)}

Expand Down
Loading