From dd0eb360c589858085f88a43a4c2f0b7c00cc99d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 07:26:52 +0700 Subject: [PATCH 01/24] Allow selecting a payer from the splits page --- src/ROUTES.ts | 5 ++ src/SCREENS.ts | 1 + ...raryForRefactorRequestConfirmationList.tsx | 80 +++++++++++------ src/languages/en.ts | 3 +- src/languages/es.ts | 1 + src/libs/API/parameters/SplitBillParams.ts | 1 + .../ModalStackNavigators/index.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 1 + src/libs/Navigation/types.ts | 6 ++ src/libs/OptionsListUtils.ts | 9 +- src/libs/actions/IOU.ts | 15 +++- .../iou/request/step/IOURequestStepAmount.tsx | 2 +- .../step/IOURequestStepConfirmation.tsx | 11 +-- .../request/step/IOURequestStepDistance.tsx | 2 +- .../step/IOURequestStepScan/index.native.tsx | 2 +- .../request/step/IOURequestStepScan/index.tsx | 2 +- .../request/step/IOURequestStepSplitPayer.tsx | 88 +++++++++++++++++++ .../step/IOURequestStepTaxAmountPage.tsx | 2 +- src/types/onyx/Transaction.ts | 3 + 19 files changed, 193 insertions(+), 42 deletions(-) create mode 100644 src/pages/iou/request/step/IOURequestStepSplitPayer.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index ec2bf11957e1..f89085be723b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -380,6 +380,11 @@ const ROUTES = { getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '', action: ValueOf = 'create') => getUrlWithBackToParam(`${action}/${iouType}/participants/${transactionID}/${reportID}`, backTo), }, + MONEY_REQUEST_STEP_SPLIT_PAYER: { + route: ':action/:iouType/confirmation/:transactionID/:reportID/payer', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, action: ValueOf = 'create') => + `${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer`, + }, MONEY_REQUEST_STEP_SCAN: { route: ':action/:iouType/scan/:transactionID/:reportID', getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 96372d5bbabb..dcc333559300 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -155,6 +155,7 @@ const SCREENS = { STEP_WAYPOINT: 'Money_Request_Step_Waypoint', STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount', STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate', + STEP_SPLIT_PAYER: 'Money_Request_Step_Split_Payer', PARTICIPANTS: 'Money_Request_Participants', CURRENCY: 'Money_Request_Currency', WAYPOINT: 'Money_Request_Waypoint', diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index f460b9d8e88c..a005240c7354 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -28,6 +28,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as TransactionUtils from '@libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; +import * as UserUtils from '@libs/UserUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -43,7 +44,9 @@ import ConfirmedRoute from './ConfirmedRoute'; import ConfirmModal from './ConfirmModal'; import FormHelpMessage from './FormHelpMessage'; import * as Expensicons from './Icon/Expensicons'; +import MenuItem from './MenuItem'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; +import {usePersonalDetails} from './OnyxProvider'; import OptionsSelector from './OptionsSelector'; import PDFThumbnail from './PDFThumbnail'; import ReceiptEmptyState from './ReceiptEmptyState'; @@ -113,7 +116,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & selectedParticipants: Participant[]; /** Payee of the money request with login */ - payeePersonalDetails?: OnyxTypes.PersonalDetails; + payeePersonalDetails?: OnyxEntry; /** Can the participants be modified or not */ canModifyParticipants?: boolean; @@ -214,6 +217,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetails = usePersonalDetails(); const {canUseViolations} = usePermissions(); const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST; @@ -347,9 +351,15 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ * Returns the participants with amount */ const getParticipantsWithAmount = useCallback( - (participantsList: Participant[]) => { - const amount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? ''); - return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(participantsList, amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : ''); + (participantsList: Participant[], payerAccountID: number) => { + const amount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? ''); + const payerAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); + return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( + participantsList, + amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : '', + payerAmount > 0 ? CurrencyUtils.convertToDisplayString(payerAmount, iouCurrencyCode) : '', + payerAccountID, + ); }, [iouAmount, iouCurrencyCode], ); @@ -384,17 +394,25 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const selectedParticipants = useMemo(() => pickedParticipants.filter((participant) => participant.selected), [pickedParticipants]); const personalDetailsOfPayee = useMemo(() => payeePersonalDetails ?? currentUserPersonalDetails, [payeePersonalDetails, currentUserPersonalDetails]); + const payeeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs([personalDetailsOfPayee.accountID], personalDetails), false); + const payeeIcons = [ + { + source: UserUtils.getAvatar(personalDetailsOfPayee.avatar, personalDetailsOfPayee.accountID), + name: personalDetailsOfPayee.login ?? '', + type: CONST.ICON_TYPE_AVATAR, + id: personalDetailsOfPayee.accountID, + }, + ]; const userCanModifyParticipants = useRef(!isReadOnly && canModifyParticipants && hasMultipleParticipants); useEffect(() => { userCanModifyParticipants.current = !isReadOnly && canModifyParticipants && hasMultipleParticipants; }, [isReadOnly, canModifyParticipants, hasMultipleParticipants]); - const shouldDisablePaidBySection = userCanModifyParticipants.current; const optionSelectorSections = useMemo(() => { const sections = []; const unselectedParticipants = pickedParticipants.filter((participant) => !participant.selected); if (hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); + const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants, personalDetailsOfPayee.accountID); let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; if (!canModifyParticipants) { @@ -402,27 +420,18 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ...participant, isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), })); + } else { + formattedParticipantsList = formattedParticipantsList.map((participant) => ({ + ...participant, + isDisabled: participant.accountID === personalDetailsOfPayee.accountID, + })); } - const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, iouAmount, iouCurrencyCode ?? '', true); - const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( - personalDetailsOfPayee, - iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', - ); - - sections.push( - { - title: translate('moneyRequestConfirmationList.paidBy'), - data: [formattedPayeeOption], - shouldShow: true, - isDisabled: shouldDisablePaidBySection, - }, - { - title: translate('moneyRequestConfirmationList.splitWith'), - data: formattedParticipantsList, - shouldShow: true, - }, - ); + sections.push({ + title: translate('moneyRequestConfirmationList.splitAmounts'), + data: formattedParticipantsList, + shouldShow: true, + }); } else { const formattedSelectedParticipants = selectedParticipants.map((participant) => ({ ...participant, @@ -439,12 +448,9 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ selectedParticipants, pickedParticipants, hasMultipleParticipants, - iouAmount, - iouCurrencyCode, getParticipantsWithAmount, personalDetailsOfPayee, translate, - shouldDisablePaidBySection, canModifyParticipants, ]); @@ -646,6 +652,24 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ // An intermediate structure that helps us classify the fields as "primary" and "supplementary". // The primary fields are always shown to the user, while an extra action is needed to reveal the supplementary ones. const classifiedFields = [ + { + item: ( + { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID)); + }} + shouldShowRightIcon + titleWithTooltips={payeeTooltipDetails} + /> + ), + shouldShow: isTypeSplit, + isSupplementary: false, + }, { item: ( require('../../../../pages/iou/request/step/IOURequestStepScan').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_TAG]: () => require('../../../../pages/iou/request/step/IOURequestStepTag').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: () => require('../../../../pages/iou/request/step/IOURequestStepWaypoint').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.STEP_SPLIT_PAYER]: () => require('../../../../pages/iou/request/step/IOURequestStepSplitPayer').default as React.ComponentType, [SCREENS.MONEY_REQUEST.PARTICIPANTS]: () => require('../../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.HOLD]: () => require('../../../../pages/iou/HoldReasonPage').default as React.ComponentType, [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: () => require('../../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 6165ccb16fa3..68b450109d1a 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -579,6 +579,7 @@ const config: LinkingOptions['config'] = { [SCREENS.MONEY_REQUEST.PARTICIPANTS]: ROUTES.MONEY_REQUEST_PARTICIPANTS.route, [SCREENS.MONEY_REQUEST.RECEIPT]: ROUTES.MONEY_REQUEST_RECEIPT.route, [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route, exact: true}, + [SCREENS.MONEY_REQUEST.STEP_SPLIT_PAYER]: ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.route, [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS, [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT, [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 8273278f971e..4af49d4a10bf 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -432,6 +432,12 @@ type MoneyRequestNavigatorParamList = { reportID: string; backTo: Routes; }; + [SCREENS.MONEY_REQUEST.STEP_SPLIT_PAYER]: { + action: ValueOf; + iouType: ValueOf; + transactionID: string; + reportID: string; + }; [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: undefined; [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: undefined; [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: undefined; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index aa16d7b2dc5a..438964f9659b 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1962,10 +1962,15 @@ function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: Person /** * Build the IOUConfirmationOptions for showing participants */ -function getIOUConfirmationOptionsFromParticipants(participants: Array, amountText: string): Array { +function getIOUConfirmationOptionsFromParticipants( + participants: Array, + amountText: string, + payerAmountText = '', + payerAccountID = -1, +): Array { return participants.map((participant) => ({ ...participant, - descriptiveText: amountText, + descriptiveText: participant.accountID === payerAccountID ? payerAmountText : amountText, })); } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 896b88988818..dcde22604b18 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -442,6 +442,10 @@ function setMoneyRequestParticipants_temporaryForRefactor(transactionID: string, Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {participants}); } +function setSplitPayer(transactionID: string, payerAccountID: number) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {splitPayerAccountIDs: [payerAccountID]}); +} + function setMoneyRequestReceipt(transactionID: string, source: string, filename: string, isDraft: boolean, type?: string) { Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { receipt: {source, type: type ?? ''}, @@ -3506,6 +3510,7 @@ type SplitBillActionsParams = { billable?: boolean; iouRequestType?: IOURequestType; existingSplitChatReportID?: string; + splitPayerAccoutIDs?: number[]; }; /** @@ -3526,6 +3531,7 @@ function splitBill({ billable = false, iouRequestType = CONST.IOU.REQUEST_TYPE.MANUAL, existingSplitChatReportID = '', + splitPayerAccoutIDs = [], }: SplitBillActionsParams) { const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created); const {splitData, splits, onyxData} = createSplitsAndOnyxData( @@ -3560,6 +3566,7 @@ function splitBill({ createdReportActionID: splitData.createdReportActionID, policyID: splitData.policyID, chatType: splitData.chatType, + splitPayerAccoutIDs, }; API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData); @@ -3619,6 +3626,7 @@ function splitBillAndOpenReport({ createdReportActionID: splitData.createdReportActionID, policyID: splitData.policyID, chatType: splitData.chatType, + splitPayerAccoutIDs: [], }; API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData); @@ -5800,7 +5808,7 @@ function replaceReceipt(transactionID: string, file: File, source: string) { * @param transactionID of the transaction to set the participants of * @param report attached to the transaction */ -function setMoneyRequestParticipantsFromReport(transactionID: string, report: OnyxEntry) { +function setMoneyRequestParticipantsFromReport(transactionID: string, report: OnyxEntry, iouType: ValueOf) { // If the report is iou or expense report, we should get the chat report to set participant for request money const chatReport = ReportUtils.isMoneyRequestReport(report) ? ReportUtils.getReport(report?.chatReportID) : report; const currentUserAccountID = currentUserPersonalDetails.accountID; @@ -5810,6 +5818,10 @@ function setMoneyRequestParticipantsFromReport(transactionID: string, report: On ? [{accountID: 0, reportID: chatReport?.reportID, isPolicyExpenseChat: ReportUtils.isPolicyExpenseChat(chatReport), selected: true}] : (chatReport?.participantAccountIDs ?? []).filter((accountID) => currentUserAccountID !== accountID).map((accountID) => ({accountID, selected: true})); + if (iouType === CONST.IOU.TYPE.SPLIT) { + participants.push({accountID: currentUserAccountID, selected: true}); + } + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {participants, participantsAutoAssigned: true}); } @@ -6029,6 +6041,7 @@ export { setMoneyRequestPendingFields, setMoneyRequestReceipt, setMoneyRequestAmount, + setSplitPayer, setMoneyRequestBillable, setMoneyRequestCategory, setMoneyRequestCurrency, diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 690a7e3d9d0d..92828b59952a 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -118,7 +118,7 @@ function IOURequestStepAmount({ // inside a report. In this case, the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirm step. if (report?.reportID) { - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 46e663956e4a..999302c69945 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -78,6 +78,7 @@ function IOURequestStepConfirmation({ const isSharingTrackExpense = action === CONST.IOU.ACTION.SHARE; const isCategorizingTrackExpense = action === CONST.IOU.ACTION.CATEGORIZE; const isRequestingFromTrackExpense = action === CONST.IOU.ACTION.MOVE; + const payeePersonalDetails = personalDetails?.[transaction?.splitPayerAccountIDs?.[0] ?? -1]; const requestType = TransactionUtils.getRequestType(transaction); @@ -103,14 +104,12 @@ function IOURequestStepConfirmation({ return translate(TransactionUtils.getHeaderTitleTranslationKey(transaction)); }, [iouType, transaction, translate, isSharingTrackExpense, isCategorizingTrackExpense, isRequestingFromTrackExpense]); - const participants = useMemo( - () => + const participants = useMemo(() => ( transaction?.participants?.map((participant) => { const participantAccountID = participant.accountID ?? 0; return participantAccountID ? OptionsListUtils.getParticipantsOption(participant, personalDetails) : OptionsListUtils.getReportOption(participant); - }) ?? [], - [transaction?.participants, personalDetails], - ); + }) ?? [] + ), [transaction?.participants, personalDetails]); const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); const formHasBeenSubmitted = useRef(false); @@ -326,6 +325,7 @@ function IOURequestStepConfirmation({ existingSplitChatReportID: report?.reportID, billable: transaction.billable, iouRequestType: transaction.iouRequestType, + splitPayerAccoutIDs: transaction.splitPayerAccountIDs ?? [], }); } return; @@ -535,6 +535,7 @@ function IOURequestStepConfirmation({ isDistanceRequest={requestType === CONST.IOU.REQUEST_TYPE.DISTANCE} shouldShowSmartScanFields={IOUUtils.isMovingTransactionFromTrackExpense(action) ? transaction?.amount !== 0 : requestType !== CONST.IOU.REQUEST_TYPE.SCAN} action={action} + payeePersonalDetails={payeePersonalDetails} /> )} diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index fae07ad2249c..b720e2f4c8f8 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -160,7 +160,7 @@ function IOURequestStepDistance({ // inside a report. In this case, the participants can be automatically assigned from the report and the user can skip the participants step and go straight // to the confirm step. if (report?.reportID) { - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); return; } diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index c1b360f89e48..50bd506fd0e0 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -175,7 +175,7 @@ function IOURequestStepScan({ // If the transaction was created from the + menu from the composer inside of a chat, the participants can automatically // be added to the transaction (taken from the chat report participants) and then the person is taken to the confirmation step. - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); }, [iouType, report, reportID, transactionID, transaction?.isFromGlobalCreate, backTo]); diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 654f9e9d9f91..4037a6cffd25 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -213,7 +213,7 @@ function IOURequestStepScan({ // If the transaction was created from the + menu from the composer inside of a chat, the participants can automatically // be added to the transaction (taken from the chat report participants) and then the person is taken to the confirmation step. - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); }, [iouType, report, reportID, transactionID, transaction?.isFromGlobalCreate, backTo]); diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx new file mode 100644 index 000000000000..8a8e636975cd --- /dev/null +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -0,0 +1,88 @@ +import React, {useMemo} from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; +import {usePersonalDetails} from '@components/OnyxProvider'; +import SelectionList from '@components/SelectionList'; +import UserListItem from '@components/SelectionList/UserListItem'; +import useLocalize from '@hooks/useLocalize'; +import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus'; +import * as IOUUtils from '@libs/IOUUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import * as OptionsListUtils from '@libs/OptionsListUtils'; +import type {OptionData} from '@libs/ReportUtils'; +import * as IOU from '@userActions/IOU'; +import type SCREENS from '@src/SCREENS'; +import type * as OnyxTypes from '@src/types/onyx'; +import type {Participant} from '@src/types/onyx/IOU'; +import StepScreenWrapper from './StepScreenWrapper'; +import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; +import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; +import withWritableReportOrNotFound from './withWritableReportOrNotFound'; + +type IOURequestStepSplitPayerProps = WithWritableReportOrNotFoundProps & { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; + }; + +function IOURequestStepSplitPayer({ + route: { + params: {iouType, transactionID}, + }, + transaction, +}: IOURequestStepSplitPayerProps) { + const {translate} = useLocalize(); + const personalDetails = usePersonalDetails(); + const {didScreenTransitionEnd} = useScreenWrapperTranstionStatus(); + const sections = useMemo(() => { + const participantOptions = + transaction?.participants + ?.filter((participant) => Boolean(participant.accountID)) + ?.map((participant) => { + const participantAccountID = participant.accountID ?? 0; + return participantAccountID ? OptionsListUtils.getParticipantsOption(participant, personalDetails) : OptionsListUtils.getReportOption(participant); + }) ?? []; + return [ + { + title: '', + data: participantOptions.map((participantOption) => ({ + ...participantOption, + isSelected: !!transaction?.splitPayerAccountIDs && transaction?.splitPayerAccountIDs?.includes(participantOption.accountID ?? 0), + })), + }, + ]; + }, [transaction?.participants, personalDetails, transaction?.splitPayerAccountIDs]); + + const navigateBack = () => { + Navigation.goBack(); + }; + + const setSplitPayer = (item: Participant | OptionData) => { + IOU.setSplitPayer(transactionID, item.accountID ?? 0); + navigateBack(); + }; + + return ( + + + + ); +} + +IOURequestStepSplitPayer.displayName = 'IOURequestStepSplitPayer'; + +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepSplitPayerWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepSplitPayer); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepSplitPayerWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepSplitPayerWithWritableReportOrNotFound); + +export default IOURequestStepSplitPayerWithFullTransactionOrNotFound; diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx index 40e3e5a06991..6ad4470b8e30 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx @@ -128,7 +128,7 @@ function IOURequestStepTaxAmountPage({ // to the confirm step. if (report?.reportID) { // TODO: Is this really needed at all? - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); return; } diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index cf997d703680..c94f339b294c 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -225,6 +225,9 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback< /** The linked report id for the tracked expense */ linkedTrackedExpenseReportID?: string; + + /** The payers of split bill transaction */ + splitPayerAccountIDs?: number[]; }, keyof Comment >; From c8771068fc49be5de12921021fbb5d85101960b6 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 07:51:08 +0700 Subject: [PATCH 02/24] refactor logic display amount --- ...neyTemporaryForRefactorRequestConfirmationList.tsx | 11 +++++------ src/libs/OptionsListUtils.ts | 5 ++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index df13dcbbf46c..53ac296b54e9 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -351,14 +351,13 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ * Returns the participants with amount */ const getParticipantsWithAmount = useCallback( - (participantsList: Participant[], payerAccountID: number) => { + (participantsList: Participant[]) => { const amount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? ''); - const payerAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); + const myAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : '', - payerAmount > 0 ? CurrencyUtils.convertToDisplayString(payerAmount, iouCurrencyCode) : '', - payerAccountID, + myAmount > 0 ? CurrencyUtils.convertToDisplayString(myAmount, iouCurrencyCode) : '', ); }, [iouAmount, iouCurrencyCode], @@ -412,7 +411,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const sections = []; const unselectedParticipants = pickedParticipants.filter((participant) => !participant.selected); if (hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants, personalDetailsOfPayee.accountID); + const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; if (!canModifyParticipants) { @@ -573,7 +572,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ playSound(SOUNDS.DONE); setDidConfirm(true); - onConfirm?.(selectedParticipants); + onConfirm?.(selectedParticipants.filter((participant) => participant.accountID !== currentUserPersonalDetails.accountID)); } }, [ diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index f21f21ddf36f..47ccf9927585 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1978,12 +1978,11 @@ function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: Person function getIOUConfirmationOptionsFromParticipants( participants: Array, amountText: string, - payerAmountText = '', - payerAccountID = -1, + myAmountText = '', ): Array { return participants.map((participant) => ({ ...participant, - descriptiveText: participant.accountID === payerAccountID ? payerAmountText : amountText, + descriptiveText: participant.accountID === currentUserAccountID ? myAmountText : amountText, })); } From 3c4f3396b327decc1ef071172ffee86011bdc457 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 12:03:56 +0700 Subject: [PATCH 03/24] run prettier --- ...eyTemporaryForRefactorRequestConfirmationList.tsx | 11 ++--------- .../iou/request/step/IOURequestStepConfirmation.tsx | 8 +++++--- .../iou/request/step/IOURequestStepSplitPayer.tsx | 12 ++++++------ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index 53ac296b54e9..adfe338c18a5 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -443,15 +443,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ }); } return sections; - }, [ - selectedParticipants, - pickedParticipants, - hasMultipleParticipants, - getParticipantsWithAmount, - personalDetailsOfPayee, - translate, - canModifyParticipants, - ]); + }, [selectedParticipants, pickedParticipants, hasMultipleParticipants, getParticipantsWithAmount, personalDetailsOfPayee, translate, canModifyParticipants]); const selectedOptions = useMemo(() => { if (!hasMultipleParticipants) { @@ -589,6 +581,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ iouAmount, isEditingSplitBill, onConfirm, + currentUserPersonalDetails.accountID, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index dce7f4319f6f..237ad5eb7eb2 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -104,12 +104,14 @@ function IOURequestStepConfirmation({ return translate(TransactionUtils.getHeaderTitleTranslationKey(transaction)); }, [iouType, report, transaction, translate, isSharingTrackExpense, isCategorizingTrackExpense, isRequestingFromTrackExpense]); - const participants = useMemo(() => ( + const participants = useMemo( + () => transaction?.participants?.map((participant) => { const participantAccountID = participant.accountID ?? 0; return participantAccountID ? OptionsListUtils.getParticipantsOption(participant, personalDetails) : OptionsListUtils.getReportOption(participant); - }) ?? [] - ), [transaction?.participants, personalDetails]); + }) ?? [], + [transaction?.participants, personalDetails], + ); const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); const formHasBeenSubmitted = useRef(false); diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx index 8a8e636975cd..8327e37579a9 100644 --- a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -19,9 +19,9 @@ import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotF import withWritableReportOrNotFound from './withWritableReportOrNotFound'; type IOURequestStepSplitPayerProps = WithWritableReportOrNotFoundProps & { - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - transaction: OnyxEntry; - }; + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ + transaction: OnyxEntry; +}; function IOURequestStepSplitPayer({ route: { @@ -44,9 +44,9 @@ function IOURequestStepSplitPayer({ { title: '', data: participantOptions.map((participantOption) => ({ - ...participantOption, - isSelected: !!transaction?.splitPayerAccountIDs && transaction?.splitPayerAccountIDs?.includes(participantOption.accountID ?? 0), - })), + ...participantOption, + isSelected: !!transaction?.splitPayerAccountIDs && transaction?.splitPayerAccountIDs?.includes(participantOption.accountID ?? 0), + })), }, ]; }, [transaction?.participants, personalDetails, transaction?.splitPayerAccountIDs]); From 535b2838ef4e5ed9727d540f911ba8397976ca75 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 12:25:33 +0700 Subject: [PATCH 04/24] Not allow deselect the payer --- src/ROUTES.ts | 2 +- ...yTemporaryForRefactorRequestConfirmationList.tsx | 13 ++++--------- src/libs/actions/IOU.ts | 1 + 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index e894e470b670..89044261145d 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -383,7 +383,7 @@ const ROUTES = { MONEY_REQUEST_STEP_SPLIT_PAYER: { route: ':action/:iouType/confirmation/:transactionID/:reportID/payer', getRoute: (iouType: ValueOf, transactionID: string, reportID: string, action: ValueOf = 'create') => - `${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer`, + `${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer` as const, }, MONEY_REQUEST_STEP_SCAN: { route: ':action/:iouType/scan/:transactionID/:reportID', diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index adfe338c18a5..ad2a2d63ad2e 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -419,11 +419,6 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ...participant, isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), })); - } else { - formattedParticipantsList = formattedParticipantsList.map((participant) => ({ - ...participant, - isDisabled: participant.accountID === personalDetailsOfPayee.accountID, - })); } sections.push({ @@ -449,8 +444,8 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ if (!hasMultipleParticipants) { return []; } - return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetailsOfPayee)]; - }, [selectedParticipants, hasMultipleParticipants, personalDetailsOfPayee]); + return [...selectedParticipants]; + }, [selectedParticipants, hasMultipleParticipants]); useEffect(() => { if (!isDistanceRequest || isMovingTransactionFromTrackExpense) { @@ -500,12 +495,12 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const selectParticipant = useCallback( (option: Participant) => { // Return early if selected option is currently logged in user. - if (option.accountID === session?.accountID) { + if (option.accountID === session?.accountID || option.accountID === personalDetailsOfPayee.accountID) { return; } onSelectParticipant?.(option); }, - [session?.accountID, onSelectParticipant], + [session?.accountID, onSelectParticipant, personalDetailsOfPayee.accountID], ); /** diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 5d9196fc0b10..8eb5e56fc4d1 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -335,6 +335,7 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, transactionID: newTransactionID, isFromGlobalCreate, merchant: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, + splitPayerAccountIDs: [currentUserPersonalDetails.accountID] }); } From 24fb63b19a7b0bf01fedc02146fdc29a9d2d006f Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 12:49:23 +0700 Subject: [PATCH 05/24] update participants to include the payee --- ...eyTemporaryForRefactorRequestConfirmationList.tsx | 6 +++--- src/libs/actions/IOU.ts | 2 +- .../iou/request/step/IOURequestStepConfirmation.tsx | 12 ++++++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index ad2a2d63ad2e..3a373dca77f2 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -438,7 +438,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ }); } return sections; - }, [selectedParticipants, pickedParticipants, hasMultipleParticipants, getParticipantsWithAmount, personalDetailsOfPayee, translate, canModifyParticipants]); + }, [selectedParticipants, pickedParticipants, hasMultipleParticipants, getParticipantsWithAmount, translate, canModifyParticipants]); const selectedOptions = useMemo(() => { if (!hasMultipleParticipants) { @@ -586,7 +586,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ } const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND; - const shouldDisableButton = selectedParticipants.length === 0; + const shouldDisableButton = isTypeSplit ? selectedParticipants.length === 1 : selectParticipants.length === 0; const button = shouldShowSettlementButton ? ( ); - }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2]); + }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2, isTypeSplit]); // An intermediate structure that helps us classify the fields as "primary" and "supplementary". // The primary fields are always shown to the user, while an extra action is needed to reveal the supplementary ones. diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 8eb5e56fc4d1..f870ef0ddc97 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -335,7 +335,7 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, transactionID: newTransactionID, isFromGlobalCreate, merchant: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, - splitPayerAccountIDs: [currentUserPersonalDetails.accountID] + splitPayerAccountIDs: [currentUserPersonalDetails.accountID], }); } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 237ad5eb7eb2..bb709b7f6c00 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -115,6 +115,18 @@ function IOURequestStepConfirmation({ const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); const formHasBeenSubmitted = useRef(false); + useEffect(() => { + if (transaction?.participants?.findIndex((participant) => participant.accountID === payeePersonalDetails?.accountID) !== -1 || iouType !== CONST.IOU.TYPE.SPLIT) { + return; + } + + const payeeParticipant = OptionsListUtils.getParticipantsOption({accountID: payeePersonalDetails?.accountID, selected: true}, personalDetails); + IOU.setMoneyRequestParticipants_temporaryForRefactor(transaction.transactionID, [...(transaction?.participants ?? []), payeeParticipant]); + + // We only want to run it when the component is mounted + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { const policyExpenseChat = participants?.find((participant) => participant.isPolicyExpenseChat); if (policyExpenseChat?.policyID) { From 0de971c1fbea30434cf9b7ef6f73365b473a559c Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 18 Apr 2024 12:53:36 +0700 Subject: [PATCH 06/24] fix lint --- .../MoneyTemporaryForRefactorRequestConfirmationList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index 3a373dca77f2..3246928ec271 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -586,7 +586,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ } const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND; - const shouldDisableButton = isTypeSplit ? selectedParticipants.length === 1 : selectParticipants.length === 0; + const shouldDisableButton = isTypeSplit ? selectedParticipants.length === 1 : selectedParticipants.length === 0; const button = shouldShowSettlementButton ? ( Date: Thu, 18 Apr 2024 14:37:35 +0700 Subject: [PATCH 07/24] revert mistake change --- src/languages/en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 24ef3eee3215..33c9180d0f43 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2318,7 +2318,7 @@ export default { roomMembersPage: { memberNotFound: 'Member not found. To invite a new member to the room, please use the Invite button above.', notAuthorized: `You do not have access to this page. Are you trying to join the room? Please reach out to a member of this room so they can add you as a member! Something else? Reach out to ${CONST.EMAIL.CONCIERGE}`, - removeMembersPrompt: 'Are you sure you want to remove the selecmoneyRequestConfirmationListted members from the room?', + removeMembersPrompt: 'Are you sure you want to remove the selected members from the room?', }, newTaskPage: { assignTask: 'Assign task', From 94e18ada20c16a29e16a27d6990a12d99461e6d6 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 19 Apr 2024 00:36:32 +0700 Subject: [PATCH 08/24] resolve conflict --- src/pages/iou/request/step/IOURequestStepScan/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index d007881f9679..8bca59b11580 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -234,7 +234,7 @@ function IOURequestStepScan({ // If the transaction was created from the + menu from the composer inside of a chat, the participants can automatically // be added to the transaction (taken from the chat report participants) and then the person is taken to the confirmation step. - const selectedParticipants = IOU.setMoneyRequestParticipantsFromReport(transactionID, report, iouType); + const selectedParticipants = IOU.setMoneyRequestParticipantsFromReport(transactionID, report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? 0; return participantAccountID ? OptionsListUtils.getParticipantsOption(participant, personalDetails) : OptionsListUtils.getReportOption(participant); From 517ad3afea3e804a328c97b33fb5862d4fcdc618 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 19 Apr 2024 01:00:46 +0700 Subject: [PATCH 09/24] Add backTo param and disable edit payer for policy expense chat --- src/ROUTES.ts | 4 ++-- ...neyTemporaryForRefactorRequestConfirmationList.tsx | 8 ++++---- src/libs/Navigation/types.ts | 1 + .../iou/request/step/IOURequestStepSplitPayer.tsx | 11 ++++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 55b8729bf249..1dd6dc1cfe29 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -388,8 +388,8 @@ const ROUTES = { }, MONEY_REQUEST_STEP_SPLIT_PAYER: { route: ':action/:iouType/confirmation/:transactionID/:reportID/payer', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, action: ValueOf = 'create') => - `${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer` as const, + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '', action: ValueOf = 'create') => + getUrlWithBackToParam(`${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer`, backTo), }, MONEY_REQUEST_STEP_SCAN: { route: ':action/:iouType/scan/:transactionID/:reportID', diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx index 97c34c58fa6d..1de4e3e879d9 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.tsx @@ -643,18 +643,18 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ item: ( { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); }} - shouldShowRightIcon + shouldShowRightIcon={!isPolicyExpenseChat && !transaction?.isFromGlobalCreate} titleWithTooltips={payeeTooltipDetails} /> ), - shouldShow: isTypeSplit, + shouldShow: isTypeSplit && action === CONST.IOU.ACTION.CREATE, isSupplementary: false, }, { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 7e25eda12bb8..7834fdf40b7b 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -440,6 +440,7 @@ type MoneyRequestNavigatorParamList = { iouType: ValueOf; transactionID: string; reportID: string; + backTo: Routes; }; [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: undefined; [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: undefined; diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx index 8327e37579a9..dc1a958ed538 100644 --- a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -9,7 +9,9 @@ import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import type {OptionData} from '@libs/ReportUtils'; +import * as ReportUtils from '@libs/ReportUtils'; import * as IOU from '@userActions/IOU'; +import CONST from '@src/CONST'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; @@ -25,9 +27,10 @@ type IOURequestStepSplitPayerProps = WithWritableReportOrNotFoundProps { - Navigation.goBack(); + Navigation.goBack(backTo); }; const setSplitPayer = (item: Participant | OptionData) => { @@ -64,7 +67,9 @@ function IOURequestStepSplitPayer({ From 34149a4d9d903b89d6dab5b0407d6dd1c17acca1 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 19 Apr 2024 14:34:54 +0700 Subject: [PATCH 10/24] move logic to new page and update translation --- .../MoneyRequestConfirmationList.tsx | 90 ++++++++++--------- src/languages/es.ts | 2 +- .../step/IOURequestStepConfirmation.tsx | 3 +- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index e90cb7584c43..62544689796c 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -27,6 +27,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as TransactionUtils from '@libs/TransactionUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; +import * as UserUtils from '@libs/UserUtils'; import * as IOU from '@userActions/IOU'; import type {IOUAction, IOUType} from '@src/CONST'; import CONST from '@src/CONST'; @@ -41,7 +42,9 @@ import type {DropdownOption} from './ButtonWithDropdownMenu/types'; import ConfirmedRoute from './ConfirmedRoute'; import ConfirmModal from './ConfirmModal'; import FormHelpMessage from './FormHelpMessage'; +import MenuItem from './MenuItem'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; +import {usePersonalDetails} from './OnyxProvider'; import OptionsSelector from './OptionsSelector'; import PDFThumbnail from './PDFThumbnail'; import ReceiptEmptyState from './ReceiptEmptyState'; @@ -214,6 +217,7 @@ function MoneyRequestConfirmationList({ const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetails = usePersonalDetails(); const {canUseViolations} = usePermissions(); const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST; @@ -350,8 +354,13 @@ function MoneyRequestConfirmationList({ */ const getParticipantsWithAmount = useCallback( (participantsList: Participant[]) => { - const amount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? ''); - return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(participantsList, amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : ''); + const amount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? ''); + const myAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); + return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( + participantsList, + amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : '', + myAmount > 0 ? CurrencyUtils.convertToDisplayString(myAmount, iouCurrencyCode) : '', + ); }, [iouAmount, iouCurrencyCode], ); @@ -386,8 +395,16 @@ function MoneyRequestConfirmationList({ const selectedParticipants = useMemo(() => selectedParticipantsProp.filter((participant) => participant.selected), [selectedParticipantsProp]); const payeePersonalDetails = useMemo(() => payeePersonalDetailsProp ?? currentUserPersonalDetails, [payeePersonalDetailsProp, currentUserPersonalDetails]); + const payeeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs([payeePersonalDetails.accountID], personalDetails), false); + const payeeIcons = [ + { + source: UserUtils.getAvatar(payeePersonalDetails.avatar, payeePersonalDetails.accountID), + name: payeePersonalDetails.login ?? '', + type: CONST.ICON_TYPE_AVATAR, + id: payeePersonalDetails.accountID, + }, + ]; const canModifyParticipants = !isReadOnly && canModifyParticipantsProp && hasMultipleParticipants; - const shouldDisablePaidBySection = canModifyParticipants; const optionSelectorSections = useMemo(() => { const sections = []; const unselectedParticipants = selectedParticipantsProp.filter((participant) => !participant.selected); @@ -402,25 +419,11 @@ function MoneyRequestConfirmationList({ })); } - const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, iouAmount, iouCurrencyCode ?? '', true); - const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( - payeePersonalDetails, - iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', - ); - - sections.push( - { - title: translate('moneyRequestConfirmationList.paidBy'), - data: [formattedPayeeOption], - shouldShow: true, - isDisabled: shouldDisablePaidBySection, - }, - { - title: translate('moneyRequestConfirmationList.splitWith'), - data: formattedParticipantsList, - shouldShow: true, - }, - ); + sections.push({ + title: translate('moneyRequestConfirmationList.splitAmounts'), + data: formattedParticipantsList, + shouldShow: true, + }); } else { const formattedSelectedParticipants = selectedParticipants.map((participant) => ({ ...participant, @@ -433,25 +436,14 @@ function MoneyRequestConfirmationList({ }); } return sections; - }, [ - selectedParticipants, - selectedParticipantsProp, - hasMultipleParticipants, - iouAmount, - iouCurrencyCode, - getParticipantsWithAmount, - payeePersonalDetails, - translate, - shouldDisablePaidBySection, - canModifyParticipants, - ]); + }, [selectedParticipants, selectedParticipantsProp, hasMultipleParticipants, getParticipantsWithAmount, translate, canModifyParticipants]); const selectedOptions = useMemo(() => { if (!hasMultipleParticipants) { return []; } - return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetails)]; - }, [selectedParticipants, hasMultipleParticipants, payeePersonalDetails]); + return [...selectedParticipants]; + }, [selectedParticipants, hasMultipleParticipants]); useEffect(() => { if (!isDistanceRequest || isMovingTransactionFromTrackExpense) { @@ -514,12 +506,12 @@ function MoneyRequestConfirmationList({ const selectParticipant = useCallback( (option: Participant) => { // Return early if selected option is currently logged in user. - if (option.accountID === session?.accountID) { + if (option.accountID === session?.accountID || option.accountID === payeePersonalDetails.accountID) { return; } onSelectParticipant?.(option); }, - [session?.accountID, onSelectParticipant], + [session?.accountID, onSelectParticipant, payeePersonalDetails.accountID], ); /** @@ -609,7 +601,7 @@ function MoneyRequestConfirmationList({ } const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND; - const shouldDisableButton = selectedParticipants.length === 0; + const shouldDisableButton = isTypeSplit ? selectedParticipants.length === 1 : selectedParticipants.length === 0; const button = shouldShowSettlementButton ? ( ); - }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2]); + }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2, isTypeSplit]); // An intermediate structure that helps us classify the fields as "primary" and "supplementary". // The primary fields are always shown to the user, while an extra action is needed to reveal the supplementary ones. const classifiedFields = [ + { + item: ( + { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); + }} + shouldShowRightIcon={!isPolicyExpenseChat && !transaction?.isFromGlobalCreate} + titleWithTooltips={payeeTooltipDetails} + /> + ), + shouldShow: isTypeSplit && action === CONST.IOU.ACTION.CREATE, + isSupplementary: false, + }, { item: ( Date: Mon, 22 Apr 2024 13:24:47 +0700 Subject: [PATCH 11/24] edit amount for payer --- src/components/MoneyRequestConfirmationList.tsx | 14 ++++++++------ src/libs/OptionsListUtils.ts | 5 +++-- src/libs/actions/IOU.ts | 12 ++++++++++-- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 19090071fe58..b98726242475 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -382,13 +382,14 @@ function MoneyRequestConfirmationList({ * Returns the participants with amount */ const getParticipantsWithAmount = useCallback( - (participantsList: Participant[]) => { + (participantsList: Participant[], payerAccountID: number) => { const amount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? ''); - const myAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); + const payerAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : '', - myAmount > 0 ? CurrencyUtils.convertToDisplayString(myAmount, iouCurrencyCode) : '', + payerAmount > 0 ? CurrencyUtils.convertToDisplayString(payerAmount, iouCurrencyCode) : '', + payerAccountID, ); }, [iouAmount, iouCurrencyCode], @@ -438,7 +439,7 @@ function MoneyRequestConfirmationList({ const sections = []; const unselectedParticipants = selectedParticipantsProp.filter((participant) => !participant.selected); if (hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); + const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants, payeePersonalDetails.accountID); let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; if (!canModifyParticipants) { @@ -465,7 +466,7 @@ function MoneyRequestConfirmationList({ }); } return sections; - }, [selectedParticipants, selectedParticipantsProp, hasMultipleParticipants, getParticipantsWithAmount, translate, canModifyParticipants]); + }, [selectedParticipants, selectedParticipantsProp, hasMultipleParticipants, getParticipantsWithAmount, translate, canModifyParticipants, payeePersonalDetails.accountID]); const selectedOptions = useMemo(() => { if (!hasMultipleParticipants) { @@ -603,7 +604,7 @@ function MoneyRequestConfirmationList({ playSound(SOUNDS.DONE); setDidConfirm(true); - onConfirm?.(selectedParticipants); + onConfirm?.(selectedParticipants.filter((participant) => participant.accountID !== currentUserPersonalDetails.accountID)); } }, [ @@ -621,6 +622,7 @@ function MoneyRequestConfirmationList({ iouAmount, isEditingSplitBill, onConfirm, + currentUserPersonalDetails.accountID, ], ); diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index ce61cf06f062..ccbdbe56cb53 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1978,11 +1978,12 @@ function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: Person function getIOUConfirmationOptionsFromParticipants( participants: Array, amountText: string, - myAmountText = '', + payerAmountText: string, + payerAccountID: number, ): Array { return participants.map((participant) => ({ ...participant, - descriptiveText: participant.accountID === currentUserAccountID ? myAmountText : amountText, + descriptiveText: participant.accountID === payerAccountID ? payerAmountText : amountText, })); } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 8ab4eb676633..b4ec985cdbd7 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3127,6 +3127,7 @@ function createSplitsAndOnyxData( existingSplitChatReportID = '', billable = false, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL, + splitPayerAccountIDs: number[] = [], ): SplitsAndOnyxData { const currentUserEmailForIOUSplit = PhoneNumber.addSMSDomainIfPhoneNumber(currentUserLogin); const participantAccountIDs = participants.map((participant) => Number(participant.accountID)); @@ -3292,11 +3293,17 @@ function createSplitsAndOnyxData( } // Loop through participants creating individual chats, iouReports and reportActionIDs as needed - const splitAmount = IOUUtils.calculateAmount(participants.length, amount, currency, false); - const splits: Split[] = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID, amount: IOUUtils.calculateAmount(participants.length, amount, currency, true)}]; + const splits: Split[] = [ + { + email: currentUserEmailForIOUSplit, + accountID: currentUserAccountID, + amount: IOUUtils.calculateAmount(participants.length, amount, currency, splitPayerAccountIDs.includes(currentUserAccountID)), + }, + ]; const hasMultipleParticipants = participants.length > 1; participants.forEach((participant) => { + const splitAmount = IOUUtils.calculateAmount(participants.length, amount, currency, splitPayerAccountIDs.includes(participant.accountID ?? 0)); // In a case when a participant is a workspace, even when a current user is not an owner of the workspace const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(participant); @@ -3526,6 +3533,7 @@ function splitBill({ existingSplitChatReportID, billable, iouRequestType, + splitPayerAccoutIDs, ); const parameters: SplitBillParams = { From e3608124f1b138d574be3587c3da10bdf4b2fbbc Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 22 Apr 2024 14:12:12 +0700 Subject: [PATCH 12/24] fix update payer to participant --- src/components/MoneyRequestConfirmationList.tsx | 1 + src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index b98726242475..70063ced9f2e 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -688,6 +688,7 @@ function MoneyRequestConfirmationList({ { item: ( Date: Mon, 22 Apr 2024 14:17:15 +0700 Subject: [PATCH 13/24] not show right icon of split payer when opening split detail page --- src/components/MoneyRequestConfirmationList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 70063ced9f2e..59d400735c0a 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -690,14 +690,14 @@ function MoneyRequestConfirmationList({ { Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); }} - shouldShowRightIcon={!isPolicyExpenseChat && !transaction?.isFromGlobalCreate} + shouldShowRightIcon={!isPolicyExpenseChat && !transaction?.isFromGlobalCreate && !isReadOnly} titleWithTooltips={payeeTooltipDetails} /> ), From d2059d7405513da455bda51e17e58d78e6128cc1 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 22 Apr 2024 18:48:10 +0700 Subject: [PATCH 14/24] allow edit payer when creating split bill request from global FAB --- .../MoneyRequestConfirmationList.tsx | 10 ++++----- .../step/IOURequestStepConfirmation.tsx | 22 ++++++++++++++++--- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 59d400735c0a..cbd62d7df6e7 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -690,15 +690,15 @@ function MoneyRequestConfirmationList({ { Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); }} - shouldShowRightIcon={!isPolicyExpenseChat && !transaction?.isFromGlobalCreate && !isReadOnly} - titleWithTooltips={payeeTooltipDetails} + shouldShowRightIcon={!isPolicyExpenseChat && !isReadOnly} + titleWithTooltips={payeePersonalDetails?.isOptimisticPersonalDetail ? undefined : payeeTooltipDetails} /> ), shouldShow: isTypeSplit && action === CONST.IOU.ACTION.CREATE, diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 4299893ac9c3..75c720c55e99 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -21,6 +21,7 @@ import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; +import * as UserUtils from '@libs/UserUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -77,7 +78,21 @@ function IOURequestStepConfirmation({ const transactionTaxAmount = transaction?.taxAmount; const isSharingTrackExpense = action === CONST.IOU.ACTION.SHARE; const isCategorizingTrackExpense = action === CONST.IOU.ACTION.CATEGORIZE; - const payeePersonalDetails = personalDetails?.[transaction?.splitPayerAccountIDs?.[0] ?? -1]; + const payeePersonalDetails = useMemo(() => { + if (personalDetails?.[transaction?.splitPayerAccountIDs?.[0] ?? -1]) { + return personalDetails?.[transaction?.splitPayerAccountIDs?.[0] ?? -1]; + } + + const participant = transaction?.participants?.find((val) => val.accountID === (transaction?.splitPayerAccountIDs?.[0] ?? -1)); + + return { + login: participant?.login ?? '', + accountID: participant?.accountID ?? -1, + avatar: UserUtils.getDefaultAvatarURL(participant?.accountID ?? -1), + displayName: participant?.login ?? '', + isOptimisticPersonalDetail: true, + }; + }, [personalDetails, transaction?.participants, transaction?.splitPayerAccountIDs]); const isRequestingFromTrackExpense = action === CONST.IOU.ACTION.REQUEST; const requestType = TransactionUtils.getRequestType(transaction); @@ -116,11 +131,11 @@ function IOURequestStepConfirmation({ const formHasBeenSubmitted = useRef(false); useEffect(() => { - if (transaction?.participants?.findIndex((participant) => participant.accountID === payeePersonalDetails?.accountID) !== -1 || iouType !== CONST.IOU.TYPE.SPLIT) { + if (transaction?.participants?.findIndex((participant) => participant.accountID === transaction?.splitPayerAccountIDs?.[0]) !== -1 || iouType !== CONST.IOU.TYPE.SPLIT) { return; } - const payeeParticipant: Participant = {accountID: payeePersonalDetails?.accountID, selected: true}; + const payeeParticipant: Participant = {accountID: transaction?.splitPayerAccountIDs?.[0], selected: true}; IOU.setMoneyRequestParticipants_temporaryForRefactor(transaction.transactionID, [payeeParticipant, ...(transaction?.participants ?? [])]); // We only want to run it when the component is mounted @@ -362,6 +377,7 @@ function IOURequestStepConfirmation({ tag: transaction.tag, billable: !!transaction.billable, iouRequestType: transaction.iouRequestType, + splitPayerAccoutIDs: transaction.splitPayerAccountIDs, }); } return; From 0269d586a48ea36fe4f8e4b67cbe67048c340e8c Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 23 Apr 2024 22:52:55 +0700 Subject: [PATCH 15/24] move action param to first --- src/ROUTES.ts | 2 +- src/components/MoneyRequestConfirmationList.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 681b72c2da6a..bd1fec98ae80 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -384,7 +384,7 @@ const ROUTES = { }, MONEY_REQUEST_STEP_SPLIT_PAYER: { route: ':action/:iouType/confirmation/:transactionID/:reportID/payer', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '', action: ValueOf = 'create') => + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => getUrlWithBackToParam(`${action}/${iouType}/confirmation/${transactionID}/${reportID}/payer`, backTo), }, MONEY_REQUEST_STEP_SCAN: { diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 496621993885..740933dd166b 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -695,7 +695,7 @@ function MoneyRequestConfirmationList({ title={payeePersonalDetails.displayName ?? ReportUtils.getDisplayNameForParticipant(payeePersonalDetails.accountID)} icon={payeeIcons} onPress={() => { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(action, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); }} shouldShowRightIcon={!isPolicyExpenseChat && !isReadOnly} titleWithTooltips={payeePersonalDetails?.isOptimisticPersonalDetail ? undefined : payeeTooltipDetails} From defac609fb75142731243c6a019ab21c3a14f7ee Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 24 Apr 2024 11:27:15 +0700 Subject: [PATCH 16/24] fix lint --- src/components/MoneyRequestConfirmationList.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 2a290832092d..185972e1b596 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -695,7 +695,9 @@ function MoneyRequestConfirmationList({ title={payeePersonalDetails.displayName ?? ReportUtils.getDisplayNameForParticipant(payeePersonalDetails.accountID)} icon={payeeIcons} onPress={() => { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(action, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams())); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(action, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ); }} shouldShowRightIcon={!isPolicyExpenseChat && !isReadOnly} titleWithTooltips={payeePersonalDetails?.isOptimisticPersonalDetail ? undefined : payeeTooltipDetails} From 84947fc19b83de92c73129611a88f8d5fb02b301 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 12:02:36 +0700 Subject: [PATCH 17/24] Fix crash app and move paid by option to the top --- .../MoneyRequestConfirmationList.tsx | 159 +++++++++--------- src/libs/actions/IOU.ts | 1 + .../step/IOURequestStepConfirmation.tsx | 4 +- .../step/IOURequestStepParticipants.tsx | 4 +- 4 files changed, 86 insertions(+), 82 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 185972e1b596..d8b4df136d7c 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -425,10 +425,13 @@ function MoneyRequestConfirmationList({ const selectedParticipants = useMemo(() => selectedParticipantsProp.filter((participant) => participant.selected), [selectedParticipantsProp]); const payeePersonalDetails = useMemo(() => payeePersonalDetailsProp ?? currentUserPersonalDetails, [payeePersonalDetailsProp, currentUserPersonalDetails]); - const payeeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs([payeePersonalDetails.accountID], personalDetails), false); + const payeeTooltipDetails = useMemo( + () => ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs([payeePersonalDetails.accountID], personalDetails), false), + [payeePersonalDetails.accountID, personalDetails], + ); const payeeIcons = [ { - source: UserUtils.getAvatar(payeePersonalDetails.avatar, payeePersonalDetails.accountID), + source: UserUtils.getAvatar(payeePersonalDetails.avatar, payeePersonalDetails.accountID) ?? '', name: payeePersonalDetails.login ?? '', type: CONST.ICON_TYPE_AVATAR, id: payeePersonalDetails.accountID, @@ -685,27 +688,6 @@ function MoneyRequestConfirmationList({ // An intermediate structure that helps us classify the fields as "primary" and "supplementary". // The primary fields are always shown to the user, while an extra action is needed to reveal the supplementary ones. const classifiedFields = [ - { - item: ( - { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(action, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), - ); - }} - shouldShowRightIcon={!isPolicyExpenseChat && !isReadOnly} - titleWithTooltips={payeePersonalDetails?.isOptimisticPersonalDetail ? undefined : payeeTooltipDetails} - /> - ), - shouldShow: isTypeSplit && action === CONST.IOU.ACTION.CREATE, - isSupplementary: false, - }, { item: ( - {isDistanceRequest && ( - - - - )} - {!isDistanceRequest && - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - (receiptImage || receiptThumbnail - ? receiptThumbnailContent - : // The empty receipt component should only show for IOU Requests of a paid policy ("Team" or "Corporate") - PolicyUtils.isPaidGroupPolicy(policy) && - !isDistanceRequest && - iouType === CONST.IOU.TYPE.SUBMIT && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()), - ) - } - /> - ))} - {primaryFields} - {!shouldShowAllFields && ( - + {isTypeSplit && action === CONST.IOU.ACTION.CREATE && ( + { + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.getRoute(action, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ); + }} + shouldShowRightIcon={!isPolicyExpenseChat && !isReadOnly} + titleWithTooltips={payeePersonalDetails?.isOptimisticPersonalDetail ? undefined : payeeTooltipDetails} /> )} - {shouldShowAllFields && supplementaryFields} - - + {/** @ts-expect-error This component is deprecated and will not be migrated to TypeScript (context: https://expensify.slack.com/archives/C01GTK53T8Q/p1709232289899589?thread_ts=1709156803.359359&cid=C01GTK53T8Q) */} + + {isDistanceRequest && ( + + + + )} + {!isDistanceRequest && + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + (receiptImage || receiptThumbnail + ? receiptThumbnailContent + : // The empty receipt component should only show for IOU Requests of a paid policy ("Team" or "Corporate") + PolicyUtils.isPaidGroupPolicy(policy) && + !isDistanceRequest && + iouType === CONST.IOU.TYPE.SUBMIT && ( + + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()), + ) + } + /> + ))} + {primaryFields} + {!shouldShowAllFields && ( + + )} + {shouldShowAllFields && supplementaryFields} + + + ); } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 48c5e3c40cc3..f3d35106e6ba 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3443,6 +3443,7 @@ function createSplitsAndOnyxData( const individualSplit = { email, accountID, + isOptimisticAccount: ReportUtils.isOptimisticPersonalDetail(accountID), amount: splitAmount, iouReportID: oneOnOneIOUReport.reportID, chatReportID: oneOnOneChatReport.reportID, diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index fd40a7c1296e..27db6ca89f78 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -89,7 +89,7 @@ function IOURequestStepConfirmation({ return { login: participant?.login ?? '', accountID: participant?.accountID ?? -1, - avatar: UserUtils.getDefaultAvatarURL(participant?.accountID ?? -1), + avatar: Expensicons.FallbackAvatar, displayName: participant?.login ?? '', isOptimisticPersonalDetail: true, }; @@ -136,7 +136,7 @@ function IOURequestStepConfirmation({ } const payeeParticipant: Participant = {accountID: transaction?.splitPayerAccountIDs?.[0], selected: true}; - IOU.setMoneyRequestParticipants_temporaryForRefactor(transaction.transactionID, [payeeParticipant, ...(transaction?.participants ?? [])]); + IOU.setMoneyRequestParticipants(transaction.transactionID, [payeeParticipant, ...(transaction?.participants ?? [])]); // We only want to run it when the component is mounted // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 374d4e9777cf..c99de6236a43 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import * as IOUUtils from '@libs/IOUUtils'; @@ -33,7 +34,8 @@ function IOURequestStepParticipants({ }, transaction, }: IOURequestStepParticipantsProps) { - const participants = transaction?.participants; + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const participants = transaction?.participants?.filter((participant) => participant.accountID !== currentUserPersonalDetails.accountID); const {translate} = useLocalize(); const selectedReportID = useRef(reportID); const numberOfParticipants = useRef(participants?.length ?? 0); From a7d846c50ab14e90289750327b210f600b88239f Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 12:05:43 +0700 Subject: [PATCH 18/24] add splitPayerAccountIDs in splitBillAndOpenReport function --- src/libs/actions/IOU.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index f3d35106e6ba..10c1fa3f0008 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3577,6 +3577,7 @@ function splitBillAndOpenReport({ tag = '', billable = false, iouRequestType = CONST.IOU.REQUEST_TYPE.MANUAL, + splitPayerAccountIDs = [] }: SplitBillActionsParams) { const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created); const {splitData, splits, onyxData} = createSplitsAndOnyxData( @@ -3593,6 +3594,7 @@ function splitBillAndOpenReport({ '', billable, iouRequestType, + splitPayerAccountIDs ); const parameters: SplitBillParams = { From d43d24ab24caf96062141e9e41ad93e8a615f5ba Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 12:06:51 +0700 Subject: [PATCH 19/24] add splitPayerAccountIDs in splitBillAndOpenReport function --- src/libs/actions/IOU.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index f3d35106e6ba..20aaf5655ae7 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3577,6 +3577,7 @@ function splitBillAndOpenReport({ tag = '', billable = false, iouRequestType = CONST.IOU.REQUEST_TYPE.MANUAL, + splitPayerAccountIDs = [], }: SplitBillActionsParams) { const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created); const {splitData, splits, onyxData} = createSplitsAndOnyxData( @@ -3593,6 +3594,7 @@ function splitBillAndOpenReport({ '', billable, iouRequestType, + splitPayerAccountIDs, ); const parameters: SplitBillParams = { From 749e4d2e839b359c403dbf719e6312697e60100e Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 12:16:08 +0700 Subject: [PATCH 20/24] fix lint --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 27db6ca89f78..80eb858eb5a8 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -21,7 +21,6 @@ import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; -import * as UserUtils from '@libs/UserUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; From 3ec1eb645aab9ada79b77e402bda140fc4e14b96 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 14:52:40 +0700 Subject: [PATCH 21/24] implement alternative solution --- .../MoneyRequestConfirmationList.tsx | 68 ++++++++++++------- src/libs/OptionsListUtils.ts | 9 +-- .../step/IOURequestStepConfirmation.tsx | 12 ---- .../step/IOURequestStepParticipants.tsx | 4 +- .../request/step/IOURequestStepSplitPayer.tsx | 17 ++++- 5 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index d8b4df136d7c..d5cc00bce1cc 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -382,15 +382,9 @@ function MoneyRequestConfirmationList({ * Returns the participants with amount */ const getParticipantsWithAmount = useCallback( - (participantsList: Participant[], payerAccountID: number) => { - const amount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? ''); - const payerAmount = IOUUtils.calculateAmount(participantsList.length - 1, iouAmount, iouCurrencyCode ?? '', true); - return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( - participantsList, - amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : '', - payerAmount > 0 ? CurrencyUtils.convertToDisplayString(payerAmount, iouCurrencyCode) : '', - payerAccountID, - ); + (participantsList: Participant[]) => { + const amount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? ''); + return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(participantsList, amount > 0 ? CurrencyUtils.convertToDisplayString(amount, iouCurrencyCode) : ''); }, [iouAmount, iouCurrencyCode], ); @@ -438,11 +432,12 @@ function MoneyRequestConfirmationList({ }, ]; const canModifyParticipants = !isReadOnly && canModifyParticipantsProp && hasMultipleParticipants; + const shouldDisablePaidBySection = canModifyParticipants; const optionSelectorSections = useMemo(() => { const sections = []; const unselectedParticipants = selectedParticipantsProp.filter((participant) => !participant.selected); if (hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants, payeePersonalDetails.accountID); + const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; if (!canModifyParticipants) { @@ -452,11 +447,26 @@ function MoneyRequestConfirmationList({ })); } - sections.push({ - title: translate('moneyRequestConfirmationList.splitAmounts'), - data: formattedParticipantsList, - shouldShow: true, - }); + const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, iouAmount, iouCurrencyCode ?? '', true); + + const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( + payeePersonalDetails, + iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', + ); + + sections.push( + { + title: translate('moneyRequestConfirmationList.paidBy'), + data: [formattedPayeeOption], + shouldShow: true, + isDisabled: shouldDisablePaidBySection, + }, + { + title: translate('moneyRequestConfirmationList.splitWith'), + data: formattedParticipantsList, + shouldShow: true, + }, + ); } else { const formattedSelectedParticipants = selectedParticipants.map((participant) => ({ ...participant, @@ -469,14 +479,25 @@ function MoneyRequestConfirmationList({ }); } return sections; - }, [selectedParticipants, selectedParticipantsProp, hasMultipleParticipants, getParticipantsWithAmount, translate, canModifyParticipants, payeePersonalDetails.accountID]); + }, [ + selectedParticipants, + selectedParticipantsProp, + hasMultipleParticipants, + iouAmount, + iouCurrencyCode, + getParticipantsWithAmount, + payeePersonalDetails, + translate, + shouldDisablePaidBySection, + canModifyParticipants, + ]); const selectedOptions = useMemo(() => { if (!hasMultipleParticipants) { return []; } - return [...selectedParticipants]; - }, [selectedParticipants, hasMultipleParticipants]); + return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetails)]; + }, [selectedParticipants, hasMultipleParticipants, payeePersonalDetails]); useEffect(() => { if (!isDistanceRequest || isMovingTransactionFromTrackExpense) { @@ -539,12 +560,12 @@ function MoneyRequestConfirmationList({ const selectParticipant = useCallback( (option: Participant) => { // Return early if selected option is currently logged in user. - if (option.accountID === session?.accountID || option.accountID === payeePersonalDetails.accountID) { + if (option.accountID === session?.accountID) { return; } onSelectParticipant?.(option); }, - [session?.accountID, onSelectParticipant, payeePersonalDetails.accountID], + [session?.accountID, onSelectParticipant], ); /** @@ -607,7 +628,7 @@ function MoneyRequestConfirmationList({ playSound(SOUNDS.DONE); setDidConfirm(true); - onConfirm?.(selectedParticipants.filter((participant) => participant.accountID !== currentUserPersonalDetails.accountID)); + onConfirm?.(selectedParticipants); } }, [ @@ -625,7 +646,6 @@ function MoneyRequestConfirmationList({ iouAmount, isEditingSplitBill, onConfirm, - currentUserPersonalDetails.accountID, ], ); @@ -635,7 +655,7 @@ function MoneyRequestConfirmationList({ } const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.PAY; - const shouldDisableButton = isTypeSplit ? selectedParticipants.length === 1 : selectedParticipants.length === 0; + const shouldDisableButton = selectedParticipants.length === 0; const button = shouldShowSettlementButton ? ( ); - }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2, isTypeSplit]); + }, [isReadOnly, iouType, selectedParticipants.length, confirm, bankAccountRoute, iouCurrencyCode, policyID, splitOrRequestOptions, formError, styles.ph1, styles.mb2]); // An intermediate structure that helps us classify the fields as "primary" and "supplementary". // The primary fields are always shown to the user, while an extra action is needed to reveal the supplementary ones. diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index a9329b5c07ae..e9f0fc9dc451 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1965,15 +1965,10 @@ function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: Person /** * Build the IOUConfirmationOptions for showing participants */ -function getIOUConfirmationOptionsFromParticipants( - participants: Array, - amountText: string, - payerAmountText: string, - payerAccountID: number, -): Array { +function getIOUConfirmationOptionsFromParticipants(participants: Array, amountText: string): Array { return participants.map((participant) => ({ ...participant, - descriptiveText: participant.accountID === payerAccountID ? payerAmountText : amountText, + descriptiveText: amountText, })); } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 80eb858eb5a8..fe08d231eae8 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -129,18 +129,6 @@ function IOURequestStepConfirmation({ const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]); const formHasBeenSubmitted = useRef(false); - useEffect(() => { - if (transaction?.participants?.findIndex((participant) => participant.accountID === transaction?.splitPayerAccountIDs?.[0]) !== -1 || iouType !== CONST.IOU.TYPE.SPLIT) { - return; - } - - const payeeParticipant: Participant = {accountID: transaction?.splitPayerAccountIDs?.[0], selected: true}; - IOU.setMoneyRequestParticipants(transaction.transactionID, [payeeParticipant, ...(transaction?.participants ?? [])]); - - // We only want to run it when the component is mounted - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - useEffect(() => { const policyExpenseChat = participants?.find((participant) => participant.isPolicyExpenseChat); if (policyExpenseChat?.policyID) { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index c99de6236a43..374d4e9777cf 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -1,6 +1,5 @@ import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import * as IOUUtils from '@libs/IOUUtils'; @@ -34,8 +33,7 @@ function IOURequestStepParticipants({ }, transaction, }: IOURequestStepParticipantsProps) { - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const participants = transaction?.participants?.filter((participant) => participant.accountID !== currentUserPersonalDetails.accountID); + const participants = transaction?.participants; const {translate} = useLocalize(); const selectedReportID = useRef(reportID); const numberOfParticipants = useRef(participants?.length ?? 0); diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx index dc1a958ed538..d6d542f126f6 100644 --- a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -3,6 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {usePersonalDetails} from '@components/OnyxProvider'; import SelectionList from '@components/SelectionList'; import UserListItem from '@components/SelectionList/UserListItem'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus'; import * as IOUUtils from '@libs/IOUUtils'; @@ -35,9 +36,21 @@ function IOURequestStepSplitPayer({ const {translate} = useLocalize(); const personalDetails = usePersonalDetails(); const {didScreenTransitionEnd} = useScreenWrapperTranstionStatus(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + + const currentUserOption = useMemo( + () => ({ + accountID: currentUserPersonalDetails.accountID, + searchText: currentUserPersonalDetails.login, + selected: true, + }), + [currentUserPersonalDetails], + ); + const sections = useMemo(() => { + const participants = transaction?.participants ?? []; const participantOptions = - transaction?.participants + [currentUserOption, ...participants] ?.filter((participant) => Boolean(participant.accountID)) ?.map((participant) => { const participantAccountID = participant.accountID ?? 0; @@ -52,7 +65,7 @@ function IOURequestStepSplitPayer({ })), }, ]; - }, [transaction?.participants, personalDetails, transaction?.splitPayerAccountIDs]); + }, [transaction?.participants, personalDetails, transaction?.splitPayerAccountIDs, currentUserOption]); const navigateBack = () => { Navigation.goBack(backTo); From 2ab8f7f159fc7208f97ada978bf1ba31f3ed21e8 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 25 Apr 2024 15:26:55 +0700 Subject: [PATCH 22/24] return participant option directly --- src/pages/iou/request/step/IOURequestStepSplitPayer.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx index d6d542f126f6..c2ee404b1205 100644 --- a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -52,10 +52,7 @@ function IOURequestStepSplitPayer({ const participantOptions = [currentUserOption, ...participants] ?.filter((participant) => Boolean(participant.accountID)) - ?.map((participant) => { - const participantAccountID = participant.accountID ?? 0; - return participantAccountID ? OptionsListUtils.getParticipantsOption(participant, personalDetails) : OptionsListUtils.getReportOption(participant); - }) ?? []; + ?.map((participant) => OptionsListUtils.getParticipantsOption(participant, personalDetails)) ?? []; return [ { title: '', From 259e557ddf82b5d861482fa4099a977213812044 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 26 Apr 2024 13:22:56 +0700 Subject: [PATCH 23/24] send splitPayerAccountIDs in split and open report API --- src/libs/actions/IOU.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 20aaf5655ae7..ae48a274665a 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -3613,7 +3613,7 @@ function splitBillAndOpenReport({ createdReportActionID: splitData.createdReportActionID, policyID: splitData.policyID, chatType: splitData.chatType, - splitPayerAccountIDs: [], + splitPayerAccountIDs, }; API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData); From baae10ecbb15b2416d4ef53ac6e709f327fa8092 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 26 Apr 2024 16:35:17 +0700 Subject: [PATCH 24/24] Hide new paid by item --- src/components/MoneyRequestConfirmationList.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index d5cc00bce1cc..14e6f636ebae 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -994,7 +994,8 @@ function MoneyRequestConfirmationList({ return ( <> - {isTypeSplit && action === CONST.IOU.ACTION.CREATE && ( + {/** Hide it temporarily, it will back when https://github.com/Expensify/App/pull/40386 is merged */} + {isTypeSplit && action === CONST.IOU.ACTION.CREATE && false && (