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

Build read-only bill split details page #19390

Merged
merged 54 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
c590fe6
add split details route
luacmartins May 18, 2023
b84cb09
create details page
luacmartins May 18, 2023
08e5ec1
update route
luacmartins May 18, 2023
bf8f3d8
pass chatReportID to route
luacmartins May 18, 2023
bd6a0dc
add SplitBillDetailsPage
luacmartins May 18, 2023
c5900ac
update page
luacmartins May 18, 2023
c1b2bec
use right participants
luacmartins May 18, 2023
46fdadd
rm unused prop
luacmartins May 18, 2023
5f40115
Merge branch 'main' into cmartins-fixSplitDetails
luacmartins May 19, 2023
9210b3e
add modal header
luacmartins May 19, 2023
561e1ef
disable editing in details page
luacmartins May 19, 2023
5a33228
rm button from details page
luacmartins May 19, 2023
8585770
fix prop type, add screenwrapper
luacmartins May 19, 2023
36826ab
fix style
luacmartins May 19, 2023
5a98489
update incorrect component name
Julesssss May 22, 2023
e4442e1
create split details navigation route
Julesssss May 22, 2023
5c12e00
launch new route when bill split IOUPreview is tapped
Julesssss May 22, 2023
31c4efb
fix split details routing
Julesssss May 22, 2023
89c8c3b
display new split details page instead of participants
Julesssss May 22, 2023
5f7f5a8
reuse IOUConfirmationList component within SplitDetailsPage
Julesssss May 22, 2023
f2dbf54
remove props from read-only request confirmation comp
Julesssss May 22, 2023
a02033f
add readOnly mode to RequestConfirmationList
Julesssss May 22, 2023
eb9973a
completely remove participants list from split details page
Julesssss May 22, 2023
0e74bd7
fix outstanding lint issues
Julesssss May 22, 2023
d52719c
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 22, 2023
448942a
disable the editable fields when in read-only mode
Julesssss May 23, 2023
5ae444e
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 23, 2023
8413236
prevent exception by rending 404 page when action missing
Julesssss May 23, 2023
a20ca87
pass the reportActionID to the SplitDetailsPage component via URL route
Julesssss May 23, 2023
f6be7e6
retrieve reportActions within SplitDetailsPage using chatReportID
Julesssss May 23, 2023
6ca85da
retrieve split reportAction from Onyx using route param
Julesssss May 23, 2023
a1002b6
when showing split details, get amount from the reportAction
Julesssss May 23, 2023
b18e838
remove split creator from the participants array to avoid invalid lis…
Julesssss May 23, 2023
091019a
hide chevron from split details when in read-only mode
Julesssss May 23, 2023
125798d
move SplitDetailsPage to iou pages folder
Julesssss May 23, 2023
750a3ee
Merge branch 'main' into cmartins-fixSplitDetails
Julesssss May 23, 2023
4c72eea
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 23, 2023
58d1d75
fix lint issues
Julesssss May 23, 2023
80f1966
Merge branch 'jules-buildReadOnlySplitConfirmationPage' into cmartins…
Julesssss May 23, 2023
37666fe
Merge pull request #19452 from Expensify/cmartins-fixSplitDetails
Julesssss May 23, 2023
b1e3d8f
switch to Carlos' stack navigator
Julesssss May 23, 2023
9c56718
further formatting and prettier fixes
Julesssss May 23, 2023
9f97480
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 24, 2023
8444113
improve navigation routing
Julesssss May 24, 2023
7d4e046
apply review feedback, refactor participants and footer logic
Julesssss May 24, 2023
81909f0
show payee instead of authenticated user, plus other formatting fixes
Julesssss May 24, 2023
669884d
make the request confirmation payee dynamic
Julesssss May 24, 2023
f5e5b7f
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 25, 2023
f9e144d
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 25, 2023
f402d46
further read-only split details page improvements based on feedback
Julesssss May 25, 2023
24781eb
apply prettier change
Julesssss May 25, 2023
ea1882a
Merge branch 'main' into jules-buildReadOnlySplitConfirmationPage
Julesssss May 26, 2023
693ebe3
further improvements to split bill details page
Julesssss May 26, 2023
f2024d0
fix secondary route for split bill page
Julesssss May 26, 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
2 changes: 2 additions & 0 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ export default {
getIouRequestCurrencyRoute: (reportID, currency, backTo) => `${IOU_REQUEST_CURRENCY}/${reportID}?currency=${currency}&backTo=${backTo}`,
getIouBillCurrencyRoute: (reportID, currency, backTo) => `${IOU_BILL_CURRENCY}/${reportID}?currency=${currency}&backTo=${backTo}`,
getIouSendCurrencyRoute: (reportID, currency, backTo) => `${IOU_SEND_CURRENCY}/${reportID}?currency=${currency}&backTo=${backTo}`,
SPLIT_BILL_DETAILS: `/:reportID/split/:reportActionID`,
getSplitBillDetailsRoute: (reportID, reportActionID) => `/${reportID}/split/${reportActionID}`,
Julesssss marked this conversation as resolved.
Show resolved Hide resolved
getNewTaskRoute: (reportID) => `${NEW_TASK}/${reportID}`,
NEW_TASK_WITH_REPORT_ID: `${NEW_TASK}/:reportID?`,
TASK_TITLE: 'r/:reportID/title',
Expand Down
105 changes: 68 additions & 37 deletions src/components/MoneyRequestConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import * as CurrencyUtils from '../libs/CurrencyUtils';

const propTypes = {
/** Callback to inform parent modal of success */
onConfirm: PropTypes.func.isRequired,
onConfirm: PropTypes.func,

/** Callback to parent modal to send money */
onSendMoney: PropTypes.func.isRequired,
onSendMoney: PropTypes.func,

/** Should we request a single or multiple participant selection from user */
hasMultipleParticipants: PropTypes.bool.isRequired,
Expand All @@ -40,11 +40,17 @@ const propTypes = {
/** Selected participants from MoneyRequestModal with login */
participants: PropTypes.arrayOf(optionPropTypes).isRequired,

/** Payee of the money request with login */
payeePersonalDetails: optionPropTypes,

/** Can the participants be modified or not */
canModifyParticipants: PropTypes.bool,

/** Should the list be read only, and not editable? */
isReadOnly: PropTypes.bool,

/** Depending on expense report or personal IOU report, respective bank account route */
bankAccountRoute: PropTypes.string.isRequired,
bankAccountRoute: PropTypes.string,

...windowDimensionsPropTypes,

Expand All @@ -69,18 +75,24 @@ const propTypes = {
}),

/** Callback function to navigate to a provided step in the MoneyRequestModal flow */
navigateToStep: PropTypes.func.isRequired,
navigateToStep: PropTypes.func,

/** The policyID of the request */
policyID: PropTypes.string,
};

const defaultProps = {
onConfirm: () => {},
onSendMoney: () => {},
navigateToStep: () => {},
iou: {
selectedCurrencyCode: CONST.CURRENCY.USD,
},
iouType: CONST.IOU.MONEY_REQUEST_TYPE.REQUEST,
payee: null,
Julesssss marked this conversation as resolved.
Show resolved Hide resolved
canModifyParticipants: false,
isReadOnly: false,
bankAccountRoute: '',
session: {
email: null,
},
Expand Down Expand Up @@ -158,6 +170,18 @@ class MoneyRequestConfirmationList extends Component {
return _.map(participants, (option) => _.omit(option, 'descriptiveText'));
}

/**
* Returns the personalDetails object for the requester
Julesssss marked this conversation as resolved.
Show resolved Hide resolved
*
* @returns {Object} personalDetails
*/
getRequestorPersonalDetails() {
Julesssss marked this conversation as resolved.
Show resolved Hide resolved
if (this.props.payeePersonalDetails) {
return this.props.payeePersonalDetails;
}
return this.props.currentUserPersonalDetails;
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Returns the sections needed for the OptionsSelector
*
Expand All @@ -174,15 +198,15 @@ class MoneyRequestConfirmationList extends Component {
const formattedParticipants = _.union(formattedSelectedParticipants, formattedUnselectedParticipants);

const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, this.props.iouAmount, true);
const formattedMyPersonalDetails = OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(
this.props.currentUserPersonalDetails,
const formattedPayeePersonalDetails = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(
this.getRequestorPersonalDetails(),
CurrencyUtils.convertToDisplayString(myIOUAmount, this.props.iou.selectedCurrencyCode),
);

sections.push(
{
title: this.props.translate('moneyRequestConfirmationList.whoPaid'),
data: [formattedMyPersonalDetails],
data: [formattedPayeePersonalDetails],
shouldShow: true,
indexOffset: 0,
isDisabled: true,
Expand All @@ -206,6 +230,36 @@ class MoneyRequestConfirmationList extends Component {
return sections;
}

getFooterContent() {
if (this.props.isReadOnly) {
return;
}

const selectedParticipants = this.getSelectedParticipants();
const shouldShowSettlementButton = this.props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.SEND;
const shouldDisableButton = selectedParticipants.length === 0;
const recipient = this.state.participants[0];

return shouldShowSettlementButton ? (
<SettlementButton
isDisabled={shouldDisableButton}
onPress={this.confirm}
shouldShowPaypal={Boolean(recipient.payPalMeAddress)}
enablePaymentsRoute={ROUTES.IOU_SEND_ENABLE_PAYMENTS}
addBankAccountRoute={this.props.bankAccountRoute}
addDebitCardRoute={ROUTES.IOU_SEND_ADD_DEBIT_CARD}
currency={this.props.iou.selectedCurrencyCode}
policyID={this.props.policyID}
/>
) : (
<ButtonWithDropdownMenu
isDisabled={shouldDisableButton}
onPress={(_event, value) => this.confirm(value)}
options={this.getSplitOrRequestOptions()}
/>
);
}

/**
* Returns selected options -- there is checkmark for every row in List for split flow
* @returns {Array}
Expand All @@ -215,7 +269,7 @@ class MoneyRequestConfirmationList extends Component {
return [];
}
const selectedParticipants = this.getSelectedParticipants();
return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(this.props.currentUserPersonalDetails)];
return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(this.getRequestorPersonalDetails())];
}

/**
Expand Down Expand Up @@ -263,11 +317,7 @@ class MoneyRequestConfirmationList extends Component {
}

render() {
const selectedParticipants = this.getSelectedParticipants();
const shouldShowSettlementButton = this.props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.SEND;
const shouldDisableButton = selectedParticipants.length === 0;
const recipient = this.state.participants[0];
const canModifyParticipants = this.props.canModifyParticipants && this.props.hasMultipleParticipants;
const canModifyParticipants = !this.props.isReadOnly && this.props.canModifyParticipants && this.props.hasMultipleParticipants;
const formattedAmount = CurrencyUtils.convertToDisplayString(this.props.iouAmount, this.props.iou.selectedCurrencyCode);

return (
Expand All @@ -285,43 +335,24 @@ class MoneyRequestConfirmationList extends Component {
shouldShowTextInput={false}
shouldUseStyleForChildren={false}
optionHoveredStyle={canModifyParticipants ? styles.hoveredComponentBG : {}}
footerContent={
shouldShowSettlementButton ? (
<SettlementButton
isDisabled={shouldDisableButton}
onPress={this.confirm}
shouldShowPaypal={Boolean(recipient.payPalMeAddress)}
enablePaymentsRoute={ROUTES.IOU_SEND_ENABLE_PAYMENTS}
addBankAccountRoute={this.props.bankAccountRoute}
addDebitCardRoute={ROUTES.IOU_SEND_ADD_DEBIT_CARD}
currency={this.props.iou.selectedCurrencyCode}
policyID={this.props.policyID}
/>
) : (
<ButtonWithDropdownMenu
isDisabled={shouldDisableButton}
onPress={(_event, value) => this.confirm(value)}
options={this.getSplitOrRequestOptions()}
/>
)
}
footerContent={this.getFooterContent()}
>
<MenuItemWithTopDescription
shouldShowRightIcon
shouldShowRightIcon={!this.props.isReadOnly}
title={formattedAmount}
description={this.props.translate('iou.amount')}
onPress={() => this.props.navigateToStep(0)}
style={[styles.moneyRequestMenuItem, styles.mt2]}
titleStyle={styles.moneyRequestConfirmationAmount}
disabled={this.state.didConfirm}
disabled={this.state.didConfirm || this.props.isReadOnly}
/>
<MenuItemWithTopDescription
shouldShowRightIcon
shouldShowRightIcon={!this.props.isReadOnly}
title={this.props.iou.comment}
description={this.props.translate('common.description')}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DESCRIPTION)}
style={[styles.moneyRequestMenuItem, styles.mb2]}
disabled={this.state.didConfirm}
disabled={this.state.didConfirm || this.props.isReadOnly}
/>
</OptionsSelector>
);
Expand Down
3 changes: 2 additions & 1 deletion src/components/OptionsSelector/BaseOptionsSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ class BaseOptionsSelector extends Component {
}

render() {
const shouldShowFooter = (this.props.shouldShowConfirmButton || this.props.footerContent) && !(this.props.canSelectMultipleOptions && _.isEmpty(this.props.selectedOptions));
const shouldShowFooter =
!this.props.isReadOnly && (this.props.shouldShowConfirmButton || this.props.footerContent) && !(this.props.canSelectMultipleOptions && _.isEmpty(this.props.selectedOptions));
const defaultConfirmButtonText = _.isUndefined(this.props.confirmButtonText) ? this.props.translate('common.confirm') : this.props.confirmButtonText;
const shouldShowDefaultConfirmButton = !this.props.footerContent && defaultConfirmButtonText;
const textInput = (
Expand Down
6 changes: 3 additions & 3 deletions src/components/ReportActionItem/MoneyRequestAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ const defaultProps = {
};

const MoneyRequestAction = (props) => {
const hasMultipleParticipants = lodashGet(props.chatReport, 'participants', []).length > 1;
const isSplitBillAction = lodashGet(props.action, 'originalMessage.type', '') === CONST.IOU.REPORT_ACTION_TYPE.SPLIT;

const onIOUPreviewPressed = () => {
if (isSplitBillAction && hasMultipleParticipants) {
Navigation.navigate(ROUTES.getReportParticipantsRoute(props.chatReportID));
if (isSplitBillAction) {
const reportActionID = lodashGet(props.action, 'reportActionID', '0');
Navigation.navigate(ROUTES.getSplitBillDetailsRoute(props.chatReportID, reportActionID));
return;
}

Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,12 @@ class AuthScreens extends React.Component {
component={ModalStackNavigators.EnablePaymentsStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name="SplitDetails"
options={modalScreenOptions}
component={ModalStackNavigators.SplitDetailsModalStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name="AddPersonalBankAccount"
options={modalScreenOptions}
Expand Down
11 changes: 11 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ const IOUSendModalStackNavigator = createModalStackNavigator([
},
]);

const SplitDetailsModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const SplitBillDetailsPage = require('../../../pages/iou/SplitBillDetailsPage').default;
return SplitBillDetailsPage;
},
name: 'SplitDetails_Root',
},
]);

const DetailsModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
Expand Down Expand Up @@ -679,6 +689,7 @@ export {
IOUBillStackNavigator,
IOURequestModalStackNavigator,
IOUSendModalStackNavigator,
SplitDetailsModalStackNavigator,
DetailsModalStackNavigator,
ReportDetailsModalStackNavigator,
TaskModalStackNavigator,
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ export default {
IOU_Send_Add_Debit_Card: ROUTES.IOU_SEND_ADD_DEBIT_CARD,
},
},
SplitDetails: {
screens: {
SplitDetails_Root: ROUTES.SPLIT_BILL_DETAILS,
},
},
Task_Details: {
screens: {
Task_Title: ROUTES.TASK_TITLE,
Expand Down
18 changes: 9 additions & 9 deletions src/libs/OptionsListUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -785,25 +785,25 @@ function getSearchOptions(reports, personalDetails, searchValue = '', betas) {
}

/**
* Build the IOUConfirmation options for showing MyPersonalDetail
* Build the IOUConfirmation options for showing the payee personalDetail
*
* @param {Object} myPersonalDetail
* @param {Object} personalDetail
* @param {String} amountText
* @returns {Object}
*/
function getIOUConfirmationOptionsFromMyPersonalDetail(myPersonalDetail, amountText) {
function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail, amountText) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This can now be any user, not just the authenticated one

return {
text: myPersonalDetail.displayName,
alternateText: myPersonalDetail.login,
text: personalDetail.displayName ? personalDetail.displayName : personalDetail.login,
alternateText: personalDetail.login,
icons: [
{
source: ReportUtils.getAvatar(myPersonalDetail.avatar, myPersonalDetail.login),
name: myPersonalDetail.login,
source: ReportUtils.getAvatar(personalDetail.avatar, personalDetail.login),
name: personalDetail.login,
type: CONST.ICON_TYPE_AVATAR,
},
],
descriptiveText: amountText,
login: myPersonalDetail.login,
login: personalDetail.login,
};
}

Expand Down Expand Up @@ -944,7 +944,7 @@ export {
getMemberInviteOptions,
getHeaderMessage,
getPersonalDetailsForLogins,
getIOUConfirmationOptionsFromMyPersonalDetail,
getIOUConfirmationOptionsFromPayeePersonalDetail,
getIOUConfirmationOptionsFromParticipants,
getSearchText,
getAllReportErrors,
Expand Down
Loading