Skip to content

Commit

Permalink
Merge pull request #26219 from Expensify/beaman-addContextMenuForRece…
Browse files Browse the repository at this point in the history
…ipts

Allow detaching receipts from transactions
  • Loading branch information
luacmartins authored Oct 11, 2023
2 parents df6acf9 + b976628 commit c952f9c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 13 deletions.
75 changes: 62 additions & 13 deletions src/components/AttachmentModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ import useWindowDimensions from '../hooks/useWindowDimensions';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
import useNativeDriver from '../libs/useNativeDriver';
import * as ReportUtils from '../libs/ReportUtils';
import * as ReportActionsUtils from '../libs/ReportActionsUtils';
import * as ReportUtils from '../libs/ReportUtils';
import ONYXKEYS from '../ONYXKEYS';
import * as Policy from '../libs/actions/Policy';
import useNetwork from '../hooks/useNetwork';
import * as IOU from '../libs/actions/IOU';
import transactionPropTypes from './transactionPropTypes';
import * as TransactionUtils from '../libs/TransactionUtils';

/**
* Modal render prop component that exposes modal launching triggers that can be used
Expand Down Expand Up @@ -79,6 +82,9 @@ const propTypes = {
/** The report that has this attachment */
report: reportPropTypes,

/** The transaction associated with the receipt attachment, if any */
transaction: transactionPropTypes,

...withLocalizePropTypes,

...windowDimensionsPropTypes,
Expand All @@ -97,6 +103,7 @@ const defaultProps = {
allowDownload: false,
headerTitle: null,
report: {},
transaction: {},
onModalShow: () => {},
onModalHide: () => {},
onCarouselAttachmentChange: () => {},
Expand All @@ -108,6 +115,7 @@ function AttachmentModal(props) {
const [isModalOpen, setIsModalOpen] = useState(props.defaultOpen);
const [shouldLoadAttachment, setShouldLoadAttachment] = useState(false);
const [isAttachmentInvalid, setIsAttachmentInvalid] = useState(false);
const [isDeleteReceiptConfirmModalVisible, setIsDeleteReceiptConfirmModalVisible] = useState(false);
const [isAuthTokenRequired, setIsAuthTokenRequired] = useState(props.isAuthTokenRequired);
const [isAttachmentReceipt, setIsAttachmentReceipt] = useState(false);
const [attachmentInvalidReasonTitle, setAttachmentInvalidReasonTitle] = useState('');
Expand Down Expand Up @@ -205,12 +213,22 @@ function AttachmentModal(props) {
}, [isModalOpen, isConfirmButtonDisabled, props.onConfirm, file, source]);

/**
* Close the confirm modal.
* Close the confirm modals.
*/
const closeConfirmModal = useCallback(() => {
setIsAttachmentInvalid(false);
setIsDeleteReceiptConfirmModalVisible(false);
}, []);

/**
* Detach the receipt and close the modal.
*/
const deleteAndCloseModal = useCallback(() => {
IOU.detachReceipt(props.transaction.transactionID, props.report.reportID);
setIsDeleteReceiptConfirmModalVisible(false);
Navigation.dismissModal(props.report.reportID);
}, [props.transaction, props.report]);

/**
* @param {Object} _file
* @returns {Boolean}
Expand Down Expand Up @@ -358,9 +376,18 @@ function AttachmentModal(props) {
text: props.translate('common.download'),
onSelected: () => downloadAttachment(source),
});
if (TransactionUtils.hasReceipt(props.transaction) && !TransactionUtils.isReceiptBeingScanned(props.transaction)) {
menuItems.push({
icon: Expensicons.Trashcan,
text: props.translate('receipt.deleteReceipt'),
onSelected: () => {
setIsDeleteReceiptConfirmModalVisible(true);
},
});
}
return menuItems;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isAttachmentReceipt, props.parentReport, props.parentReportActions, props.policy]);
}, [isAttachmentReceipt, props.parentReport, props.parentReportActions, props.policy, props.transaction]);

return (
<>
Expand Down Expand Up @@ -442,18 +469,30 @@ function AttachmentModal(props) {
)}
</SafeAreaConsumer>
)}
{isAttachmentReceipt ? (
<ConfirmModal
title={translate('receipt.deleteReceipt')}
isVisible={isDeleteReceiptConfirmModalVisible}
onConfirm={deleteAndCloseModal}
onCancel={closeConfirmModal}
prompt={translate('receipt.deleteConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
/>
) : (
<ConfirmModal
title={attachmentInvalidReasonTitle ? translate(attachmentInvalidReasonTitle) : ''}
onConfirm={closeConfirmModal}
onCancel={closeConfirmModal}
isVisible={isAttachmentInvalid}
prompt={attachmentInvalidReason ? translate(attachmentInvalidReason) : ''}
confirmText={translate('common.close')}
shouldShowCancelButton={false}
/>
)}
</Modal>

<ConfirmModal
title={attachmentInvalidReasonTitle ? translate(attachmentInvalidReasonTitle) : ''}
onConfirm={closeConfirmModal}
onCancel={closeConfirmModal}
isVisible={isAttachmentInvalid}
prompt={attachmentInvalidReason ? translate(attachmentInvalidReason) : ''}
confirmText={translate('common.close')}
shouldShowCancelButton={false}
/>

{props.children &&
props.children({
displayFileInModal: validateAndDisplayFileToUpload,
Expand All @@ -470,6 +509,16 @@ export default compose(
withWindowDimensions,
withLocalize,
withOnyx({
transaction: {
key: ({report}) => {
if (!report) {
return undefined;
}
const parentReportAction = ReportActionsUtils.getReportAction(report.parentReportID, report.parentReportActionID);
const transactionID = lodashGet(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0);
return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`;
},
},
parentReport: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report ? report.parentReportID : '0'}`,
},
Expand Down
2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ export default {
flash: 'flash',
shutter: 'shutter',
gallery: 'gallery',
deleteReceipt: 'Delete receipt',
deleteConfirmation: 'Are you sure you want to delete this receipt?',
addReceipt: 'Add receipt',
},
iou: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,8 @@ export default {
flash: 'flash',
shutter: 'obturador',
gallery: 'galería',
deleteReceipt: 'Eliminar recibo',
deleteConfirmation: '¿Estás seguro de que quieres borrar este recibo?',
addReceipt: 'Añadir recibo',
},
iou: {
Expand Down
24 changes: 24 additions & 0 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -2431,6 +2431,29 @@ function payMoneyRequest(paymentType, chatReport, iouReport) {
Navigation.dismissModal(chatReport.reportID);
}

function detachReceipt(transactionID) {
const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] || {};
const newTransaction = {...transaction, filename: '', receipt: {}};

const optimisticData = [
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: newTransaction,
},
];

const failureData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: transaction,
},
];

API.write('DetachReceipt', {transactionID}, {optimisticData, failureData});
}

/**
* @param {String} transactionID
* @param {Object} receipt
Expand Down Expand Up @@ -2663,5 +2686,6 @@ export {
navigateToNextPage,
updateDistanceRequest,
replaceReceipt,
detachReceipt,
getIOUReportID,
};

0 comments on commit c952f9c

Please sign in to comment.