fix: keep added map areas in bounds

This commit is contained in:
Nico 2026-06-16 00:25:45 -07:00
parent fc883e9f62
commit 25b1efc214
2 changed files with 45 additions and 2 deletions

View File

@ -54,11 +54,11 @@ export default function useLocationMapObjectActions({
remember(); remember();
const usedZoneIds = new Set(objects.map((object) => objectZoneId(object)).filter(Boolean)); const usedZoneIds = new Set(objects.map((object) => objectZoneId(object)).filter(Boolean));
const nextZone = zones.find((zone) => !usedZoneIds.has(String(zone.id))) || zones[0]; const nextZone = zones.find((zone) => !usedZoneIds.has(String(zone.id))) || zones[0];
const nextObject = createClientObject(nextZone, objects.length); const nextObject = clampObjectToMap(createClientObject(nextZone, objects.length), mapSize);
setObjects((currentObjects) => [...currentObjects, nextObject]); setObjects((currentObjects) => [...currentObjects, nextObject]);
setSelectedObjectKey(getObjectKey(nextObject)); setSelectedObjectKey(getObjectKey(nextObject));
setHasUnsavedChanges(true); setHasUnsavedChanges(true);
}, [canManage, objects, remember, setHasUnsavedChanges, setObjects, setSelectedObjectKey, zones]); }, [canManage, mapSize, objects, remember, setHasUnsavedChanges, setObjects, setSelectedObjectKey, zones]);
const handleDuplicateObject = useCallback(() => { const handleDuplicateObject = useCallback(() => {
if (!selectedObject) return; if (!selectedObject) return;

View File

@ -1184,6 +1184,49 @@ test("admin can add the first area from a blank map canvas", async ({ page }) =>
await expect(page.getByRole("button", { name: "Save Draft" })).toBeEnabled(); await expect(page.getByRole("button", { name: "Save Draft" })).toBeEnabled();
}); });
test("admin added map areas stay inside the canvas", async ({ page }) => {
await mockMapShell(page);
const existingObjects = Array.from({ length: 31 }, (_, index) => ({
id: 5000 + index,
location_map_id: 900,
zone_id: null,
zone_name: null,
type: "zone",
label: `Existing Area ${index + 1}`,
x: 24 + (index % 5) * 128,
y: 24 + Math.floor(index / 5) * 88,
width: 120,
height: 72,
rotation: 0,
locked: false,
visible: true,
sort_order: index + 1,
}));
const mapState = {
...draftMapState(existingObjects, true),
zones: [],
};
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: "Continue Editing" }).click();
await page.getByRole("button", { name: "Add Area" }).click();
const newArea = page.getByRole("button", { name: "Map area New Area" });
await expect(newArea).toHaveAttribute("aria-pressed", "true");
await expect(newArea).toHaveAttribute("x", "780");
await expect(newArea).toHaveAttribute("y", "570");
await expect(page.locator(".location-map-status")).toHaveText("Unsaved Draft");
});
test("admin view mode previews the edited draft when a saved draft exists", async ({ page }) => { test("admin view mode previews the edited draft when a saved draft exists", async ({ page }) => {
await mockMapShell(page); await mockMapShell(page);