import { useCallback, useMemo, useReducer, useState } from "react"; import { useSidePanel } from "../../../../hooks/useSidePanel"; import { submitCreateCopyJob } from "../../Actions/CopyJobActions"; import { useCopyJobContext } from "../../Context/CopyJobContext"; import { getContainerIdentifiers, isIntraAccountCopy } from "../../CopyJobUtils"; import { CopyJobMigrationType } from "../../Enums/CopyJobEnums"; import { useCopyJobPrerequisitesCache } from "./useCopyJobPrerequisitesCache"; import { SCREEN_KEYS, useCreateCopyJobScreensList } from "./useCreateCopyJobScreensList"; type NavigationState = { screenHistory: string[]; }; type Action = { type: "NEXT"; nextScreen: string } | { type: "PREVIOUS" } | { type: "RESET" }; function navigationReducer(state: NavigationState, action: Action): NavigationState { switch (action.type) { case "NEXT": return { screenHistory: [...state.screenHistory, action.nextScreen], }; case "PREVIOUS": return { screenHistory: state.screenHistory.length > 1 ? state.screenHistory.slice(0, -1) : state.screenHistory, }; case "RESET": return { screenHistory: [SCREEN_KEYS.SelectAccount], }; default: return state; } } export function useCopyJobNavigation() { const [isLoading, setIsLoading] = useState(false); const { copyJobState, resetCopyJobState, setContextError } = useCopyJobContext(); const { validationCache: cache } = useCopyJobPrerequisitesCache(); const [state, dispatch] = useReducer(navigationReducer, { screenHistory: [SCREEN_KEYS.SelectAccount] }); const handlePrevious = useCallback(() => { setContextError(null); dispatch({ type: "PREVIOUS" }); }, [dispatch]); const screens = useCreateCopyJobScreensList(handlePrevious); const currentScreenKey = state.screenHistory[state.screenHistory.length - 1]; const currentScreen = screens.find((screen) => screen.key === currentScreenKey); const isPrimaryDisabled = useMemo(() => { if (isLoading) { return true; } const context = currentScreenKey === SCREEN_KEYS.AssignPermissions ? cache : copyJobState; return !currentScreen?.validations.every((v) => v.validate(context)); }, [currentScreen.key, copyJobState, cache, isLoading]); const primaryBtnText = useMemo(() => { if (currentScreenKey === SCREEN_KEYS.CreateCollection) { return "Create"; } else if (currentScreenKey === SCREEN_KEYS.PreviewCopyJob) { return "Copy"; } return "Next"; }, [currentScreenKey]); const isPreviousDisabled = state.screenHistory.length <= 1; const handleCancel = useCallback(() => { dispatch({ type: "RESET" }); resetCopyJobState(); useSidePanel.getState().closeSidePanel(); }, []); const areContainersIdentical = () => { const { source, target } = copyJobState; const sourceIds = getContainerIdentifiers(source); const targetIds = getContainerIdentifiers(target); return ( isIntraAccountCopy(sourceIds.accountId, targetIds.accountId) && sourceIds.databaseId === targetIds.databaseId && sourceIds.containerId === targetIds.containerId ); }; const shouldNotShowPermissionScreen = () => { const { source, target, migrationType } = copyJobState; const sourceIds = getContainerIdentifiers(source); const targetIds = getContainerIdentifiers(target); return ( migrationType === CopyJobMigrationType.Offline && isIntraAccountCopy(sourceIds.accountId, targetIds.accountId) ); }; const handleCopyJobSubmission = async () => { try { setIsLoading(true); await submitCreateCopyJob(copyJobState, handleCancel); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message || "Failed to create copy job. Please try again later." : "Failed to create copy job. Please try again later."; setContextError(errorMessage); } finally { setIsLoading(false); } }; const handleAddCollectionPanelSubmit = () => { const form = document.getElementById("panelContainer") as HTMLFormElement; if (form) { const submitEvent = new Event("submit", { bubbles: true, cancelable: true, }); form.dispatchEvent(submitEvent); } }; const showAddCollectionPanel = useCallback(() => { dispatch({ type: "NEXT", nextScreen: SCREEN_KEYS.CreateCollection }); }, [dispatch]); const handlePrimary = useCallback(() => { if (currentScreenKey === SCREEN_KEYS.CreateCollection) { handleAddCollectionPanelSubmit(); return; } if (currentScreenKey === SCREEN_KEYS.SelectSourceAndTargetContainers && areContainersIdentical()) { setContextError( "Source and destination containers cannot be the same. Please select different containers to proceed.", ); return; } setContextError(null); const transitions = { [SCREEN_KEYS.SelectAccount]: shouldNotShowPermissionScreen() ? SCREEN_KEYS.SelectSourceAndTargetContainers : SCREEN_KEYS.AssignPermissions, [SCREEN_KEYS.AssignPermissions]: SCREEN_KEYS.SelectSourceAndTargetContainers, [SCREEN_KEYS.SelectSourceAndTargetContainers]: SCREEN_KEYS.PreviewCopyJob, }; const nextScreen = transitions[currentScreenKey]; if (nextScreen) { dispatch({ type: "NEXT", nextScreen }); } else if (currentScreenKey === SCREEN_KEYS.PreviewCopyJob) { handleCopyJobSubmission(); } }, [currentScreenKey, copyJobState, areContainersIdentical, handleCopyJobSubmission]); return { currentScreen, isPrimaryDisabled, isPreviousDisabled, handlePrimary, handlePrevious, handleCancel, showAddCollectionPanel, primaryBtnText, }; }