diff --git a/frontend/src/components/modals/ConfirmBuyModal.jsx b/frontend/src/components/modals/ConfirmBuyModal.jsx index 60b3e44..a9fa1e6 100644 --- a/frontend/src/components/modals/ConfirmBuyModal.jsx +++ b/frontend/src/components/modals/ConfirmBuyModal.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import "../../styles/ConfirmBuyModal.css"; function ChevronIcon({ direction }) { @@ -27,17 +27,6 @@ export default function ConfirmBuyModal({ setIsSubmitting(false); }, [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 hasPrev = currentIndex > 0; const hasNext = currentIndex < allItems.length - 1; @@ -65,21 +54,46 @@ export default function ConfirmBuyModal({ } }; - const handlePrev = () => { + const handlePrev = useCallback(() => { if (isSubmitting) return; if (hasPrev && onNavigate) { onNavigate(allItems[currentIndex - 1]); } - }; + }, [allItems, currentIndex, hasPrev, isSubmitting, onNavigate]); - const handleNext = () => { + const handleNext = useCallback(() => { if (isSubmitting) return; if (hasNext && onNavigate) { 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 ? `data:${item.image_mime_type};base64,${item.item_image}` diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts index 06d2c69..7fb8dde 100644 --- a/frontend/tests/location-map-manager.spec.ts +++ b/frontend/tests/location-map-manager.spec.ts @@ -3670,6 +3670,10 @@ test("viewer can buy selected zone items from the map", async ({ page }) => { expect(nextItemButtonBox.height).toBeGreaterThanOrEqual(40); await nextItemButton.click(); 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 previousItemButtonBox = await previousItemButton.boundingBox(); expect(previousItemButtonBox).not.toBeNull();