From 214e2626fed73d8e53563b6546a4e11c1e98747f Mon Sep 17 00:00:00 2001 From: Nico Date: Wed, 3 Jun 2026 21:53:39 -0700 Subject: [PATCH] fix: explain hidden unmapped map items --- .../maps/LocationMapBottomSheet.jsx | 32 ++++++++++++-- frontend/src/pages/LocationMapManager.jsx | 2 + frontend/tests/location-map-manager.spec.ts | 42 +++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/maps/LocationMapBottomSheet.jsx b/frontend/src/components/maps/LocationMapBottomSheet.jsx index ab8aa90..a82c5c9 100644 --- a/frontend/src/components/maps/LocationMapBottomSheet.jsx +++ b/frontend/src/components/maps/LocationMapBottomSheet.jsx @@ -30,6 +30,7 @@ export default function LocationMapBottomSheet({ selectedObject, selectedZoneItems, visibleUnmappedItems, + unmappedItemCount, hiddenAreaCount, history, future, @@ -81,7 +82,9 @@ export default function LocationMapBottomSheet({ const showSelectedObjectForm = Boolean(mode === "edit" && editorTool === "edit" && selectedObject); const changedLayerCount = DISPLAY_CONTROLS.filter(([key]) => filters[key] !== DEFAULT_MAP_FILTERS[key]).length; const unmappedItemPreview = visibleUnmappedItems.slice(0, 8); - const hiddenUnmappedItemCount = visibleUnmappedItems.length - unmappedItemPreview.length; + const overflowUnmappedItemCount = visibleUnmappedItems.length - unmappedItemPreview.length; + const hasHiddenUnmappedItems = + filters.showUnmapped && unmappedItemCount > 0 && visibleUnmappedItems.length === 0; const selectedWidth = Number(selectedObject?.width) || 40; const selectedHeight = Number(selectedObject?.height) || 40; const hiddenAreaLabel = `Show Hidden Areas (${hiddenAreaCount})`; @@ -100,6 +103,15 @@ export default function LocationMapBottomSheet({ showCompleted: true, })); }; + const showUnmappedItems = () => { + setFilters((current) => ({ + ...current, + showUnmapped: true, + showMyItems: true, + showOtherItems: true, + showCompleted: true, + })); + }; const primaryDraftActions = showEditorControls ? (
+ ) : hasHiddenUnmappedItems ? ( +
+ Unmapped Items +
+

+ Unmapped items are hidden by layer filters. +

+ +
+
) : null} ); diff --git a/frontend/src/pages/LocationMapManager.jsx b/frontend/src/pages/LocationMapManager.jsx index a8fcd33..1e4d435 100644 --- a/frontend/src/pages/LocationMapManager.jsx +++ b/frontend/src/pages/LocationMapManager.jsx @@ -81,6 +81,7 @@ export default function LocationMapManager() { ? itemsForZone(mapState?.items || [], selectedObject.zone_id, filters, username) : []; const visibleUnmappedItems = unmappedItems(mapState?.items || [], filters, username); + const unmappedItemCount = (mapState?.items || []).filter((item) => !item.zone_id).length; const hiddenAreaCount = objects.filter((object) => object.visible === false).length; const shouldGuardLeave = canManage && hasUnsavedChanges; @@ -579,6 +580,7 @@ export default function LocationMapManager() { selectedObject={selectedObject} selectedZoneItems={selectedZoneItems} visibleUnmappedItems={visibleUnmappedItems} + unmappedItemCount={unmappedItemCount} hiddenAreaCount={hiddenAreaCount} history={history} future={future} diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index ac61caf..d93d649 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -1367,6 +1367,48 @@ test("viewer shows a compact overflow cue for long unmapped lists", async ({ pag await expect(page.getByLabel("3 more unmapped items")).toHaveText("+3 more"); }); +test("viewer explains when unmapped items are hidden by filters", async ({ page }) => { + await mockMapShell(page); + + const mapState = { + ...publishedMapState([], true), + items: [ + { + id: 4100, + item_name: "other batteries", + quantity: 1, + bought: false, + zone_id: null, + zone: null, + added_by_users: ["other-user"], + }, + ], + unmapped_count: 1, + }; + + 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: "Layers" }).click(); + await page.getByLabel("Unmapped").check(); + + await expect(page.getByText("other batteries")).toHaveCount(0); + await expect(page.getByText("Unmapped items are hidden by layer filters.")).toBeVisible(); + await expect(page.getByRole("button", { name: "Show Unmapped Items" })).toBeVisible(); + + await page.getByRole("button", { name: "Show Unmapped Items" }).click(); + + await expect(page.getByText("other batteries")).toBeVisible(); + await expect(page.getByText("Unmapped items are hidden by layer filters.")).toHaveCount(0); + await expect(page.getByRole("button", { name: "Layers, 3 changed" })).toBeVisible(); +}); + test("viewer explains when selected zone items are hidden by filters", async ({ page }) => { await mockMapShell(page);