From eade9461dab92cc5e4bb8f4d782f48397cd4a949 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 19 Dec 2023 08:23:39 -0800 Subject: [PATCH 1/5] Add a route for easy redirects to the start request flow --- src/ROUTES.ts | 6 +++ src/SCREENS.ts | 1 + .../AppNavigator/ModalStackNavigators.tsx | 1 + src/libs/Navigation/linkingConfig.ts | 1 + .../request/IOURequestRedirectToStartPage.js | 44 +++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 src/pages/iou/request/IOURequestRedirectToStartPage.js diff --git a/src/ROUTES.ts b/src/ROUTES.ts index ca1fe9f0e81a..69dab002ffd3 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -372,6 +372,12 @@ const ROUTES = { getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => getUrlWithBackToParam(`create/${iouType}/waypoint/${transactionID}/${reportID}/${pageIndex}`, backTo), }, + // This URL is used as a redirect to one of the create tabs below. This is so that we can message users with a link + // straight to those flows without needing to have optimistic transaction and report IDs. + MONEY_REQUEST_START: { + route: 'start/:iouType/:iouRequestType', + getRoute: (iouType: ValueOf, iouRequestType: ValueOf) => `start/${iouType}/${iouRequestType}` as const, + }, MONEY_REQUEST_CREATE_TAB_DISTANCE: { route: 'create/:iouType/start/:transactionID/:reportID/distance', getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/distance` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 9e52ea0a38ca..c5107f1c9c29 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -120,6 +120,7 @@ const SCREENS = { DISTANCE_TAB: 'distance', CREATE: 'Money_Request_Create', STEP_CONFIRMATION: 'Money_Request_Step_Confirmation', + START: 'Money_Request_Start', STEP_AMOUNT: 'Money_Request_Step_Amount', STEP_CATEGORY: 'Money_Request_Step_Category', STEP_CURRENCY: 'Money_Request_Step_Currency', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 256ea6d4eceb..51dada669131 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -73,6 +73,7 @@ function createModalStackNavigator(screens: } const MoneyRequestModalStackNavigator = createModalStackNavigator({ + [SCREENS.MONEY_REQUEST.START]: () => require('../../../pages/iou/request/IOURequestRedirectToStartPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.CREATE]: () => require('../../../pages/iou/request/IOURequestStartPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: () => require('../../../pages/iou/request/step/IOURequestStepConfirmation').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: () => require('../../../pages/iou/request/step/IOURequestStepAmount').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts index afe75e59c407..a88bd0e0436b 100644 --- a/src/libs/Navigation/linkingConfig.ts +++ b/src/libs/Navigation/linkingConfig.ts @@ -376,6 +376,7 @@ const linkingConfig: LinkingOptions = { }, [SCREENS.RIGHT_MODAL.MONEY_REQUEST]: { screens: { + [SCREENS.MONEY_REQUEST.START]: ROUTES.MONEY_REQUEST_START.route, [SCREENS.MONEY_REQUEST.CREATE]: { path: ROUTES.MONEY_REQUEST_CREATE.route, exact: true, diff --git a/src/pages/iou/request/IOURequestRedirectToStartPage.js b/src/pages/iou/request/IOURequestRedirectToStartPage.js new file mode 100644 index 000000000000..3800c2041356 --- /dev/null +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -0,0 +1,44 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import _ from 'underscore'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +const propTypes = { + /** Navigation route context info provided by react navigation */ + route: PropTypes.shape({ + /** Route specific parameters used on this screen */ + params: PropTypes.shape({ + /** The type of IOU report, i.e. bill, request, send */ + iouType: PropTypes.oneOf(_.values(CONST.IOU.TYPE)).isRequired, + + /** The type of IOU Request, i.e. manual, scan, distance */ + iouRequestType: PropTypes.oneOf(_.values(CONST.IOU.REQUEST_TYPE)).isRequired, + }), + }).isRequired, +}; + +function IOURequestRedirectToStartPage({ + route: { + params: {iouType, iouRequestType}, + }, +}) { + // Redirect the person to the right start page using a rendom reportID + const optimisticReportID = ReportUtils.generateReportID(); + if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_DISTANCE.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_MANUAL.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } + return ; +} + +IOURequestRedirectToStartPage.displayName = 'IOURequestRedirectToStartPage'; +IOURequestRedirectToStartPage.propTypes = propTypes; + +export default IOURequestRedirectToStartPage; From a203ca195b8a921559f23f500b93c0ce5a8b078e Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 26 Dec 2023 14:58:16 -0700 Subject: [PATCH 2/5] Dismiss modal before redirecting --- src/pages/iou/request/IOURequestRedirectToStartPage.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/iou/request/IOURequestRedirectToStartPage.js b/src/pages/iou/request/IOURequestRedirectToStartPage.js index 3800c2041356..510f55690785 100644 --- a/src/pages/iou/request/IOURequestRedirectToStartPage.js +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -26,6 +26,9 @@ function IOURequestRedirectToStartPage({ params: {iouType, iouRequestType}, }, }) { + // Dismiss this modal because the redirects below will open a new modal and there shouldn't be two modals stacked on top of each other. + Navigation.dismissModal(); + // Redirect the person to the right start page using a rendom reportID const optimisticReportID = ReportUtils.generateReportID(); if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { From aa5b2eaa94da0ab9236e5a5f5cce8d650c94cfe6 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Tue, 26 Dec 2023 15:43:13 -0700 Subject: [PATCH 3/5] Do navigation once component has mounted --- .../request/IOURequestRedirectToStartPage.js | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/pages/iou/request/IOURequestRedirectToStartPage.js b/src/pages/iou/request/IOURequestRedirectToStartPage.js index 510f55690785..0197a2482842 100644 --- a/src/pages/iou/request/IOURequestRedirectToStartPage.js +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import {useEffect} from 'react'; import _ from 'underscore'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; @@ -26,19 +25,24 @@ function IOURequestRedirectToStartPage({ params: {iouType, iouRequestType}, }, }) { - // Dismiss this modal because the redirects below will open a new modal and there shouldn't be two modals stacked on top of each other. - Navigation.dismissModal(); + useEffect(() => { + // Dismiss this modal because the redirects below will open a new modal and there shouldn't be two modals stacked on top of each other. + Navigation.dismissModal(); - // Redirect the person to the right start page using a rendom reportID - const optimisticReportID = ReportUtils.generateReportID(); - if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { - Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_DISTANCE.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); - } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL) { - Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_MANUAL.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); - } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); - } - return ; + // Redirect the person to the right start page using a rendom reportID + const optimisticReportID = ReportUtils.generateReportID(); + if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_DISTANCE.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_MANUAL.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } else if (iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { + Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID)); + } + + // This useEffect should only run on mount which is why there are no dependencies being passed in the second parameter + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return null; } IOURequestRedirectToStartPage.displayName = 'IOURequestRedirectToStartPage'; From c744ec120c5e3c991c6b6e0d129d5007ac3babd5 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 27 Dec 2023 08:47:36 -0700 Subject: [PATCH 4/5] Check for valid iou types and show not found if invalid --- .../iou/request/IOURequestRedirectToStartPage.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/IOURequestRedirectToStartPage.js b/src/pages/iou/request/IOURequestRedirectToStartPage.js index 0197a2482842..45f5b9abf954 100644 --- a/src/pages/iou/request/IOURequestRedirectToStartPage.js +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; -import {useEffect} from 'react'; +import React, {useEffect} from 'react'; import _ from 'underscore'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; @@ -25,7 +26,14 @@ function IOURequestRedirectToStartPage({ params: {iouType, iouRequestType}, }, }) { + const isIouTypeValid = _.values(CONST.IOU.TYPE).indexOf(iouType) > -1; + const isIouRequestTypeValid = _.values(CONST.IOU.REQUEST_TYPE).indexOf(iouRequestType) > -1; + useEffect(() => { + if (!isIouTypeValid || !isIouRequestTypeValid) { + return; + } + // Dismiss this modal because the redirects below will open a new modal and there shouldn't be two modals stacked on top of each other. Navigation.dismissModal(); @@ -42,6 +50,11 @@ function IOURequestRedirectToStartPage({ // This useEffect should only run on mount which is why there are no dependencies being passed in the second parameter // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + + if (!isIouTypeValid || !isIouRequestTypeValid) { + return ; + } + return null; } From 9d960f30e4017b4ef9d5c039f804b51beb86e46b Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 27 Dec 2023 09:57:25 -0700 Subject: [PATCH 5/5] Add screenwrapper --- .../iou/request/IOURequestRedirectToStartPage.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/IOURequestRedirectToStartPage.js b/src/pages/iou/request/IOURequestRedirectToStartPage.js index 45f5b9abf954..ee98c8006cdb 100644 --- a/src/pages/iou/request/IOURequestRedirectToStartPage.js +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React, {useEffect} from 'react'; import _ from 'underscore'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import ScreenWrapper from '@components/ScreenWrapper'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import CONST from '@src/CONST'; @@ -26,8 +27,8 @@ function IOURequestRedirectToStartPage({ params: {iouType, iouRequestType}, }, }) { - const isIouTypeValid = _.values(CONST.IOU.TYPE).indexOf(iouType) > -1; - const isIouRequestTypeValid = _.values(CONST.IOU.REQUEST_TYPE).indexOf(iouRequestType) > -1; + const isIouTypeValid = _.values(CONST.IOU.TYPE).includes(iouType); + const isIouRequestTypeValid = _.values(CONST.IOU.REQUEST_TYPE).includes(iouRequestType); useEffect(() => { if (!isIouTypeValid || !isIouRequestTypeValid) { @@ -52,7 +53,11 @@ function IOURequestRedirectToStartPage({ }, []); if (!isIouTypeValid || !isIouRequestTypeValid) { - return ; + return ( + + + + ); } return null;