grocery-app/frontend/src/components/modals/ConfirmBuyModal.jsx
Nico bd945568c8
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 49s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 1s
Build & Deploy Costco Grocery List / deploy (push) Successful in 14s
Build & Deploy Costco Grocery List / notify (push) Successful in 0s
fix: auto-advance buy modal by list order
2026-03-29 13:09:04 -07:00

147 lines
4.0 KiB
JavaScript

import { useEffect, useState } from "react";
import "../../styles/ConfirmBuyModal.css";
export default function ConfirmBuyModal({
item,
onConfirm,
onCancel,
allItems = [],
onNavigate
}) {
const [quantity, setQuantity] = useState(item.quantity);
const [isSubmitting, setIsSubmitting] = useState(false);
const maxQuantity = item.quantity;
useEffect(() => {
setQuantity(item.quantity);
setIsSubmitting(false);
}, [item.id, item.quantity]);
const currentIndex = allItems.findIndex((listItem) => listItem.id === item.id);
const hasPrev = currentIndex > 0;
const hasNext = currentIndex < allItems.length - 1;
const handleIncrement = () => {
if (!isSubmitting && quantity < maxQuantity) {
setQuantity((prev) => prev + 1);
}
};
const handleDecrement = () => {
if (!isSubmitting && quantity > 1) {
setQuantity((prev) => prev - 1);
}
};
const handleConfirm = async () => {
if (isSubmitting) return;
setIsSubmitting(true);
try {
await onConfirm(quantity);
} finally {
setIsSubmitting(false);
}
};
const handlePrev = () => {
if (isSubmitting) return;
if (hasPrev && onNavigate) {
onNavigate(allItems[currentIndex - 1]);
}
};
const handleNext = () => {
if (isSubmitting) return;
if (hasNext && onNavigate) {
onNavigate(allItems[currentIndex + 1]);
}
};
const imageUrl = item.item_image && item.image_mime_type
? `data:${item.image_mime_type};base64,${item.item_image}`
: null;
return (
<div
className="confirm-buy-modal-overlay"
onClick={() => {
if (!isSubmitting) {
onCancel();
}
}}
>
<div className="confirm-buy-modal" onClick={(event) => event.stopPropagation()}>
<div className="confirm-buy-header">
{item.zone && <div className="confirm-buy-zone">{item.zone}</div>}
<h2 className="confirm-buy-item-name">{item.item_name}</h2>
</div>
<div className="confirm-buy-image-section">
<button
className="confirm-buy-nav-btn confirm-buy-nav-prev"
onClick={handlePrev}
style={{ visibility: hasPrev ? "visible" : "hidden" }}
disabled={!hasPrev || isSubmitting}
>
{"<"}
</button>
<div className="confirm-buy-image-container">
{imageUrl ? (
<img src={imageUrl} alt={item.item_name} className="confirm-buy-image" />
) : (
<div className="confirm-buy-image-placeholder">[ ]</div>
)}
</div>
<button
className="confirm-buy-nav-btn confirm-buy-nav-next"
onClick={handleNext}
style={{ visibility: hasNext ? "visible" : "hidden" }}
disabled={!hasNext || isSubmitting}
>
{">"}
</button>
</div>
<div className="confirm-buy-quantity-section">
<div className="confirm-buy-counter">
<button
onClick={handleDecrement}
className="confirm-buy-counter-btn"
disabled={quantity <= 1 || isSubmitting}
>
-
</button>
<input
type="number"
value={quantity}
readOnly
className="confirm-buy-counter-display"
/>
<button
onClick={handleIncrement}
className="confirm-buy-counter-btn"
disabled={quantity >= maxQuantity || isSubmitting}
>
+
</button>
</div>
</div>
<div className="confirm-buy-actions">
<button onClick={onCancel} className="confirm-buy-cancel" disabled={isSubmitting}>
Cancel
</button>
<button onClick={handleConfirm} className="confirm-buy-confirm" disabled={isSubmitting}>
{isSubmitting ? "Saving..." : "Mark as Bought"}
</button>
</div>
</div>
</div>
);
}