-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat: show full distance e-receipt on hover for map distance requests #92525
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
Changes from 1 commit
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 |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import React, {useState} from 'react'; | ||
| import {View} from 'react-native'; | ||
| import type {LayoutChangeEvent} from 'react-native'; | ||
| import DistanceEReceipt from '@components/DistanceEReceipt'; | ||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||
| import variables from '@styles/variables'; | ||
| import type {Transaction} from '@src/types/onyx'; | ||
|
|
||
| // The DistanceEReceipt panel is `variables.eReceiptBGHWidth` wide plus the 20px margin on each side (styles.m5). | ||
| const E_RECEIPT_CARD_WIDTH = variables.eReceiptBGHWidth + 40; | ||
|
|
||
| type HoveredDistanceEReceiptProps = { | ||
| /** The transaction for the distance expense */ | ||
| transaction: Transaction; | ||
| }; | ||
|
|
||
| /** | ||
| * Overlay that shows the full distance e-receipt on hover scaled down (object-fit: contain) to sit inside the | ||
| * fixed-size receipt box without changing the box dimensions. The space around the portrait card is filled with | ||
| * the card's own background color so there is no white gap. | ||
| */ | ||
| function HoveredDistanceEReceipt({transaction}: HoveredDistanceEReceiptProps) { | ||
| const styles = useThemeStyles(); | ||
| const [boxWidth, setBoxWidth] = useState(0); | ||
| const [boxHeight, setBoxHeight] = useState(0); | ||
| const [cardHeight, setCardHeight] = useState(0); | ||
|
|
||
| const scale = boxWidth && boxHeight && cardHeight ? Math.min(boxWidth / E_RECEIPT_CARD_WIDTH, boxHeight / cardHeight) : 0; | ||
|
|
||
| const onOverlayLayout = (event: LayoutChangeEvent) => { | ||
| setBoxWidth(event.nativeEvent.layout.width); | ||
| setBoxHeight(event.nativeEvent.layout.height); | ||
| }; | ||
|
|
||
| const onCardLayout = (event: LayoutChangeEvent) => { | ||
| setCardHeight(event.nativeEvent.layout.height); | ||
| }; | ||
|
|
||
| return ( | ||
| <View | ||
| style={[styles.pAbsolute, styles.t0, styles.l0, styles.r0, styles.b0, styles.justifyContentCenter, styles.alignItemsCenter, styles.overflowHidden, styles.eReceiptHoverFill]} | ||
| onLayout={onOverlayLayout} | ||
| > | ||
|
WojtekBoman marked this conversation as resolved.
|
||
| <View | ||
| style={[{width: E_RECEIPT_CARD_WIDTH}, scale ? {transform: [{scale}]} : styles.opacity0]} | ||
| onLayout={onCardLayout} | ||
| > | ||
| <DistanceEReceipt transaction={transaction} /> | ||
| </View> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| HoveredDistanceEReceipt.displayName = 'HoveredDistanceEReceipt'; | ||
|
WojtekBoman marked this conversation as resolved.
Outdated
|
||
|
|
||
| export default HoveredDistanceEReceipt; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,6 +79,7 @@ import type * as OnyxTypes from '@src/types/onyx'; | |
| import type {TransactionPendingFieldsKey} from '@src/types/onyx/Transaction'; | ||
| import type {FileObject} from '@src/types/utils/Attachment'; | ||
| import {isEmptyObject} from '@src/types/utils/EmptyObject'; | ||
| import HoveredDistanceEReceipt from './HoveredDistanceEReceipt'; | ||
| import {isElementHovered, resetButtonHoverState} from './receiptHoverUtils'; | ||
| import ReportActionItemImage from './ReportActionItemImage'; | ||
|
|
||
|
|
@@ -172,6 +173,7 @@ function MoneyRequestReceiptView({ | |
| const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${moneyRequestReport?.policyID}`); | ||
|
|
||
| const isDistanceRequest = isDistanceRequestTransactionUtils(transaction); | ||
| const isMapDistanceRequest = !!transaction && isDistanceRequest && !isManualDistanceRequest(transaction); | ||
|
Contributor
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. This comment is genuine. Steps to reproduce:
Expected result:E-receipt displays on hover. Actual result:Only the map enlarges on hover. Screen.Recording.2026-06-04.at.10.55.21.PM.mov
Contributor
Author
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. Now it should work fine, I've added here logic checking if the transaction has defined waypoints, if so, we'll display an e-receipt |
||
| const hasReceipt = hasReceiptTransactionUtils(updatedTransaction ?? transaction); | ||
| const isTransactionScanning = isScanning(updatedTransaction ?? transaction); | ||
| const didReceiptScanSucceed = hasReceipt && didReceiptScanSucceedTransactionUtils(transaction); | ||
|
|
@@ -504,8 +506,6 @@ function MoneyRequestReceiptView({ | |
|
|
||
| const showBorderlessLoading = isLoading && fillSpace; | ||
|
|
||
| const isMapDistanceRequest = !!transaction && isDistanceRequest && !isManualDistanceRequest(transaction); | ||
|
|
||
| const canShowReceiptActions = hasReceipt && !isLoading && isEditable && !isMapDistanceRequest && !mergeTransactionID; | ||
| const receiptPendingAction = isDistanceRequest ? getPendingFieldAction('waypoints') : getPendingFieldAction('receipt'); | ||
| const isReceiptOfflinePending = isOffline && !!receiptPendingAction; | ||
|
|
@@ -623,23 +623,28 @@ function MoneyRequestReceiptView({ | |
| isEnabled={canZoomReceipt} | ||
|
Contributor
Author
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. E-receipts zoom on hover is intended |
||
| hoverContainerRef={receiptContainerRef} | ||
| > | ||
| <ReportActionItemImage | ||
| shouldUseThumbnailImage={!fillSpace} | ||
| shouldUseFullHeight={fillSpace} | ||
| thumbnail={receiptURIs?.thumbnail} | ||
| fileExtension={receiptURIs?.fileExtension} | ||
| isThumbnail={receiptURIs?.isThumbnail} | ||
| image={receiptURIs?.image} | ||
| isLocalFile={receiptURIs?.isLocalFile} | ||
| filename={receiptURIs?.filename} | ||
| transaction={updatedTransaction ?? transaction} | ||
| enablePreviewModal | ||
| readonly={readonly || !canEditReceipt} | ||
| mergeTransactionID={mergeTransactionID} | ||
| report={report} | ||
| onLoad={() => setIsLoading(false)} | ||
| onLoadFailure={() => setIsLoading(false)} | ||
| /> | ||
| <> | ||
| <ReportActionItemImage | ||
| shouldUseThumbnailImage={!fillSpace} | ||
| shouldUseFullHeight={fillSpace} | ||
| thumbnail={receiptURIs?.thumbnail} | ||
| fileExtension={receiptURIs?.fileExtension} | ||
| isThumbnail={receiptURIs?.isThumbnail} | ||
| image={receiptURIs?.image} | ||
| isLocalFile={receiptURIs?.isLocalFile} | ||
| filename={receiptURIs?.filename} | ||
| transaction={updatedTransaction ?? transaction} | ||
| enablePreviewModal | ||
| readonly={readonly || !canEditReceipt} | ||
| mergeTransactionID={mergeTransactionID} | ||
| report={report} | ||
| onLoad={() => setIsLoading(false)} | ||
| onLoadFailure={() => setIsLoading(false)} | ||
| /> | ||
| {/* On hover, a map distance receipt overlays the full e-receipt (map + amount + waypoints), scaled to fit the | ||
| box without resizing it, matching Expensify Classic. The map underneath keeps the box at its resting size. */} | ||
|
WojtekBoman marked this conversation as resolved.
Outdated
|
||
| {isMapDistanceRequest && hovered && !!transactionForReceipt && <HoveredDistanceEReceipt transaction={transactionForReceipt} />} | ||
|
WojtekBoman marked this conversation as resolved.
Outdated
|
||
| </> | ||
| </ReceiptHoverZoom> | ||
| </View> | ||
| {canShowReceiptActions && ( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.