diff --git a/frontend/src/components/maps/LocationMapCanvas.jsx b/frontend/src/components/maps/LocationMapCanvas.jsx index c2b985d..673ca0a 100644 --- a/frontend/src/components/maps/LocationMapCanvas.jsx +++ b/frontend/src/components/maps/LocationMapCanvas.jsx @@ -20,6 +20,7 @@ export default function LocationMapCanvas({ svgRef, dragState, editingLocked = false, + onShowZones, setDragState, setSelectedObjectKey, remember, @@ -27,6 +28,18 @@ export default function LocationMapCanvas({ }) { const canEditObjects = !editingLocked && mode === "edit" && editorTool === "edit"; const canDragPan = mode === "view" || editorTool === "pan"; + const hiddenByZonesLayer = objects.length > 0 && !filters.showZones; + const visibleObjectCount = filters.showZones + ? objects.filter((object) => object.visible).length + : 0; + const hasNoVisibleObjects = objects.length > 0 && filters.showZones && visibleObjectCount === 0; + const emptyCanvasMessage = objects.length === 0 + ? "No map areas yet" + : hiddenByZonesLayer + ? "Zones hidden in Layers" + : hasNoVisibleObjects + ? "No visible map areas" + : ""; const scrollRef = useRef(null); const panDragRef = useRef(null); const objectDragHistoryCapturedRef = useRef(false); @@ -113,6 +126,11 @@ export default function LocationMapCanvas({ selectObject(object); }; + const handleShowZones = (event) => { + event.stopPropagation(); + onShowZones?.(); + }; + const clearSelection = () => { if (suppressPanClickRef.current) { suppressPanClickRef.current = false; @@ -339,9 +357,23 @@ export default function LocationMapCanvas({ ) : null} {objects.map(renderMapObject)} - {objects.length === 0 ? ( -
- No map areas yet + {emptyCanvasMessage ? ( +
+ {emptyCanvasMessage} + {hiddenByZonesLayer ? ( + + ) : null}
) : null}
diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index 0f6e3f3..e2bc22b 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -528,6 +528,12 @@ export default function LocationMapManager() { setSelectedObjectKey={setSelectedObjectKey} remember={remember} updateObjects={updateObjects} + onShowZones={() => + setFilters((current) => ({ + ...current, + showZones: true, + })) + } /> { + await mockMapShell(page); + + const mapState = publishedMapState([ + { + id: 1521, + location_map_id: 901, + 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 expect(page.getByRole("button", { name: "Map area Bakery" })).toBeVisible(); + + await page.getByRole("button", { name: "Layers" }).click(); + await page.getByLabel("Zones").uncheck(); + + await expect(page.getByRole("button", { name: "Map area Bakery" })).toHaveCount(0); + await expect(page.getByText("Zones hidden in Layers")).toBeVisible(); + await expect(page.getByRole("button", { name: "Show Zones" })).toBeVisible(); + await expect(page.getByRole("button", { name: "Layers, 1 changed" })).toBeVisible(); + + await page.getByRole("button", { name: "Show Zones" }).click(); + await expect(page.getByRole("button", { name: "Map area Bakery" })).toBeVisible(); + await expect(page.getByText("Zones hidden in Layers")).toHaveCount(0); + await expect(page.getByRole("button", { name: "Layers" })).toBeVisible(); +}); + test("viewer shows a compact overflow cue for long unmapped lists", async ({ page }) => { await mockMapShell(page);