From c0ed1c0472042a2cb517a9a89ac12ce9944e16a8 Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 3 Jun 2026 14:02:00 -0700 Subject: [PATCH] fix: clarify map setup without zones --- .../components/maps/LocationMapSetupPanel.jsx | 44 +++++++++++-------- frontend/src/pages/LocationMapManager.jsx | 1 + .../src/styles/pages/LocationMapManager.css | 11 +++++ frontend/tests/location-map-manager.spec.ts | 31 +++++++++++-- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/maps/LocationMapSetupPanel.jsx b/frontend/src/components/maps/LocationMapSetupPanel.jsx index 6336dc9..30d9f37 100644 --- a/frontend/src/components/maps/LocationMapSetupPanel.jsx +++ b/frontend/src/components/maps/LocationMapSetupPanel.jsx @@ -1,6 +1,7 @@ export default function LocationMapSetupPanel({ hasAnyMap, canManage, + zoneCount = 0, saving, onContinue, onPreview, @@ -15,6 +16,10 @@ export default function LocationMapSetupPanel({ : canManage ? "Create a rough map for this store location." : "A household admin has not published a map yet."; + const hasZones = zoneCount > 0; + const createFromZonesLabel = hasZones + ? `Create From ${zoneCount} Zone${zoneCount === 1 ? "" : "s"}` + : "Create From Zones"; return (
@@ -22,28 +27,29 @@ export default function LocationMapSetupPanel({

{description}

{hasAnyMap && canManage ? (
- <> - - - - + + +
) : !hasAnyMap && canManage ? (
- <> - - - + {!hasZones ? ( +

+ No zones are available yet. Create a blank map now, or add zones first for an automatic starter layout. +

+ ) : null} + +
) : null}
diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index b37fd08..dad093c 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -475,6 +475,7 @@ export default function LocationMapManager() { setMode("edit")} onPreview={handlePreviewDraft} diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css index a3c7ee5..2d7c051 100644 --- a/frontend/src/styles/pages/LocationMapManager.css +++ b/frontend/src/styles/pages/LocationMapManager.css @@ -553,6 +553,17 @@ gap: 0.6rem; } +.location-map-setup-note { + margin: 0; + padding: 0.6rem 0.7rem; + border: 1px solid rgba(245, 158, 11, 0.28); + border-radius: 8px; + background: rgba(245, 158, 11, 0.1); + color: #f8fafc; + font-size: 0.9rem; + font-weight: 700; +} + .location-map-loading { margin: 3rem auto; color: #9fb3c8; diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index 62d4548..14c39c2 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -262,10 +262,10 @@ test("admin creates a map from zones, saves a draft, and publishes it", async ({ await expect(page.getByRole("heading", { name: "Costco" })).toBeVisible(); await expect(page.getByText("Eastvale")).toBeVisible(); await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible(); - await expect(page.getByRole("button", { name: "Create Map From Existing Zones" })).toBeVisible(); + await expect(page.getByRole("button", { name: "Create From 2 Zones" })).toBeVisible(); await expect(page.getByLabel("Map controls")).toHaveCount(0); - await page.getByRole("button", { name: "Create Map From Existing Zones" }).click(); + await page.getByRole("button", { name: "Create From 2 Zones" }).click(); await expect(page.getByText("Bakery")).toBeVisible(); await expect(page.getByText("Frozen Foods")).toBeVisible(); await expect(page.getByRole("button", { name: "Pan Mode" })).toBeVisible(); @@ -373,6 +373,31 @@ test("admin creates a map from zones, saves a draft, and publishes it", async ({ await expect(page.getByText("loose batteries")).toBeVisible(); }); +test("admin setup explains when no zones exist yet", async ({ page }) => { + await mockMapShell(page); + + await page.route("**/households/1/locations/10/map", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify({ + ...noMapState(true), + zones: [], + items: [], + unmapped_count: 0, + }), + }); + }); + + await page.goto("/stores/100/locations/10/map"); + + await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible(); + await expect(page.getByText("No zones are available yet.")).toBeVisible(); + await expect(page.getByRole("button", { name: "Create From Zones" })).toBeDisabled(); + await expect(page.getByRole("button", { name: "Create Blank Map" })).toBeEnabled(); + await expect(page.getByLabel("Map controls")).toHaveCount(0); +}); + test("admin status follows the visible map when a saved draft exists", async ({ page }) => { await mockMapShell(page); @@ -857,7 +882,7 @@ test("members see a clean empty state when no map is published", async ({ page } await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible(); await expect(page.getByText("A household admin has not published a map yet.")).toBeVisible(); await expect(page.getByText("Create a rough map for this store location.")).toHaveCount(0); - await expect(page.getByRole("button", { name: "Create Map From Existing Zones" })).toHaveCount(0); + await expect(page.getByRole("button", { name: /Create From/ })).toHaveCount(0); await expect(page.getByRole("button", { name: "Create Blank Map" })).toHaveCount(0); await expect(page.getByLabel("Map controls")).toHaveCount(0); });