Add store location map manager #20

Open
nalalangan wants to merge 206 commits from feature/location-map-manager into feature/store-selector-modal
3 changed files with 70 additions and 2 deletions
Showing only changes of commit ba48ece884 - Show all commits

View File

@ -23,6 +23,7 @@ export default function LocationMapCanvas({
dragState,
editingLocked = false,
hiddenAreaCount = 0,
onAddObject,
onShowZones,
onShowHiddenAreas,
setDragState,
@ -37,9 +38,11 @@ export default function LocationMapCanvas({
? objects.filter((object) => object.visible).length
: 0;
const hasNoVisibleObjects = objects.length > 0 && filters.showZones && visibleObjectCount === 0;
const canAddFirstArea =
!editingLocked && mode === "edit" && objects.length === 0 && typeof onAddObject === "function";
const canRecoverHiddenAreas =
mode === "edit" && hasNoVisibleObjects && hiddenAreaCount > 0 && typeof onShowHiddenAreas === "function";
const hasEmptyCanvasAction = hiddenByZonesLayer || canRecoverHiddenAreas;
const hasEmptyCanvasAction = canAddFirstArea || hiddenByZonesLayer || canRecoverHiddenAreas;
const emptyCanvasMessage = objects.length === 0
? "No map areas yet"
: hiddenByZonesLayer
@ -160,6 +163,11 @@ export default function LocationMapCanvas({
onShowZones?.();
};
const handleAddObject = (event) => {
event.stopPropagation();
onAddObject?.();
};
const handleShowHiddenAreas = (event) => {
event.stopPropagation();
onShowHiddenAreas?.();
@ -406,7 +414,15 @@ export default function LocationMapCanvas({
].filter(Boolean).join(" ")}
>
<span>{emptyCanvasMessage}</span>
{hiddenByZonesLayer ? (
{canAddFirstArea ? (
<button
type="button"
onPointerDown={(event) => event.stopPropagation()}
onClick={handleAddObject}
>
Add Area
</button>
) : hiddenByZonesLayer ? (
<button
type="button"
onPointerDown={(event) => event.stopPropagation()}

View File

@ -559,6 +559,7 @@ export default function LocationMapManager() {
dragState={dragState}
editingLocked={saving}
hiddenAreaCount={hiddenAreaCount}
onAddObject={handleAddObject}
setDragState={setDragState}
setSelectedObjectKey={setSelectedObjectKey}
remember={remember}

View File

@ -405,6 +405,57 @@ test("admin setup explains when no zones exist yet", async ({ page }) => {
await expect(page.getByLabel("Map controls")).toHaveCount(0);
});
test("admin can add the first area from a blank map canvas", async ({ page }) => {
await mockMapShell(page);
let mapState = {
...noMapState(true),
zones: [],
items: [],
unmapped_count: 0,
};
await page.route("**/households/1/locations/10/map", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify(mapState),
});
});
await page.route("**/households/1/locations/10/map/blank", async (route) => {
mapState = {
...draftMapState([], true),
zones: [],
items: [],
unmapped_count: 0,
};
await route.fulfill({
status: 201,
contentType: "application/json",
body: JSON.stringify(mapState),
});
});
await page.goto("/stores/100/locations/10/map");
await page.getByRole("button", { name: "Create Blank Map" }).click();
await expect(page.locator(".location-map-status")).toHaveText("Draft");
await expect(page.getByText("No map areas yet")).toBeVisible();
await expect(
page.locator(".location-map-empty-canvas").getByRole("button", { name: "Add Area" })
).toBeVisible();
await page.locator(".location-map-empty-canvas").getByRole("button", { name: "Add Area" }).click();
await expect(page.getByRole("button", { name: "Map area New Area" })).toBeVisible();
await expect(page.locator(".location-map-empty-canvas")).toHaveCount(0);
await expect(page.locator(".location-map-sheet-header strong")).toHaveText("New Area");
await expect(page.getByRole("textbox", { name: "Label" })).toHaveValue("New Area");
await expect(page.locator(".location-map-status")).toHaveText("Unsaved Draft");
await expect(page.getByRole("button", { name: "Save Draft" })).toBeEnabled();
});
test("admin status follows the visible map when a saved draft exists", async ({ page }) => {
await mockMapShell(page);