From fabe55fdbbec43e1b8a872d538afb42949277c3b Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 11 Sep 2023 15:48:37 -0700 Subject: [PATCH 01/52] WIP render an eReceipt for distance requests --- .../Attachments/AttachmentView/index.js | 20 +++++++ src/components/EReceipt.js | 54 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/components/EReceipt.js diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 47353d915060..584827f499c6 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -17,6 +17,11 @@ import AttachmentViewPdf from './AttachmentViewPdf'; import addEncryptedAuthTokenToURL from '../../../libs/addEncryptedAuthTokenToURL'; import * as StyleUtils from '../../../styles/StyleUtils'; import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes'; +import {useRoute} from '@react-navigation/native'; +import * as ReportUtils from '../../../libs/ReportUtils'; +import * as TransactionUtils from '../../../libs/TransactionUtils'; +import EReceipt from '../../EReceipt'; +import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; const propTypes = { ...attachmentViewPropTypes, @@ -107,6 +112,21 @@ function AttachmentView({ ); } + const currentRoute = useRoute(); + const reportID = _.get(currentRoute, ['params', 'reportID']); + const report = ReportUtils.getReport(reportID); + + // Get the money request transaction + const parentReportAction = ReportActionsUtils.getParentReportAction(report); + const transactionID = _.get(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0); + const transaction = TransactionUtils.getTransaction(transactionID); + console.log('transaction', transaction); + + const shouldShowEReceipt = TransactionUtils.isDistanceRequest(transaction); + if (shouldShowEReceipt) { + return + } + // For this check we use both source and file.name since temporary file source is a blob // both PDFs and images will appear as images when pasted into the the text field const isImage = Str.isImage(source); diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js new file mode 100644 index 000000000000..406825926820 --- /dev/null +++ b/src/components/EReceipt.js @@ -0,0 +1,54 @@ +import React, {useEffect} from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; + +import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; +import _ from 'underscore'; +import ONYXKEYS from '../ONYXKEYS'; +import CONST from '../CONST'; +import * as MapboxToken from '../libs/actions/MapboxToken'; +import * as TransactionUtils from '../libs/TransactionUtils'; +import * as Expensicons from './Icon/Expensicons'; +import theme from '../styles/themes/default'; +import styles from '../styles/styles'; +import transactionPropTypes from './transactionPropTypes'; +import BlockingView from './BlockingViews/BlockingView'; +import useNetwork from '../hooks/useNetwork'; +import useLocalize from '../hooks/useLocalize'; + +const propTypes = { + /** The transaction for the eReceipt */ + transaction: transactionPropTypes, +}; + +const defaultProps = { + transaction: {}, +}; + + +function EReceipt({transaction}) { + const {isOffline} = useNetwork(); + const {translate} = useLocalize(); + const {route0: route} = transaction.routes || {}; + + useEffect(() => { + MapboxToken.init(); + return MapboxToken.stop; + }, []); + + return ( + <> + + ); +} + +export default withOnyx({ + transaction: { + key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + }, +})(EReceipt); + +EReceipt.displayName = 'EReceipt'; +EReceipt.propTypes = propTypes; +EReceipt.defaultProps = defaultProps; From a6b83fedb4f1f1380cb433ee216da7169453a470 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 11 Sep 2023 16:26:00 -0700 Subject: [PATCH 02/52] Render the receipt image --- src/components/EReceipt.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 406825926820..20d4c3789838 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -16,6 +16,8 @@ import transactionPropTypes from './transactionPropTypes'; import BlockingView from './BlockingViews/BlockingView'; import useNetwork from '../hooks/useNetwork'; import useLocalize from '../hooks/useLocalize'; +import * as ReceiptUtils from '../libs/ReceiptUtils'; +import Image from './Image'; const propTypes = { /** The transaction for the eReceipt */ @@ -32,13 +34,19 @@ function EReceipt({transaction}) { const {translate} = useLocalize(); const {route0: route} = transaction.routes || {}; - useEffect(() => { - MapboxToken.init(); - return MapboxToken.stop; - }, []); - + const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); return ( <> + + + ); } From 9d7538c13ae968c886d6b266f91974a88fc7ef7f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 11 Sep 2023 16:33:08 -0700 Subject: [PATCH 03/52] Style and clean up --- .../Attachments/AttachmentView/index.js | 2 +- src/components/EReceipt.js | 31 ++----------------- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 584827f499c6..e7d1dd5abb6b 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -124,7 +124,7 @@ function AttachmentView({ const shouldShowEReceipt = TransactionUtils.isDistanceRequest(transaction); if (shouldShowEReceipt) { - return + return ; } // For this check we use both source and file.name since temporary file source is a blob diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 20d4c3789838..2068a5e50f12 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -1,21 +1,8 @@ -import React, {useEffect} from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; import {View} from 'react-native'; - -import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import _ from 'underscore'; -import ONYXKEYS from '../ONYXKEYS'; -import CONST from '../CONST'; -import * as MapboxToken from '../libs/actions/MapboxToken'; -import * as TransactionUtils from '../libs/TransactionUtils'; -import * as Expensicons from './Icon/Expensicons'; -import theme from '../styles/themes/default'; import styles from '../styles/styles'; import transactionPropTypes from './transactionPropTypes'; -import BlockingView from './BlockingViews/BlockingView'; -import useNetwork from '../hooks/useNetwork'; -import useLocalize from '../hooks/useLocalize'; import * as ReceiptUtils from '../libs/ReceiptUtils'; import Image from './Image'; @@ -28,18 +15,11 @@ const defaultProps = { transaction: {}, }; - function EReceipt({transaction}) { - const {isOffline} = useNetwork(); - const {translate} = useLocalize(); - const {route0: route} = transaction.routes || {}; - const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); return ( <> - + `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - }, -})(EReceipt); - +export default EReceipt; EReceipt.displayName = 'EReceipt'; EReceipt.propTypes = propTypes; EReceipt.defaultProps = defaultProps; From 71689bd7edd91cd94c4d871f7d5546d2c2bfb3b1 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:10:42 +0800 Subject: [PATCH 04/52] Add amount and thumbnail image --- src/components/EReceipt.js | 19 +++++++++++++------ src/styles/styles.js | 7 +++++++ src/styles/themes/default.js | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 2068a5e50f12..1d4057c6e437 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -1,10 +1,13 @@ import React from 'react'; import {View} from 'react-native'; -import _ from 'underscore'; +import Text from './Text'; import styles from '../styles/styles'; import transactionPropTypes from './transactionPropTypes'; import * as ReceiptUtils from '../libs/ReceiptUtils'; -import Image from './Image'; +import * as ReportUtils from '../libs/ReportUtils'; +import * as CurrencyUtils from '../libs/CurrencyUtils'; +import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot'; +import ThumbnailImage from './ThumbnailImage'; const propTypes = { /** The transaction for the eReceipt */ @@ -17,16 +20,20 @@ const defaultProps = { function EReceipt({transaction}) { const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); + const {amount: transactionAmount, currency: transactionCurrency} = ReportUtils.getTransactionDetails(transaction); + const formattedTransactionAmount = CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); + const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); return ( <> - - + + {formattedTransactionAmount} ); } diff --git a/src/styles/styles.js b/src/styles/styles.js index 4a2472913fd2..58a6ada7de0c 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3553,6 +3553,13 @@ const styles = (theme) => ({ lineHeight: variables.lineHeightXXLarge, }, + eReceiptAmount: { + ...headlineFont, + fontSize: variables.fontSizeXXXLarge, + lineHeight: variables.lineHeightXXXLarge, + color: theme.eReceiptAmount, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index 5ff997684304..75d3ded6b545 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -83,6 +83,7 @@ const darkTheme = { QRLogo: colors.green400, starDefaultBG: 'rgb(254, 228, 94)', loungeAccessOverlay: colors.blue800, + eReceiptAmount: colors.green400, }; darkTheme.PAGE_BACKGROUND_COLORS = { From 8095338a5e17b95d7aaea97d38b5831ffe29d0e2 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:29:28 +0800 Subject: [PATCH 05/52] Add merchant --- src/components/EReceipt.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 1d4057c6e437..bca23ae83e24 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -20,7 +20,7 @@ const defaultProps = { function EReceipt({transaction}) { const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); - const {amount: transactionAmount, currency: transactionCurrency} = ReportUtils.getTransactionDetails(transaction); + const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant} = ReportUtils.getTransactionDetails(transaction); const formattedTransactionAmount = CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); return ( @@ -34,6 +34,7 @@ function EReceipt({transaction}) { /> {formattedTransactionAmount} + {transactionMerchant} ); } From d9ddb6f3def934ab57c0a2803855212f8b9acedf Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:40:40 +0800 Subject: [PATCH 06/52] Display waypoints --- src/components/EReceipt.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index bca23ae83e24..58d49f5a54be 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -1,13 +1,17 @@ import React from 'react'; import {View} from 'react-native'; +import lodashGet from 'lodash/get'; +import _ from 'underscore'; import Text from './Text'; import styles from '../styles/styles'; import transactionPropTypes from './transactionPropTypes'; import * as ReceiptUtils from '../libs/ReceiptUtils'; import * as ReportUtils from '../libs/ReportUtils'; import * as CurrencyUtils from '../libs/CurrencyUtils'; +import * as TransactionUtils from '../libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot'; import ThumbnailImage from './ThumbnailImage'; +import useLocalize from '../hooks/useLocalize'; const propTypes = { /** The transaction for the eReceipt */ @@ -19,10 +23,12 @@ const defaultProps = { }; function EReceipt({transaction}) { + const {translate} = useLocalize(); const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant} = ReportUtils.getTransactionDetails(transaction); const formattedTransactionAmount = CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); + const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( <> @@ -35,6 +41,25 @@ function EReceipt({transaction}) { {formattedTransactionAmount} {transactionMerchant} + <> + {_.map(waypoints, (waypoint, key) => { + const index = TransactionUtils.getWaypointIndex(key); + let descriptionKey = 'distance.waypointDescription.'; + if (index === 0) { + descriptionKey += 'start'; + } else if (index === _.size(waypoints) - 1) { + descriptionKey += 'finish'; + } else { + descriptionKey += 'stop'; + } + return ( + + {translate(descriptionKey)} + {waypoint.address || ''} + + ); + })} + ); } From 71ff545f73fac187bf1db127243daf1a2c53794f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:50:53 +0800 Subject: [PATCH 07/52] Remove unused import --- src/styles/themes/default.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index 75d3ded6b545..561a1bafb532 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -1,7 +1,6 @@ /* eslint-disable no-unused-vars */ import colors from '../colors'; import SCREENS from '../../SCREENS'; -import ROUTES from '../../ROUTES'; const darkTheme = { // Figma keys From 215c03eda0b4bbe33f0b9e8c891418342936da4c Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:51:13 +0800 Subject: [PATCH 08/52] Style e receipt merchant text --- src/components/EReceipt.js | 2 +- src/styles/styles.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 58d49f5a54be..3094ef59bf9c 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -40,7 +40,7 @@ function EReceipt({transaction}) { /> {formattedTransactionAmount} - {transactionMerchant} + {transactionMerchant} <> {_.map(waypoints, (waypoint, key) => { const index = TransactionUtils.getWaypointIndex(key); diff --git a/src/styles/styles.js b/src/styles/styles.js index 58a6ada7de0c..0b7aff4037fe 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3560,6 +3560,13 @@ const styles = (theme) => ({ color: theme.eReceiptAmount, }, + eReceiptMerchant: { + fontFamily: fontFamily.EXP_NEUE, + fontSize: variables.fontSizeXLarge, + lineHeight: variables.lineHeightXLarge, + color: theme.text, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, From 90ad2292efab5db14689ba5f0aa11fe6964b381b Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 15:57:30 +0800 Subject: [PATCH 09/52] Style eReceipt waypoint titles --- src/components/EReceipt.js | 2 +- src/styles/styles.js | 9 ++++++++- src/styles/themes/default.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 3094ef59bf9c..ba9dd13ae276 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -54,7 +54,7 @@ function EReceipt({transaction}) { } return ( - {translate(descriptionKey)} + {translate(descriptionKey)} {waypoint.address || ''} ); diff --git a/src/styles/styles.js b/src/styles/styles.js index 0b7aff4037fe..d17547341df0 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3557,7 +3557,7 @@ const styles = (theme) => ({ ...headlineFont, fontSize: variables.fontSizeXXXLarge, lineHeight: variables.lineHeightXXXLarge, - color: theme.eReceiptAmount, + color: theme.textBrand, }, eReceiptMerchant: { @@ -3567,6 +3567,13 @@ const styles = (theme) => ({ color: theme.text, }, + eReceiptWaypointTitle: { + fontFamily: fontFamily.EXP_NEUE, + fontSize: variables.fontSizeSmall, + lineHeight: variables.lineHeightSmall, + color: theme.textBrand, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index 561a1bafb532..eac8b087ead0 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -82,7 +82,7 @@ const darkTheme = { QRLogo: colors.green400, starDefaultBG: 'rgb(254, 228, 94)', loungeAccessOverlay: colors.blue800, - eReceiptAmount: colors.green400, + textBrand: colors.green400, }; darkTheme.PAGE_BACKGROUND_COLORS = { From c1aa7b37a9a84eeb6fffbab0bb5a72e09d8f1ef0 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 16:05:51 +0800 Subject: [PATCH 10/52] Style eReceipt waypoint address --- src/components/EReceipt.js | 2 +- src/styles/styles.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index ba9dd13ae276..bd26b0a5b4b0 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -55,7 +55,7 @@ function EReceipt({transaction}) { return ( {translate(descriptionKey)} - {waypoint.address || ''} + {waypoint.address || ''} ); })} diff --git a/src/styles/styles.js b/src/styles/styles.js index d17547341df0..c15b0f8b9dcf 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3574,6 +3574,13 @@ const styles = (theme) => ({ color: theme.textBrand, }, + eReceiptWaypointAddress: { + fontFamily: fontFamily.MONOSPACE, + fontSize: variables.fontSizeNormal, + lineHeight: variables.lineHeightNormal, + color: theme.textColorfulBackground, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, From 5bb7b9eb6661903993300ded689d3f19c4e06ef2 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 16:10:18 +0800 Subject: [PATCH 11/52] Add date text --- src/components/EReceipt.js | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index bd26b0a5b4b0..b84be5dc8be7 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -25,7 +25,7 @@ const defaultProps = { function EReceipt({transaction}) { const {translate} = useLocalize(); const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); - const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant} = ReportUtils.getTransactionDetails(transaction); + const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction); const formattedTransactionAmount = CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); @@ -41,25 +41,25 @@ function EReceipt({transaction}) { {formattedTransactionAmount} {transactionMerchant} - <> - {_.map(waypoints, (waypoint, key) => { - const index = TransactionUtils.getWaypointIndex(key); - let descriptionKey = 'distance.waypointDescription.'; - if (index === 0) { - descriptionKey += 'start'; - } else if (index === _.size(waypoints) - 1) { - descriptionKey += 'finish'; - } else { - descriptionKey += 'stop'; - } - return ( - - {translate(descriptionKey)} - {waypoint.address || ''} - - ); - })} - + {_.map(waypoints, (waypoint, key) => { + const index = TransactionUtils.getWaypointIndex(key); + let descriptionKey = 'distance.waypointDescription.'; + if (index === 0) { + descriptionKey += 'start'; + } else if (index === _.size(waypoints) - 1) { + descriptionKey += 'finish'; + } else { + descriptionKey += 'stop'; + } + return ( + + {translate(descriptionKey)} + {waypoint.address || ''} + + ); + })} + {translate('common.date')} + {transactionDate} ); } From dd0fe7ebe01a713d0ba42004d9fc07c9f249160b Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 21 Sep 2023 16:18:38 +0800 Subject: [PATCH 12/52] WIP add logo --- src/components/EReceipt.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index b84be5dc8be7..cd5959b1a41d 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -12,6 +12,7 @@ import * as TransactionUtils from '../libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot'; import ThumbnailImage from './ThumbnailImage'; import useLocalize from '../hooks/useLocalize'; +import fontFamily from '../styles/fontFamily'; const propTypes = { /** The transaction for the eReceipt */ @@ -60,6 +61,14 @@ function EReceipt({transaction}) { })} {translate('common.date')} {transactionDate} + + + ); } From f69bf9936eb47e7bb9d2a671b06020ab5fc91efa Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 08:37:03 +0800 Subject: [PATCH 13/52] Add logo and guaranteed eReceipt --- src/components/EReceipt.js | 7 +++++-- src/languages/en.ts | 3 +++ src/styles/styles.js | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index cd5959b1a41d..1f24144031d4 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -12,7 +12,9 @@ import * as TransactionUtils from '../libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '../libs/tryResolveUrlFromApiRoot'; import ThumbnailImage from './ThumbnailImage'; import useLocalize from '../hooks/useLocalize'; -import fontFamily from '../styles/fontFamily'; +import Icon from './Icon'; +import themeColors from '../styles/themes/default'; +import * as Expensicons from './Icon/Expensicons'; const propTypes = { /** The transaction for the eReceipt */ @@ -65,9 +67,10 @@ function EReceipt({transaction}) { + {translate('eReceipt.guaranteed')} ); diff --git a/src/languages/en.ts b/src/languages/en.ts index f7c028d2a106..495e7b0f7105 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1778,4 +1778,7 @@ export default { selectSuggestedAddress: 'Please select a suggested address', }, }, + eReceipt: { + guaranteed: 'Guaranteed eReceipt', + }, } satisfies TranslationBase; diff --git a/src/styles/styles.js b/src/styles/styles.js index c15b0f8b9dcf..de7cfec48ef7 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3581,6 +3581,13 @@ const styles = (theme) => ({ color: theme.textColorfulBackground, }, + eReceiptGuaranteed: { + fontFamily: fontFamily.MONOSPACE, + fontSize: variables.fontSizeSmall, + lineHeight: variables.lineHeightSmall, + color: theme.textColorfulBackground, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, From 3a67ed468d4721a7d819c92bb9c082683b416a83 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 08:57:16 +0800 Subject: [PATCH 14/52] Set up wrapping views with padding --- src/components/EReceipt.js | 80 +++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index 1f24144031d4..d89439e32326 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -33,46 +33,48 @@ function EReceipt({transaction}) { const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - <> - - + + + + + + {formattedTransactionAmount} + {transactionMerchant} + {_.map(waypoints, (waypoint, key) => { + const index = TransactionUtils.getWaypointIndex(key); + let descriptionKey = 'distance.waypointDescription.'; + if (index === 0) { + descriptionKey += 'start'; + } else if (index === _.size(waypoints) - 1) { + descriptionKey += 'finish'; + } else { + descriptionKey += 'stop'; + } + return ( + + {translate(descriptionKey)} + {waypoint.address || ''} + + ); + })} + {translate('common.date')} + {transactionDate} + + + {translate('eReceipt.guaranteed')} + - {formattedTransactionAmount} - {transactionMerchant} - {_.map(waypoints, (waypoint, key) => { - const index = TransactionUtils.getWaypointIndex(key); - let descriptionKey = 'distance.waypointDescription.'; - if (index === 0) { - descriptionKey += 'start'; - } else if (index === _.size(waypoints) - 1) { - descriptionKey += 'finish'; - } else { - descriptionKey += 'stop'; - } - return ( - - {translate(descriptionKey)} - {waypoint.address || ''} - - ); - })} - {translate('common.date')} - {transactionDate} - - - {translate('eReceipt.guaranteed')} - - + ); } From 74664ceab6450c5411d8bdab9cc533cf11d61dd4 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 10:12:10 +0800 Subject: [PATCH 15/52] Fix lint issues / clean up --- src/components/Attachments/AttachmentView/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index e7d1dd5abb6b..b0e22c237eaf 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -69,6 +69,7 @@ function AttachmentView({ isWorkspaceAvatar, }) { const [loadComplete, setLoadComplete] = useState(false); + const currentRoute = useRoute(); // Handles case where source is a component (ex: SVG) if (_.isFunction(source)) { @@ -112,7 +113,6 @@ function AttachmentView({ ); } - const currentRoute = useRoute(); const reportID = _.get(currentRoute, ['params', 'reportID']); const report = ReportUtils.getReport(reportID); @@ -120,8 +120,6 @@ function AttachmentView({ const parentReportAction = ReportActionsUtils.getParentReportAction(report); const transactionID = _.get(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0); const transaction = TransactionUtils.getTransaction(transactionID); - console.log('transaction', transaction); - const shouldShowEReceipt = TransactionUtils.isDistanceRequest(transaction); if (shouldShowEReceipt) { return ; From 6e1440edff178f5be01b29cef62756565971c6c6 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 10:12:35 +0800 Subject: [PATCH 16/52] Add the eReceipt background --- assets/images/eReceipt_background.svg | 1635 +++++++++++++++++++++++++ src/components/EReceipt.js | 25 +- src/styles/styles.js | 28 + src/styles/themes/default.js | 1 + src/styles/utilities/spacing.ts | 4 + 5 files changed, 1686 insertions(+), 7 deletions(-) create mode 100644 assets/images/eReceipt_background.svg diff --git a/assets/images/eReceipt_background.svg b/assets/images/eReceipt_background.svg new file mode 100644 index 000000000000..257489bd6fdd --- /dev/null +++ b/assets/images/eReceipt_background.svg @@ -0,0 +1,1635 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/EReceipt.js b/src/components/EReceipt.js index d89439e32326..5f5619cb22e4 100644 --- a/src/components/EReceipt.js +++ b/src/components/EReceipt.js @@ -15,6 +15,7 @@ import useLocalize from '../hooks/useLocalize'; import Icon from './Icon'; import themeColors from '../styles/themes/default'; import * as Expensicons from './Icon/Expensicons'; +import EReceiptBackground from '../../assets/images/eReceipt_background.svg'; const propTypes = { /** The transaction for the eReceipt */ @@ -33,8 +34,14 @@ function EReceipt({transaction}) { const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - - + + + + + - {formattedTransactionAmount} - {transactionMerchant} + + {formattedTransactionAmount} + {transactionMerchant} + {_.map(waypoints, (waypoint, key) => { const index = TransactionUtils.getWaypointIndex(key); let descriptionKey = 'distance.waypointDescription.'; @@ -56,14 +65,16 @@ function EReceipt({transaction}) { descriptionKey += 'stop'; } return ( - + {translate(descriptionKey)} {waypoint.address || ''} ); })} - {translate('common.date')} - {transactionDate} + + {translate('common.date')} + {transactionDate} + ({ color: theme.textColorfulBackground, }, + eReceiptBackgroundContainer: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + }, + + eReceiptBackground: { + ...sizing.w100, + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + minHeight: 540, + }, + + eReceiptPanel: { + ...spacing.p5, + ...spacing.pb8, + ...flex.flex1, + backgroundColor: theme.panelBackground, + borderRadius: 20, + }, + loginHeroBody: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSignInHeroBody, diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index eac8b087ead0..5e06753d719a 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -83,6 +83,7 @@ const darkTheme = { starDefaultBG: 'rgb(254, 228, 94)', loungeAccessOverlay: colors.blue800, textBrand: colors.green400, + panelBackground: colors.green800, }; darkTheme.PAGE_BACKGROUND_COLORS = { diff --git a/src/styles/utilities/spacing.ts b/src/styles/utilities/spacing.ts index a3667f05ac06..a47efe504326 100644 --- a/src/styles/utilities/spacing.ts +++ b/src/styles/utilities/spacing.ts @@ -55,6 +55,10 @@ export default { marginHorizontal: -20, }, + mv0: { + marginVertical: 0, + }, + mv1: { marginVertical: 4, }, From f8ef14475d4abb35300cea6a4898138c3611d713 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 15:20:08 +0800 Subject: [PATCH 17/52] The eReceipt is specific to distance requests --- src/components/Attachments/AttachmentView/index.js | 6 +++--- src/components/{EReceipt.js => DistanceEReceipt.js} | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) rename src/components/{EReceipt.js => DistanceEReceipt.js} (95%) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index b0e22c237eaf..aca92bf7ba5d 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -3,6 +3,7 @@ import {View, ActivityIndicator} from 'react-native'; import _ from 'underscore'; import PropTypes from 'prop-types'; import Str from 'expensify-common/lib/str'; +import {useRoute} from '@react-navigation/native'; import styles from '../../../styles/styles'; import Icon from '../../Icon'; import * as Expensicons from '../../Icon/Expensicons'; @@ -17,10 +18,9 @@ import AttachmentViewPdf from './AttachmentViewPdf'; import addEncryptedAuthTokenToURL from '../../../libs/addEncryptedAuthTokenToURL'; import * as StyleUtils from '../../../styles/StyleUtils'; import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes'; -import {useRoute} from '@react-navigation/native'; import * as ReportUtils from '../../../libs/ReportUtils'; import * as TransactionUtils from '../../../libs/TransactionUtils'; -import EReceipt from '../../EReceipt'; +import DistanceEReceipt from '../../DistanceEReceipt'; import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; const propTypes = { @@ -122,7 +122,7 @@ function AttachmentView({ const transaction = TransactionUtils.getTransaction(transactionID); const shouldShowEReceipt = TransactionUtils.isDistanceRequest(transaction); if (shouldShowEReceipt) { - return ; + return ; } // For this check we use both source and file.name since temporary file source is a blob diff --git a/src/components/EReceipt.js b/src/components/DistanceEReceipt.js similarity index 95% rename from src/components/EReceipt.js rename to src/components/DistanceEReceipt.js index 5f5619cb22e4..c8d428dde000 100644 --- a/src/components/EReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -26,7 +26,7 @@ const defaultProps = { transaction: {}, }; -function EReceipt({transaction}) { +function DistanceEReceipt({transaction}) { const {translate} = useLocalize(); const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction); @@ -89,7 +89,7 @@ function EReceipt({transaction}) { ); } -export default EReceipt; -EReceipt.displayName = 'EReceipt'; -EReceipt.propTypes = propTypes; -EReceipt.defaultProps = defaultProps; +export default DistanceEReceipt; +DistanceEReceipt.displayName = 'DistanceEReceipt'; +DistanceEReceipt.propTypes = propTypes; +DistanceEReceipt.defaultProps = defaultProps; From ab4db9793693bd7e57b254a3fd025657f61ee81d Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 15:38:36 +0800 Subject: [PATCH 18/52] Set up gap between main sections --- src/components/DistanceEReceipt.js | 46 ++++++++++++++++-------------- src/styles/utilities/spacing.ts | 4 +++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index c8d428dde000..0543cbc00794 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -42,7 +42,7 @@ function DistanceEReceipt({transaction}) { pointerEvents="none" /> - + - + {formattedTransactionAmount} {transactionMerchant} - {_.map(waypoints, (waypoint, key) => { - const index = TransactionUtils.getWaypointIndex(key); - let descriptionKey = 'distance.waypointDescription.'; - if (index === 0) { - descriptionKey += 'start'; - } else if (index === _.size(waypoints) - 1) { - descriptionKey += 'finish'; - } else { - descriptionKey += 'stop'; - } - return ( - - {translate(descriptionKey)} - {waypoint.address || ''} - - ); - })} - - {translate('common.date')} - {transactionDate} + + {_.map(waypoints, (waypoint, key) => { + const index = TransactionUtils.getWaypointIndex(key); + let descriptionKey = 'distance.waypointDescription.'; + if (index === 0) { + descriptionKey += 'start'; + } else if (index === _.size(waypoints) - 1) { + descriptionKey += 'finish'; + } else { + descriptionKey += 'stop'; + } + return ( + + {translate(descriptionKey)} + {waypoint.address || ''} + + ); + })} + + {translate('common.date')} + {transactionDate} + Date: Fri, 22 Sep 2023 16:19:11 +0800 Subject: [PATCH 19/52] Spacing and layout within sections --- src/components/DistanceEReceipt.js | 17 ++++++++++------- src/styles/utilities/spacing.ts | 4 ++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 0543cbc00794..0f83adc86ef2 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -50,11 +50,11 @@ function DistanceEReceipt({transaction}) { shouldDynamicallyResize={false} /> - + {formattedTransactionAmount} {transactionMerchant} - + {_.map(waypoints, (waypoint, key) => { const index = TransactionUtils.getWaypointIndex(key); let descriptionKey = 'distance.waypointDescription.'; @@ -66,21 +66,24 @@ function DistanceEReceipt({transaction}) { descriptionKey += 'stop'; } return ( - + {translate(descriptionKey)} {waypoint.address || ''} ); })} - + {translate('common.date')} {transactionDate} - + diff --git a/src/styles/utilities/spacing.ts b/src/styles/utilities/spacing.ts index e87d8cf85b31..a998b3302b3a 100644 --- a/src/styles/utilities/spacing.ts +++ b/src/styles/utilities/spacing.ts @@ -171,6 +171,10 @@ export default { marginLeft: -32, }, + mt0: { + marginTop: 0, + }, + mt1: { marginTop: 4, }, From 8b8afe9c1aea0cd85ba57e50bed19bc49ca805ad Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 22 Sep 2023 16:35:58 +0800 Subject: [PATCH 20/52] Set width on eReceipt for large screens --- src/components/DistanceEReceipt.js | 2 +- src/styles/styles.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 0f83adc86ef2..ab9065a8c49f 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -34,7 +34,7 @@ function DistanceEReceipt({transaction}) { const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - + ({ eReceiptPanel: { ...spacing.p5, ...spacing.pb8, - ...flex.flex1, backgroundColor: theme.panelBackground, borderRadius: 20, + width: 335, }, loginHeroBody: { From 8c28a58bfb93ce1434adecf244fbb6f75a048bbf Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 25 Sep 2023 15:41:20 +0800 Subject: [PATCH 21/52] Center eReceipt vertically on page --- src/components/DistanceEReceipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index ab9065a8c49f..a96e8fb4c31b 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -34,7 +34,7 @@ function DistanceEReceipt({transaction}) { const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - + Date: Mon, 25 Sep 2023 16:05:24 +0800 Subject: [PATCH 22/52] Use colors directly since it's a specific purpose --- src/styles/styles.js | 6 +++--- src/styles/themes/default.js | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 936e16464fac..47407cb5c2a8 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3557,7 +3557,7 @@ const styles = (theme) => ({ ...headlineFont, fontSize: variables.fontSizeXXXLarge, lineHeight: variables.lineHeightXXXLarge, - color: theme.textBrand, + color: colors.green400, }, eReceiptMerchant: { @@ -3571,7 +3571,7 @@ const styles = (theme) => ({ fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeSmall, lineHeight: variables.lineHeightSmall, - color: theme.textBrand, + color: colors.green400, }, eReceiptWaypointAddress: { @@ -3611,7 +3611,7 @@ const styles = (theme) => ({ eReceiptPanel: { ...spacing.p5, ...spacing.pb8, - backgroundColor: theme.panelBackground, + color: colors.green800, borderRadius: 20, width: 335, }, diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index 5e06753d719a..807d14d0a7aa 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -82,8 +82,6 @@ const darkTheme = { QRLogo: colors.green400, starDefaultBG: 'rgb(254, 228, 94)', loungeAccessOverlay: colors.blue800, - textBrand: colors.green400, - panelBackground: colors.green800, }; darkTheme.PAGE_BACKGROUND_COLORS = { From 16f3d79c508c05ee7e979348c4cb636fb55749e1 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 25 Sep 2023 16:24:01 +0800 Subject: [PATCH 23/52] Fix missing colors import --- src/styles/styles.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/styles/styles.js b/src/styles/styles.js index 47407cb5c2a8..7b09f7c2e8cc 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -26,6 +26,7 @@ import * as Browser from '../libs/Browser'; import cursor from './utilities/cursor'; import userSelect from './utilities/userSelect'; import textUnderline from './utilities/textUnderline'; +import colors from './colors'; // touchCallout is an iOS safari only property that controls the display of the callout information when you touch and hold a target const touchCalloutNone = Browser.isMobileSafari() ? {WebkitTouchCallout: 'none'} : {}; From 7aef1259f94efeff401093b1f18856a390f29cef Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 25 Sep 2023 16:55:29 +0800 Subject: [PATCH 24/52] Fix background color --- src/styles/styles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 7b09f7c2e8cc..bf66e8c378fd 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3612,7 +3612,7 @@ const styles = (theme) => ({ eReceiptPanel: { ...spacing.p5, ...spacing.pb8, - color: colors.green800, + backgroundColor: colors.green800, borderRadius: 20, width: 335, }, From 00108d1aa7bf8c8ba63d662527cf13eb085b4f47 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 25 Sep 2023 16:55:52 +0800 Subject: [PATCH 25/52] Make large eReceipts scrollable --- src/components/DistanceEReceipt.js | 110 +++++++++++++++-------------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index a96e8fb4c31b..115eac5b3939 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -1,5 +1,5 @@ import React from 'react'; -import {View} from 'react-native'; +import {View, ScrollView} from 'react-native'; import lodashGet from 'lodash/get'; import _ from 'underscore'; import Text from './Text'; @@ -35,61 +35,63 @@ function DistanceEReceipt({transaction}) { const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - - - - - - - - - {formattedTransactionAmount} - {transactionMerchant} - - - {_.map(waypoints, (waypoint, key) => { - const index = TransactionUtils.getWaypointIndex(key); - let descriptionKey = 'distance.waypointDescription.'; - if (index === 0) { - descriptionKey += 'start'; - } else if (index === _.size(waypoints) - 1) { - descriptionKey += 'finish'; - } else { - descriptionKey += 'stop'; - } - return ( - - {translate(descriptionKey)} - {waypoint.address || ''} - - ); - })} - - {translate('common.date')} - {transactionDate} + + + + + + + + + + {formattedTransactionAmount} + {transactionMerchant} + + + {_.map(waypoints, (waypoint, key) => { + const index = TransactionUtils.getWaypointIndex(key); + let descriptionKey = 'distance.waypointDescription.'; + if (index === 0) { + descriptionKey += 'start'; + } else if (index === _.size(waypoints) - 1) { + descriptionKey += 'finish'; + } else { + descriptionKey += 'stop'; + } + return ( + + {translate(descriptionKey)} + {waypoint.address || ''} + + ); + })} + + {translate('common.date')} + {transactionDate} + + + + + {translate('eReceipt.guaranteed')} - - - {translate('eReceipt.guaranteed')} - - + ); } From d2305c241ae86d1f5c4adbe592d238a2ab484456 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 25 Sep 2023 17:21:10 +0800 Subject: [PATCH 26/52] Fix center eReceipt vertically with scroll view --- src/components/DistanceEReceipt.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 115eac5b3939..03aa5bf82ce5 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -34,8 +34,8 @@ function DistanceEReceipt({transaction}) { const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( - - + + Date: Tue, 26 Sep 2023 09:47:22 +0800 Subject: [PATCH 27/52] Add spanish translation --- src/languages/es.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/languages/es.ts b/src/languages/es.ts index a68f33a33730..bf18c0dce2d2 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2261,4 +2261,7 @@ export default { selectSuggestedAddress: 'Por favor, selecciona una dirección sugerida', }, }, + eReceipt: { + guaranteed: 'eRecibo garantizado', + }, } satisfies EnglishTranslation; From 001799d5d7ca99fd92bd82ff3f04df1ac90f75c6 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 26 Sep 2023 10:56:33 +0800 Subject: [PATCH 28/52] Align background with top of eReceipt --- src/components/DistanceEReceipt.js | 10 ++++------ src/styles/styles.js | 14 +------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 03aa5bf82ce5..74e46fe5abb5 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -37,12 +37,10 @@ function DistanceEReceipt({transaction}) { - - - + ({ color: theme.textColorfulBackground, }, - eReceiptBackgroundContainer: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - justifyContent: 'center', - alignItems: 'center', - }, - eReceiptBackground: { ...sizing.w100, + borderRadius: 20, position: 'absolute', top: 0, left: 0, - right: 0, - bottom: 0, - minHeight: 540, }, eReceiptPanel: { From 87c8457e0be08b61c5dc6c14ff433dd5b794daac Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 26 Sep 2023 11:00:44 +0800 Subject: [PATCH 29/52] Remove receipt image border for prettier loading --- src/components/DistanceEReceipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 74e46fe5abb5..e8b4e0ecfc44 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -41,7 +41,7 @@ function DistanceEReceipt({transaction}) { style={styles.eReceiptBackground} pointerEvents="none" /> - + Date: Wed, 27 Sep 2023 11:50:22 +0800 Subject: [PATCH 30/52] Fix distance request next button while offline --- src/components/DistanceRequest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js index 5e9b73f2eb3a..4c732e025fac 100644 --- a/src/components/DistanceRequest.js +++ b/src/components/DistanceRequest.js @@ -297,9 +297,9 @@ function DistanceRequest({iou, iouType, report, transaction, mapboxAccessToken, success style={[styles.w100, styles.mb4, styles.ph4, styles.flexShrink0]} onPress={navigateToNextPage} - isDisabled={_.size(validatedWaypoints) < 2 || hasRouteError || isLoadingRoute} + isDisabled={_.size(validatedWaypoints) < 2 || (!isOffline && (hasRouteError || isLoadingRoute))} text={translate('common.next')} - isLoading={isLoadingRoute || shouldFetchRoute} + isLoading={!isOffline && (isLoadingRoute || shouldFetchRoute)} /> ); From 32d4091197b6448fef44ec7cd7317f4f02c666f7 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 28 Sep 2023 17:23:03 +0800 Subject: [PATCH 31/52] Fix isDistanceRequest for optimistic transactions --- src/libs/actions/IOU.js | 9 ++++++--- src/pages/iou/DistanceRequestPage.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index b346900b37dc..555cfd79a2f4 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -2102,9 +2102,12 @@ function setMoneyRequestReceipt(receiptPath, receiptSource) { Onyx.merge(ONYXKEYS.IOU, {receiptPath, receiptSource, merchant: ''}); } -function createEmptyTransaction() { +function setUpDistanceTransaction() { const transactionID = NumberUtils.rand64(); - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {transactionID}); + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { + transactionID, + comment: {type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, customUnit: {name: CONST.CUSTOM_UNITS.NAME_DISTANCE}}, + }); Onyx.merge(ONYXKEYS.IOU, {transactionID}); } @@ -2180,7 +2183,7 @@ export { setMoneyRequestBillable, setMoneyRequestParticipants, setMoneyRequestReceipt, - createEmptyTransaction, + setUpDistanceTransaction, navigateToNextPage, replaceReceipt, }; diff --git a/src/pages/iou/DistanceRequestPage.js b/src/pages/iou/DistanceRequestPage.js index 39b068975c77..2d35b500bd51 100644 --- a/src/pages/iou/DistanceRequestPage.js +++ b/src/pages/iou/DistanceRequestPage.js @@ -49,7 +49,7 @@ function DistanceRequestPage({iou, report, route}) { if (iou.transactionID) { return; } - IOU.createEmptyTransaction(); + IOU.setUpDistanceTransaction(); }, [iou.transactionID]); return ( From 54a25c4707648f1d371d67799b0fde1064de23ec Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 28 Sep 2023 17:42:57 +0800 Subject: [PATCH 32/52] Use placeholders for offline distance eReceipts --- src/components/DistanceEReceipt.js | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index e8b4e0ecfc44..dc059cc1015c 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -16,6 +16,8 @@ import Icon from './Icon'; import themeColors from '../styles/themes/default'; import * as Expensicons from './Icon/Expensicons'; import EReceiptBackground from '../../assets/images/eReceipt_background.svg'; +import useNetwork from '../hooks/useNetwork'; +import PendingMapView from './MapView/PendingMapView'; const propTypes = { /** The transaction for the eReceipt */ @@ -28,9 +30,11 @@ const defaultProps = { function DistanceEReceipt({transaction}) { const {translate} = useLocalize(); + const {isOffline} = useNetwork(); const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction); - const formattedTransactionAmount = CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); + const hasRoute = TransactionUtils.hasRoute(transaction); + const formattedTransactionAmount = hasRoute ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( @@ -42,12 +46,16 @@ function DistanceEReceipt({transaction}) { pointerEvents="none" /> - + {isOffline ? ( + + ) : ( + + )} {formattedTransactionAmount} From 5c5f717ce230b1653d7bc32e7bb13b20b4b1ec5b Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 28 Sep 2023 18:16:31 +0800 Subject: [PATCH 33/52] Use withOnyx for transaction vs deprecated utils --- .../Attachments/AttachmentView/index.js | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 1b05861b581e..a08f72b9c604 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -3,7 +3,6 @@ import {View, ActivityIndicator} from 'react-native'; import _ from 'underscore'; import PropTypes from 'prop-types'; import Str from 'expensify-common/lib/str'; -import {useRoute} from '@react-navigation/native'; import styles from '../../../styles/styles'; import Icon from '../../Icon'; import * as Expensicons from '../../Icon/Expensicons'; @@ -18,10 +17,8 @@ import AttachmentViewPdf from './AttachmentViewPdf'; import addEncryptedAuthTokenToURL from '../../../libs/addEncryptedAuthTokenToURL'; import * as StyleUtils from '../../../styles/StyleUtils'; import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes'; -import * as ReportUtils from '../../../libs/ReportUtils'; import * as TransactionUtils from '../../../libs/TransactionUtils'; import DistanceEReceipt from '../../DistanceEReceipt'; -import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; import useNetwork from '../../../hooks/useNetwork'; const propTypes = { @@ -69,10 +66,9 @@ function AttachmentView({ isFocused, isWorkspaceAvatar, fallbackSource, + transaction, }) { const [loadComplete, setLoadComplete] = useState(false); - const currentRoute = useRoute(); - const [imageError, setImageError] = useState(false); useNetwork({onReconnect: () => setImageError(false)}); @@ -119,15 +115,7 @@ function AttachmentView({ ); } - const reportID = _.get(currentRoute, ['params', 'reportID']); - const report = ReportUtils.getReport(reportID); - - // Get the money request transaction - const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const transactionID = _.get(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0); - const transaction = TransactionUtils.getTransaction(transactionID); - const shouldShowEReceipt = TransactionUtils.isDistanceRequest(transaction); - if (shouldShowEReceipt) { + if (TransactionUtils.isDistanceRequest(transaction)) { return ; } @@ -185,4 +173,20 @@ AttachmentView.propTypes = propTypes; AttachmentView.defaultProps = defaultProps; AttachmentView.displayName = 'AttachmentView'; -export default compose(memo, withLocalize)(AttachmentView); +export default compose( + memo, + withLocalize, + withOnyx({ + parentReport: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, + }, + parentReportAction: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${(report.parentReportID, report.parentReportActionID)}`, + selector: (reportActions, props) => props && props.parentReport && reportActions && reportActions[props.parentReport.parentReportActionID], + canEvict: false, + }, + transaction: { + key: ({parentReportAction}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(parentReportAction, 'originalMessage.IOUTransactionID', 0)}`, + }, + }), +)(AttachmentView); From db6e4dad0ed580451ca409cb5e51f59bc2f5872f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 28 Sep 2023 18:23:28 +0800 Subject: [PATCH 34/52] Update comment --- src/components/DistanceEReceipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index dc059cc1015c..4a92079bcce5 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -20,7 +20,7 @@ import useNetwork from '../hooks/useNetwork'; import PendingMapView from './MapView/PendingMapView'; const propTypes = { - /** The transaction for the eReceipt */ + /** The transaction for the distance request */ transaction: transactionPropTypes, }; From 7877d5edbbcf62154e1cd72447e7992eb6b08b6f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 29 Sep 2023 09:53:26 +0800 Subject: [PATCH 35/52] Fix and simplify transaction access --- .../AttachmentCarousel/CarouselItem.js | 1 + .../Attachments/AttachmentView/index.js | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js index 3aeef8482e2d..6cecfb03fd83 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -97,6 +97,7 @@ function CarouselItem({item, isFocused, onPress}) { isFocused={isFocused} onPress={onPress} isUsedInCarousel + transactionID={item.transactionID} /> diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index a08f72b9c604..b8699764173c 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -20,6 +20,8 @@ import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes'; import * as TransactionUtils from '../../../libs/TransactionUtils'; import DistanceEReceipt from '../../DistanceEReceipt'; import useNetwork from '../../../hooks/useNetwork'; +import {withOnyx} from 'react-native-onyx'; +import ONYXKEYS from '../../../ONYXKEYS'; const propTypes = { ...attachmentViewPropTypes, @@ -40,6 +42,8 @@ const propTypes = { /** Denotes whether it is a workspace avatar or not */ isWorkspaceAvatar: PropTypes.bool, + + transactionID: PropTypes.number, }; const defaultProps = { @@ -49,6 +53,7 @@ const defaultProps = { onToggleKeyboard: () => {}, containerStyles: [], isWorkspaceAvatar: false, + transactionID: 0, }; function AttachmentView({ @@ -177,16 +182,8 @@ export default compose( memo, withLocalize, withOnyx({ - parentReport: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, - }, - parentReportAction: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${(report.parentReportID, report.parentReportActionID)}`, - selector: (reportActions, props) => props && props.parentReport && reportActions && reportActions[props.parentReport.parentReportActionID], - canEvict: false, - }, transaction: { - key: ({parentReportAction}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(parentReportAction, 'originalMessage.IOUTransactionID', 0)}`, + key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, }, }), )(AttachmentView); From b2c3f9e7705bfdbb6fc77f1811f58f835e07ff2f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 29 Sep 2023 10:00:48 +0800 Subject: [PATCH 36/52] Fix prop type --- src/components/Attachments/AttachmentView/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index b8699764173c..f6bc0160e1af 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -43,7 +43,7 @@ const propTypes = { /** Denotes whether it is a workspace avatar or not */ isWorkspaceAvatar: PropTypes.bool, - transactionID: PropTypes.number, + transactionID: PropTypes.string, }; const defaultProps = { From 6963757f5975277919ea36b3ac30a10346992062 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 29 Sep 2023 10:28:40 +0800 Subject: [PATCH 37/52] Fix online and offline transaction amount --- src/components/DistanceEReceipt.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 4a92079bcce5..abc88e1306a2 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -33,8 +33,7 @@ function DistanceEReceipt({transaction}) { const {isOffline} = useNetwork(); const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction); - const hasRoute = TransactionUtils.hasRoute(transaction); - const formattedTransactionAmount = hasRoute ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); + const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); return ( From 1d3a8b9d10165c3ef93d391a04ff15efc46dbfdf Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 29 Sep 2023 10:33:39 +0800 Subject: [PATCH 38/52] Load thumbnail only when image source is ready --- src/components/DistanceEReceipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index abc88e1306a2..6e91edcca5e4 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -45,7 +45,7 @@ function DistanceEReceipt({transaction}) { pointerEvents="none" /> - {isOffline ? ( + {isOffline || !Boolean(thumbnailSource) ? ( ) : ( Date: Fri, 29 Sep 2023 12:53:36 +0800 Subject: [PATCH 39/52] Ensure waypoints are ordered properly for eReceipt --- src/components/DistanceEReceipt.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 6e91edcca5e4..3a79f33effe1 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import {View, ScrollView} from 'react-native'; import lodashGet from 'lodash/get'; import _ from 'underscore'; @@ -36,6 +36,17 @@ function DistanceEReceipt({transaction}) { const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); + const sortedWaypoints = useMemo(() => { + // The waypoint keys are sometimes out of order + return _.chain(waypoints) + .keys() + .sort((keyA, keyB) => { + return TransactionUtils.getWaypointIndex(keyA) - TransactionUtils.getWaypointIndex(keyB); + }) + .map((key) => ({[key]: waypoints[key]})) + .reduce((result, obj) => Object.assign(result, obj), {}) + .value(); + }, [waypoints]); return ( @@ -61,7 +72,7 @@ function DistanceEReceipt({transaction}) { {transactionMerchant} - {_.map(waypoints, (waypoint, key) => { + {_.map(sortedWaypoints, (waypoint, key) => { const index = TransactionUtils.getWaypointIndex(key); let descriptionKey = 'distance.waypointDescription.'; if (index === 0) { From b62df64019c81536f09915b4eb94e703ce9882ec Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 29 Sep 2023 15:51:35 +0800 Subject: [PATCH 40/52] Set the rate to TBD when it's unavailable --- src/libs/DistanceRequestUtils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/DistanceRequestUtils.js b/src/libs/DistanceRequestUtils.js index 7744ee3d8bb1..34a5e68e21a2 100644 --- a/src/libs/DistanceRequestUtils.js +++ b/src/libs/DistanceRequestUtils.js @@ -89,8 +89,7 @@ const getDistanceMerchant = (hasRoute, distanceInMeters, unit, rate, currency, t const distanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.miles') : translate('common.kilometers'); const singularDistanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer'); const unitString = distanceInUnits === 1 ? singularDistanceUnit : distanceUnit; - - const ratePerUnit = PolicyUtils.getUnitRateValue({rate}, toLocaleDigit); + const ratePerUnit = Boolean(rate) ? PolicyUtils.getUnitRateValue({rate}, toLocaleDigit) : translate('common.tbd'); const currencySymbol = CurrencyUtils.getCurrencySymbol(currency) || `${currency} `; return `${distanceInUnits} ${unitString} @ ${currencySymbol}${ratePerUnit} / ${singularDistanceUnit}`; From 25d66cc3fbf2e97dbc289f13fa0493fca45818cd Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 2 Oct 2023 17:07:21 -0700 Subject: [PATCH 41/52] Fix crash / prop types with default receipt source --- .../Attachments/AttachmentCarousel/CarouselItem.js | 5 +++-- src/components/Attachments/AttachmentView/index.js | 2 +- src/components/Attachments/propTypes.js | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js index 6cecfb03fd83..2a97b3327e9c 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -10,6 +10,7 @@ import Button from '../../Button'; import AttachmentView from '../AttachmentView'; import SafeAreaConsumer from '../../SafeAreaConsumer'; import ReportAttachmentsContext from '../../../pages/home/report/ReportAttachmentsContext'; +import * as AttachmentsPropTypes from '../propTypes'; const propTypes = { /** Attachment required information such as the source and file name */ @@ -20,8 +21,8 @@ const propTypes = { /** Whether source URL requires authentication */ isAuthTokenRequired: PropTypes.bool, - /** The source (URL) of the attachment */ - source: PropTypes.string, + /** URL to full-sized attachment or SVG function */ + source: AttachmentsPropTypes.attachmentSourcePropType.isRequired, /** Additional information about the attachment file */ file: PropTypes.shape({ diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index f6bc0160e1af..63111b75a17f 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -101,7 +101,7 @@ function AttachmentView({ // Check both source and file.name since PDFs dragged into the the text field // will appear with a source that is a blob - if (Str.isPDF(source) || (file && Str.isPDF(file.name || translate('attachmentView.unknownFilename')))) { + if ((_.isString(source) && Str.isPDF(source)) || (file && Str.isPDF(file.name || translate('attachmentView.unknownFilename')))) { const encryptedSourceUrl = isAuthTokenRequired ? addEncryptedAuthTokenToURL(source) : source; return ( diff --git a/src/components/Attachments/propTypes.js b/src/components/Attachments/propTypes.js index b3f0af6ab217..97717a1e51da 100644 --- a/src/components/Attachments/propTypes.js +++ b/src/components/Attachments/propTypes.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; -const attachmentSourcePropType = PropTypes.oneOfType([PropTypes.string, PropTypes.func]); +const attachmentSourcePropType = PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.number]); const attachmentFilePropType = PropTypes.shape({ name: PropTypes.string, }); From 2d653b80cd36969ef970479f1d00fce11d9c884d Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 3 Oct 2023 08:06:14 -0700 Subject: [PATCH 42/52] Fix eReceipt background on Android --- assets/images/eReceipt_background.svg | 32 +++++++++++++-------------- src/styles/styles.js | 1 + 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/assets/images/eReceipt_background.svg b/assets/images/eReceipt_background.svg index 257489bd6fdd..5070ed3b2f24 100644 --- a/assets/images/eReceipt_background.svg +++ b/assets/images/eReceipt_background.svg @@ -1,24 +1,24 @@ + viewBox="0 0 335 540" style="enable-background:new 0 0 335 540;" xml:space="preserve"> - + - + - + - - + + - + diff --git a/src/styles/styles.js b/src/styles/styles.js index 40dfa19d5448..6605b6c0ce53 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3280,6 +3280,7 @@ const styles = (theme) => ({ position: 'absolute', top: 0, left: 0, + height: 540, }, eReceiptPanel: { From 1e86e514f8b9cba795398562863fce8fe22ea99c Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 3 Oct 2023 16:27:17 -0700 Subject: [PATCH 43/52] Fix linter --- .../AttachmentCarousel/CarouselItem.js | 3 +++ .../Attachments/AttachmentView/index.js | 4 +++- src/components/DistanceEReceipt.js | 24 +++++++++---------- src/libs/DistanceRequestUtils.js | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js index 2a97b3327e9c..096b6d60d428 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -32,6 +32,9 @@ const propTypes = { /** Whether the attachment has been flagged */ hasBeenFlagged: PropTypes.bool, + + /** The id of the transaction related to the attachment */ + transactionID: PropTypes.string, }).isRequired, /** Whether the attachment is currently being viewed in the carousel */ diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 63111b75a17f..8d88efa06714 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -3,6 +3,7 @@ import {View, ActivityIndicator} from 'react-native'; import _ from 'underscore'; import PropTypes from 'prop-types'; import Str from 'expensify-common/lib/str'; +import {withOnyx} from 'react-native-onyx'; import styles from '../../../styles/styles'; import Icon from '../../Icon'; import * as Expensicons from '../../Icon/Expensicons'; @@ -20,7 +21,6 @@ import {attachmentViewPropTypes, attachmentViewDefaultProps} from './propTypes'; import * as TransactionUtils from '../../../libs/TransactionUtils'; import DistanceEReceipt from '../../DistanceEReceipt'; import useNetwork from '../../../hooks/useNetwork'; -import {withOnyx} from 'react-native-onyx'; import ONYXKEYS from '../../../ONYXKEYS'; const propTypes = { @@ -43,6 +43,8 @@ const propTypes = { /** Denotes whether it is a workspace avatar or not */ isWorkspaceAvatar: PropTypes.bool, + /** The id of the transaction related to the attachment */ + // eslint-disable-next-line react/no-unused-prop-types transactionID: PropTypes.string, }; diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 3a79f33effe1..c461db397b3b 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -36,17 +36,17 @@ function DistanceEReceipt({transaction}) { const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); const waypoints = lodashGet(transaction, 'comment.waypoints', {}); - const sortedWaypoints = useMemo(() => { - // The waypoint keys are sometimes out of order - return _.chain(waypoints) - .keys() - .sort((keyA, keyB) => { - return TransactionUtils.getWaypointIndex(keyA) - TransactionUtils.getWaypointIndex(keyB); - }) - .map((key) => ({[key]: waypoints[key]})) - .reduce((result, obj) => Object.assign(result, obj), {}) - .value(); - }, [waypoints]); + const sortedWaypoints = useMemo( + () => + // The waypoint keys are sometimes out of order + _.chain(waypoints) + .keys() + .sort((keyA, keyB) => TransactionUtils.getWaypointIndex(keyA) - TransactionUtils.getWaypointIndex(keyB)) + .map((key) => ({[key]: waypoints[key]})) + .reduce((result, obj) => _.assign(result, obj), {}) + .value(), + [waypoints], + ); return ( @@ -56,7 +56,7 @@ function DistanceEReceipt({transaction}) { pointerEvents="none" /> - {isOffline || !Boolean(thumbnailSource) ? ( + {isOffline || !thumbnailSource ? ( ) : ( Date: Tue, 3 Oct 2023 17:33:07 -0700 Subject: [PATCH 44/52] Prevent top of merchant text being cut off --- src/styles/styles.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 6605b6c0ce53..a29636cbf796 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3249,7 +3249,10 @@ const styles = (theme) => ({ eReceiptMerchant: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeXLarge, - lineHeight: variables.lineHeightXLarge, + + // Setting the line height caused the top of the text to be cut off. Here is an issue to investigate and fix this. + // https://github.com/Expensify/App/issues/28772 + // lineHeight: variables.lineHeightXLarge, color: theme.text, }, From 3bd0c26b10639a920b765a50637481d347d773eb Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 4 Oct 2023 08:58:22 -0700 Subject: [PATCH 45/52] Line height can be larger by convention --- src/styles/styles.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 56593e97817a..104eff3e9874 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3260,10 +3260,7 @@ const styles = (theme) => ({ eReceiptMerchant: { fontFamily: fontFamily.EXP_NEUE, fontSize: variables.fontSizeXLarge, - - // Setting the line height caused the top of the text to be cut off. Here is an issue to investigate and fix this. - // https://github.com/Expensify/App/issues/28772 - // lineHeight: variables.lineHeightXLarge, + lineHeight: variables.lineHeightXXLarge, color: theme.text, }, From 50349b28868034813ceb4fbfcbfe7e8a4cbd9d1f Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 4 Oct 2023 11:49:57 -0700 Subject: [PATCH 46/52] Show scroll bar at the full width of the modal --- src/components/DistanceEReceipt.js | 7 +++++-- src/styles/styles.js | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index c461db397b3b..ee725ea54f67 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -48,8 +48,11 @@ function DistanceEReceipt({transaction}) { [waypoints], ); return ( - - + + ({ eReceiptPanel: { ...spacing.p5, ...spacing.pb8, + ...spacing.m5, backgroundColor: colors.green800, borderRadius: 20, width: 335, From d28fcfce884f108ee6f21874e16fd19435da4c20 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 5 Oct 2023 16:04:01 -0700 Subject: [PATCH 47/52] Clean up after review feedback --- src/components/Attachments/AttachmentView/index.js | 2 +- src/components/DistanceEReceipt.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 54b7764e6ac1..a1b07fb99dd8 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -55,7 +55,7 @@ const defaultProps = { onToggleKeyboard: () => {}, containerStyles: [], isWorkspaceAvatar: false, - transactionID: 0, + transactionID: '', }; function AttachmentView({ diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index ee725ea54f67..3a64a987c307 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -31,7 +31,7 @@ const defaultProps = { function DistanceEReceipt({transaction}) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename); + const {thumbnail} = TransactionUtils.hasReceipt(transaction) ? ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename) : {}; const {amount: transactionAmount, currency: transactionCurrency, merchant: transactionMerchant, created: transactionDate} = ReportUtils.getTransactionDetails(transaction); const formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : translate('common.tbd'); const thumbnailSource = tryResolveUrlFromApiRoot(thumbnail || ''); From 93687c93bc94e80a1c4b135ed94a78d7e3fc22e4 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 5 Oct 2023 16:17:16 -0700 Subject: [PATCH 48/52] Show distance amount as TBD on request preview --- src/components/ReportActionItem/MoneyRequestPreview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js index 35215cadd15d..e66fce5dd757 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.js +++ b/src/components/ReportActionItem/MoneyRequestPreview.js @@ -212,7 +212,7 @@ function MoneyRequestPreview(props) { const getDisplayAmountText = () => { if (isDistanceRequest) { - return CurrencyUtils.convertToDisplayString(TransactionUtils.getAmount(props.transaction), props.transaction.currency); + return requestAmount ? CurrencyUtils.convertToDisplayString(requestAmount, props.transaction.currency) : props.translate('common.tbd'); } if (isScanning) { From 94fc6d787278b26fc10f7de41bf7b918b35ac34c Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 5 Oct 2023 16:40:59 -0700 Subject: [PATCH 49/52] Use TBD amount for distance request view --- src/components/ReportActionItem/MoneyRequestView.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 079bc64d96bf..5e93884205b5 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -93,10 +93,15 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should } = ReportUtils.getTransactionDetails(transaction); const isEmptyMerchant = transactionMerchant === '' || transactionMerchant === CONST.TRANSACTION.UNKNOWN_MERCHANT || transactionMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; - const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency); + const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); + let formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : ''; + if (isDistanceRequest && !formattedTransactionAmount) { + formattedTransactionAmount = translate('common.tbd'); + } const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); const canEdit = ReportUtils.canEditMoneyRequest(parentReportAction); + // A flag for verifying that the current report is a sub-report of a workspace chat const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); @@ -130,7 +135,6 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should hasErrors = canEdit && TransactionUtils.hasMissingSmartscanFields(transaction); } - const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); const pendingAction = lodashGet(transaction, 'pendingAction'); const getPendingFieldAction = (fieldPath) => lodashGet(transaction, fieldPath) || pendingAction; From d37453960b43e86de14cc69b175811d3eca6fa12 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 5 Oct 2023 16:41:49 -0700 Subject: [PATCH 50/52] Remove cash from distance amount field description --- src/components/ReportActionItem/MoneyRequestView.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 5e93884205b5..988c61f0aad4 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -114,7 +114,10 @@ function MoneyRequestView({report, betas, parentReport, policyCategories, should const shouldShowTag = isPolicyExpenseChat && Permissions.canUseTags(betas) && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagsList))); const shouldShowBillable = isPolicyExpenseChat && Permissions.canUseTags(betas) && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true)); - let description = `${translate('iou.amount')} • ${translate('iou.cash')}`; + let description = `${translate('iou.amount')}`; + if (!isDistanceRequest) { + description += ` • ${translate('iou.cash')}`; + } if (isSettled) { description += ` • ${translate('iou.settledExpensify')}`; } else if (report.isWaitingOnBankAccount) { From 70ead5065931f438fb2dcb2d4db0f7cec7909f81 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 10 Oct 2023 14:55:13 -0700 Subject: [PATCH 51/52] Remove possibly undefined waypoints --- src/components/DistanceEReceipt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DistanceEReceipt.js b/src/components/DistanceEReceipt.js index 3a64a987c307..7c7837b8413d 100644 --- a/src/components/DistanceEReceipt.js +++ b/src/components/DistanceEReceipt.js @@ -43,7 +43,7 @@ function DistanceEReceipt({transaction}) { .keys() .sort((keyA, keyB) => TransactionUtils.getWaypointIndex(keyA) - TransactionUtils.getWaypointIndex(keyB)) .map((key) => ({[key]: waypoints[key]})) - .reduce((result, obj) => _.assign(result, obj), {}) + .reduce((result, obj) => (obj ? _.assign(result, obj) : result), {}) .value(), [waypoints], ); From 4e23ab45b25e6f45dd7c4f4d65fc02e34d23ccf0 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Thu, 12 Oct 2023 13:09:45 -0700 Subject: [PATCH 52/52] Fix duplicate translation key after merge --- src/languages/en.ts | 5 +---- src/languages/es.ts | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 62220cc53f10..22294e00d0ba 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1842,12 +1842,9 @@ export default { }, eReceipt: { guaranteed: 'Guaranteed eReceipt', + transactionDate: 'Transaction date', }, globalNavigationOptions: { chats: 'Chats', }, - eReceipt: { - guaranteed: 'Guaranteed eReceipt', - transactionDate: 'Transaction date', - }, } satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index 997c59bd68a8..202a8c4c9a64 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2327,12 +2327,9 @@ export default { }, eReceipt: { guaranteed: 'eRecibo garantizado', + transactionDate: 'Fecha de transacción', }, globalNavigationOptions: { chats: 'Chats', }, - eReceipt: { - guaranteed: 'eRecibo garantizado', - transactionDate: 'Fecha de transacción', - }, } satisfies EnglishTranslation;