Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Show eReceipts for distance requests #27204

Merged
merged 60 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
fabe55f
WIP render an eReceipt for distance requests
neil-marcellini Sep 11, 2023
a6b83fe
Render the receipt image
neil-marcellini Sep 11, 2023
9d7538c
Style and clean up
neil-marcellini Sep 11, 2023
bffd20b
Merge branch 'main' into neil-distance-receipts
neil-marcellini Sep 21, 2023
71689bd
Add amount and thumbnail image
neil-marcellini Sep 21, 2023
8095338
Add merchant
neil-marcellini Sep 21, 2023
d9ddb6f
Display waypoints
neil-marcellini Sep 21, 2023
71ff545
Remove unused import
neil-marcellini Sep 21, 2023
215c03e
Style e receipt merchant text
neil-marcellini Sep 21, 2023
90ad229
Style eReceipt waypoint titles
neil-marcellini Sep 21, 2023
c1aa7b3
Style eReceipt waypoint address
neil-marcellini Sep 21, 2023
5bb7b9e
Add date text
neil-marcellini Sep 21, 2023
dd0fe7e
WIP add logo
neil-marcellini Sep 21, 2023
f69bf99
Add logo and guaranteed eReceipt
neil-marcellini Sep 22, 2023
3a67ed4
Set up wrapping views with padding
neil-marcellini Sep 22, 2023
74664ce
Fix lint issues / clean up
neil-marcellini Sep 22, 2023
6e1440e
Add the eReceipt background
neil-marcellini Sep 22, 2023
f8ef144
The eReceipt is specific to distance requests
neil-marcellini Sep 22, 2023
ab4db97
Set up gap between main sections
neil-marcellini Sep 22, 2023
0954367
Spacing and layout within sections
neil-marcellini Sep 22, 2023
8b8afe9
Set width on eReceipt for large screens
neil-marcellini Sep 22, 2023
8c28a58
Center eReceipt vertically on page
neil-marcellini Sep 25, 2023
3382e90
Use colors directly since it's a specific purpose
neil-marcellini Sep 25, 2023
16f3d79
Fix missing colors import
neil-marcellini Sep 25, 2023
7aef125
Fix background color
neil-marcellini Sep 25, 2023
00108d1
Make large eReceipts scrollable
neil-marcellini Sep 25, 2023
d2305c2
Fix center eReceipt vertically with scroll view
neil-marcellini Sep 25, 2023
327109e
Add spanish translation
neil-marcellini Sep 26, 2023
001799d
Align background with top of eReceipt
neil-marcellini Sep 26, 2023
87c8457
Remove receipt image border for prettier loading
neil-marcellini Sep 26, 2023
6b1983e
Merge branch 'main' into neil-distance-receipts
neil-marcellini Sep 27, 2023
d891e79
Fix distance request next button while offline
neil-marcellini Sep 27, 2023
32d4091
Fix isDistanceRequest for optimistic transactions
neil-marcellini Sep 28, 2023
54a25c4
Use placeholders for offline distance eReceipts
neil-marcellini Sep 28, 2023
bb6aa08
Merge branch 'main' into neil-distance-receipts
neil-marcellini Sep 28, 2023
5c5f717
Use withOnyx for transaction vs deprecated utils
neil-marcellini Sep 28, 2023
db6e4da
Update comment
neil-marcellini Sep 28, 2023
7877d5e
Fix and simplify transaction access
neil-marcellini Sep 29, 2023
b2c3f9e
Fix prop type
neil-marcellini Sep 29, 2023
6963757
Fix online and offline transaction amount
neil-marcellini Sep 29, 2023
1d3a8b9
Load thumbnail only when image source is ready
neil-marcellini Sep 29, 2023
5545564
Ensure waypoints are ordered properly for eReceipt
neil-marcellini Sep 29, 2023
b62df64
Set the rate to TBD when it's unavailable
neil-marcellini Sep 29, 2023
25d66cc
Fix crash / prop types with default receipt source
neil-marcellini Oct 3, 2023
2d653b8
Fix eReceipt background on Android
neil-marcellini Oct 3, 2023
1e86e51
Fix linter
neil-marcellini Oct 3, 2023
058f38e
Prevent top of merchant text being cut off
neil-marcellini Oct 4, 2023
0a04398
Merge branch 'main' into neil-distance-receipts
neil-marcellini Oct 4, 2023
3bd0c26
Line height can be larger by convention
neil-marcellini Oct 4, 2023
50349b2
Show scroll bar at the full width of the modal
neil-marcellini Oct 4, 2023
0ae77b6
Merge branch 'main' into neil-distance-receipts
neil-marcellini Oct 5, 2023
d28fcfc
Clean up after review feedback
neil-marcellini Oct 5, 2023
93687c9
Show distance amount as TBD on request preview
neil-marcellini Oct 5, 2023
94fc6d7
Use TBD amount for distance request view
neil-marcellini Oct 5, 2023
d374539
Remove cash from distance amount field description
neil-marcellini Oct 5, 2023
70ead50
Remove possibly undefined waypoints
neil-marcellini Oct 10, 2023
712dc86
Merge branch 'main' into neil-distance-receipts
neil-marcellini Oct 10, 2023
4d49405
Merge branch 'main' into neil-distance-receipts
neil-marcellini Oct 11, 2023
8dedc7a
Merge branch 'main' into neil-distance-receipts
neil-marcellini Oct 12, 2023
4e23ab4
Fix duplicate translation key after merge
neil-marcellini Oct 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,635 changes: 1,635 additions & 0 deletions assets/images/eReceipt_background.svg
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/components/Attachments/AttachmentView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -17,6 +18,10 @@ 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';

const propTypes = {
...attachmentViewPropTypes,
Expand Down Expand Up @@ -64,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)) {
Expand Down Expand Up @@ -107,6 +113,18 @@ 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) {
return <DistanceEReceipt transaction={transaction} />;
}

// 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);
Expand Down
100 changes: 100 additions & 0 deletions src/components/DistanceEReceipt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
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';
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 */
transaction: transactionPropTypes,
};

const defaultProps = {
transaction: {},
};

function DistanceEReceipt({transaction}) {
const {translate} = useLocalize();
const {thumbnail} = ReceiptUtils.getThumbnailAndImageURIs(transaction.receipt.source, transaction.filename);
neil-marcellini marked this conversation as resolved.
Show resolved Hide resolved
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', {});
return (
<View style={[styles.ph5, styles.pv5, styles.flex1, styles.alignItemsCenter]}>
<View style={styles.eReceiptPanel}>
<View style={styles.eReceiptBackgroundContainer}>
<EReceiptBackground
style={styles.eReceiptBackground}
pointerEvents="none"
/>
</View>
<View style={[styles.moneyRequestViewImage, styles.mh0, styles.mt0, styles.mb5]}>
<ThumbnailImage
previewSourceURL={thumbnailSource}
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(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 (
<View
style={styles.gap1}
key={key}
>
<Text style={styles.eReceiptWaypointTitle}>{translate(descriptionKey)}</Text>
<Text style={styles.eReceiptWaypointAddress}>{waypoint.address || ''}</Text>
</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>
</View>
);
}

export default DistanceEReceipt;
DistanceEReceipt.displayName = 'DistanceEReceipt';
DistanceEReceipt.propTypes = propTypes;
DistanceEReceipt.defaultProps = defaultProps;
3 changes: 3 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1778,4 +1778,7 @@ export default {
selectSuggestedAddress: 'Please select a suggested address',
},
},
eReceipt: {
neil-marcellini marked this conversation as resolved.
Show resolved Hide resolved
guaranteed: 'Guaranteed eReceipt',
},
} satisfies TranslationBase;
63 changes: 63 additions & 0 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3553,6 +3553,69 @@ const styles = (theme) => ({
lineHeight: variables.lineHeightXXLarge,
},

eReceiptAmount: {
...headlineFont,
fontSize: variables.fontSizeXXXLarge,
lineHeight: variables.lineHeightXXXLarge,
Copy link
Contributor

Choose a reason for hiding this comment

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

This line caused an edge case regression in #29616; when device font size is set to the minimum, the amount in the e-receipt is cut off.

color: theme.textBrand,
},

eReceiptMerchant: {
fontFamily: fontFamily.EXP_NEUE,
fontSize: variables.fontSizeXLarge,
lineHeight: variables.lineHeightXLarge,
color: theme.text,
},

eReceiptWaypointTitle: {
fontFamily: fontFamily.EXP_NEUE,
fontSize: variables.fontSizeSmall,
lineHeight: variables.lineHeightSmall,
color: theme.textBrand,
},

eReceiptWaypointAddress: {
fontFamily: fontFamily.MONOSPACE,
fontSize: variables.fontSizeNormal,
lineHeight: variables.lineHeightNormal,
color: theme.textColorfulBackground,
},

eReceiptGuaranteed: {
fontFamily: fontFamily.MONOSPACE,
fontSize: variables.fontSizeSmall,
lineHeight: variables.lineHeightSmall,
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,
backgroundColor: theme.panelBackground,
borderRadius: 20,
width: 335,
},

loginHeroBody: {
fontFamily: fontFamily.EXP_NEUE,
fontSize: variables.fontSizeSignInHeroBody,
Expand Down
3 changes: 2 additions & 1 deletion src/styles/themes/default.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -83,6 +82,8 @@ const darkTheme = {
QRLogo: colors.green400,
starDefaultBG: 'rgb(254, 228, 94)',
loungeAccessOverlay: colors.blue800,
textBrand: colors.green400,
neil-marcellini marked this conversation as resolved.
Show resolved Hide resolved
panelBackground: colors.green800,
neil-marcellini marked this conversation as resolved.
Show resolved Hide resolved
};

darkTheme.PAGE_BACKGROUND_COLORS = {
Expand Down
12 changes: 12 additions & 0 deletions src/styles/utilities/spacing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export default {
marginHorizontal: -20,
},

mv0: {
marginVertical: 0,
},

mv1: {
marginVertical: 4,
},
Expand Down Expand Up @@ -167,6 +171,10 @@ export default {
marginLeft: -32,
},

mt0: {
marginTop: 0,
},

mt1: {
marginTop: 4,
},
Expand Down Expand Up @@ -239,6 +247,10 @@ export default {
marginBottom: 32,
},

mb10: {
marginBottom: 40,
},

mb15: {
marginBottom: 60,
},
Expand Down
Loading