Skip to content

Commit

Permalink
Merge pull request #17964 from bernhardoj/fix/17662-refactor-iou-page
Browse files Browse the repository at this point in the history
  • Loading branch information
thienlnam authored Jun 21, 2023
2 parents 62323c4 + a2bef09 commit 7c04c2f
Show file tree
Hide file tree
Showing 24 changed files with 826 additions and 921 deletions.
30 changes: 14 additions & 16 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ const REPORT = 'r';
const IOU_REQUEST = 'request/new';
const IOU_BILL = 'split/new';
const IOU_SEND = 'send/new';
const IOU_REQUEST_CURRENCY = `${IOU_REQUEST}/currency`;
const IOU_BILL_CURRENCY = `${IOU_BILL}/currency`;
const IOU_SEND_CURRENCY = `${IOU_SEND}/currency`;
const NEW_TASK = 'new/task';
const SETTINGS_PERSONAL_DETAILS = 'settings/profile/personal-details';
const SETTINGS_CONTACT_METHODS = 'settings/profile/contact-methods';
Expand Down Expand Up @@ -77,22 +74,23 @@ export default {
IOU_REQUEST,
IOU_BILL,
IOU_SEND,
IOU_REQUEST_WITH_REPORT_ID: `${IOU_REQUEST}/:reportID?`,
IOU_BILL_WITH_REPORT_ID: `${IOU_BILL}/:reportID?`,
IOU_SEND_WITH_REPORT_ID: `${IOU_SEND}/:reportID?`,
getIouRequestRoute: (reportID) => `${IOU_REQUEST}/${reportID}`,
getIouSplitRoute: (reportID) => `${IOU_BILL}/${reportID}`,
getIOUSendRoute: (reportID) => `${IOU_SEND}/${reportID}`,
IOU_BILL_CURRENCY: `${IOU_BILL_CURRENCY}/:reportID?`,
IOU_REQUEST_CURRENCY: `${IOU_REQUEST_CURRENCY}/:reportID?`,
MONEY_REQUEST_DESCRIPTION: `${IOU_REQUEST}/description`,
IOU_SEND_CURRENCY: `${IOU_SEND_CURRENCY}/:reportID?`,

// To see the available iouType, please refer to CONST.IOU.MONEY_REQUEST_TYPE
MONEY_REQUEST: ':iouType/new/:reportID?',
MONEY_REQUEST_AMOUNT: ':iouType/new/amount/:reportID?',
MONEY_REQUEST_PARTICIPANTS: ':iouType/new/participants/:reportID?',
MONEY_REQUEST_CONFIRMATION: ':iouType/new/confirmation/:reportID?',
MONEY_REQUEST_CURRENCY: ':iouType/new/currency/:reportID?',
MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?',
IOU_SEND_ADD_BANK_ACCOUNT: `${IOU_SEND}/add-bank-account`,
IOU_SEND_ADD_DEBIT_CARD: `${IOU_SEND}/add-debit-card`,
IOU_SEND_ENABLE_PAYMENTS: `${IOU_SEND}/enable-payments`,
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}`,
getMoneyRequestRoute: (iouType, reportID = '') => `${iouType}/new/${reportID}`,
getMoneyRequestAmountRoute: (iouType, reportID = '') => `${iouType}/new/amount/${reportID}`,
getMoneyRequestParticipantsRoute: (iouType, reportID = '') => `${iouType}/new/participants/${reportID}`,
getMoneyRequestConfirmationRoute: (iouType, reportID = '') => `${iouType}/new/confirmation/${reportID}`,
getMoneyRequestCurrencyRoute: (iouType, reportID = '', currency, backTo) => `${iouType}/new/currency/${reportID}?currency=${currency}&backTo=${backTo}`,
getMoneyRequestDescriptionRoute: (iouType, reportID = '') => `${iouType}/new/description/${reportID}`,
SPLIT_BILL_DETAILS: `r/:reportID/split/:reportActionID`,
getSplitBillDetailsRoute: (reportID, reportActionID) => `r/${reportID}/split/${reportActionID}`,
getNewTaskRoute: (reportID) => `${NEW_TASK}/${reportID}`,
Expand Down
81 changes: 22 additions & 59 deletions src/components/MoneyRequestConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const propTypes = {
/** Callback to parent modal to send money */
onSendMoney: PropTypes.func,

/** Callback to inform a participant is selected */
onSelectParticipant: PropTypes.func,

/** Should we request a single or multiple participant selection from user */
hasMultipleParticipants: PropTypes.bool.isRequired,

Expand Down Expand Up @@ -66,31 +69,22 @@ const propTypes = {

/* Onyx Props */

/** Holds data related to IOU view state, rather than the underlying IOU data. */
iou: PropTypes.shape({
/** Whether or not the IOU step is loading (creating the IOU Report) */
loading: PropTypes.bool,
}),

/** Current user session */
session: PropTypes.shape({
email: PropTypes.string.isRequired,
}),

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

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

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

const defaultProps = {
onConfirm: () => {},
onSendMoney: () => {},
navigateToStep: () => {},
iou: {
loading: false,
},
onSelectParticipant: () => {},
iouType: CONST.IOU.MONEY_REQUEST_TYPE.REQUEST,
payeePersonalDetails: null,
canModifyParticipants: false,
Expand All @@ -100,13 +94,14 @@ const defaultProps = {
email: null,
},
policyID: '',
reportID: '',
...withCurrentUserPersonalDetailsDefaultProps,
};

function MoneyRequestConfirmationList(props) {
// Destructure functions from props to pass it as a dependecy to useCallback/useMemo hooks.
// Prop functions pass props itself as a "this" value to the function which means they change every time props change.
const {translate, onSendMoney, onConfirm} = props;
const {translate, onSendMoney, onConfirm, onSelectParticipant} = props;

/**
* Returns the participants with amount
Expand All @@ -121,13 +116,6 @@ function MoneyRequestConfirmationList(props) {
[props.iouAmount, props.iouCurrencyCode],
);

const getFormattedParticipants = () =>
_.map(getParticipantsWithAmount(props.participants), (participant) => ({
...participant,
selected: true,
}));

const [participants, setParticipants] = useState(getFormattedParticipants);
const [didConfirm, setDidConfirm] = useState(false);

const splitOrRequestOptions = useMemo(() => {
Expand All @@ -142,17 +130,15 @@ function MoneyRequestConfirmationList(props) {
];
}, [props.hasMultipleParticipants, props.iouAmount, props.iouCurrencyCode, translate]);

const selectedParticipants = useMemo(() => _.filter(participants, (participant) => participant.selected), [participants]);
const getParticipantsWithoutAmount = useCallback((participantsList) => _.map(participantsList, (option) => _.omit(option, 'descriptiveText')), []);
const selectedParticipants = useMemo(() => _.filter(props.participants, (participant) => participant.selected), [props.participants]);
const payeePersonalDetails = useMemo(() => props.payeePersonalDetails || props.currentUserPersonalDetails, [props.payeePersonalDetails, props.currentUserPersonalDetails]);

const optionSelectorSections = useMemo(() => {
const sections = [];
const unselectedParticipants = _.filter(participants, (participant) => !participant.selected);
const unselectedParticipants = _.filter(props.participants, (participant) => !participant.selected);
if (props.hasMultipleParticipants) {
const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants);
const formattedUnselectedParticipants = getParticipantsWithoutAmount(unselectedParticipants);
const formattedParticipantsList = _.union(formattedSelectedParticipants, formattedUnselectedParticipants);
const formattedParticipantsList = _.union(formattedSelectedParticipants, unselectedParticipants);

const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, props.iouAmount, true);
const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(
Expand All @@ -175,27 +161,15 @@ function MoneyRequestConfirmationList(props) {
},
);
} else {
const formattedParticipantsList = getParticipantsWithoutAmount(props.participants);
sections.push({
title: translate('common.to'),
data: formattedParticipantsList,
data: props.participants,
shouldShow: true,
indexOffset: 0,
});
}
return sections;
}, [
selectedParticipants,
getParticipantsWithAmount,
getParticipantsWithoutAmount,
props.hasMultipleParticipants,
props.iouAmount,
props.iouCurrencyCode,
props.participants,
participants,
translate,
payeePersonalDetails,
]);
}, [selectedParticipants, getParticipantsWithAmount, props.hasMultipleParticipants, props.iouAmount, props.iouCurrencyCode, props.participants, translate, payeePersonalDetails]);

const selectedOptions = useMemo(() => {
if (!props.hasMultipleParticipants) {
Expand All @@ -205,27 +179,17 @@ function MoneyRequestConfirmationList(props) {
}, [selectedParticipants, props.hasMultipleParticipants, payeePersonalDetails]);

/**
* Toggle selected option's selected prop.
* @param {Object} option
*/
const toggleOption = useCallback(
const selectParticipant = useCallback(
(option) => {
// Return early if selected option is currently logged in user.
if (option.accountID === props.session.accountID) {
return;
}

setParticipants((prevParticipants) => {
const newParticipants = _.map(prevParticipants, (participant) => {
if (participant.accountID === option.accountID) {
return {...participant, selected: !participant.selected};
}
return participant;
});
return newParticipants;
});
onSelectParticipant(option);
},
[props.session.accountID],
[props.session.accountID, onSelectParticipant],
);

/**
Expand Down Expand Up @@ -274,7 +238,7 @@ function MoneyRequestConfirmationList(props) {

const shouldShowSettlementButton = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.SEND;
const shouldDisableButton = selectedParticipants.length === 0;
const recipient = participants[0];
const recipient = props.participants[0] || {};

return shouldShowSettlementButton ? (
<SettlementButton
Expand All @@ -295,13 +259,13 @@ function MoneyRequestConfirmationList(props) {
options={splitOrRequestOptions}
/>
);
}, [confirm, participants, props.bankAccountRoute, props.iouCurrencyCode, props.iouType, props.isReadOnly, props.policyID, selectedParticipants, splitOrRequestOptions]);
}, [confirm, props.participants, props.bankAccountRoute, props.iouCurrencyCode, props.iouType, props.isReadOnly, props.policyID, selectedParticipants, splitOrRequestOptions]);

return (
<OptionsSelector
sections={optionSelectorSections}
value=""
onSelectRow={canModifyParticipants ? toggleOption : navigateToUserDetail}
onSelectRow={canModifyParticipants ? selectParticipant : navigateToUserDetail}
onConfirmSelection={confirm}
selectedOptions={selectedOptions}
canSelectMultipleOptions={canModifyParticipants}
Expand All @@ -318,7 +282,7 @@ function MoneyRequestConfirmationList(props) {
shouldShowRightIcon={!props.isReadOnly}
title={formattedAmount}
description={translate('iou.amount')}
onPress={() => props.navigateToStep(0)}
onPress={() => Navigation.navigate(ROUTES.getMoneyRequestAmountRoute(props.iouType, props.reportID))}
style={[styles.moneyRequestMenuItem, styles.mt2]}
titleStyle={styles.moneyRequestConfirmationAmount}
disabled={didConfirm || props.isReadOnly}
Expand All @@ -327,7 +291,7 @@ function MoneyRequestConfirmationList(props) {
shouldShowRightIcon={!props.isReadOnly}
title={props.iouComment}
description={translate('common.description')}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DESCRIPTION)}
onPress={() => Navigation.navigate(ROUTES.getMoneyRequestDescriptionRoute(props.iouType, props.reportID))}
style={[styles.moneyRequestMenuItem, styles.mb2]}
disabled={didConfirm || props.isReadOnly}
/>
Expand All @@ -343,7 +307,6 @@ export default compose(
withWindowDimensions,
withCurrentUserPersonalDetails,
withOnyx({
iou: {key: ONYXKEYS.IOU},
session: {
key: ONYXKEYS.SESSION,
},
Expand Down
11 changes: 10 additions & 1 deletion src/libs/IOUUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,13 @@ function isIOUReportPendingCurrencyConversion(reportActions, iouReport) {
return hasPendingRequests;
}

export {calculateAmount, updateIOUOwnerAndTotal, getIOUReportActions, isIOUReportPendingCurrencyConversion};
/**
* Checks if the iou type is one of request, send, or split.
* @param {String} iouType
* @returns {Boolean}
*/
function isValidMoneyRequestType(iouType) {
return [CONST.IOU.MONEY_REQUEST_TYPE.REQUEST, CONST.IOU.MONEY_REQUEST_TYPE.SEND, CONST.IOU.MONEY_REQUEST_TYPE.SPLIT].includes(iouType);
}

export {calculateAmount, updateIOUOwnerAndTotal, getIOUReportActions, isIOUReportPendingCurrencyConversion, isValidMoneyRequestType};
53 changes: 19 additions & 34 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,37 +32,41 @@ function createModalStackNavigator(screens) {
}

// We use getComponent/require syntax so that file used by screens are not loaded until we need them.
const IOUBillStackNavigator = createModalStackNavigator([
const MoneyRequestModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const IOUBillPage = require('../../../pages/iou/IOUBillPage').default;
return IOUBillPage;
const MoneyRequestAmountPage = require('../../../pages/iou/steps/MoneyRequestAmountPage').default;
return MoneyRequestAmountPage;
},
name: 'IOU_Bill_Root',
name: 'Money_Request',
},
{
getComponent: () => {
const IOUCurrencySelection = require('../../../pages/iou/IOUCurrencySelection').default;
return IOUCurrencySelection;
const MoneyRequestEditAmountPage = require('../../../pages/iou/steps/MoneyRequestAmountPage').default;
return MoneyRequestEditAmountPage;
},
name: 'IOU_Bill_Currency',
name: 'Money_Request_Amount',
},
{
getComponent: () => {
const MoneyRequestParticipantsPage = require('../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default;
return MoneyRequestParticipantsPage;
},
name: 'Money_Request_Participants',
},
]);

const IOURequestModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const IOURequestPage = require('../../../pages/iou/IOURequestPage').default;
return IOURequestPage;
const MoneyRequestConfirmPage = require('../../../pages/iou/steps/MoneyRequestConfirmPage').default;
return MoneyRequestConfirmPage;
},
name: 'IOU_Request_Root',
name: 'Money_Request_Confirmation',
},
{
getComponent: () => {
const IOUCurrencySelection = require('../../../pages/iou/IOUCurrencySelection').default;
return IOUCurrencySelection;
},
name: 'IOU_Request_Currency',
name: 'Money_Request_Currency',
},
{
getComponent: () => {
Expand All @@ -71,23 +75,6 @@ const IOURequestModalStackNavigator = createModalStackNavigator([
},
name: 'Money_Request_Description',
},
]);

const IOUSendModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const IOUSendPage = require('../../../pages/iou/IOUSendPage').default;
return IOUSendPage;
},
name: 'IOU_Send_Root',
},
{
getComponent: () => {
const IOUCurrencySelection = require('../../../pages/iou/IOUCurrencySelection').default;
return IOUCurrencySelection;
},
name: 'IOU_Send_Currency',
},
{
getComponent: () => {
const AddPersonalBankAccountPage = require('../../../pages/AddPersonalBankAccountPage').default;
Expand Down Expand Up @@ -730,9 +717,7 @@ const FlagCommentStackNavigator = createModalStackNavigator([
]);

export {
IOUBillStackNavigator,
IOURequestModalStackNavigator,
IOUSendModalStackNavigator,
MoneyRequestModalStackNavigator,
SplitDetailsModalStackNavigator,
DetailsModalStackNavigator,
ProfileModalStackNavigator,
Expand Down
14 changes: 2 additions & 12 deletions src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ function RigthModalNavigator() {
component={ModalStackNavigators.ReportParticipantsModalStackNavigator}
/>
<Stack.Screen
name="IOU_Request"
name="MoneyRequest"
options={defaultModalScreenOptions}
component={ModalStackNavigators.IOURequestModalStackNavigator}
component={ModalStackNavigators.MoneyRequestModalStackNavigator}
/>
<Stack.Screen
name="NewTask"
Expand All @@ -74,11 +74,6 @@ function RigthModalNavigator() {
options={defaultModalScreenOptions}
component={ModalStackNavigators.TaskModalStackNavigator}
/>
<Stack.Screen
name="IOU_Bill"
options={defaultModalScreenOptions}
component={ModalStackNavigators.IOUBillStackNavigator}
/>
<Stack.Screen
name="EnablePayments"
options={defaultModalScreenOptions}
Expand All @@ -94,11 +89,6 @@ function RigthModalNavigator() {
options={defaultModalScreenOptions}
component={ModalStackNavigators.AddPersonalBankAccountModalStackNavigator}
/>
<Stack.Screen
name="IOU_Send"
options={defaultModalScreenOptions}
component={ModalStackNavigators.IOUSendModalStackNavigator}
/>
<Stack.Screen
name="Wallet_Statement"
options={defaultModalScreenOptions}
Expand Down
Loading

0 comments on commit 7c04c2f

Please sign in to comment.