diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 63579c5854fa..050f2a6e403b 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -798,7 +798,7 @@ function MoneyRequestConfirmationList({ } const newIOUType = iouType === CONST.IOU.TYPE.SUBMIT || iouType === CONST.IOU.TYPE.TRACK ? CONST.IOU.TYPE.CREATE : iouType; - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(newIOUType, transactionID, transaction.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(newIOUType, transactionID, transaction.reportID, Navigation.getActiveRoute())); }; /** diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index d1aa0b331d60..35e204a8f2f4 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1100,7 +1100,7 @@ type MoneyRequestNavigatorParamList = { iouType: Exclude; transactionID: string; reportID: string; - backTo: string; + backTo: Routes; }; [SCREENS.MONEY_REQUEST.STEP_DATE]: { action: IOUAction; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 5798f45dde72..a747b6b5edb7 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -86,6 +86,16 @@ function getActivePolicies(policies: OnyxCollection | null, currentUserL !!policy && policy.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !!policy.name && !!policy.id && !!getPolicyRole(policy, currentUserLogin), ); } + +function getPerDiemCustomUnits(policies: OnyxCollection | null, email: string | undefined): Array<{policyID: string; customUnit: CustomUnit}> { + return ( + getActivePolicies(policies, email) + .map((mappedPolicy) => ({policyID: mappedPolicy.id, customUnit: getPerDiemCustomUnit(mappedPolicy)})) + // We filter out custom units that are undefine but ts cant' figure it out. + .filter(({customUnit}) => !isEmptyObject(customUnit) && !!customUnit.enabled) as Array<{policyID: string; customUnit: CustomUnit}> + ); +} + /** * Checks if the current user is an admin of the policy. */ @@ -1338,6 +1348,7 @@ export { extractPolicyIDFromPath, escapeTagName, getActivePolicies, + getPerDiemCustomUnits, getAllSelfApprovers, getAdminEmployees, getCleanedTagName, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 4456886f0ae8..5f6819976bb2 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -15,7 +15,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import Navigation from '@libs/Navigation/Navigation'; import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Navigation/OnyxTabNavigator'; -import {getActivePolicies, getPerDiemCustomUnit} from '@libs/PolicyUtils'; +import {getPerDiemCustomUnit, getPerDiemCustomUnits} from '@libs/PolicyUtils'; import {getPayeeName} from '@libs/ReportUtils'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {IOURequestType} from '@userActions/IOU'; @@ -103,10 +103,7 @@ function IOURequestStartPage({ return [headerWithBackBtnContainerElement, tabBarContainerElement, activeTabContainerElement].filter((element) => !!element) as HTMLElement[]; }, [headerWithBackBtnContainerElement, tabBarContainerElement, activeTabContainerElement]); - const perDiemCustomUnits = getActivePolicies(allPolicies, session?.email) - .map((mappedPolicy) => ({policyID: mappedPolicy.id, customUnit: getPerDiemCustomUnit(mappedPolicy)})) - .filter(({customUnit}) => !isEmptyObject(customUnit) && !!customUnit.enabled); - + const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email); const doesPerDiemPolicyExist = perDiemCustomUnits.length > 0; const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 4ea550be00d0..20b0739e869a 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -216,15 +216,35 @@ function IOURequestStepConfirmation({ Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_SUBRATE.getRoute(action, iouType, transactionID, reportID)); return; } - // If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken - // back to the participants step - if (!transaction?.participantsAutoAssigned && participantsAutoAssignedFromRoute !== 'true') { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action), {compareParams: false}); + + if (transaction?.isFromGlobalCreate) { + // If the participants weren't automatically added to the transaction, then we should go back to the IOURequestStepParticipants. + if (!transaction?.participantsAutoAssigned && participantsAutoAssignedFromRoute !== 'true') { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action), {compareParams: false}); + return; + } + + // If the participant was auto-assigned, we need to keep the reportID that is already on the stack. + // This will allow the user to edit the participant field after going back and forward. + Navigation.goBack(); return; } + + // This has selected the participants from the beginning and the participant field shouldn't be editable. navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action); - }, [action, isPerDiemRequest, transaction?.participantsAutoAssigned, transaction?.reportID, participantsAutoAssignedFromRoute, requestType, iouType, transactionID, reportID]); + }, [ + action, + isPerDiemRequest, + transaction?.participantsAutoAssigned, + transaction?.isFromGlobalCreate, + transaction?.reportID, + participantsAutoAssignedFromRoute, + requestType, + iouType, + transactionID, + reportID, + ]); const navigateToAddReceipt = useCallback(() => { Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams())); diff --git a/src/pages/iou/request/step/IOURequestStepDestination.tsx b/src/pages/iou/request/step/IOURequestStepDestination.tsx index fa08e7d0d5e7..cc6928079061 100644 --- a/src/pages/iou/request/step/IOURequestStepDestination.tsx +++ b/src/pages/iou/request/step/IOURequestStepDestination.tsx @@ -93,9 +93,9 @@ function IOURequestStepDestination({ if (backTo) { navigateBack(); } else if (explicitPolicyID) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, policyExpenseReport?.reportID ?? reportID, Navigation.getActiveRoute())); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, policyExpenseReport?.reportID ?? reportID)); } else { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute())); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, reportID)); } }; diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 8d1ef11ef23f..afd00a99373b 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -26,7 +26,6 @@ import { } from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Participant} from '@src/types/onyx/IOU'; @@ -42,7 +41,7 @@ type IOURequestStepParticipantsProps = WithWritableReportOrNotFoundProps void) => { + if (isAndroidNative || isMobileSafari) { + KeyboardUtils.dismiss().then(() => { + callback(); + }); + } else { + callback(); + } + }, + [isAndroidNative, isMobileSafari], + ); + const trackExpense = useCallback(() => { // If coming from the combined submit/track flow and the user proceeds to just track the expense, // we will use the track IOU type in the confirmation flow. @@ -120,8 +132,16 @@ function IOURequestStepParticipants({ setCustomUnitRateID(transactionID, rateID); setMoneyRequestParticipantsFromReport(transactionID, selfDMReport); const iouConfirmationPageRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.TRACK, transactionID, selfDMReportID); - Navigation.navigate(iouConfirmationPageRoute); - }, [action, selfDMReport, selfDMReportID, transactionID]); + waitForKeyboardDismiss(() => { + // If the backTo parameter is set, we should navigate back to the confirmation screen that is already on the stack. + if (backTo) { + // We don't want to compare params because we just changed the participants. + Navigation.goBack(iouConfirmationPageRoute, {compareParams: false}); + } else { + Navigation.navigate(iouConfirmationPageRoute); + } + }); + }, [action, backTo, selfDMReport, selfDMReportID, transactionID, waitForKeyboardDismiss]); const addParticipant = useCallback( (val: Participant[]) => { @@ -159,19 +179,6 @@ function IOURequestStepParticipants({ [iouType, reportID, trackExpense, transactionID, isMovingTransactionFromTrackExpense], ); - const handleNavigation = useCallback( - (route: Route) => { - if (isAndroidNative || isMobileSafari) { - KeyboardUtils.dismiss().then(() => { - Navigation.navigate(route); - }); - } else { - Navigation.navigate(route); - } - }, - [isAndroidNative, isMobileSafari], - ); - const goToNextStep = useCallback(() => { const isCategorizing = action === CONST.IOU.ACTION.CATEGORIZE; const isShareAction = action === CONST.IOU.ACTION.SHARE; @@ -202,12 +209,24 @@ function IOURequestStepParticipants({ ? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, selectedReportID.current || reportID, iouConfirmationPageRoute) : iouConfirmationPageRoute; - handleNavigation(route); - }, [action, participants, iouType, transaction, transactionID, reportID, handleNavigation]); + waitForKeyboardDismiss(() => { + // If the backTo parameter is set, we should navigate back to the confirmation screen that is already on the stack. + if (backTo) { + // We don't want to compare params because we just changed the participants. + Navigation.goBack(route, {compareParams: false}); + } else { + Navigation.navigate(route); + } + }); + }, [action, participants, iouType, transaction, transactionID, reportID, waitForKeyboardDismiss, backTo]); const navigateBack = useCallback(() => { + if (backTo) { + Navigation.goBack(backTo); + return; + } navigateToStartMoneyRequestStep(iouRequestType, iouType, transactionID, reportID, action); - }, [iouRequestType, iouType, transactionID, reportID, action]); + }, [backTo, iouRequestType, iouType, transactionID, reportID, action]); useEffect(() => { const isCategorizing = action === CONST.IOU.ACTION.CATEGORIZE; diff --git a/src/pages/iou/request/step/IOURequestStepTime.tsx b/src/pages/iou/request/step/IOURequestStepTime.tsx index 76dca80e8cd9..f8817c6ae8f2 100644 --- a/src/pages/iou/request/step/IOURequestStepTime.tsx +++ b/src/pages/iou/request/step/IOURequestStepTime.tsx @@ -13,6 +13,7 @@ import DateUtils from '@libs/DateUtils'; import {addErrorMessage} from '@libs/ErrorUtils'; import {isValidMoneyRequestType} from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {getPerDiemCustomUnits} from '@libs/PolicyUtils'; import {getIOURequestPolicyID, setMoneyRequestDateAttribute} from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -44,6 +45,8 @@ function IOURequestStepTime({ }: IOURequestStepTimeProps) { const styles = useThemeStyles(); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getIOURequestPolicyID(transaction, report)}`); + const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [session] = useOnyx(ONYXKEYS.SESSION); const {translate} = useLocalize(); const currentDateAttributes = transaction?.comment?.customUnit?.attributes?.dates; const currentStartDate = currentDateAttributes?.start ? DateUtils.extractDate(currentDateAttributes.start) : undefined; @@ -52,6 +55,9 @@ function IOURequestStepTime({ const shouldShowNotFound = !isValidMoneyRequestType(iouType) || isEmptyObject(transaction?.comment?.customUnit) || isEmptyObject(policy); const isEditPage = name === SCREENS.MONEY_REQUEST.STEP_TIME_EDIT; + const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email); + const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1; + const navigateBack = () => { if (isEditPage) { Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID)); @@ -62,7 +68,18 @@ function IOURequestStepTime({ Navigation.goBack(backTo); return; } - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DESTINATION.getRoute(action, iouType, transactionID, reportID)); + + if (transaction?.isFromGlobalCreate) { + if (moreThanOnePerDiemExist) { + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DESTINATION.getRoute(action, iouType, transactionID, reportID)); + return; + } + + // If there is only one per diem policy, we can't override the reportID that is already on the stack to make sure we go back to the right screen. + Navigation.goBack(); + } + + Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_PER_DIEM.getRoute(action, iouType, transactionID, reportID)); }; const validate = (value: FormOnyxValues) => {