fix: explain hidden map zones
This commit is contained in:
parent
aaf0876b63
commit
e09a95e172
@ -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)}
|
||||
</svg>
|
||||
{objects.length === 0 ? (
|
||||
<div className="location-map-empty-canvas">
|
||||
No map areas yet
|
||||
{emptyCanvasMessage ? (
|
||||
<div
|
||||
className={[
|
||||
"location-map-empty-canvas",
|
||||
hiddenByZonesLayer ? "has-action" : "",
|
||||
].filter(Boolean).join(" ")}
|
||||
>
|
||||
<span>{emptyCanvasMessage}</span>
|
||||
{hiddenByZonesLayer ? (
|
||||
<button
|
||||
type="button"
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onClick={handleShowZones}
|
||||
>
|
||||
Show Zones
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@ -528,6 +528,12 @@ export default function LocationMapManager() {
|
||||
setSelectedObjectKey={setSelectedObjectKey}
|
||||
remember={remember}
|
||||
updateObjects={updateObjects}
|
||||
onShowZones={() =>
|
||||
setFilters((current) => ({
|
||||
...current,
|
||||
showZones: true,
|
||||
}))
|
||||
}
|
||||
/>
|
||||
<LocationMapBottomSheet
|
||||
mode={mode}
|
||||
|
||||
@ -325,6 +325,25 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.location-map-empty-canvas.has-action {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.55rem;
|
||||
padding: 0.4rem 0.45rem 0.4rem 0.7rem;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.location-map-empty-canvas button {
|
||||
min-height: 40px;
|
||||
padding: 0 0.75rem;
|
||||
border: 1px solid rgba(96, 165, 250, 0.52);
|
||||
border-radius: 999px;
|
||||
background: rgba(59, 130, 246, 0.24);
|
||||
color: #f8fafc;
|
||||
font-weight: 900;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.location-map-bottom-sheet {
|
||||
max-height: 43vh;
|
||||
overflow-y: auto;
|
||||
|
||||
@ -924,6 +924,53 @@ test("viewer wraps long zone labels and keeps item counts visible", async ({ pag
|
||||
await expect(produceArea.locator(".location-map-count")).toHaveAttribute("y", "116");
|
||||
});
|
||||
|
||||
test("viewer explains when the zones layer hides the map", async ({ page }) => {
|
||||
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);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user