fix: clarify partial map item filters

This commit is contained in:
Nico 2026-06-03 23:04:53 -07:00
parent e2128a4ad7
commit 76dcea237e
4 changed files with 119 additions and 12 deletions

View File

@ -59,9 +59,10 @@ export default function LocationMapBottomSheet({
const selectedAssignedItems = selectedObject?.zone_id
? (mapState?.items || []).filter((item) => String(item.zone_id || "") === objectZoneId(selectedObject))
: [];
const hasHiddenSelectedItems = selectedAssignedItems.length > 0 && selectedZoneItems.length === 0;
const hiddenSelectedItemCount = Math.max(0, selectedAssignedItems.length - selectedZoneItems.length);
const hasHiddenSelectedItems = hiddenSelectedItemCount > 0;
const selectedItemCountLabel = hasHiddenSelectedItems
? "0 shown"
? `${selectedZoneItems.length} shown`
: `${selectedZoneItems.length} item${selectedZoneItems.length === 1 ? "" : "s"}`;
const sheetTitle = mode === "edit"
? selectedObject && editorTool === "edit"
@ -383,14 +384,26 @@ export default function LocationMapBottomSheet({
) : null}
</div>
) : (
<ul>
{selectedZoneItems.map((item) => (
<li key={item.id}>
<span>{item.item_name}</span>
<small>x{item.quantity}</small>
</li>
))}
</ul>
<>
<ul>
{selectedZoneItems.map((item) => (
<li key={item.id}>
<span>{item.item_name}</span>
<small>x{item.quantity}</small>
</li>
))}
</ul>
{hasHiddenSelectedItems ? (
<div className="location-map-zone-hidden-note">
<p className="location-map-muted">
{hiddenSelectedItemCount} more hidden by layer filters.
</p>
<button type="button" onClick={showSelectedZoneItems}>
Show All Zone Items
</button>
</div>
) : null}
</>
)}
</div>
) : (

View File

@ -268,8 +268,9 @@ export default function LocationMapCanvas({
).length
: 0;
const count = zoneItems.length;
const countLabel = assignedZoneItemCount > 0 && count === 0
? "0 shown"
const hasHiddenZoneItems = assignedZoneItemCount > count;
const countLabel = hasHiddenZoneItems
? `${count} shown`
: `${count} item${count === 1 ? "" : "s"}`;
const labelLines = fittedLabelLines(object, "Area");
const countY = filters.showLabels && labelLines.length > 1 ? object.y + 76 : object.y + 52;

View File

@ -639,6 +639,28 @@
cursor: pointer;
}
.location-map-zone-hidden-note {
display: grid;
gap: 0.45rem;
margin-top: 0.55rem;
}
.location-map-zone-hidden-note p {
margin: 0;
}
.location-map-zone-hidden-note button {
min-height: 40px;
width: fit-content;
padding: 0.45rem 0.7rem;
border: 1px solid var(--color-border-light);
border-radius: 8px;
background: #15283b;
color: #f8fafc;
font-weight: 800;
cursor: pointer;
}
.location-map-zone-items ul,
.location-map-unmapped-list ul {
display: grid;

View File

@ -1587,6 +1587,77 @@ test("viewer explains when selected zone items are hidden by filters", async ({
await expect(page.locator(".location-map-pin")).toHaveCount(0);
});
test("viewer marks partial zone counts when filters hide some items", async ({ page }) => {
await mockMapShell(page);
const mapState = {
...publishedMapState([
{
id: 1552,
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),
items: [
{
id: 5001,
item_name: "visible bread",
quantity: 1,
bought: false,
zone_id: 501,
zone: "Bakery",
added_by_users: ["map-user"],
},
{
id: 5002,
item_name: "hidden baguette",
quantity: 1,
bought: false,
zone_id: 501,
zone: "Bakery",
added_by_users: ["other-user"],
},
],
};
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");
const bakeryArea = page.locator('[data-object-key="1552"]');
await expect(bakeryArea.locator(".location-map-count")).toHaveText("1 shown");
await bakeryArea.locator("rect").first().click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("1 shown");
await expect(page.getByText("visible bread")).toBeVisible();
await expect(page.getByText("hidden baguette")).toHaveCount(0);
await expect(page.getByText("1 more hidden by layer filters.")).toBeVisible();
await expect(page.getByRole("button", { name: "Show All Zone Items" })).toBeVisible();
await page.getByRole("button", { name: "Show All Zone Items" }).click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("2 items");
await expect(page.getByText("hidden baguette")).toBeVisible();
await expect(bakeryArea.locator(".location-map-count")).toHaveText("2 items");
});
test("viewer handles empty and many-item zone panels without default pins", async ({ page }) => {
await mockMapShell(page);