fix: navigate buy modal with arrow keys

This commit is contained in:
Nico 2026-06-16 00:39:14 -07:00
parent 25b1efc214
commit 37614ea499
2 changed files with 34 additions and 16 deletions

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import "../../styles/ConfirmBuyModal.css"; import "../../styles/ConfirmBuyModal.css";
function ChevronIcon({ direction }) { function ChevronIcon({ direction }) {
@ -27,17 +27,6 @@ export default function ConfirmBuyModal({
setIsSubmitting(false); setIsSubmitting(false);
}, [item.id, item.quantity]); }, [item.id, item.quantity]);
useEffect(() => {
const handleKeyDown = (event) => {
if (event.key === "Escape" && !isSubmitting) {
onCancel();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [isSubmitting, onCancel]);
const currentIndex = allItems.findIndex((listItem) => listItem.id === item.id); const currentIndex = allItems.findIndex((listItem) => listItem.id === item.id);
const hasPrev = currentIndex > 0; const hasPrev = currentIndex > 0;
const hasNext = currentIndex < allItems.length - 1; const hasNext = currentIndex < allItems.length - 1;
@ -65,22 +54,47 @@ export default function ConfirmBuyModal({
} }
}; };
const handlePrev = () => { const handlePrev = useCallback(() => {
if (isSubmitting) return; if (isSubmitting) return;
if (hasPrev && onNavigate) { if (hasPrev && onNavigate) {
onNavigate(allItems[currentIndex - 1]); onNavigate(allItems[currentIndex - 1]);
} }
}; }, [allItems, currentIndex, hasPrev, isSubmitting, onNavigate]);
const handleNext = () => { const handleNext = useCallback(() => {
if (isSubmitting) return; if (isSubmitting) return;
if (hasNext && onNavigate) { if (hasNext && onNavigate) {
onNavigate(allItems[currentIndex + 1]); onNavigate(allItems[currentIndex + 1]);
} }
}, [allItems, currentIndex, hasNext, isSubmitting, onNavigate]);
useEffect(() => {
const handleKeyDown = (event) => {
if (isSubmitting) return;
if (event.key === "Escape") {
onCancel();
return;
}
if (event.key === "ArrowLeft") {
event.preventDefault();
handlePrev();
return;
}
if (event.key === "ArrowRight") {
event.preventDefault();
handleNext();
}
}; };
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [handleNext, handlePrev, isSubmitting, onCancel]);
const imageUrl = item.item_image && item.image_mime_type const imageUrl = item.item_image && item.image_mime_type
? `data:${item.image_mime_type};base64,${item.item_image}` ? `data:${item.image_mime_type};base64,${item.item_image}`
: null; : null;

View File

@ -3670,6 +3670,10 @@ test("viewer can buy selected zone items from the map", async ({ page }) => {
expect(nextItemButtonBox.height).toBeGreaterThanOrEqual(40); expect(nextItemButtonBox.height).toBeGreaterThanOrEqual(40);
await nextItemButton.click(); await nextItemButton.click();
await expect(page.locator(".confirm-buy-item-name")).toHaveText("sourdough"); await expect(page.locator(".confirm-buy-item-name")).toHaveText("sourdough");
await page.keyboard.press("ArrowLeft");
await expect(page.locator(".confirm-buy-item-name")).toHaveText("french bread");
await page.keyboard.press("ArrowRight");
await expect(page.locator(".confirm-buy-item-name")).toHaveText("sourdough");
const previousItemButton = page.getByRole("button", { name: "Previous item" }); const previousItemButton = page.getByRole("button", { name: "Previous item" });
const previousItemButtonBox = await previousItemButton.boundingBox(); const previousItemButtonBox = await previousItemButton.boundingBox();
expect(previousItemButtonBox).not.toBeNull(); expect(previousItemButtonBox).not.toBeNull();