@@ -27,39 +27,37 @@ import useReportIsArchived from '@hooks/useReportIsArchived';
2727import useSelfDMReport from '@hooks/useSelfDMReport' ;
2828import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep' ;
2929import useWaypointItems from '@hooks/useWaypointItems' ;
30- import { setMoneyRequestAmount , setMoneyRequestDistance } from '@libs/actions/IOU' ;
31- import { handleMoneyRequestStepDistanceNavigation } from '@libs/actions/IOU/MoneyRequest' ;
32- import { setDraftSplitTransaction , setSplitShares } from '@libs/actions/IOU/Split' ;
30+ import { setMoneyRequestDistance } from '@libs/actions/IOU' ;
31+ import { setDraftSplitTransaction } from '@libs/actions/IOU/Split' ;
3332import { updateMoneyRequestDistance } from '@libs/actions/IOU/UpdateMoneyRequest' ;
3433import { init , stop } from '@libs/actions/MapboxToken' ;
35- import { openReport } from '@libs/actions/Report' ;
3634import { openDraftDistanceExpense , removeWaypoint , updateWaypoints as updateWaypointsUtil } from '@libs/actions/Transaction' ;
37- import { createBackupTransaction , removeBackupTransaction , restoreOriginalTransactionFromBackup } from '@libs/actions/TransactionEdit' ;
35+ import { removeBackupTransaction } from '@libs/actions/TransactionEdit' ;
3836import DistanceRequestUtils from '@libs/DistanceRequestUtils' ;
39- import type { MileageRate } from '@libs/DistanceRequestUtils' ;
4037import { getLatestErrorField } from '@libs/ErrorUtils' ;
4138import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID' ;
4239import { shouldUseTransactionDraft } from '@libs/IOUUtils' ;
4340import Navigation from '@libs/Navigation/Navigation' ;
4441import OnyxTabNavigator , { TabScreenWithFocusTrapWrapper , TopTab } from '@libs/Navigation/OnyxTabNavigator' ;
4542import { roundToTwoDecimalPlaces } from '@libs/NumberUtils' ;
4643import { isPolicyExpenseChat as isPolicyExpenseChatUtil } from '@libs/ReportUtils' ;
47- import { getDistanceInMeters , getRateID , getRequestType , hasRoute , haveWaypointAddressesChanged , isCustomUnitRateIDForP2P , isWaypointNullIsland } from '@libs/TransactionUtils' ;
44+ import { getDistanceInMeters , getRateID , getRequestType , haveWaypointAddressesChanged } from '@libs/TransactionUtils' ;
4845import CONST from '@src/CONST' ;
4946import type { IOUType } from '@src/CONST' ;
5047import ONYXKEYS from '@src/ONYXKEYS' ;
5148import ROUTES from '@src/ROUTES' ;
5249import type SCREENS from '@src/SCREENS' ;
53- import { hasSeenTourSelector } from '@src/selectors/Onboarding' ;
54- import { validTransactionDraftIDsSelector } from '@src/selectors/TransactionDraft' ;
55- import type { Participant } from '@src/types/onyx/IOU' ;
5650import type { Errors } from '@src/types/onyx/OnyxCommon' ;
57- import type { Waypoint , WaypointCollection } from '@src/types/onyx/Transaction' ;
51+ import type { WaypointCollection } from '@src/types/onyx/Transaction' ;
5852import type Transaction from '@src/types/onyx/Transaction' ;
5953import { isEmptyObject } from '@src/types/utils/EmptyObject' ;
6054import type TransactionStateType from '@src/types/utils/TransactionStateType' ;
6155import DistanceManualTabContent from './DistanceManualTabContent' ;
6256import DistanceMapTabContent from './DistanceMapTabContent' ;
57+ import useDistanceNavigation from './IOURequestStepDistance/hooks/useDistanceNavigation' ;
58+ import useDistanceRequestData from './IOURequestStepDistance/hooks/useDistanceRequestData' ;
59+ import useDistanceTransactionBackup from './IOURequestStepDistance/hooks/useDistanceTransactionBackup' ;
60+ import useWaypointValidation , { isWaypointEmpty } from './IOURequestStepDistance/hooks/useWaypointValidation' ;
6361import StepScreenWrapper from './StepScreenWrapper' ;
6462import withFullTransactionOrNotFound from './withFullTransactionOrNotFound' ;
6563import type { WithWritableReportOrNotFoundProps } from './withWritableReportOrNotFound' ;
@@ -97,20 +95,11 @@ function IOURequestStepDistance({
9795 const personalPolicy = usePersonalPolicy ( ) ;
9896 const [ personalDetails ] = useOnyx ( ONYXKEYS . PERSONAL_DETAILS_LIST ) ;
9997 const defaultExpensePolicy = useDefaultExpensePolicy ( ) ;
100- const [ amountOwed ] = useOnyx ( ONYXKEYS . NVP_PRIVATE_AMOUNT_OWED ) ;
101- const [ userBillingGracePeriodEnds ] = useOnyx ( ONYXKEYS . COLLECTION . SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END ) ;
102- const [ ownerBillingGracePeriodEnd ] = useOnyx ( ONYXKEYS . NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END ) ;
10398 const [ skipConfirmation ] = useOnyx ( `${ ONYXKEYS . COLLECTION . SKIP_CONFIRMATION } ${ transactionID } ` ) ;
104- const [ lastSelectedDistanceRates ] = useOnyx ( ONYXKEYS . NVP_LAST_SELECTED_DISTANCE_RATES ) ;
105- const [ quickAction ] = useOnyx ( ONYXKEYS . NVP_QUICK_ACTION_GLOBAL_CREATE ) ;
10699 const [ optimisticWaypoints , setOptimisticWaypoints ] = useState < WaypointCollection | null > ( null ) ;
107- const [ policyRecentlyUsedCurrencies ] = useOnyx ( ONYXKEYS . RECENTLY_USED_CURRENCIES ) ;
108100 const [ introSelected ] = useOnyx ( ONYXKEYS . NVP_INTRO_SELECTED ) ;
109101 const { policyForMovingExpenses} = usePolicyForMovingExpenses ( ) ;
110102 const [ betas ] = useOnyx ( ONYXKEYS . BETAS ) ;
111- const [ draftTransactionIDs ] = useOnyx ( ONYXKEYS . COLLECTION . TRANSACTION_DRAFT , { selector : validTransactionDraftIDsSelector } ) ;
112- const [ isSelfTourViewed ] = useOnyx ( ONYXKEYS . NVP_ONBOARDING , { selector : hasSeenTourSelector } ) ;
113- const [ conciergeReportID ] = useOnyx ( ONYXKEYS . CONCIERGE_REPORT_ID ) ;
114103
115104 const isEditing = action === CONST . IOU . ACTION . EDIT ;
116105 const isEditingSplit = ( iouType === CONST . IOU . TYPE . SPLIT || iouType === CONST . IOU . TYPE . SPLIT_EXPENSE ) && isEditing ;
@@ -154,26 +143,11 @@ function IOURequestStepDistance({
154143 const isSplitRequest = iouType === CONST . IOU . TYPE . SPLIT ;
155144 const hasRouteError = ! ! currentTransaction ?. errorFields ?. route ;
156145 const [ shouldShowAtLeastTwoDifferentWaypointsError , setShouldShowAtLeastTwoDifferentWaypointsError ] = useState ( false ) ;
157- const isWaypointEmpty = ( waypoint ?: Waypoint ) => {
158- if ( ! waypoint ) {
159- return true ;
160- }
161- const { keyForList, ...waypointWithoutKey } = waypoint ;
162- return isEmpty ( waypointWithoutKey ) ;
163- } ;
164- const nonEmptyWaypointsCount = useMemo ( ( ) => Object . keys ( waypoints ) . filter ( ( key ) => ! isWaypointEmpty ( waypoints [ key ] ) ) . length , [ waypoints ] ) ;
165146 const currentUserAccountIDParam = currentUserPersonalDetails . accountID ;
166147 const currentUserEmailParam = currentUserPersonalDetails . login ?? '' ;
167- const isWaypointsNullIslandError = useMemo ( ( ) => Object . values ( waypoints ) . some ( isWaypointNullIsland ) , [ waypoints ] ) ;
168- const duplicateWaypointsError = useMemo (
169- ( ) => nonEmptyWaypointsCount >= 2 && Object . keys ( validatedWaypoints ) . length !== nonEmptyWaypointsCount ,
170- [ nonEmptyWaypointsCount , validatedWaypoints ] ,
171- ) ;
172- const atLeastTwoDifferentWaypointsError = useMemo ( ( ) => Object . keys ( validatedWaypoints ) . length < 2 , [ validatedWaypoints ] ) ;
173- const transactionWasSaved = useRef ( false ) ;
148+ const { nonEmptyWaypointsCount, isWaypointsNullIslandError, duplicateWaypointsError, atLeastTwoDifferentWaypointsError} = useWaypointValidation ( { waypoints, validatedWaypoints} ) ;
174149 const isCreatingNewRequest = ! ( backTo || isEditing ) ;
175150 const [ recentWaypoints , { status : recentWaypointsStatus } ] = useOnyx ( ONYXKEYS . NVP_RECENT_WAYPOINTS ) ;
176- const [ transactionViolations ] = useOnyx ( ONYXKEYS . COLLECTION . TRANSACTION_VIOLATIONS ) ;
177151 const iouRequestType = getRequestType ( currentTransaction ) ;
178152 const customUnitRateID = getRateID ( currentTransaction ) ;
179153
@@ -229,32 +203,7 @@ function IOURequestStepDistance({
229203 lastSyncedRouteDistance . current = routeDistance ;
230204 } , [ routeDistance , distanceUnit ] ) ;
231205
232- // Sets `amount` and `split` share data before moving to the next step to avoid briefly showing `0.00` as the split share for participants
233- const setDistanceRequestData = useCallback (
234- ( participants : Participant [ ] ) => {
235- // Get policy report based on transaction participants
236- const isPolicyExpenseChat = participants ?. some ( ( participant ) => participant . isPolicyExpenseChat ) ;
237- const policyCurrency = policy ?. outputCurrency ?? personalPolicy ?. outputCurrency ?? CONST . CURRENCY . USD ;
238-
239- const policyMileageRates = DistanceRequestUtils . getMileageRates ( policy ) ;
240- const defaultMileageRate = DistanceRequestUtils . getDefaultMileageRate ( policy ) ;
241- const selectedMileageRate : MileageRate | undefined = isCustomUnitRateIDForP2P ( transaction )
242- ? DistanceRequestUtils . getRateForP2P ( policyCurrency , transaction )
243- : ( customUnitRateID && policyMileageRates ?. [ customUnitRateID ] ) || defaultMileageRate ;
244-
245- const { unit, rate} = selectedMileageRate ?? { } ;
246- const distance = getDistanceInMeters ( transaction , unit ) ;
247- const currency = selectedMileageRate ?. currency ?? policyCurrency ;
248- const amount = DistanceRequestUtils . getDistanceRequestAmount ( distance , unit ?? CONST . CUSTOM_UNITS . DISTANCE_UNIT_MILES , rate ?? 0 ) ;
249- setMoneyRequestAmount ( transactionID , amount , currency ) ;
250-
251- const participantAccountIDs : number [ ] | undefined = participants ?. map ( ( participant ) => Number ( participant . accountID ?? CONST . DEFAULT_NUMBER_ID ) ) ;
252- if ( isSplitRequest && amount && currency && ! isPolicyExpenseChat ) {
253- setSplitShares ( transaction , amount , currency ?? '' , participantAccountIDs ?? [ ] ) ;
254- }
255- } ,
256- [ policy , personalPolicy ?. outputCurrency , transaction , customUnitRateID , transactionID , isSplitRequest ] ,
257- ) ;
206+ const setDistanceRequestData = useDistanceRequestData ( { policy, personalPolicy, transaction, customUnitRateID, transactionID, isSplitRequest} ) ;
258207
259208 // For quick button actions, we'll skip the confirmation page unless the report is archived or this is a workspace
260209 // request and the workspace requires a category or a tag
@@ -303,35 +252,16 @@ function IOURequestStepDistance({
303252 setShouldShowAtLeastTwoDifferentWaypointsError ( false ) ;
304253 } , [ atLeastTwoDifferentWaypointsError , duplicateWaypointsError , hasRouteError , isLoading , isLoadingRoute , nonEmptyWaypointsCount , transaction ] ) ;
305254
306- // This effect runs when the component is mounted and unmounted. It's purpose is to be able to properly
307- // discard changes if the user cancels out of making any changes. This is accomplished by backing up the
308- // original transaction, letting the user modify the current transaction, and then if the user ever
309- // cancels out of the modal without saving changes, the original transaction is restored from the backup.
310- useEffect ( ( ) => {
311- if ( isCreatingNewRequest || isEditingSplit ) {
312- return ( ) => { } ;
313- }
314- const isDraft = shouldUseTransactionDraft ( action ) ;
315- // On mount, create the backup transaction.
316- createBackupTransaction ( transaction , isDraft ) ;
317-
318- return ( ) => {
319- // If the user cancels out of the modal without saving changes, then the original transaction
320- // needs to be restored from the backup so that all changes are removed.
321- if ( transactionWasSaved . current ) {
322- removeBackupTransaction ( transaction ?. transactionID ) ;
323- return ;
324- }
325- restoreOriginalTransactionFromBackup ( transaction ?. transactionID , isDraft ) ;
326-
327- // If the user opens IOURequestStepDistance in offline mode and then goes online, re-open the report to fill in missing fields from the transaction backup
328- if ( ! transaction ?. reportID || hasRoute ( transaction , true ) ) {
329- return ;
330- }
331- openReport ( { reportID : transaction ?. reportID , introSelected, betas} ) ;
332- } ;
333- // eslint-disable-next-line react-hooks/exhaustive-deps
334- } , [ ] ) ;
255+ const transactionWasSaved = useRef ( false ) ;
256+ useDistanceTransactionBackup ( {
257+ transaction,
258+ isCreatingNewRequest,
259+ isEditingSplit,
260+ isDraft : shouldUseTransactionDraft ( action ) ,
261+ introSelected,
262+ betas,
263+ transactionWasSavedRef : transactionWasSaved ,
264+ } ) ;
335265
336266 const navigateBack = useCallback ( ( ) => {
337267 Navigation . goBack ( backTo ) ;
@@ -371,46 +301,7 @@ function IOURequestStepDistance({
371301 [ action , iouType , transactionID , report ?. reportID , reportID , backTo , isEditingSplit , isEditing ] ,
372302 ) ;
373303
374- const navigateToNextStep = useCallback ( ( ) => {
375- handleMoneyRequestStepDistanceNavigation ( {
376- iouType,
377- report,
378- policy,
379- transaction,
380- reportID,
381- transactionID,
382- reportAttributesDerived,
383- personalDetails,
384- waypoints,
385- currentUserLogin : currentUserEmailParam ,
386- currentUserAccountID : currentUserAccountIDParam ,
387- backTo,
388- backToReport,
389- shouldSkipConfirmation,
390- defaultExpensePolicy,
391- isArchivedExpenseReport : isArchived ,
392- isAutoReporting : ! ! personalPolicy ?. autoReporting ,
393- isASAPSubmitBetaEnabled,
394- transactionViolations,
395- lastSelectedDistanceRates,
396- setDistanceRequestData,
397- translate,
398- quickAction,
399- policyRecentlyUsedCurrencies,
400- introSelected,
401- privateIsArchived : isArchived ,
402- selfDMReport,
403- policyForMovingExpenses,
404- betas,
405- recentWaypoints,
406- draftTransactionIDs,
407- isSelfTourViewed : ! ! isSelfTourViewed ,
408- amountOwed,
409- userBillingGracePeriodEnds,
410- ownerBillingGracePeriodEnd,
411- conciergeReportID,
412- } ) ;
413- } , [
304+ const navigateToNextStep = useDistanceNavigation ( {
414305 iouType,
415306 report,
416307 policy,
@@ -420,33 +311,23 @@ function IOURequestStepDistance({
420311 reportAttributesDerived,
421312 personalDetails,
422313 waypoints,
423- currentUserEmailParam ,
424- currentUserAccountIDParam ,
314+ currentUserLogin : currentUserEmailParam ,
315+ currentUserAccountID : currentUserAccountIDParam ,
425316 backTo,
426317 backToReport,
427318 shouldSkipConfirmation,
428319 defaultExpensePolicy,
429320 isArchived,
430- personalPolicy ?. autoReporting ,
321+ isAutoReporting : ! ! personalPolicy ?. autoReporting ,
431322 isASAPSubmitBetaEnabled,
432- transactionViolations ,
433- lastSelectedDistanceRates ,
434323 setDistanceRequestData,
435324 translate,
436- quickAction ,
437- policyRecentlyUsedCurrencies ,
438- introSelected ,
439- policyForMovingExpenses ,
440325 selfDMReport,
326+ policyForMovingExpenses,
441327 betas,
442328 recentWaypoints,
443- draftTransactionIDs ,
444- isSelfTourViewed ,
445- amountOwed ,
446- userBillingGracePeriodEnds ,
447- ownerBillingGracePeriodEnd ,
448- conciergeReportID ,
449- ] ) ;
329+ introSelected,
330+ } ) ;
450331
451332 const getError = useCallback ( ( ) => {
452333 // Get route error if available else show the invalid number of waypoints error.
0 commit comments