diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css index 2d7c051..ae3b260 100644 --- a/frontend/src/styles/pages/LocationMapManager.css +++ b/frontend/src/styles/pages/LocationMapManager.css @@ -596,12 +596,23 @@ } .location-map-topbar { - grid-template-columns: auto minmax(0, 1fr); + grid-template-columns: auto minmax(0, 1fr) auto; + gap: 0.5rem; + padding: 0.55rem 0.65rem; + } + + .location-map-back { + padding: 0 0.65rem; } .location-map-status { - grid-column: 2; - justify-self: start; + min-width: 0; + max-width: 104px; + justify-self: end; + padding: 0.28rem 0.45rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .location-map-toolbar { diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index 14c39c2..de0e7b3 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -458,6 +458,67 @@ test("admin status follows the visible map when a saved draft exists", async ({ await expect(page.locator(".location-map-object", { hasText: "Live Bakery" })).toBeVisible(); }); +test("mobile keeps draft preview status compact in the topbar", async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }); + await mockMapShell(page); + + const publishedObjects = [ + { + id: 1251, + location_map_id: 901, + zone_id: 501, + zone_name: "Bakery", + type: "zone", + label: "Live Bakery", + x: 40, + y: 40, + width: 260, + height: 160, + rotation: 0, + locked: false, + visible: true, + sort_order: 1, + }, + ]; + const draftObjects = [ + { + ...publishedObjects[0], + id: 1252, + location_map_id: 900, + label: "Draft Bakery", + x: 80, + y: 80, + }, + ]; + + await page.route("**/households/1/locations/10/map", async (route) => { + await route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify(draftAndPublishedMapState(draftObjects, publishedObjects, true)), + }); + }); + + await page.goto("/stores/100/locations/10/map"); + await page.getByRole("button", { name: "Edit Draft" }).click(); + await page.getByRole("button", { name: "Preview Draft" }).click(); + + const topbar = page.locator(".location-map-topbar"); + const status = page.locator(".location-map-status"); + await expect(status).toHaveText("Draft Preview"); + + const topbarBox = await topbar.boundingBox(); + const titleBox = await page.locator(".location-map-title").boundingBox(); + const statusBox = await status.boundingBox(); + expect(topbarBox).not.toBeNull(); + expect(titleBox).not.toBeNull(); + expect(statusBox).not.toBeNull(); + if (!topbarBox || !titleBox || !statusBox) throw new Error("Mobile topbar layout was not measurable"); + expect(topbarBox.height).toBeLessThanOrEqual(66); + expect(statusBox.y).toBeLessThan(titleBox.y + titleBox.height); + expect(statusBox.x).toBeGreaterThan(titleBox.x); +}); + test("admin selecting an object does not mark a draft dirty until it changes", async ({ page }) => { await mockMapShell(page);