From daef7a86de23245ade9c20783e64f7aa6a90639c Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 3 Jun 2026 20:10:31 -0700 Subject: [PATCH] fix: preserve map area accessible names --- .../src/components/maps/LocationMapCanvas.jsx | 10 ++++- frontend/tests/location-map-manager.spec.ts | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/maps/LocationMapCanvas.jsx b/frontend/src/components/maps/LocationMapCanvas.jsx index 2d06fbe..af8fc67 100644 --- a/frontend/src/components/maps/LocationMapCanvas.jsx +++ b/frontend/src/components/maps/LocationMapCanvas.jsx @@ -8,6 +8,12 @@ import { const DRAG_CHANGE_THRESHOLD = 2; const NUDGE_KEYS = new Set(["ArrowUp", "ArrowRight", "ArrowDown", "ArrowLeft"]); +function mapObjectDisplayLabel(object, fallback) { + const label = String(object.label || "").trim(); + const zoneName = String(object.zone_name || "").trim(); + return label || zoneName || fallback; +} + export default function LocationMapCanvas({ mode, editorTool, @@ -212,7 +218,7 @@ export default function LocationMapCanvas({ }; const fittedLabelLines = (object, fallback) => { - const rawLabel = String(object.label || object.zone_name || fallback).trim(); + const rawLabel = mapObjectDisplayLabel(object, fallback); const maxCharacters = Math.max(8, Math.floor((Number(object.width) - 28) / 13)); const canUseTwoLines = Number(object.height) >= 92 && rawLabel.length > maxCharacters; if (!canUseTwoLines) return [truncateLabel(rawLabel, maxCharacters)]; @@ -295,7 +301,7 @@ export default function LocationMapCanvas({ height={object.height} rx="12" role="button" - aria-label={`Map area ${object.label || index + 1}`} + aria-label={`Map area ${mapObjectDisplayLabel(object, index + 1)}`} aria-pressed={isSelected} tabIndex={mode === "view" || canEditObjects ? 0 : -1} onPointerDown={(event) => startDrag(event, object, "move")} diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index 19efac0..5c3c0aa 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -596,6 +596,47 @@ test("admin selecting an object does not mark a draft dirty until it changes", a await expect(page.getByRole("button", { name: "Undo" })).toBeEnabled(); }); +test("admin cleared map area labels keep linked zone accessible names", async ({ page }) => { + await mockMapShell(page); + + const mapState = draftMapState([ + { + id: 1353, + location_map_id: 900, + zone_id: 501, + zone_name: "Bakery", + type: "zone", + label: "Bakery", + x: 40, + y: 40, + width: 260, + height: 160, + rotation: 0, + locked: false, + visible: true, + sort_order: 1, + }, + ], true); + + await page.route("**/households/1/locations/10/map", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify(mapState), + }); + }); + + await page.goto("/stores/100/locations/10/map"); + + await page.getByRole("button", { name: "Continue Editing" }).click(); + await page.getByRole("button", { name: "Edit Objects" }).click(); + await page.getByRole("button", { name: "Map area Bakery" }).click(); + await page.getByRole("textbox", { name: "Label" }).fill(""); + + await expect(page.getByRole("button", { name: "Map area Bakery", exact: true })).toBeVisible(); + await expect(page.getByRole("button", { name: "Map area 1", exact: true })).toHaveCount(0); +}); + test("admin nudges selected map areas with arrow keys", async ({ page }) => { await mockMapShell(page);