-
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
Enable IOUPreview for bill splits #18143
Changes from all commits
570bc0c
dc1fe5b
0cc25d7
70579f1
2de4b4b
e60913e
2fb9ab4
7836e1f
605fce5
c89d438
0d21ffc
808d427
467959f
fd92e3c
10f1d6a
5d778a6
ef66bd7
dd89377
8042ffb
87f468e
2937138
b3f0d25
c741b6b
74f6ca0
5a27113
ab25d1a
23b7cad
7625547
b5dd4f2
b3f1805
c12892a
46e52b9
81eb920
df7f304
bd7569e
2645cec
af90d08
689ae2b
3dcf988
166d5d6
ac3083b
721d353
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 |
---|---|---|
|
@@ -23,6 +23,9 @@ const propTypes = { | |
/** The ID of the associated chatReport */ | ||
chatReportID: PropTypes.string.isRequired, | ||
|
||
/** The ID of the associated request report */ | ||
requestReportID: PropTypes.string.isRequired, | ||
|
||
/** Is this IOUACTION the most recent? */ | ||
isMostRecentIOUReportAction: PropTypes.bool.isRequired, | ||
|
||
|
@@ -66,14 +69,16 @@ const defaultProps = { | |
}; | ||
|
||
const IOUAction = (props) => { | ||
const launchDetailsModal = () => { | ||
Navigation.navigate(ROUTES.getIouDetailsRoute(props.chatReportID, props.action.originalMessage.IOUReportID)); | ||
const hasMultipleParticipants = props.chatReport.participants.length > 1; | ||
const onIOUPreviewPressed = () => { | ||
if (hasMultipleParticipants) { | ||
Navigation.navigate(ROUTES.getReportParticipantsRoute(props.chatReportID)); | ||
} else { | ||
Navigation.navigate(ROUTES.getIouDetailsRoute(props.chatReportID, props.action.originalMessage.IOUReportID)); | ||
} | ||
}; | ||
|
||
const shouldShowIOUPreview = ( | ||
props.isMostRecentIOUReportAction | ||
&& Boolean(props.action.originalMessage.IOUReportID) | ||
&& props.chatReport.hasOutstandingIOU) || props.action.originalMessage.type === 'pay'; | ||
const shouldShowIOUPreview = props.isMostRecentIOUReportAction || props.action.originalMessage.type === 'pay'; | ||
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. While we could include 'pay' in the array, it doesn't really make sense because it is not a IOURequest. Also, we're going to completely remove this condition with my next PR. 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. We can do that |
||
|
||
let shouldShowPendingConversionMessage = false; | ||
if ( | ||
|
@@ -93,21 +98,21 @@ const IOUAction = (props) => { | |
action={props.action} | ||
chatReportID={props.chatReportID} | ||
contextMenuAnchor={props.contextMenuAnchor} | ||
shouldAllowViewDetails={Boolean(props.action.originalMessage.IOUReportID)} | ||
onViewDetailsPressed={launchDetailsModal} | ||
onViewDetailsPressed={onIOUPreviewPressed} | ||
checkIfContextMenuActive={props.checkIfContextMenuActive} | ||
isHovered={props.isHovered} | ||
/> | ||
{shouldShowIOUPreview && ( | ||
Julesssss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<IOUPreview | ||
iouReportID={props.action.originalMessage.IOUReportID.toString()} | ||
iouReportID={props.requestReportID} | ||
chatReportID={props.chatReportID} | ||
isBillSplit={hasMultipleParticipants} | ||
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. Coming from #18671. |
||
action={props.action} | ||
contextMenuAnchor={props.contextMenuAnchor} | ||
checkIfContextMenuActive={props.checkIfContextMenuActive} | ||
shouldShowPendingConversionMessage={shouldShowPendingConversionMessage} | ||
onPayButtonPressed={launchDetailsModal} | ||
onPreviewPressed={launchDetailsModal} | ||
onPayButtonPressed={onIOUPreviewPressed} | ||
onPreviewPressed={onIOUPreviewPressed} | ||
containerStyles={[ | ||
styles.cursorPointer, | ||
props.isHovered | ||
|
@@ -131,7 +136,7 @@ export default compose( | |
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, | ||
}, | ||
iouReport: { | ||
key: ({action}) => `${ONYXKEYS.COLLECTION.REPORT}${action.originalMessage.IOUReportID}`, | ||
key: ({requestReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${requestReportID}`, | ||
}, | ||
reportActions: { | ||
key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`, | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,7 +4,6 @@ import { | |||||
Pressable, | ||||||
} from 'react-native'; | ||||||
import PropTypes from 'prop-types'; | ||||||
import Str from 'expensify-common/lib/str'; | ||||||
import {withOnyx} from 'react-native-onyx'; | ||||||
import lodashGet from 'lodash/get'; | ||||||
import _ from 'underscore'; | ||||||
|
@@ -26,7 +25,7 @@ import ControlSelection from '../../libs/ControlSelection'; | |||||
import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; | ||||||
import reportActionPropTypes from '../../pages/home/report/reportActionPropTypes'; | ||||||
import {showContextMenuForReport} from '../ShowContextMenuContext'; | ||||||
import * as ReportUtils from '../../libs/ReportUtils'; | ||||||
import * as OptionsListUtils from '../../libs/OptionsListUtils'; | ||||||
import Button from '../Button'; | ||||||
import * as CurrencyUtils from '../../libs/CurrencyUtils'; | ||||||
|
||||||
|
@@ -80,16 +79,12 @@ const propTypes = { | |||||
hasOutstandingIOU: PropTypes.bool, | ||||||
}), | ||||||
|
||||||
/** True if this is this IOU is a split instead of a 1:1 request */ | ||||||
isBillSplit: PropTypes.bool.isRequired, | ||||||
|
||||||
/** True if the IOU Preview card is hovered */ | ||||||
isHovered: PropTypes.bool, | ||||||
|
||||||
/** All of the personal details for everyone */ | ||||||
personalDetails: PropTypes.objectOf(PropTypes.shape({ | ||||||
|
||||||
/** This is either the user's full name, or their login if full name is an empty string */ | ||||||
displayName: PropTypes.string.isRequired, | ||||||
})), | ||||||
|
||||||
/** Session info for the currently logged in user. */ | ||||||
session: PropTypes.shape({ | ||||||
/** Currently logged in user email */ | ||||||
|
@@ -122,7 +117,6 @@ const defaultProps = { | |||||
walletTerms: {}, | ||||||
pendingAction: null, | ||||||
isHovered: false, | ||||||
personalDetails: {}, | ||||||
session: { | ||||||
email: null, | ||||||
}, | ||||||
|
@@ -137,30 +131,21 @@ const IOUPreview = (props) => { | |||||
if (props.iouReport.total === 0) { | ||||||
return null; | ||||||
} | ||||||
|
||||||
const sessionEmail = lodashGet(props.session, 'email', null); | ||||||
const managerEmail = props.iouReport.managerEmail || ''; | ||||||
const ownerEmail = props.iouReport.ownerEmail || ''; | ||||||
|
||||||
// When displaying within a IOUDetailsModal we cannot guarentee that participants are included in the originalMessage data | ||||||
// Because an IOUPreview of type split can never be rendered within the IOUDetailsModal, manually building the email array is only needed for non-billSplit ious | ||||||
const participantEmails = props.isBillSplit ? props.action.originalMessage.participants : [managerEmail, ownerEmail]; | ||||||
pecanoro marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
const participantAvatars = OptionsListUtils.getAvatarsForLogins(participantEmails); | ||||||
|
||||||
// Pay button should only be visible to the manager of the report. | ||||||
const isCurrentUserManager = managerEmail === sessionEmail; | ||||||
|
||||||
const managerName = ReportUtils.getDisplayNameForParticipant(managerEmail, true); | ||||||
const ownerName = ReportUtils.getDisplayNameForParticipant(ownerEmail, true); | ||||||
const managerAvatar = { | ||||||
source: ReportUtils.getAvatar(lodashGet(props.personalDetails, [managerEmail, 'avatar']), managerEmail), | ||||||
type: CONST.ICON_TYPE_AVATAR, | ||||||
name: managerEmail, | ||||||
}; | ||||||
const ownerAvatar = { | ||||||
source: ReportUtils.getAvatar(lodashGet(props.personalDetails, [ownerEmail, 'avatar']), ownerEmail), | ||||||
type: CONST.ICON_TYPE_AVATAR, | ||||||
name: ownerEmail, | ||||||
}; | ||||||
const cachedTotal = props.iouReport.total && props.iouReport.currency | ||||||
? CurrencyUtils.convertToDisplayString(props.iouReport.total, props.iouReport.currency) | ||||||
: ''; | ||||||
const avatarTooltip = [Str.removeSMSDomain(managerEmail), Str.removeSMSDomain(ownerEmail)]; | ||||||
// Get request formatting options, as long as currency is provided | ||||||
const requestAmount = props.isBillSplit ? props.action.originalMessage.amount : props.iouReport.total; | ||||||
const requestCurrency = props.isBillSplit ? lodashGet(props.action, 'originalMessage.currency', CONST.CURRENCY.USD) : props.iouReport.currency; | ||||||
|
||||||
const showContextMenu = (event) => { | ||||||
// Use action and shouldHidePayButton props to check if we are in IOUDetailsModal, | ||||||
|
@@ -191,51 +176,42 @@ const IOUPreview = (props) => { | |||||
needsOffscreenAlphaCompositing | ||||||
> | ||||||
<View style={[styles.iouPreviewBox, ...props.containerStyles]}> | ||||||
<Text> | ||||||
{props.isBillSplit ? props.translate('iou.split') : props.translate('iou.cash')} | ||||||
</Text> | ||||||
<View style={[styles.flexRow]}> | ||||||
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]}> | ||||||
<Text style={styles.h1}> | ||||||
{cachedTotal} | ||||||
{CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency)} | ||||||
</Text> | ||||||
{!props.iouReport.hasOutstandingIOU && ( | ||||||
{!props.iouReport.hasOutstandingIOU && !props.isBillSplit && ( | ||||||
<View style={styles.iouPreviewBoxCheckmark}> | ||||||
<Icon src={Expensicons.Checkmark} fill={themeColors.iconSuccessFill} /> | ||||||
</View> | ||||||
)} | ||||||
</View> | ||||||
<View style={styles.iouPreviewBoxAvatar}> | ||||||
<MultipleAvatars | ||||||
icons={[managerAvatar, ownerAvatar]} | ||||||
icons={participantAvatars} | ||||||
secondAvatarStyle={[ | ||||||
styles.secondAvatarInline, | ||||||
props.isHovered | ||||||
? styles.iouPreviewBoxAvatarHover | ||||||
: undefined, | ||||||
]} | ||||||
avatarTooltips={avatarTooltip} | ||||||
avatarTooltips={participantEmails} | ||||||
/> | ||||||
</View> | ||||||
</View> | ||||||
{isCurrentUserManager | ||||||
? ( | ||||||
<Text> | ||||||
{props.iouReport.hasOutstandingIOU | ||||||
? props.translate('iou.youowe', {owner: ownerName}) | ||||||
: props.translate('iou.youpaid', {owner: ownerName})} | ||||||
</Text> | ||||||
) : ( | ||||||
<> | ||||||
<Text> | ||||||
{props.iouReport.hasOutstandingIOU | ||||||
? props.translate('iou.owesyou', {manager: managerName}) | ||||||
: props.translate('iou.paidyou', {manager: managerName})} | ||||||
</Text> | ||||||
{props.shouldShowPendingConversionMessage && ( | ||||||
<Text style={[styles.textLabel, styles.colorMuted]}> | ||||||
{props.translate('iou.pendingConversionMessage')} | ||||||
</Text> | ||||||
)} | ||||||
</> | ||||||
)} | ||||||
|
||||||
{!isCurrentUserManager && props.shouldShowPendingConversionMessage && ( | ||||||
<Text style={[styles.textLabel, styles.colorMuted]}> | ||||||
{props.translate('iou.pendingConversionMessage')} | ||||||
</Text> | ||||||
)} | ||||||
|
||||||
<Text>{lodashGet(props.action, 'originalMessage.comment', '')}</Text> | ||||||
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. I think we should use decoded comment here for html characters
Suggested change
|
||||||
|
||||||
{(isCurrentUserManager | ||||||
&& !props.shouldHidePayButton | ||||||
&& props.iouReport.stateNum === CONST.REPORT.STATE_NUM.PROCESSING && ( | ||||||
|
@@ -278,9 +254,6 @@ IOUPreview.displayName = 'IOUPreview'; | |||||
export default compose( | ||||||
withLocalize, | ||||||
withOnyx({ | ||||||
personalDetails: { | ||||||
key: ONYXKEYS.PERSONAL_DETAILS, | ||||||
}, | ||||||
iouReport: { | ||||||
key: ({iouReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, | ||||||
}, | ||||||
|
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.
Coming from #18823:
This change was overlooked. There's another case of letter needs to be uppercased as well as first letter.
i.e. "Request CA$6.00"
This could have been caught earlier if we had tested this copy change in Spanish.