diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index a4b8fdc..0535f32 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -73,7 +73,7 @@ export default function LocationMapManager() { const [future, setFuture] = useState([]); const [dragState, setDragState] = useState(null); const [pendingDeleteObject, setPendingDeleteObject] = useState(null); - const [pendingLeave, setPendingLeave] = useState(false); + const [pendingLeaveTarget, setPendingLeaveTarget] = useState(null); const svgRef = useRef(null); const toastRef = useRef(toast); const loadRequestRef = useRef(0); @@ -141,6 +141,45 @@ export default function LocationMapManager() { { capture: true } ); + useEffect(() => { + if (!shouldGuardLeave) { + setPendingLeaveTarget(null); + return undefined; + } + + const handleDocumentClick = (event) => { + if ( + event.defaultPrevented || + event.button !== 0 || + event.altKey || + event.ctrlKey || + event.metaKey || + event.shiftKey + ) { + return; + } + + const target = event.target instanceof Element ? event.target : null; + const anchor = target?.closest("a[href]"); + if (!anchor || (anchor.target && anchor.target !== "_self") || anchor.hasAttribute("download")) { + return; + } + + const nextUrl = new URL(anchor.href, window.location.href); + if (nextUrl.origin !== window.location.origin) return; + + const currentPath = `${window.location.pathname}${window.location.search}${window.location.hash}`; + const nextPath = `${nextUrl.pathname}${nextUrl.search}${nextUrl.hash}`; + if (nextPath === currentPath) return; + + event.preventDefault(); + setPendingLeaveTarget({ type: "path", path: nextPath }); + }; + + document.addEventListener("click", handleDocumentClick, true); + return () => document.removeEventListener("click", handleDocumentClick, true); + }, [shouldGuardLeave]); + const syncMapDraftFromState = useCallback((nextState, nextMode, nextPreviewDraft) => { const nextMap = mapForMode(nextState, nextMode, nextPreviewDraft); const nextObjects = objectsForMode(nextState, nextMode, nextPreviewDraft); @@ -562,12 +601,22 @@ export default function LocationMapManager() { const handleBack = useCallback(() => { if (shouldGuardLeave) { - setPendingLeave(true); + setPendingLeaveTarget({ type: "back" }); return; } performBackNavigation(); }, [performBackNavigation, shouldGuardLeave]); + const confirmPendingLeave = useCallback(() => { + const target = pendingLeaveTarget; + setPendingLeaveTarget(null); + if (target?.type === "path" && target.path) { + navigate(target.path); + return; + } + performBackNavigation(); + }, [navigate, pendingLeaveTarget, performBackNavigation]); + if (!hasLoaded || householdLoading || loading) { return (