diff --git a/frontend/src/components/TimeUnit/TimeUnitDetails.tsx b/frontend/src/components/TimeUnit/TimeUnitDetails.tsx index f52b0861..f739d85a 100755 --- a/frontend/src/components/TimeUnit/TimeUnitDetails.tsx +++ b/frontend/src/components/TimeUnit/TimeUnitDetails.tsx @@ -65,7 +65,10 @@ export const TimeUnitDetails = ({ }) unsavedChanges?.setDirty(false) notify('Edited item successfully.') - return () => navigate(`/time-unit/${tu_name}`) + return () => { + unsavedChanges?.allowNextNavigation?.() + navigate(`/time-unit/${tu_name}`) + } } catch (e) { if (data) { setEditData(makeEditData(data)) diff --git a/frontend/src/components/UnsavedChangesProvider.tsx b/frontend/src/components/UnsavedChangesProvider.tsx index 7c4af878..3ac1f993 100644 --- a/frontend/src/components/UnsavedChangesProvider.tsx +++ b/frontend/src/components/UnsavedChangesProvider.tsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react' +import { useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from 'react' import { UNSAFE_DataRouterContext, useBlocker } from 'react-router-dom' import { UnsavedChangesDialog } from './UnsavedChangesDialog' @@ -20,12 +20,13 @@ const unblockedState = { } type BlockerState = typeof unblockedState | ReturnType +type BlockerPredicate = Parameters[0] const BlockerBridge = ({ shouldBlock, onChange, }: { - shouldBlock: boolean + shouldBlock: BlockerPredicate onChange: (blocker: ReturnType) => void }) => { const blocker = useBlocker(shouldBlock) @@ -45,6 +46,7 @@ export const UnsavedChangesProvider = ({ const [isDirty, setDirty] = useState(false) const [message, setMessage] = useState(defaultMessage) const [blocker, setBlocker] = useState(unblockedState) + const allowNextNavigationRef = useRef(false) const dataRouterContext = useContext(UNSAFE_DataRouterContext) const isSamePathNavigation = blocker.state === 'blocked' && blocker.location?.pathname === window.location.pathname @@ -54,6 +56,20 @@ export const UnsavedChangesProvider = ({ setMessage(defaultMessage) }, [defaultMessage]) + const allowNextNavigation = useCallback(() => { + allowNextNavigationRef.current = true + setDirty(false) + }, []) + + const shouldBlockNavigation = useCallback(() => { + if (!isDirty) return false + if (allowNextNavigationRef.current) { + allowNextNavigationRef.current = false + return false + } + return true + }, [isDirty]) + const handleConfirm = useCallback(() => { if (blocker.state === 'blocked') { setDirty(false) @@ -87,13 +103,14 @@ export const UnsavedChangesProvider = ({ setDirty, setMessage, resetMessage, + allowNextNavigation, }), - [isDirty, message, resetMessage] + [allowNextNavigation, isDirty, message, resetMessage] ) return ( - {dataRouterContext ? : null} + {dataRouterContext ? : null} {children} void setMessage: (message: string) => void resetMessage: () => void + allowNextNavigation?: () => void } export const UnsavedChangesContext = createContext(null)