diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 49f0337798ee..db17378684d6 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 2cd263237866..c1d2059cd3b0 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -118,6 +118,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 e7080b3e72ec..2630a2d2afef 100644 --- a/src/libs/Navigation/linkingConfig.ts +++ b/src/libs/Navigation/linkingConfig.ts @@ -370,6 +370,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..ee98c8006cdb --- /dev/null +++ b/src/pages/iou/request/IOURequestRedirectToStartPage.js @@ -0,0 +1,69 @@ +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'; +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}, + }, +}) { + const isIouTypeValid = _.values(CONST.IOU.TYPE).includes(iouType); + const isIouRequestTypeValid = _.values(CONST.IOU.REQUEST_TYPE).includes(iouRequestType); + + 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(); + + // 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 + }, []); + + if (!isIouTypeValid || !isIouRequestTypeValid) { + return ( + + + + ); + } + + return null; +} + +IOURequestRedirectToStartPage.displayName = 'IOURequestRedirectToStartPage'; +IOURequestRedirectToStartPage.propTypes = propTypes; + +export default IOURequestRedirectToStartPage;