From e90e0085e5e300fd841c6cf4cfafd7d56b71f288 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 29 Jan 2024 16:04:33 +0700 Subject: [PATCH 01/11] remove NewDistanceRequestPage and EditRequestDistancePage --- src/ROUTES.ts | 10 +- .../MoneyRequestConfirmationList.js | 12 -- ...oraryForRefactorRequestConfirmationList.js | 10 +- .../ReportActionItem/MoneyRequestView.js | 12 +- .../AppNavigator/ModalStackNavigators.tsx | 1 - src/libs/Navigation/linkingConfig.ts | 1 - src/libs/Navigation/types.ts | 5 +- src/pages/EditRequestDistancePage.js | 122 ------------------ src/pages/EditRequestPage.js | 11 -- src/pages/iou/MoneyRequestSelectorPage.js | 12 -- src/pages/iou/NewDistanceRequestPage.js | 85 ------------ 11 files changed, 27 insertions(+), 254 deletions(-) delete mode 100644 src/pages/EditRequestDistancePage.js delete mode 100644 src/pages/iou/NewDistanceRequestPage.js diff --git a/src/ROUTES.ts b/src/ROUTES.ts index deabdc0ac853..b985f993367a 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -295,10 +295,6 @@ const ROUTES = { route: ':iouType/new/receipt/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/receipt/${reportID}` as const, }, - MONEY_REQUEST_DISTANCE: { - route: ':iouType/new/address/:reportID?', - getRoute: (iouType: string, reportID = '') => `${iouType}/new/address/${reportID}` as const, - }, MONEY_REQUEST_DISTANCE_TAB: { route: ':iouType/new/:reportID?/distance', getRoute: (iouType: string, reportID = '') => `${iouType}/new/${reportID}/distance` as const, @@ -350,9 +346,9 @@ const ROUTES = { getUrlWithBackToParam(`create/${iouType}/description/${transactionID}/${reportID}`, backTo), }, MONEY_REQUEST_STEP_DISTANCE: { - route: 'create/:iouType/distance/:transactionID/:reportID', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => - getUrlWithBackToParam(`create/${iouType}/distance/${transactionID}/${reportID}`, backTo), + route: ':action/:iouType/distance/:transactionID/:reportID', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`${action}/${iouType}/distance/${transactionID}/${reportID}`, backTo), }, MONEY_REQUEST_STEP_MERCHANT: { route: 'create/:iouType/merchant/:transactionID/:reportID', diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index d967d04ab94b..101e135d36e1 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -703,18 +703,6 @@ function MoneyRequestConfirmationList(props) { error={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? translate('common.error.enterDate') : ''} /> )} - {props.isDistanceRequest && ( - Navigation.navigate(ROUTES.MONEY_REQUEST_DISTANCE.getRoute(props.iouType, props.reportID))} - disabled={didConfirm || !isTypeRequest} - interactive={!props.isReadOnly} - /> - )} {shouldShowMerchant && ( - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())) + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( + CONST.IOU.ACTION.CREATE, + CONST.IOU.TYPE.REQUEST, + transaction.transactionID, + reportID, + Navigation.getActiveRouteWithoutParams(), + ), + ) } disabled={didConfirm || !isTypeRequest} interactive={!isReadOnly} diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 3121328138ee..6cc2119a9044 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -301,7 +301,17 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate interactive={canEditDistance} shouldShowRightIcon={canEditDistance} titleStyle={styles.flex1} - onPress={() => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DISTANCE))} + onPress={() => + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( + CONST.IOU.ACTION.EDIT, + CONST.IOU.TYPE.REQUEST, + transaction.transactionID, + report.reportID, + Navigation.getActiveRouteWithoutParams(), + ), + ) + } /> ) : ( diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 3a843e400409..9c2361916934 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -103,7 +103,6 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator require('../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType, [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.WAYPOINT]: () => require('../../../pages/iou/MoneyRequestWaypointPage').default as React.ComponentType, - [SCREENS.MONEY_REQUEST.DISTANCE]: () => require('../../../pages/iou/NewDistanceRequestPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.RECEIPT]: () => require('../../../pages/EditRequestReceiptPage').default as React.ComponentType, }); diff --git a/src/libs/Navigation/linkingConfig.ts b/src/libs/Navigation/linkingConfig.ts index d4e04d5402e2..715b14c4cb90 100644 --- a/src/libs/Navigation/linkingConfig.ts +++ b/src/libs/Navigation/linkingConfig.ts @@ -435,7 +435,6 @@ const linkingConfig: LinkingOptions = { [SCREENS.MONEY_REQUEST.TAG]: ROUTES.MONEY_REQUEST_TAG.route, [SCREENS.MONEY_REQUEST.MERCHANT]: ROUTES.MONEY_REQUEST_MERCHANT.route, [SCREENS.MONEY_REQUEST.RECEIPT]: ROUTES.MONEY_REQUEST_RECEIPT.route, - [SCREENS.MONEY_REQUEST.DISTANCE]: ROUTES.MONEY_REQUEST_DISTANCE.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 b4a77f96cc74..ea2b48df4ed2 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -238,9 +238,12 @@ type MoneyRequestNavigatorParamList = { waypointIndex: string; threadReportID: number; }; - [SCREENS.MONEY_REQUEST.DISTANCE]: { + [SCREENS.MONEY_REQUEST.STEP_DISTANCE]: { + action: string; iouType: ValueOf; + transactionID: string; reportID: string; + backTo: string; }; [SCREENS.MONEY_REQUEST.RECEIPT]: { iouType: string; diff --git a/src/pages/EditRequestDistancePage.js b/src/pages/EditRequestDistancePage.js deleted file mode 100644 index f3ea76a3390a..000000000000 --- a/src/pages/EditRequestDistancePage.js +++ /dev/null @@ -1,122 +0,0 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; -import React, {useEffect, useRef} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import DistanceRequest from '@components/DistanceRequest'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import transactionPropTypes from '@components/transactionPropTypes'; -import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; -import usePrevious from '@hooks/usePrevious'; -import Navigation from '@libs/Navigation/Navigation'; -import * as IOU from '@userActions/IOU'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import reportPropTypes from './reportPropTypes'; - -const propTypes = { - /** The transactionID we're currently editing */ - transactionID: PropTypes.string.isRequired, - - /** The report to with which the distance request is associated */ - report: reportPropTypes.isRequired, - - /** Passed from the navigator */ - route: PropTypes.shape({ - /** Parameters the route gets */ - params: PropTypes.shape({ - /** Type of IOU */ - iouType: PropTypes.oneOf(_.values(CONST.IOU.TYPE)), - - /** Id of the report on which the distance request is being created */ - reportID: PropTypes.string, - }), - }).isRequired, - - /* Onyx props */ - /** The original transaction that is being edited */ - transaction: transactionPropTypes, - - /** backup version of the original transaction */ - transactionBackup: transactionPropTypes, -}; - -const defaultProps = { - transaction: {}, - transactionBackup: {}, -}; - -function EditRequestDistancePage({report, route, transaction, transactionBackup}) { - const {isOffline} = useNetwork(); - const {translate} = useLocalize(); - const hasWaypointError = useRef(false); - const prevIsLoading = usePrevious(transaction.isLoading); - - useEffect(() => { - hasWaypointError.current = Boolean(lodashGet(transaction, 'errorFields.route') || lodashGet(transaction, 'errorFields.waypoints')); - - // When the loading goes from true to false, then we know the transaction has just been - // saved to the server. Check for errors. If there are no errors, then the modal can be closed. - if (prevIsLoading && !transaction.isLoading && !hasWaypointError.current) { - Navigation.dismissModal(report.reportID); - } - }, [transaction, prevIsLoading, report]); - - /** - * Save the changes to the original transaction object - * @param {Object} waypoints - */ - const saveTransaction = (waypoints) => { - // If nothing was changed, simply go to transaction thread - // We compare only addresses because numbers are rounded while backup - const oldWaypoints = lodashGet(transactionBackup, 'comment.waypoints', {}); - const oldAddresses = _.mapObject(oldWaypoints, (waypoint) => _.pick(waypoint, 'address')); - const addresses = _.mapObject(waypoints, (waypoint) => _.pick(waypoint, 'address')); - if (_.isEqual(oldAddresses, addresses)) { - Navigation.dismissModal(report.reportID); - return; - } - - IOU.updateMoneyRequestDistance(transaction.transactionID, report.reportID, waypoints); - - // If the client is offline, then the modal can be closed as well (because there are no errors or other feedback to show them - // until they come online again and sync with the server). - if (isOffline) { - Navigation.dismissModal(report.reportID); - } - }; - - return ( - - Navigation.goBack()} - /> - - - ); -} - -EditRequestDistancePage.propTypes = propTypes; -EditRequestDistancePage.defaultProps = defaultProps; -EditRequestDistancePage.displayName = 'EditRequestDistancePage'; -export default withOnyx({ - transaction: { - key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`, - }, - transactionBackup: { - key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${props.transactionID}`, - }, -})(EditRequestDistancePage); diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 3eb9d88f1120..9f1ba51806e5 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -23,7 +23,6 @@ import EditRequestAmountPage from './EditRequestAmountPage'; import EditRequestCategoryPage from './EditRequestCategoryPage'; import EditRequestCreatedPage from './EditRequestCreatedPage'; import EditRequestDescriptionPage from './EditRequestDescriptionPage'; -import EditRequestDistancePage from './EditRequestDistancePage'; import EditRequestMerchantPage from './EditRequestMerchantPage'; import EditRequestReceiptPage from './EditRequestReceiptPage'; import EditRequestTagPage from './EditRequestTagPage'; @@ -264,16 +263,6 @@ function EditRequestPage({report, route, policyCategories, policyTags, parentRep ); } - if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.DISTANCE) { - return ( - - ); - } - return ( { const moneyRequestID = `${iouType}${reportID}`; @@ -133,13 +128,6 @@ function MoneyRequestSelectorPage(props) { initialParams={{reportID, iouType}} /> {() => } - {shouldDisplayDistanceRequest && ( - - )} ) : ( diff --git a/src/pages/iou/NewDistanceRequestPage.js b/src/pages/iou/NewDistanceRequestPage.js deleted file mode 100644 index 750ac5d0141e..000000000000 --- a/src/pages/iou/NewDistanceRequestPage.js +++ /dev/null @@ -1,85 +0,0 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; -import React, {useCallback, useEffect} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import DistanceRequest from '@components/DistanceRequest'; -import Navigation from '@libs/Navigation/Navigation'; -import reportPropTypes from '@pages/reportPropTypes'; -import * as IOU from '@userActions/IOU'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import {iouPropTypes} from './propTypes'; - -const propTypes = { - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - iou: iouPropTypes, - - /** The report on which the request is initiated on */ - report: reportPropTypes, - - /** Passed from the navigator */ - route: PropTypes.shape({ - /** Parameters the route gets */ - params: PropTypes.shape({ - /** Type of IOU */ - iouType: PropTypes.oneOf(_.values(CONST.IOU.TYPE)), - /** Id of the report on which the distance request is being created */ - reportID: PropTypes.string, - }), - }), -}; - -const defaultProps = { - iou: {}, - report: {}, - route: { - params: { - iouType: '', - reportID: '', - }, - }, -}; - -// This component is responsible for getting the transactionID from the IOU key, or creating the transaction if it doesn't exist yet, and then passing the transactionID. -// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that DistanceRequest can subscribe to the transaction. -function NewDistanceRequestPage({iou, report, route}) { - const iouType = lodashGet(route, 'params.iouType', 'request'); - const isEditingNewRequest = Navigation.getActiveRoute().includes('address'); - - useEffect(() => { - if (iou.transactionID) { - return; - } - IOU.setUpDistanceTransaction(); - }, [iou.transactionID]); - - const onSubmit = useCallback(() => { - if (isEditingNewRequest) { - Navigation.goBack(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, report.reportID)); - return; - } - IOU.navigateToNextPage(iou, iouType, report); - }, [iou, iouType, isEditingNewRequest, report]); - - return ( - - ); -} - -NewDistanceRequestPage.displayName = 'NewDistanceRequestPage'; -NewDistanceRequestPage.propTypes = propTypes; -NewDistanceRequestPage.defaultProps = defaultProps; -export default withOnyx({ - iou: {key: ONYXKEYS.IOU}, - report: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${lodashGet(route, 'params.reportID')}`, - }, -})(NewDistanceRequestPage); From a1cc959d9617e2db908c3cab815b99c33af50c1e Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 19 Mar 2024 13:51:04 +0700 Subject: [PATCH 02/11] update route --- src/SCREENS.ts | 1 - .../MoneyRequestConfirmationList.tsx | 12 +- .../ReportActionItem/MoneyRequestView.js | 456 ------------------ .../ReportActionItem/MoneyRequestView.tsx | 6 +- 4 files changed, 16 insertions(+), 459 deletions(-) delete mode 100644 src/components/ReportActionItem/MoneyRequestView.js diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 34c7212e7f31..6b8f072e113f 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -155,7 +155,6 @@ const SCREENS = { CURRENCY: 'Money_Request_Currency', WAYPOINT: 'Money_Request_Waypoint', EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint', - DISTANCE: 'Money_Request_Distance', RECEIPT: 'Money_Request_Receipt', }, diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 6b562525258d..9b696a401f74 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -727,7 +727,17 @@ function MoneyRequestConfirmationList({ description={translate('common.distance')} style={styles.moneyRequestMenuItem} titleStyle={styles.flex1} - onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DISTANCE.getRoute(iouType, reportID))} + onPress={() => + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( + CONST.IOU.ACTION.EDIT, + iouType, + transaction?.transactionID ?? '', + reportID, + Navigation.getActiveRouteWithoutParams(), + ), + ) + } disabled={didConfirm || !canEditDistance} interactive={!isReadOnly} /> diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js deleted file mode 100644 index 6cc2119a9044..000000000000 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ /dev/null @@ -1,456 +0,0 @@ -import lodashGet from 'lodash/get'; -import lodashValues from 'lodash/values'; -import PropTypes from 'prop-types'; -import React, {useCallback} from 'react'; -import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import categoryPropTypes from '@components/categoryPropTypes'; -import * as Expensicons from '@components/Icon/Expensicons'; -import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ReceiptEmptyState from '@components/ReceiptEmptyState'; -import SpacerView from '@components/SpacerView'; -import Switch from '@components/Switch'; -import tagPropTypes from '@components/tagPropTypes'; -import Text from '@components/Text'; -import transactionPropTypes from '@components/transactionPropTypes'; -import ViolationMessages from '@components/ViolationMessages'; -import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; -import usePermissions from '@hooks/usePermissions'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useTheme from '@hooks/useTheme'; -import useThemeStyles from '@hooks/useThemeStyles'; -import useViolations from '@hooks/useViolations'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as CardUtils from '@libs/CardUtils'; -import compose from '@libs/compose'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; -import Navigation from '@libs/Navigation/Navigation'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as ReceiptUtils from '@libs/ReceiptUtils'; -import * as ReportActionsUtils from '@libs/ReportActionsUtils'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as TransactionUtils from '@libs/TransactionUtils'; -import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground'; -import reportActionPropTypes from '@pages/home/report/reportActionPropTypes'; -import iouReportPropTypes from '@pages/iouReportPropTypes'; -import reportPropTypes from '@pages/reportPropTypes'; -import {policyDefaultProps, policyPropTypes} from '@pages/workspace/withPolicy'; -import * as IOU from '@userActions/IOU'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import ReportActionItemImage from './ReportActionItemImage'; - -const violationNames = lodashValues(CONST.VIOLATIONS); - -const transactionViolationPropType = PropTypes.shape({ - type: PropTypes.string.isRequired, - name: PropTypes.oneOf(violationNames).isRequired, - data: PropTypes.shape({ - rejectedBy: PropTypes.string, - rejectReason: PropTypes.string, - amount: PropTypes.string, - surcharge: PropTypes.number, - invoiceMarkup: PropTypes.number, - maxAge: PropTypes.number, - tagName: PropTypes.string, - formattedLimitAmount: PropTypes.string, - categoryLimit: PropTypes.string, - limit: PropTypes.string, - category: PropTypes.string, - brokenBankConnection: PropTypes.bool, - isAdmin: PropTypes.bool, - email: PropTypes.string, - isTransactionOlderThan7Days: PropTypes.bool, - member: PropTypes.string, - taxName: PropTypes.string, - }), -}); - -const propTypes = { - /** The report currently being looked at */ - report: reportPropTypes.isRequired, - - /** Whether we should display the horizontal rule below the component */ - shouldShowHorizontalRule: PropTypes.bool.isRequired, - - /* Onyx Props */ - /** The expense report or iou report (only will have a value if this is a transaction thread) */ - parentReport: iouReportPropTypes, - - /** The actions from the parent report */ - parentReportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), - - /** The policy the report is tied to */ - ...policyPropTypes, - - /** Collection of categories attached to a policy */ - policyCategories: PropTypes.objectOf(categoryPropTypes), - - /** The transaction associated with the transactionThread */ - transaction: transactionPropTypes, - - /** Violations detected in this transaction */ - transactionViolations: PropTypes.arrayOf(transactionViolationPropType), - - /** Collection of tags attached to a policy */ - policyTags: tagPropTypes, - - ...withCurrentUserPersonalDetailsPropTypes, -}; - -const defaultProps = { - parentReport: {}, - parentReportActions: {}, - transaction: { - amount: 0, - currency: CONST.CURRENCY.USD, - comment: {comment: ''}, - }, - transactionViolations: [], - policyCategories: {}, - policyTags: {}, - ...policyDefaultProps, -}; - -function MoneyRequestView({report, parentReport, parentReportActions, policyCategories, shouldShowHorizontalRule, transaction, policyTags, policy, transactionViolations}) { - const theme = useTheme(); - const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); - const {isSmallScreenWidth} = useWindowDimensions(); - const {translate} = useLocalize(); - const {canUseViolations} = usePermissions(); - const parentReportAction = parentReportActions[report.parentReportActionID] || {}; - const moneyRequestReport = parentReport; - const { - created: transactionDate, - amount: transactionAmount, - currency: transactionCurrency, - comment: transactionDescription, - merchant: transactionMerchant, - billable: transactionBillable, - category: transactionCategory, - tag: transactionTag, - originalAmount: transactionOriginalAmount, - originalCurrency: transactionOriginalCurrency, - cardID: transactionCardID, - } = ReportUtils.getTransactionDetails(transaction); - const isEmptyMerchant = transactionMerchant === '' || transactionMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; - const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction); - let formattedTransactionAmount = transactionAmount ? CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency) : ''; - const hasPendingWaypoints = lodashGet(transaction, 'pendingFields.waypoints', null); - if (isDistanceRequest && (!formattedTransactionAmount || hasPendingWaypoints)) { - formattedTransactionAmount = translate('common.tbd'); - } - const formattedOriginalAmount = transactionOriginalAmount && transactionOriginalCurrency && CurrencyUtils.convertToDisplayString(transactionOriginalAmount, transactionOriginalCurrency); - const isCardTransaction = TransactionUtils.isCardTransaction(transaction); - const cardProgramName = isCardTransaction ? CardUtils.getCardDescription(transactionCardID) : ''; - - // Flags for allowing or disallowing editing a money request - const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); - const isCancelled = moneyRequestReport && moneyRequestReport.isCancelledIOU; - - // Used for non-restricted fields such as: description, category, tag, billable, etc. - const canEdit = ReportUtils.canEditMoneyRequest(parentReportAction); - const canEditAmount = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.AMOUNT); - const canEditMerchant = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.MERCHANT); - const canEditDate = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE); - const canEditReceipt = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT); - const canEditDistance = ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DISTANCE); - - // A flag for verifying that the current report is a sub-report of a workspace chat - // if the policy of the report is either Collect or Control, then this report must be tied to workspace chat - const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report); - - // Fetches only the first tag, for now - const policyTag = PolicyUtils.getTag(policyTags); - const policyTagsList = lodashGet(policyTag, 'tags', {}); - - // Flags for showing categories and tags - const shouldShowCategory = isPolicyExpenseChat && (transactionCategory || OptionsListUtils.hasEnabledOptions(lodashValues(policyCategories))); - const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagsList))); - const shouldShowBillable = isPolicyExpenseChat && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true)); - - const {getViolationsForField} = useViolations(transactionViolations); - const hasViolations = useCallback((field) => canUseViolations && getViolationsForField(field).length > 0, [canUseViolations, getViolationsForField]); - - let amountDescription = `${translate('iou.amount')}`; - - const saveBillable = useCallback( - (newBillable) => { - // If the value hasn't changed, don't request to save changes on the server and just close the modal - if (newBillable === TransactionUtils.getBillable(transaction)) { - Navigation.dismissModal(); - return; - } - IOU.updateMoneyRequestBillable(transaction.transactionID, report.reportID, newBillable); - Navigation.dismissModal(); - }, - [transaction, report], - ); - - if (isCardTransaction) { - if (formattedOriginalAmount) { - amountDescription += ` • ${translate('iou.original')} ${formattedOriginalAmount}`; - } - if (TransactionUtils.isPending(transaction)) { - amountDescription += ` • ${translate('iou.pending')}`; - } - if (isCancelled) { - amountDescription += ` • ${translate('iou.canceled')}`; - } - } else { - if (!isDistanceRequest) { - amountDescription += ` • ${translate('iou.cash')}`; - } - if (ReportUtils.isReportApproved(report)) { - amountDescription += ` • ${translate('iou.approved')}`; - } else if (isCancelled) { - amountDescription += ` • ${translate('iou.canceled')}`; - } else if (isSettled) { - amountDescription += ` • ${translate('iou.settledExpensify')}`; - } else if (report.isWaitingOnBankAccount) { - amountDescription += ` • ${translate('iou.pending')}`; - } - } - - const hasReceipt = TransactionUtils.hasReceipt(transaction); - let receiptURIs; - let hasErrors = false; - if (hasReceipt) { - receiptURIs = ReceiptUtils.getThumbnailAndImageURIs(transaction); - hasErrors = canEdit && TransactionUtils.hasMissingSmartscanFields(transaction); - } - - const pendingAction = lodashGet(transaction, 'pendingAction'); - const getPendingFieldAction = (fieldPath) => lodashGet(transaction, fieldPath) || pendingAction; - - return ( - - - - {hasReceipt && ( - - - - - - )} - {!hasReceipt && canEditReceipt && canUseViolations && ( - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.REQUEST, - transaction.transactionID, - report.reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - /> - )} - {canUseViolations && } - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} - brickRoadIndicator={hasViolations('amount') || (hasErrors && transactionAmount === 0) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - error={hasErrors && transactionAmount === 0 ? translate('common.error.enterAmount') : ''} - /> - {canUseViolations && } - - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))} - wrapperStyle={[styles.pv2, styles.taskDescriptionMenuItem]} - brickRoadIndicator={hasViolations('comment') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - numberOfLinesTitle={0} - /> - {canUseViolations && } - - {isDistanceRequest ? ( - - - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.REQUEST, - transaction.transactionID, - report.reportID, - Navigation.getActiveRouteWithoutParams(), - ), - ) - } - /> - - ) : ( - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.MERCHANT))} - brickRoadIndicator={hasViolations('merchant') || (hasErrors && isEmptyMerchant && isPolicyExpenseChat) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - error={hasErrors && isPolicyExpenseChat && isEmptyMerchant ? translate('common.error.enterMerchant') : ''} - /> - {canUseViolations && } - - )} - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))} - brickRoadIndicator={hasViolations('date') || (hasErrors && transactionDate === '') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - error={hasErrors && transactionDate === '' ? translate('common.error.enterDate') : ''} - /> - {canUseViolations && } - - {shouldShowCategory && ( - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.CATEGORY))} - brickRoadIndicator={hasViolations('category') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - /> - {canUseViolations && } - - )} - {shouldShowTag && ( - - Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAG))} - brickRoadIndicator={hasViolations('tag') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - /> - {canUseViolations && } - - )} - {isCardTransaction && ( - - - - )} - - {shouldShowBillable && ( - <> - - {translate('common.billable')} - - - {hasViolations('billable') && ( - - )} - - )} - - - - ); -} - -MoneyRequestView.propTypes = propTypes; -MoneyRequestView.defaultProps = defaultProps; -MoneyRequestView.displayName = 'MoneyRequestView'; - -export default compose( - withCurrentUserPersonalDetails, - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, - }, - policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report.policyID}`, - }, - policyTags: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`, - }, - parentReport: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, - }, - parentReportActions: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`, - canEvict: false, - }, - }), - withOnyx({ - transaction: { - key: ({report, parentReportActions}) => { - const parentReportAction = lodashGet(parentReportActions, [report.parentReportActionID]); - const transactionID = lodashGet(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0); - return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`; - }, - }, - transactionViolations: { - key: ({report}) => { - const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const transactionID = lodashGet(parentReportAction, ['originalMessage', 'IOUTransactionID'], 0); - return `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`; - }, - }, - policyTags: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`, - }, - }), -)(MoneyRequestView); diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 70c65d1d66ce..bb0308ee4509 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -327,7 +327,11 @@ function MoneyRequestView({ interactive={canEditDistance} shouldShowRightIcon={canEditDistance} titleStyle={styles.flex1} - onPress={() => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.DISTANCE))} + onPress={() => + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(CONST.IOU.ACTION.EDIT, CONST.IOU.TYPE.REQUEST, transaction?.transactionID ?? '', report.reportID), + ) + } /> ) : ( From abef718d7fe1321b28f033139367cd5a290af4e1 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 19 Mar 2024 13:56:34 +0700 Subject: [PATCH 03/11] update route --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- src/pages/iou/request/step/IOURequestStepWaypoint.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 0d1acc31ecdf..fdf451478a81 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -721,7 +721,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ description={translate('common.distance')} style={[styles.moneyRequestMenuItem]} titleStyle={styles.flex1} - onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} + onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(CONST.IOU.ACTION.CREATE, iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing disabled={didConfirm || !canEditDistance} interactive={!isReadOnly} diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index a095b2418b82..b2eb581c356b 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -131,13 +131,13 @@ function IOURequestStepWaypoint({ } // Other flows will be handled by selecting a waypoint with selectWaypoint as this is mainly for the offline flow - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(iouType, transactionID, reportID)); + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(action, iouType, transactionID, reportID)); }; const deleteStopAndHideModal = () => { Transaction.removeWaypoint(transaction, pageIndex, true); setIsDeleteStopModalOpen(false); - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(iouType, transactionID, reportID)); + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(action, iouType, transactionID, reportID)); }; const selectWaypoint = (values: Waypoint) => { @@ -168,7 +168,7 @@ function IOURequestStepWaypoint({ title={translate(waypointDescriptionKey)} shouldShowBackButton onBackButtonPress={() => { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(iouType, transactionID, reportID)); + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_DISTANCE.getRoute(action, iouType, transactionID, reportID)); }} shouldShowThreeDotsButton={shouldShowThreeDotsButton} shouldSetModalVisibility={false} From f75f7eed474f573a521865eabc8116e27d103ea3 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 19 Mar 2024 14:08:18 +0700 Subject: [PATCH 04/11] remove redundant function --- src/libs/API/types.ts | 2 -- src/libs/actions/IOU.ts | 28 ---------------------------- 2 files changed, 30 deletions(-) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 14d963b5fa44..8de223cd89f3 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -141,7 +141,6 @@ const WRITE_COMMANDS = { UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable', UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant', UPDATE_MONEY_REQUEST_TAG: 'UpdateMoneyRequestTag', - UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY: 'UpdateMoneyRequestAmountAndCurrency', @@ -309,7 +308,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG]: Parameters.UpdateMoneyRequestParams; - [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.HOLD_MONEY_REQUEST]: Parameters.HoldMoneyRequestParams; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 868bfc28d781..ccc3e102c886 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -35,7 +35,6 @@ import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import * as Localize from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import * as NextStepUtils from '@libs/NextStepUtils'; -import * as NumberUtils from '@libs/NumberUtils'; import Permissions from '@libs/Permissions'; import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; @@ -1463,22 +1462,6 @@ function updateMoneyRequestTag( API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG, params, onyxData); } -/** Updates the waypoints of a distance money request */ -function updateMoneyRequestDistance( - transactionID: string, - transactionThreadReportID: string, - waypoints: WaypointCollection, - policy: OnyxEntry, - policyTagList: OnyxEntry, - policyCategories: OnyxEntry, -) { - const transactionChanges: TransactionChanges = { - waypoints, - }; - const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, policy, policyTagList, policyCategories, true); - API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE, params, onyxData); -} - /** Updates the category of a money request */ function updateMoneyRequestCategory( transactionID: string, @@ -4143,15 +4126,6 @@ function setShownHoldUseExplanation() { Onyx.set(ONYXKEYS.NVP_HOLD_USE_EXPLAINED, true); } -function setUpDistanceTransaction() { - const transactionID = NumberUtils.rand64(); - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, { - transactionID, - comment: {type: CONST.TRANSACTION.TYPE.CUSTOM_UNIT, customUnit: {name: CONST.CUSTOM_UNITS.NAME_DISTANCE}}, - }); - Onyx.merge(ONYXKEYS.IOU, {transactionID}); -} - /** Navigates to the next IOU page based on where the IOU request was started */ function navigateToNextPage(iou: OnyxEntry, iouType: string, report?: OnyxTypes.Report, path = '') { const moneyRequestID = `${iouType}${report?.reportID ?? ''}`; @@ -4364,14 +4338,12 @@ export { setMoneyRequestTag, setMoneyRequestTaxAmount, setMoneyRequestTaxRate, - setUpDistanceTransaction, setShownHoldUseExplanation, navigateToNextPage, updateMoneyRequestDate, updateMoneyRequestBillable, updateMoneyRequestMerchant, updateMoneyRequestTag, - updateMoneyRequestDistance, updateMoneyRequestCategory, updateMoneyRequestAmountAndCurrency, updateMoneyRequestDescription, From 726abc1ee2974f41c1a4158e8c76817e354a3faf Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 19 Mar 2024 14:42:56 +0700 Subject: [PATCH 05/11] update route --- src/ROUTES.ts | 20 +- src/components/DistanceRequest/index.tsx | 320 ------------------ ...oraryForRefactorRequestConfirmationList.js | 8 +- src/libs/IOUUtils.ts | 6 +- src/libs/Navigation/Navigation.ts | 2 +- src/libs/actions/IOU.ts | 2 +- .../request/IOURequestRedirectToStartPage.js | 6 +- .../request/step/IOURequestStepDistance.js | 18 +- .../request/step/IOURequestStepWaypoint.tsx | 2 +- 9 files changed, 40 insertions(+), 344 deletions(-) delete mode 100644 src/components/DistanceRequest/index.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c853984cb6ad..144242920f61 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -305,8 +305,9 @@ const ROUTES = { getRoute: (iouType: string, reportID = '') => `${iouType}/new/receipt/${reportID}` as const, }, MONEY_REQUEST_CREATE: { - route: 'create/:iouType/start/:transactionID/:reportID', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}` as const, + route: ':action/:iouType/start/:transactionID/:reportID', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => + `create/${iouType}/start/${transactionID}/${reportID}` as const, }, MONEY_REQUEST_STEP_CONFIRMATION: { route: 'create/:iouType/confirmation/:transactionID/:reportID', @@ -391,16 +392,19 @@ const ROUTES = { 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, + route: ':action/:iouType/start/:transactionID/:reportID/distance', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => + `create/${iouType}/start/${transactionID}/${reportID}/distance` as const, }, MONEY_REQUEST_CREATE_TAB_MANUAL: { - route: 'create/:iouType/start/:transactionID/:reportID/manual', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/manual` as const, + route: ':action/:iouType/start/:transactionID/:reportID/manual', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => + `create/${iouType}/start/${transactionID}/${reportID}/manual` as const, }, MONEY_REQUEST_CREATE_TAB_SCAN: { - route: 'create/:iouType/start/:transactionID/:reportID/scan', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/scan` as const, + route: ':action/:iouType/start/:transactionID/:reportID/scan', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => + `create/${iouType}/start/${transactionID}/${reportID}/scan` as const, }, IOU_REQUEST: 'request/new', diff --git a/src/components/DistanceRequest/index.tsx b/src/components/DistanceRequest/index.tsx deleted file mode 100644 index f9e8c0be12ff..000000000000 --- a/src/components/DistanceRequest/index.tsx +++ /dev/null @@ -1,320 +0,0 @@ -import type {RouteProp} from '@react-navigation/native'; -import lodashIsEqual from 'lodash/isEqual'; -import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {View} from 'react-native'; -// eslint-disable-next-line no-restricted-imports -import type {ScrollView} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import Button from '@components/Button'; -import DotIndicatorMessage from '@components/DotIndicatorMessage'; -import DraggableList from '@components/DraggableList'; -import type {DraggableListData} from '@components/DraggableList/types'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; -import usePrevious from '@hooks/usePrevious'; -import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; -import * as IOUUtils from '@libs/IOUUtils'; -import Navigation from '@libs/Navigation/Navigation'; -import * as TransactionUtils from '@libs/TransactionUtils'; -import * as MapboxToken from '@userActions/MapboxToken'; -import * as TransactionUserActions from '@userActions/Transaction'; -import * as TransactionEdit from '@userActions/TransactionEdit'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {Report, Transaction} from '@src/types/onyx'; -import type {WaypointCollection} from '@src/types/onyx/Transaction'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import DistanceRequestFooter from './DistanceRequestFooter'; -import DistanceRequestRenderItem from './DistanceRequestRenderItem'; - -type DistanceRequestOnyxProps = { - transaction: OnyxEntry; -}; - -type DistanceRequestProps = DistanceRequestOnyxProps & { - /** The TransactionID of this request */ - transactionID?: string; - - /** The report to which the distance request is associated */ - report: OnyxEntry; - - /** Are we editing an existing distance request, or creating a new one? */ - isEditingRequest?: boolean; - - /** Are we editing the distance while creating a new distance request */ - isEditingNewRequest?: boolean; - - /** Called on submit of this page */ - onSubmit: (waypoints?: WaypointCollection) => void; - - /** React Navigation route */ - route: RouteProp<{ - /** Params from the route */ - params: { - /** The type of IOU report, i.e. bill, request, send */ - iouType: string; - /** The report ID of the IOU */ - reportID: string; - }; - }>; -}; - -function DistanceRequest({transactionID = '', report, transaction, route, isEditingRequest = false, isEditingNewRequest = false, onSubmit}: DistanceRequestProps) { - const styles = useThemeStyles(); - const {isOffline} = useNetwork(); - const {translate} = useLocalize(); - - const [optimisticWaypoints, setOptimisticWaypoints] = useState(); - const [hasError, setHasError] = useState(false); - const reportID = report?.reportID ?? ''; - const waypoints: WaypointCollection = useMemo(() => optimisticWaypoints ?? transaction?.comment?.waypoints ?? {waypoint0: {}, waypoint1: {}}, [optimisticWaypoints, transaction]); - const waypointsList = Object.keys(waypoints); - const iouType = route?.params?.iouType ?? ''; - const previousWaypoints = usePrevious(waypoints); - const numberOfWaypoints = Object.keys(waypoints).length; - const numberOfPreviousWaypoints = Object.keys(previousWaypoints).length; - const scrollViewRef = useRef(null); - - const isLoadingRoute = transaction?.comment?.isLoading ?? false; - const isLoading = transaction?.isLoading ?? false; - const hasRouteError = Boolean(transaction?.errorFields?.route); - const hasRoute = TransactionUtils.hasRoute((transaction ?? {}) as Transaction); - const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints); - const previousValidatedWaypoints = usePrevious(validatedWaypoints); - const haveValidatedWaypointsChanged = !lodashIsEqual(previousValidatedWaypoints, validatedWaypoints); - const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError; - const shouldFetchRoute = (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && Object.keys(validatedWaypoints).length > 1; - const transactionWasSaved = useRef(false); - - useEffect(() => { - MapboxToken.init(); - return MapboxToken.stop; - }, []); - - useEffect(() => { - if (!isEditingNewRequest && !isEditingRequest) { - return () => {}; - } - // This effect runs when the component is mounted and unmounted. It's purpose is to be able to properly - // discard changes if the user cancels out of making any changes. This is accomplished by backing up the - // original transaction, letting the user modify the current transaction, and then if the user ever - // cancels out of the modal without saving changes, the original transaction is restored from the backup. - - // On mount, create the backup transaction. - TransactionEdit.createBackupTransaction(transaction); - - return () => { - // If the user cancels out of the modal without without saving changes, then the original transaction - // needs to be restored from the backup so that all changes are removed. - if (transactionWasSaved.current) { - return; - } - TransactionEdit.restoreOriginalTransactionFromBackup(transaction?.transactionID ?? ''); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - const transactionWaypoints = transaction?.comment?.waypoints ?? {}; - if (!transaction?.transactionID || Object.keys(transactionWaypoints).length) { - return; - } - - // Create the initial start and stop waypoints - TransactionUserActions.createInitialWaypoints(transactionID); - return () => { - // Whenever we reset the transaction, we need to set errors as empty/false. - setHasError(false); - }; - }, [transaction, transactionID]); - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - if (isOffline || !shouldFetchRoute) { - return; - } - - TransactionUserActions.getRoute(transactionID, validatedWaypoints); - }, [shouldFetchRoute, transactionID, validatedWaypoints, isOffline]); - - useEffect(() => { - if (numberOfWaypoints <= numberOfPreviousWaypoints) { - return; - } - scrollViewRef.current?.scrollToEnd({animated: true}); - }, [numberOfPreviousWaypoints, numberOfWaypoints]); - - useEffect(() => { - // Whenever we change waypoints we need to remove the error or it will keep showing the error. - if (lodashIsEqual(previousWaypoints, waypoints)) { - return; - } - setHasError(false); - }, [waypoints, previousWaypoints]); - - const navigateBack = () => { - Navigation.goBack(isEditingNewRequest ? ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, reportID) : ROUTES.HOME); - }; - - /** - * Takes the user to the page for editing a specific waypoint - */ - const navigateToWaypointEditPage = (index: number) => { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_WAYPOINT.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.REQUEST, - transactionID, - report?.reportID ?? '', - index.toString(), - Navigation.getActiveRouteWithoutParams(), - ), - ); - }; - - const getError = useCallback(() => { - // Get route error if available else show the invalid number of waypoints error. - if (hasRouteError) { - return ErrorUtils.getLatestErrorField((transaction ?? {}) as Transaction, 'route'); - } - - if (Object.keys(validatedWaypoints).length < 2) { - // eslint-disable-next-line @typescript-eslint/naming-convention - return {0: 'iou.error.atLeastTwoDifferentWaypoints'}; - } - - if (Object.keys(validatedWaypoints).length < Object.keys(waypoints).length) { - // eslint-disable-next-line @typescript-eslint/naming-convention - return {0: translate('iou.error.duplicateWaypointsErrorMessage')}; - } - }, [translate, transaction, hasRouteError, validatedWaypoints, waypoints]); - - const updateWaypoints = useCallback( - ({data}: DraggableListData) => { - if (lodashIsEqual(waypointsList, data)) { - return; - } - - const newWaypoints: WaypointCollection = {}; - let emptyWaypointIndex = -1; - data.forEach((waypoint, index) => { - newWaypoints[`waypoint${index}`] = waypoints?.[waypoint] ?? {}; - // Find waypoint that BECOMES empty after dragging - if (isEmptyObject(newWaypoints[`waypoint${index}`]) && !isEmptyObject(waypoints[`waypoint${index}`])) { - emptyWaypointIndex = index; - } - }); - - setOptimisticWaypoints(newWaypoints); - // eslint-disable-next-line rulesdir/no-thenable-actions-in-views - Promise.all([TransactionUserActions.removeWaypoint(transaction, emptyWaypointIndex.toString()), TransactionUserActions.updateWaypoints(transactionID, newWaypoints)]).then(() => { - setOptimisticWaypoints(undefined); - }); - }, - [transactionID, transaction, waypoints, waypointsList], - ); - - const submitWaypoints = useCallback(() => { - // If there is any error or loading state, don't let user go to next page. - if (!isEmptyObject(getError()) || isLoadingRoute || (isLoading && !isOffline)) { - setHasError(true); - return; - } - - if (isEditingNewRequest || isEditingRequest) { - transactionWasSaved.current = true; - } - - onSubmit(waypoints); - }, [onSubmit, setHasError, getError, isLoadingRoute, isLoading, waypoints, isEditingNewRequest, isEditingRequest, isOffline]); - - const content = ( - <> - - item} - shouldUsePortal - onDragEnd={updateWaypoints} - ref={scrollViewRef} - renderItem={({item, drag, isActive, getIndex}) => ( - number} - onPress={navigateToWaypointEditPage} - disabled={isLoadingRoute} - /> - )} - ListFooterComponent={ - - } - /> - - - {/* Show error message if there is route error or there are less than 2 routes and user has tried submitting, */} - {((hasError && !isEmptyObject(getError())) || hasRouteError) && ( - - )} -