Skip to content

Commit 790ab54

Browse files
authored
Merge pull request #56876 from software-mansion-labs/@adamgrzybowski/fix-iou-go-backs
[Navigation] Fix goBack in IOU steps
2 parents 64aab89 + b0e37b5 commit 790ab54

8 files changed

+100
-36
lines changed

src/components/MoneyRequestConfirmationList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ function MoneyRequestConfirmationList({
798798
}
799799

800800
const newIOUType = iouType === CONST.IOU.TYPE.SUBMIT || iouType === CONST.IOU.TYPE.TRACK ? CONST.IOU.TYPE.CREATE : iouType;
801-
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(newIOUType, transactionID, transaction.reportID));
801+
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(newIOUType, transactionID, transaction.reportID, Navigation.getActiveRoute()));
802802
};
803803

804804
/**

src/libs/Navigation/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ type MoneyRequestNavigatorParamList = {
11001100
iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
11011101
transactionID: string;
11021102
reportID: string;
1103-
backTo: string;
1103+
backTo: Routes;
11041104
};
11051105
[SCREENS.MONEY_REQUEST.STEP_DATE]: {
11061106
action: IOUAction;

src/libs/PolicyUtils.ts

+11
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ function getActivePolicies(policies: OnyxCollection<Policy> | null, currentUserL
8686
!!policy && policy.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !!policy.name && !!policy.id && !!getPolicyRole(policy, currentUserLogin),
8787
);
8888
}
89+
90+
function getPerDiemCustomUnits(policies: OnyxCollection<Policy> | null, email: string | undefined): Array<{policyID: string; customUnit: CustomUnit}> {
91+
return (
92+
getActivePolicies(policies, email)
93+
.map((mappedPolicy) => ({policyID: mappedPolicy.id, customUnit: getPerDiemCustomUnit(mappedPolicy)}))
94+
// We filter out custom units that are undefine but ts cant' figure it out.
95+
.filter(({customUnit}) => !isEmptyObject(customUnit) && !!customUnit.enabled) as Array<{policyID: string; customUnit: CustomUnit}>
96+
);
97+
}
98+
8999
/**
90100
* Checks if the current user is an admin of the policy.
91101
*/
@@ -1338,6 +1348,7 @@ export {
13381348
extractPolicyIDFromPath,
13391349
escapeTagName,
13401350
getActivePolicies,
1351+
getPerDiemCustomUnits,
13411352
getAllSelfApprovers,
13421353
getAdminEmployees,
13431354
getCleanedTagName,

src/pages/iou/request/IOURequestStartPage.tsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
1515
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
1616
import Navigation from '@libs/Navigation/Navigation';
1717
import OnyxTabNavigator, {TabScreenWithFocusTrapWrapper, TopTab} from '@libs/Navigation/OnyxTabNavigator';
18-
import {getActivePolicies, getPerDiemCustomUnit} from '@libs/PolicyUtils';
18+
import {getPerDiemCustomUnit, getPerDiemCustomUnits} from '@libs/PolicyUtils';
1919
import {getPayeeName} from '@libs/ReportUtils';
2020
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
2121
import type {IOURequestType} from '@userActions/IOU';
@@ -103,10 +103,7 @@ function IOURequestStartPage({
103103
return [headerWithBackBtnContainerElement, tabBarContainerElement, activeTabContainerElement].filter((element) => !!element) as HTMLElement[];
104104
}, [headerWithBackBtnContainerElement, tabBarContainerElement, activeTabContainerElement]);
105105

106-
const perDiemCustomUnits = getActivePolicies(allPolicies, session?.email)
107-
.map((mappedPolicy) => ({policyID: mappedPolicy.id, customUnit: getPerDiemCustomUnit(mappedPolicy)}))
108-
.filter(({customUnit}) => !isEmptyObject(customUnit) && !!customUnit.enabled);
109-
106+
const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email);
110107
const doesPerDiemPolicyExist = perDiemCustomUnits.length > 0;
111108

112109
const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1;

src/pages/iou/request/step/IOURequestStepConfirmation.tsx

+26-6
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,35 @@ function IOURequestStepConfirmation({
216216
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_SUBRATE.getRoute(action, iouType, transactionID, reportID));
217217
return;
218218
}
219-
// If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken
220-
// back to the participants step
221-
if (!transaction?.participantsAutoAssigned && participantsAutoAssignedFromRoute !== 'true') {
222-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
223-
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action), {compareParams: false});
219+
220+
if (transaction?.isFromGlobalCreate) {
221+
// If the participants weren't automatically added to the transaction, then we should go back to the IOURequestStepParticipants.
222+
if (!transaction?.participantsAutoAssigned && participantsAutoAssignedFromRoute !== 'true') {
223+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
224+
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action), {compareParams: false});
225+
return;
226+
}
227+
228+
// If the participant was auto-assigned, we need to keep the reportID that is already on the stack.
229+
// This will allow the user to edit the participant field after going back and forward.
230+
Navigation.goBack();
224231
return;
225232
}
233+
234+
// This has selected the participants from the beginning and the participant field shouldn't be editable.
226235
navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action);
227-
}, [action, isPerDiemRequest, transaction?.participantsAutoAssigned, transaction?.reportID, participantsAutoAssignedFromRoute, requestType, iouType, transactionID, reportID]);
236+
}, [
237+
action,
238+
isPerDiemRequest,
239+
transaction?.participantsAutoAssigned,
240+
transaction?.isFromGlobalCreate,
241+
transaction?.reportID,
242+
participantsAutoAssignedFromRoute,
243+
requestType,
244+
iouType,
245+
transactionID,
246+
reportID,
247+
]);
228248

229249
const navigateToAddReceipt = useCallback(() => {
230250
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()));

src/pages/iou/request/step/IOURequestStepDestination.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ function IOURequestStepDestination({
9393
if (backTo) {
9494
navigateBack();
9595
} else if (explicitPolicyID) {
96-
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, policyExpenseReport?.reportID ?? reportID, Navigation.getActiveRoute()));
96+
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, policyExpenseReport?.reportID ?? reportID));
9797
} else {
98-
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
98+
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TIME.getRoute(action, iouType, transactionID, reportID));
9999
}
100100
};
101101

src/pages/iou/request/step/IOURequestStepParticipants.tsx

+39-20
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
} from '@userActions/IOU';
2727
import CONST from '@src/CONST';
2828
import ONYXKEYS from '@src/ONYXKEYS';
29-
import type {Route} from '@src/ROUTES';
3029
import ROUTES from '@src/ROUTES';
3130
import type SCREENS from '@src/SCREENS';
3231
import type {Participant} from '@src/types/onyx/IOU';
@@ -42,7 +41,7 @@ type IOURequestStepParticipantsProps = WithWritableReportOrNotFoundProps<typeof
4241

4342
function IOURequestStepParticipants({
4443
route: {
45-
params: {iouType, reportID, transactionID, action},
44+
params: {iouType, reportID, transactionID, action, backTo},
4645
},
4746
transaction,
4847
}: IOURequestStepParticipantsProps) {
@@ -109,6 +108,19 @@ function IOURequestStepParticipants({
109108
resetDraftTransactionsCustomUnit(transactionID);
110109
}, [isFocused, isMovingTransactionFromTrackExpense, transactionID]);
111110

111+
const waitForKeyboardDismiss = useCallback(
112+
(callback: () => void) => {
113+
if (isAndroidNative || isMobileSafari) {
114+
KeyboardUtils.dismiss().then(() => {
115+
callback();
116+
});
117+
} else {
118+
callback();
119+
}
120+
},
121+
[isAndroidNative, isMobileSafari],
122+
);
123+
112124
const trackExpense = useCallback(() => {
113125
// If coming from the combined submit/track flow and the user proceeds to just track the expense,
114126
// we will use the track IOU type in the confirmation flow.
@@ -120,8 +132,16 @@ function IOURequestStepParticipants({
120132
setCustomUnitRateID(transactionID, rateID);
121133
setMoneyRequestParticipantsFromReport(transactionID, selfDMReport);
122134
const iouConfirmationPageRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.TRACK, transactionID, selfDMReportID);
123-
Navigation.navigate(iouConfirmationPageRoute);
124-
}, [action, selfDMReport, selfDMReportID, transactionID]);
135+
waitForKeyboardDismiss(() => {
136+
// If the backTo parameter is set, we should navigate back to the confirmation screen that is already on the stack.
137+
if (backTo) {
138+
// We don't want to compare params because we just changed the participants.
139+
Navigation.goBack(iouConfirmationPageRoute, {compareParams: false});
140+
} else {
141+
Navigation.navigate(iouConfirmationPageRoute);
142+
}
143+
});
144+
}, [action, backTo, selfDMReport, selfDMReportID, transactionID, waitForKeyboardDismiss]);
125145

126146
const addParticipant = useCallback(
127147
(val: Participant[]) => {
@@ -159,19 +179,6 @@ function IOURequestStepParticipants({
159179
[iouType, reportID, trackExpense, transactionID, isMovingTransactionFromTrackExpense],
160180
);
161181

162-
const handleNavigation = useCallback(
163-
(route: Route) => {
164-
if (isAndroidNative || isMobileSafari) {
165-
KeyboardUtils.dismiss().then(() => {
166-
Navigation.navigate(route);
167-
});
168-
} else {
169-
Navigation.navigate(route);
170-
}
171-
},
172-
[isAndroidNative, isMobileSafari],
173-
);
174-
175182
const goToNextStep = useCallback(() => {
176183
const isCategorizing = action === CONST.IOU.ACTION.CATEGORIZE;
177184
const isShareAction = action === CONST.IOU.ACTION.SHARE;
@@ -202,12 +209,24 @@ function IOURequestStepParticipants({
202209
? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, selectedReportID.current || reportID, iouConfirmationPageRoute)
203210
: iouConfirmationPageRoute;
204211

205-
handleNavigation(route);
206-
}, [action, participants, iouType, transaction, transactionID, reportID, handleNavigation]);
212+
waitForKeyboardDismiss(() => {
213+
// If the backTo parameter is set, we should navigate back to the confirmation screen that is already on the stack.
214+
if (backTo) {
215+
// We don't want to compare params because we just changed the participants.
216+
Navigation.goBack(route, {compareParams: false});
217+
} else {
218+
Navigation.navigate(route);
219+
}
220+
});
221+
}, [action, participants, iouType, transaction, transactionID, reportID, waitForKeyboardDismiss, backTo]);
207222

208223
const navigateBack = useCallback(() => {
224+
if (backTo) {
225+
Navigation.goBack(backTo);
226+
return;
227+
}
209228
navigateToStartMoneyRequestStep(iouRequestType, iouType, transactionID, reportID, action);
210-
}, [iouRequestType, iouType, transactionID, reportID, action]);
229+
}, [backTo, iouRequestType, iouType, transactionID, reportID, action]);
211230

212231
useEffect(() => {
213232
const isCategorizing = action === CONST.IOU.ACTION.CATEGORIZE;

src/pages/iou/request/step/IOURequestStepTime.tsx

+18-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import DateUtils from '@libs/DateUtils';
1313
import {addErrorMessage} from '@libs/ErrorUtils';
1414
import {isValidMoneyRequestType} from '@libs/IOUUtils';
1515
import Navigation from '@libs/Navigation/Navigation';
16+
import {getPerDiemCustomUnits} from '@libs/PolicyUtils';
1617
import {getIOURequestPolicyID, setMoneyRequestDateAttribute} from '@userActions/IOU';
1718
import CONST from '@src/CONST';
1819
import ONYXKEYS from '@src/ONYXKEYS';
@@ -44,6 +45,8 @@ function IOURequestStepTime({
4445
}: IOURequestStepTimeProps) {
4546
const styles = useThemeStyles();
4647
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getIOURequestPolicyID(transaction, report)}`);
48+
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
49+
const [session] = useOnyx(ONYXKEYS.SESSION);
4750
const {translate} = useLocalize();
4851
const currentDateAttributes = transaction?.comment?.customUnit?.attributes?.dates;
4952
const currentStartDate = currentDateAttributes?.start ? DateUtils.extractDate(currentDateAttributes.start) : undefined;
@@ -52,6 +55,9 @@ function IOURequestStepTime({
5255
const shouldShowNotFound = !isValidMoneyRequestType(iouType) || isEmptyObject(transaction?.comment?.customUnit) || isEmptyObject(policy);
5356
const isEditPage = name === SCREENS.MONEY_REQUEST.STEP_TIME_EDIT;
5457

58+
const perDiemCustomUnits = getPerDiemCustomUnits(allPolicies, session?.email);
59+
const moreThanOnePerDiemExist = perDiemCustomUnits.length > 1;
60+
5561
const navigateBack = () => {
5662
if (isEditPage) {
5763
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID));
@@ -62,7 +68,18 @@ function IOURequestStepTime({
6268
Navigation.goBack(backTo);
6369
return;
6470
}
65-
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DESTINATION.getRoute(action, iouType, transactionID, reportID));
71+
72+
if (transaction?.isFromGlobalCreate) {
73+
if (moreThanOnePerDiemExist) {
74+
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DESTINATION.getRoute(action, iouType, transactionID, reportID));
75+
return;
76+
}
77+
78+
// 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.
79+
Navigation.goBack();
80+
}
81+
82+
Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_PER_DIEM.getRoute(action, iouType, transactionID, reportID));
6683
};
6784

6885
const validate = (value: FormOnyxValues<typeof ONYXKEYS.FORMS.MONEY_REQUEST_TIME_FORM>) => {

0 commit comments

Comments
 (0)