Add store location map manager #20

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

View File

@ -51,6 +51,13 @@ function getLocallyReducedMapItem(item, quantity) {
};
}
function getLocallyBoughtMapItem(item) {
return {
...item,
bought: true,
};
}
export default function LocationMapManager() {
const { storeId, locationId } = useParams();
const navigate = useNavigate();
@ -129,7 +136,7 @@ export default function LocationMapManager() {
[filters, mapItems, username]
);
const buyModalItems = useMemo(
() => (selectedObject ? selectedZoneItems : visibleUnmappedItems),
() => (selectedObject ? selectedZoneItems : visibleUnmappedItems).filter((item) => !item.bought),
[selectedObject, selectedZoneItems, visibleUnmappedItems]
);
const { visibleAssignedItemCount, unmappedItemCount } = useMemo(() => {
@ -190,7 +197,11 @@ export default function LocationMapManager() {
let nextBuyModalItems = buyModalItems;
if (quantity >= item.quantity) {
nextBuyModalItems = buyModalItems.filter((candidate) => candidate.id !== item.id);
updateMapItems((currentItems) => currentItems.filter((candidate) => candidate.id !== item.id));
updateMapItems((currentItems) =>
currentItems.map((candidate) => (
candidate.id === item.id ? getLocallyBoughtMapItem(candidate) : candidate
))
);
} else {
let updatedItem;
try {

View File

@ -2339,8 +2339,8 @@ test("viewer can buy selected zone items from the map", async ({ page }) => {
quantity_bought: 1,
});
await expect(page.locator(".confirm-buy-item-name")).toHaveText("sourdough");
await expect(page.locator(".location-map-sheet-count")).toHaveText("1 item");
await expect(bakeryArea.locator(".location-map-count")).toHaveText("1 item");
await expect(page.locator(".location-map-sheet-count")).toHaveText("1 shown");
await expect(bakeryArea.locator(".location-map-count")).toHaveText("1 shown");
await expect(page.locator(".location-map-zone-items")).not.toContainText("french bread");
await page.getByRole("button", { name: "Mark as Bought" }).click();
@ -2352,9 +2352,15 @@ test("viewer can buy selected zone items from the map", async ({ page }) => {
quantity_bought: 1,
});
await expect(page.locator(".confirm-buy-modal")).toHaveCount(0);
await expect(page.locator(".location-map-sheet-count")).toHaveText("0 items");
await expect(bakeryArea.locator(".location-map-count")).toHaveText("0 items");
await expect(page.getByText("No items assigned to this zone yet.")).toBeVisible();
await expect(page.locator(".location-map-sheet-count")).toHaveText("0 shown");
await expect(bakeryArea.locator(".location-map-count")).toHaveText("0 shown");
await expect(page.getByText("Items are assigned here, but hidden by layer filters.")).toBeVisible();
await page.getByRole("button", { name: "Layers" }).click();
await page.getByRole("button", { name: "Bought" }).click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("2 items");
await expect(page.getByRole("button", { name: "french bread bought" })).toBeDisabled();
await expect(page.getByRole("button", { name: "sourdough bought" })).toBeDisabled();
});
test("viewer advances map buy modal after partial quantity buys", async ({ page }) => {
@ -2571,9 +2577,10 @@ test("viewer shows completed zone items without rebuy actions", async ({ page })
...items[0],
bought: true,
},
items[1],
],
};
let boughtRequestCount = 0;
const boughtPayloads: Array<Record<string, unknown>> = [];
await page.route("**/households/1/locations/10/map", async (route) => {
await route.fulfill({
@ -2584,7 +2591,12 @@ test("viewer shows completed zone items without rebuy actions", async ({ page })
});
await page.route("**/households/1/locations/10/list/item", async (route) => {
boughtRequestCount += 1;
if (route.request().method() !== "PATCH") {
await route.fulfill({ status: 404, contentType: "application/json", body: "{}" });
return;
}
boughtPayloads.push(await route.request().postDataJSON());
await route.fulfill({
status: 200,
contentType: "application/json",
@ -2605,7 +2617,23 @@ test("viewer shows completed zone items without rebuy actions", async ({ page })
await boughtRow.click({ force: true });
await expect(page.locator(".confirm-buy-modal")).toHaveCount(0);
expect(boughtRequestCount).toBe(0);
expect(boughtPayloads).toHaveLength(0);
await page.getByRole("button", { name: "Mark sourdough bought" }).click();
await expect(page.locator(".confirm-buy-item-name")).toHaveText("sourdough");
await page.getByRole("button", { name: "Mark as Bought" }).click();
await expect.poll(() => boughtPayloads.length).toBe(1);
expect(boughtPayloads[0]).toMatchObject({
item_name: "sourdough",
bought: true,
quantity_bought: 1,
});
await expect(page.locator(".confirm-buy-modal")).toHaveCount(0);
const newlyBoughtRow = page.getByRole("button", { name: "sourdough bought" });
await expect(newlyBoughtRow).toBeVisible();
await expect(newlyBoughtRow).toBeDisabled();
await expect(newlyBoughtRow.locator("small")).toHaveText("Bought");
});
test("viewer explains when unmapped items are hidden by filters", async ({ page }) => {