fix: clarify map setup without zones

This commit is contained in:
Nico 2026-06-03 14:02:00 -07:00
parent 1eaddd8a07
commit c0ed1c0472
4 changed files with 65 additions and 22 deletions

View File

@ -1,6 +1,7 @@
export default function LocationMapSetupPanel({ export default function LocationMapSetupPanel({
hasAnyMap, hasAnyMap,
canManage, canManage,
zoneCount = 0,
saving, saving,
onContinue, onContinue,
onPreview, onPreview,
@ -15,6 +16,10 @@ export default function LocationMapSetupPanel({
: canManage : canManage
? "Create a rough map for this store location." ? "Create a rough map for this store location."
: "A household admin has not published a map yet."; : "A household admin has not published a map yet.";
const hasZones = zoneCount > 0;
const createFromZonesLabel = hasZones
? `Create From ${zoneCount} Zone${zoneCount === 1 ? "" : "s"}`
: "Create From Zones";
return ( return (
<section className="location-map-setup"> <section className="location-map-setup">
@ -22,7 +27,6 @@ export default function LocationMapSetupPanel({
<p>{description}</p> <p>{description}</p>
{hasAnyMap && canManage ? ( {hasAnyMap && canManage ? (
<div className="location-map-setup-actions"> <div className="location-map-setup-actions">
<>
<button type="button" className="btn-primary" onClick={onContinue}> <button type="button" className="btn-primary" onClick={onContinue}>
Continue Editing Continue Editing
</button> </button>
@ -32,18 +36,20 @@ export default function LocationMapSetupPanel({
<button type="button" className="btn-primary" onClick={onPublish} disabled={saving || !canManage}> <button type="button" className="btn-primary" onClick={onPublish} disabled={saving || !canManage}>
Publish Map Publish Map
</button> </button>
</>
</div> </div>
) : !hasAnyMap && canManage ? ( ) : !hasAnyMap && canManage ? (
<div className="location-map-setup-actions"> <div className="location-map-setup-actions">
<> {!hasZones ? (
<button type="button" className="btn-primary" onClick={onCreateFromZones} disabled={saving}> <p className="location-map-setup-note">
Create Map From Existing Zones No zones are available yet. Create a blank map now, or add zones first for an automatic starter layout.
</p>
) : null}
<button type="button" className="btn-primary" onClick={onCreateFromZones} disabled={saving || !hasZones}>
{createFromZonesLabel}
</button> </button>
<button type="button" className="btn-secondary" onClick={onCreateBlank} disabled={saving}> <button type="button" className="btn-secondary" onClick={onCreateBlank} disabled={saving}>
Create Blank Map Create Blank Map
</button> </button>
</>
</div> </div>
) : null} ) : null}
</section> </section>

View File

@ -475,6 +475,7 @@ export default function LocationMapManager() {
<LocationMapSetupPanel <LocationMapSetupPanel
hasAnyMap={hasAnyMap} hasAnyMap={hasAnyMap}
canManage={canManage} canManage={canManage}
zoneCount={mapState?.zones?.length || 0}
saving={saving} saving={saving}
onContinue={() => setMode("edit")} onContinue={() => setMode("edit")}
onPreview={handlePreviewDraft} onPreview={handlePreviewDraft}

View File

@ -553,6 +553,17 @@
gap: 0.6rem; gap: 0.6rem;
} }
.location-map-setup-note {
margin: 0;
padding: 0.6rem 0.7rem;
border: 1px solid rgba(245, 158, 11, 0.28);
border-radius: 8px;
background: rgba(245, 158, 11, 0.1);
color: #f8fafc;
font-size: 0.9rem;
font-weight: 700;
}
.location-map-loading { .location-map-loading {
margin: 3rem auto; margin: 3rem auto;
color: #9fb3c8; color: #9fb3c8;

View File

@ -262,10 +262,10 @@ test("admin creates a map from zones, saves a draft, and publishes it", async ({
await expect(page.getByRole("heading", { name: "Costco" })).toBeVisible(); await expect(page.getByRole("heading", { name: "Costco" })).toBeVisible();
await expect(page.getByText("Eastvale")).toBeVisible(); await expect(page.getByText("Eastvale")).toBeVisible();
await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible(); await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible();
await expect(page.getByRole("button", { name: "Create Map From Existing Zones" })).toBeVisible(); await expect(page.getByRole("button", { name: "Create From 2 Zones" })).toBeVisible();
await expect(page.getByLabel("Map controls")).toHaveCount(0); await expect(page.getByLabel("Map controls")).toHaveCount(0);
await page.getByRole("button", { name: "Create Map From Existing Zones" }).click(); await page.getByRole("button", { name: "Create From 2 Zones" }).click();
await expect(page.getByText("Bakery")).toBeVisible(); await expect(page.getByText("Bakery")).toBeVisible();
await expect(page.getByText("Frozen Foods")).toBeVisible(); await expect(page.getByText("Frozen Foods")).toBeVisible();
await expect(page.getByRole("button", { name: "Pan Mode" })).toBeVisible(); await expect(page.getByRole("button", { name: "Pan Mode" })).toBeVisible();
@ -373,6 +373,31 @@ test("admin creates a map from zones, saves a draft, and publishes it", async ({
await expect(page.getByText("loose batteries")).toBeVisible(); await expect(page.getByText("loose batteries")).toBeVisible();
}); });
test("admin setup explains when no zones exist yet", async ({ page }) => {
await mockMapShell(page);
await page.route("**/households/1/locations/10/map", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
...noMapState(true),
zones: [],
items: [],
unmapped_count: 0,
}),
});
});
await page.goto("/stores/100/locations/10/map");
await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible();
await expect(page.getByText("No zones are available yet.")).toBeVisible();
await expect(page.getByRole("button", { name: "Create From Zones" })).toBeDisabled();
await expect(page.getByRole("button", { name: "Create Blank Map" })).toBeEnabled();
await expect(page.getByLabel("Map controls")).toHaveCount(0);
});
test("admin status follows the visible map when a saved draft exists", async ({ page }) => { test("admin status follows the visible map when a saved draft exists", async ({ page }) => {
await mockMapShell(page); await mockMapShell(page);
@ -857,7 +882,7 @@ test("members see a clean empty state when no map is published", async ({ page }
await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible(); await expect(page.getByRole("heading", { name: "No Map" })).toBeVisible();
await expect(page.getByText("A household admin has not published a map yet.")).toBeVisible(); await expect(page.getByText("A household admin has not published a map yet.")).toBeVisible();
await expect(page.getByText("Create a rough map for this store location.")).toHaveCount(0); await expect(page.getByText("Create a rough map for this store location.")).toHaveCount(0);
await expect(page.getByRole("button", { name: "Create Map From Existing Zones" })).toHaveCount(0); await expect(page.getByRole("button", { name: /Create From/ })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Create Blank Map" })).toHaveCount(0); await expect(page.getByRole("button", { name: "Create Blank Map" })).toHaveCount(0);
await expect(page.getByLabel("Map controls")).toHaveCount(0); await expect(page.getByLabel("Map controls")).toHaveCount(0);
}); });