From 82e948ee66aa2810cda829646dd3199c03a828c9 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 3 Jun 2026 12:37:02 -0700 Subject: [PATCH] fix: confirm leaving unsaved map edits --- frontend/src/pages/LocationMapManager.jsx | 22 ++++++++++++++++++++- frontend/tests/location-map-manager.spec.ts | 5 +++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index ccf6137..b8b3211 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -66,6 +66,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 svgRef = useRef(null); const toastRef = useRef(toast); @@ -402,7 +403,7 @@ export default function LocationMapManager() { setZoom(Number(nextZoom.toFixed(2))); }; - const handleBack = useCallback(() => { + const performBackNavigation = useCallback(() => { if (typeof returnPath === "string" && returnPath.startsWith("/")) { navigate(returnPath, { replace: true }); return; @@ -410,6 +411,14 @@ export default function LocationMapManager() { navigate("/"); }, [navigate, returnPath]); + const handleBack = useCallback(() => { + if (hasUnsavedChanges && canManage) { + setPendingLeave(true); + return; + } + performBackNavigation(); + }, [canManage, hasUnsavedChanges, performBackNavigation]); + if (!hasLoaded || householdLoading || loading) { return (
@@ -522,6 +531,17 @@ export default function LocationMapManager() { onClose={() => setPendingDeleteObject(null)} onConfirm={handleDeleteObject} /> + setPendingLeave(false)} + onConfirm={() => { + setPendingLeave(false); + performBackNavigation(); + }} + />
); } diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index 21711b5..ba0f14c 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -320,6 +320,11 @@ test("admin creates a map from zones, saves a draft, and publishes it", async ({ await confirmSlide(page); await expect(page.locator(".location-map-object", { hasText: "Temporary Freezer" })).toHaveCount(0); + await page.getByRole("button", { name: "Back" }).click(); + await expect(page.getByRole("heading", { name: "Leave with unsaved changes?" })).toBeVisible(); + await page.getByRole("button", { name: "Cancel" }).click(); + await expect(page).toHaveURL(/\/stores\/100\/locations\/10\/map$/); + await expect(page.locator(".location-map-status")).toHaveText("Unsaved Draft"); await page.getByRole("button", { name: "Preview Draft" }).click(); await expect(page.locator(".location-map-object", { hasText: "Bread Wall" })).toBeVisible();