-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Show eReceipts for distance requests #27204
Changes from 58 commits
fabe55f
a6b83fe
9d7538c
bffd20b
71689bd
8095338
d9ddb6f
71ff545
215c03e
90ad229
c1aa7b3
5bb7b9e
dd0fe7e
f69bf99
3a67ed4
74664ce
6e1440e
f8ef144
ab4db97
0954367
8b8afe9
8c28a58
3382e90
16f3d79
7aef125
00108d1
d2305c2
327109e
001799d
87c8457
6b1983e
d891e79
32d4091
54a25c4
bb6aa08
5c5f717
db6e4da
7877d5e
b2c3f9e
6963757
1d3a8b9
5545564
b62df64
25d66cc
2d653b8
1e86e51
058f38e
0a04398
3bd0c26
50349b2
0ae77b6
d28fcfc
93687c9
94fc6d7
d374539
70ead50
712dc86
4d49405
8dedc7a
4e23ab4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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({ | ||||||||||||||||||||||
|
@@ -31,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, | ||||||||||||||||||||||
Comment on lines
+35
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this being passed in? (Trying to understand patterns for ECard transactions eReceipts). I'm having trouble finding where the URL is coming from, do you save it to the receipt key in the transaction object in the BE? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The AttachmentCarousel renders items here App/src/components/Attachments/AttachmentCarousel/index.js Lines 145 to 148 in 04e3eb1
renderItem is passed data from attachments App/src/components/Attachments/AttachmentCarousel/index.js Lines 204 to 206 in 04e3eb1
attachments are set up here
Here's where the transactionID is set App/src/components/Attachments/AttachmentCarousel/extractAttachmentsFromReport.js Line 62 in 61920ff
Yeah it's from transaction.filename here App/src/components/DistanceEReceipt.js Line 34 in 8dedc7a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! This was super helpful |
||||||||||||||||||||||
}).isRequired, | ||||||||||||||||||||||
|
||||||||||||||||||||||
/** Whether the attachment is currently being viewed in the carousel */ | ||||||||||||||||||||||
|
@@ -97,6 +101,7 @@ function CarouselItem({item, isFocused, onPress}) { | |||||||||||||||||||||
isFocused={isFocused} | ||||||||||||||||||||||
onPress={onPress} | ||||||||||||||||||||||
isUsedInCarousel | ||||||||||||||||||||||
transactionID={item.transactionID} | ||||||||||||||||||||||
/> | ||||||||||||||||||||||
</View> | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import React, {useMemo} from 'react'; | ||
import {View, ScrollView} 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'; | ||
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 distance request */ | ||
transaction: transactionPropTypes, | ||
}; | ||
|
||
const defaultProps = { | ||
transaction: {}, | ||
}; | ||
|
||
function DistanceEReceipt({transaction}) { | ||
const {translate} = useLocalize(); | ||
const {isOffline} = useNetwork(); | ||
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 || ''); | ||
const waypoints = lodashGet(transaction, 'comment.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) => (obj ? _.assign(result, obj) : result), {}) | ||
.value(), | ||
[waypoints], | ||
); | ||
return ( | ||
<View style={[styles.flex1, styles.alignItemsCenter]}> | ||
<ScrollView | ||
style={styles.w100} | ||
contentContainerStyle={[styles.flexGrow1, styles.justifyContentCenter, styles.alignItemsCenter]} | ||
> | ||
<View style={styles.eReceiptPanel}> | ||
<EReceiptBackground | ||
style={styles.eReceiptBackground} | ||
pointerEvents="none" | ||
/> | ||
<View style={[styles.moneyRequestViewImage, styles.mh0, styles.mt0, styles.mb5, styles.borderNone]}> | ||
{isOffline || !thumbnailSource ? ( | ||
<PendingMapView /> | ||
) : ( | ||
<ThumbnailImage | ||
previewSourceURL={thumbnailSource} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, we had a bug here - App crashes when tapping on the receipt thumbnail while receipt is generating On native, the pending attachment uses a static image, and it has the source: 1 (that's a standard RN, see this), which is not a string so it breaks the Str.isPDF() and Str.isImage() checks. More details: #28814 |
||
style={[styles.w100, styles.h100]} | ||
isAuthTokenRequired | ||
shouldDynamicallyResize={false} | ||
/> | ||
)} | ||
</View> | ||
<View style={[styles.mb10, styles.gap5, styles.ph2, styles.flexColumn, styles.alignItemsCenter]}> | ||
<Text style={styles.eReceiptAmount}>{formattedTransactionAmount}</Text> | ||
<Text style={styles.eReceiptMerchant}>{transactionMerchant}</Text> | ||
</View> | ||
<View style={[styles.mb10, styles.gap5, styles.ph2]}> | ||
{_.map(sortedWaypoints, (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 ( | ||
<View | ||
style={styles.gap1} | ||
key={key} | ||
> | ||
<Text style={styles.eReceiptWaypointTitle}>{translate(descriptionKey)}</Text> | ||
<Text style={styles.eReceiptWaypointAddress}>{waypoint.address || ''}</Text> | ||
neil-marcellini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</View> | ||
); | ||
})} | ||
<View style={styles.gap1}> | ||
<Text style={styles.eReceiptWaypointTitle}>{translate('common.date')}</Text> | ||
<Text style={styles.eReceiptWaypointAddress}>{transactionDate}</Text> | ||
</View> | ||
</View> | ||
<View style={[styles.ph2, styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter]}> | ||
<Icon | ||
width={86} | ||
height={19.25} | ||
fill={themeColors.textBrand} | ||
src={Expensicons.ExpensifyWordmark} | ||
/> | ||
<Text style={styles.eReceiptGuaranteed}>{translate('eReceipt.guaranteed')}</Text> | ||
</View> | ||
</View> | ||
</ScrollView> | ||
</View> | ||
); | ||
} | ||
|
||
export default DistanceEReceipt; | ||
DistanceEReceipt.displayName = 'DistanceEReceipt'; | ||
DistanceEReceipt.propTypes = propTypes; | ||
DistanceEReceipt.defaultProps = defaultProps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @neil-marcellini could you link me to this asset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can download it here 🙂 https://github.com/Expensify/App/blob/0a04398d12f0d68873a8fafd95227d08de8f5be3/assets/images/eReceipt_background.svg