Skip to content

Commit

Permalink
Merge pull request #27224 from Expensify/cmartins-attachReceipt
Browse files Browse the repository at this point in the history
Attach receipt
  • Loading branch information
luacmartins authored Sep 25, 2023
2 parents 5099522 + 32221ae commit e87927e
Show file tree
Hide file tree
Showing 12 changed files with 59 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export default {
MONEY_REQUEST_TAG: { route: ':iouType/new/tag/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/tag/${reportID}`},
MONEY_REQUEST_MERCHANT: { route: ':iouType/new/merchant/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/merchant/${reportID}`},
MONEY_REQUEST_WAYPOINT: { route: ':iouType/new/waypoint/:waypointIndex', getRoute: (iouType: string, waypointIndex: number) => `${iouType}/new/waypoint/${waypointIndex}`},
MONEY_REQUEST_RECEIPT: { route: ':iouType/new/receipt/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/receipt/${reportID}`},
MONEY_REQUEST_ADDRESS: { route: ':iouType/new/address/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/address/${reportID}`},
MONEY_REQUEST_DISTANCE_TAB: { route: ':iouType/new/:reportID?/distance', getRoute: (iouType: string, reportID = '') => `${iouType}/new/${reportID}/distance`},
MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual',
Expand Down
10 changes: 10 additions & 0 deletions src/components/MoneyRequestHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import participantPropTypes from './participantPropTypes';
import styles from '../styles/styles';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
import CONST from '../CONST';
import ONYXKEYS from '../ONYXKEYS';
import * as IOU from '../libs/actions/IOU';
import ConfirmModal from './ConfirmModal';
Expand Down Expand Up @@ -85,6 +86,15 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
shouldShowPinButton={false}
shouldShowThreeDotsButton={isActionOwner && !isSettled}
threeDotsMenuItems={[
...(TransactionUtils.hasReceipt(transaction)
? []
: [
{
icon: Expensicons.Receipt,
text: translate('receipt.addReceipt'),
onSelected: () => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.RECEIPT)),
},
]),
{
icon: Expensicons.Trashcan,
text: translate('reportActionContextMenu.deleteAction', {action: parentReportAction}),
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ export default {
flash: 'flash',
shutter: 'shutter',
gallery: 'gallery',
addReceipt: 'Add receipt',
},
iou: {
amount: 'Amount',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ export default {
flash: 'flash',
shutter: 'obturador',
gallery: 'galería',
addReceipt: 'Añadir recibo',
},
iou: {
amount: 'Importe',
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator({
IOU_Send_Add_Debit_Card: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default,
IOU_Send_Enable_Payments: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default,
Money_Request_Waypoint: () => require('../../../pages/iou/WaypointEditorPage').default,
Money_Request_Receipt: () => require('../../../pages/EditRequestReceiptPage').default,
Money_Request_Address: () => require('../../../pages/iou/DistanceRequestPage').default,
});

Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ export default {
Money_Request_Tag: ROUTES.MONEY_REQUEST_TAG.route,
Money_Request_Merchant: ROUTES.MONEY_REQUEST_MERCHANT.route,
Money_Request_Waypoint: ROUTES.MONEY_REQUEST_WAYPOINT.route,
Money_Request_Receipt: ROUTES.MONEY_REQUEST_RECEIPT.route,
Money_Request_Address: ROUTES.MONEY_REQUEST_ADDRESS.route,
IOU_Send_Enable_Payments: ROUTES.IOU_SEND_ENABLE_PAYMENTS,
IOU_Send_Add_Bank_Account: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT,
Expand Down
5 changes: 3 additions & 2 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2229,7 +2229,7 @@ function buildOptimisticIOUReportAction(
created: DateUtils.getDBTime(),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
receipt,
whisperedToAccountIDs: !_.isEmpty(receipt) ? [currentUserAccountID] : [],
whisperedToAccountIDs: _.contains([CONST.IOU.RECEIPT_STATE.SCANREADY, CONST.IOU.RECEIPT_STATE.SCANNING], receipt.state) ? [currentUserAccountID] : [],
};
}
/**
Expand Down Expand Up @@ -2282,6 +2282,7 @@ function buildOptimisticApprovedReportAction(amount, currency, expenseReportID)
*/
function buildOptimisticReportPreview(chatReport, iouReport, comment = '', transaction = undefined) {
const hasReceipt = TransactionUtils.hasReceipt(transaction);
const isReceiptBeingScanned = hasReceipt && TransactionUtils.isReceiptBeingScanned(transaction);
const message = getReportPreviewMessage(iouReport);
return {
reportActionID: NumberUtils.rand64(),
Expand All @@ -2306,7 +2307,7 @@ function buildOptimisticReportPreview(chatReport, iouReport, comment = '', trans
childMoneyRequestCount: 1,
childLastMoneyRequestComment: comment,
childLastReceiptTransactionIDs: hasReceipt ? transaction.transactionID : '',
whisperedToAccountIDs: hasReceipt ? [currentUserAccountID] : [],
whisperedToAccountIDs: isReceiptBeingScanned ? [currentUserAccountID] : [],
};
}

Expand Down
10 changes: 9 additions & 1 deletion src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ function requestMoney(
createdIOUReportActionID,
reportPreviewReportActionID: reportPreviewAction.reportActionID,
receipt,
receiptState: lodashGet(receipt, 'state'),
category,
tag,
billable,
Expand Down Expand Up @@ -2086,8 +2087,9 @@ function createEmptyTransaction() {
* @param {String} iouType
* @param {String} reportID
* @param {Object} report
* @param {String} path
*/
function navigateToNextPage(iou, iouType, reportID, report) {
function navigateToNextPage(iou, iouType, reportID, report, path = '') {
const moneyRequestID = `${iouType}${reportID}`;
const shouldReset = iou.id !== moneyRequestID;

Expand All @@ -2097,6 +2099,12 @@ function navigateToNextPage(iou, iouType, reportID, report) {
resetMoneyRequestInfo(moneyRequestID);
}

// If we're adding a receipt, that means the user came from the confirmation page and we need to navigate back to it.
if (path.slice(1) === ROUTES.MONEY_REQUEST_RECEIPT.getRoute(iouType, reportID)) {
Navigation.navigate(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, reportID));
return;
}

// If a request is initiated on a report, skip the participants selection step and navigate to the confirmation page.
if (report.reportID) {
// If the report is iou or expense report, we should get the chat report to set participant for request money
Expand Down
7 changes: 6 additions & 1 deletion src/pages/EditRequestReceiptPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ const propTypes = {
}).isRequired,

/** The id of the transaction we're editing */
transactionID: PropTypes.string.isRequired,
transactionID: PropTypes.string,
};

const defaultProps = {
transactionID: '',
};

function EditRequestReceiptPage({route, transactionID}) {
Expand Down Expand Up @@ -49,6 +53,7 @@ function EditRequestReceiptPage({route, transactionID}) {
}

EditRequestReceiptPage.propTypes = propTypes;
EditRequestReceiptPage.defaultProps = defaultProps;
EditRequestReceiptPage.displayName = 'EditRequestReceiptPage';

export default EditRequestReceiptPage;
5 changes: 4 additions & 1 deletion src/pages/iou/ReceiptSelector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ const propTypes = {
/** The report ID of the IOU */
reportID: PropTypes.string,
}),

/** The current route path */
path: PropTypes.string,
}).isRequired,

/** Holds data related to Money Request view state, rather than the underlying Money Request data. */
Expand Down Expand Up @@ -124,7 +127,7 @@ function ReceiptSelector(props) {
return;
}

IOU.navigateToNextPage(iou, iouType, reportID, report);
IOU.navigateToNextPage(iou, iouType, reportID, report, props.route.path);
};

return (
Expand Down
9 changes: 6 additions & 3 deletions src/pages/iou/ReceiptSelector/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const propTypes = {
/** The report ID of the IOU */
reportID: PropTypes.string,
}),

/** The current route path */
path: PropTypes.string,
}).isRequired,

/** The report on which the request is initiated on */
Expand Down Expand Up @@ -220,13 +223,13 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
return;
}

IOU.navigateToNextPage(iou, iouType, reportID, report);
IOU.navigateToNextPage(iou, iouType, reportID, report, route.path);
})
.catch((error) => {
showCameraAlert();
Log.warn('Error taking photo', error);
});
}, [flash, iouType, iou, report, reportID, translate, transactionID]);
}, [flash, iouType, iou, report, reportID, translate, transactionID, route.path]);

CameraPermission.getCameraPermissionStatus().then((permissionStatus) => {
setPermissions(permissionStatus);
Expand Down Expand Up @@ -295,7 +298,7 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
return;
}

IOU.navigateToNextPage(iou, iouType, reportID, report);
IOU.navigateToNextPage(iou, iouType, reportID, report, route.path);
})
.catch(() => {
Log.info('User did not select an image from gallery');
Expand Down
18 changes: 16 additions & 2 deletions src/pages/iou/steps/MoneyRequestConfirmPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import useNetwork from '../../../hooks/useNetwork';
import useWindowDimensions from '../../../hooks/useWindowDimensions';
import * as StyleUtils from '../../../styles/StyleUtils';
import {iouPropTypes, iouDefaultProps} from '../propTypes';
import * as Expensicons from '../../../components/Icon/Expensicons';

const propTypes = {
/** React Navigation route */
Expand Down Expand Up @@ -61,7 +62,7 @@ const defaultProps = {

function MoneyRequestConfirmPage(props) {
const {isOffline} = useNetwork();
const {windowHeight} = useWindowDimensions();
const {windowHeight, windowWidth} = useWindowDimensions();
const prevMoneyRequestId = useRef(props.iou.id);
const iouType = useRef(lodashGet(props.route, 'params.iouType', ''));
const isDistanceRequest = MoneyRequestUtils.isDistanceRequest(iouType.current, props.selectedTab);
Expand All @@ -74,6 +75,7 @@ function MoneyRequestConfirmPage(props) {
}),
[props.iou.participants, props.personalDetails],
);
const isManualRequestDM = props.selectedTab === CONST.TAB.MANUAL && iouType.current === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST;

useEffect(() => {
const policyExpenseChat = _.find(participants, (participant) => participant.isPolicyExpenseChat);
Expand Down Expand Up @@ -214,7 +216,9 @@ function MoneyRequestConfirmPage(props) {
}

if (props.iou.receiptPath && props.iou.receiptSource) {
FileUtils.readFileAsync(props.iou.receiptPath, props.iou.receiptSource).then((receipt) => {
FileUtils.readFileAsync(props.iou.receiptPath, props.iou.receiptSource).then((file) => {
const receipt = file;
receipt.state = file && isManualRequestDM ? CONST.IOU.RECEIPT_STATE.OPEN : CONST.IOU.RECEIPT_STATE.SCANREADY;
requestMoney(selectedParticipants, trimmedComment, receipt);
});
return;
Expand All @@ -238,6 +242,7 @@ function MoneyRequestConfirmPage(props) {
isDistanceRequest,
requestMoney,
createDistanceRequest,
isManualRequestDM,
],
);

Expand Down Expand Up @@ -286,6 +291,15 @@ function MoneyRequestConfirmPage(props) {
<HeaderWithBackButton
title={headerTitle()}
onBackButtonPress={navigateBack}
shouldShowThreeDotsButton={isManualRequestDM}
threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)}
threeDotsMenuItems={[
{
icon: Expensicons.Receipt,
text: props.translate('receipt.addReceipt'),
onSelected: () => Navigation.navigate(ROUTES.MONEY_REQUEST_RECEIPT.getRoute(iouType.current, reportID.current)),
},
]}
/>
{/*
* The MoneyRequestConfirmationList component uses a SectionList which uses a VirtualizedList internally.
Expand Down

0 comments on commit e87927e

Please sign in to comment.