"use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { useAuth } from "@/context/AuthContext"; import { useCart } from "@/context/CartContext"; import { loadStripe } from "@stripe/stripe-js"; import { Elements, PaymentElement, useStripe, useElements, } from "@stripe/react-stripe-js"; import { apiCompleteCheckout } from "@/lib/cartApi"; const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || ""); function PaymentForm({ clientSecret, totalAmount, onSuccess, onCancel }) { const stripe = useStripe(); const elements = useElements(); const { token } = useAuth(); const [paying, setPaying] = useState(false); const [payError, setPayError] = useState(null); async function handlePay(e) { e.preventDefault(); if (!stripe || !elements) return; setPaying(true); setPayError(null); const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: window.location.origin + "/cart/confirmation" }, redirect: "if_required", }); if (error) { setPayError(error.message); setPaying(false); } else { const paymentIntentId = clientSecret.split("_secret_")[0]; try { await apiCompleteCheckout(token, paymentIntentId); } catch { setPayError("Order confirmation failed. Please contact support."); setPaying(false); return; } onSuccess(); } } return (

Payment Details

Total to pay: ${parseFloat(totalAmount).toFixed(2)}

{payError &&

{payError}

}
); } export default function CartPage() { const { user, loading: authLoading } = useAuth(); const { cart, cartLoading, cartError, selectedStoreId, updateItem, removeItem, clearCart, applyCoupon, checkout, cancelCheckout, } = useCart(); const router = useRouter(); const [couponInput, setCouponInput] = useState(""); const [couponError, setCouponError] = useState(null); const [couponLoading, setCouponLoading] = useState(false); const [checkoutLoading, setCheckoutLoading] = useState(false); const [checkoutError, setCheckoutError] = useState(null); const [clientSecret, setClientSecret] = useState(null); const [checkoutTotal, setCheckoutTotal] = useState(null); const [confirmed, setConfirmed] = useState(false); const [localQuantities, setLocalQuantities] = useState({}); useEffect(() => { if (!authLoading && !user) { router.push("/login"); } }, [authLoading, user, router]); useEffect(() => { if (cart?.items) { const map = {}; cart.items.forEach((i) => (map[i.cartItemId] = i.quantity)); setLocalQuantities(map); } }, [cart]); // If the cart arrives already locked (e.g. user closed the page mid-checkout) // and there is no active Stripe session, release the lock automatically. useEffect(() => { if (cart?.checkoutPending && !clientSecret) { cancelCheckout().catch(() => {}); } }, [cart?.checkoutPending, clientSecret, cancelCheckout]); async function handleQuantityChange(cartItemId, newQty) { if (newQty < 1) { return; } setLocalQuantities((prev) => ({ ...prev, [cartItemId]: newQty })); try { await updateItem(cartItemId, newQty); } catch { if (cart?.items) { const original = cart.items.find((i) => i.cartItemId === cartItemId); if (original) { setLocalQuantities((prev) => ({ ...prev, [cartItemId]: original.quantity })); } } } } async function handleRemove(cartItemId) { try { await removeItem(cartItemId); } catch { } } async function handleApplyCoupon() { if (!couponInput.trim()) return; setCouponLoading(true); setCouponError(null); try { await applyCoupon(couponInput.trim()); setCouponInput(""); } catch (err) { setCouponError(err.message); } finally { setCouponLoading(false); } } async function handleCheckout() { if (!cart?.items?.length) return; setCheckoutLoading(true); setCheckoutError(null); try { const result = await checkout(); if (result?.clientSecret) { setClientSecret(result.clientSecret); setCheckoutTotal(result.totalAmount); } else if (result?.status === "succeeded") { setConfirmed(true); } } catch (err) { setCheckoutError(err.message); } finally { setCheckoutLoading(false); } } if (authLoading || cartLoading) { return

Loading…

; } if (!user) return null; if (confirmed) { return (

Order Confirmed!

Thank you for your purchase. Your order has been placed successfully.

); } if (!selectedStoreId) { return (

Please select a store from the navigation bar to view your cart.

); } const items = cart?.items ?? []; return (

Your Cart

{cartError &&

{cartError}

} {items.length === 0 && !cartError && (

Your cart is empty.

)} {items.length > 0 && (
{items.map((item) => (
{item.prodName} { e.currentTarget.onerror = null; e.currentTarget.src = "/images/pet-placeholder.png"; }} />

{item.prodName}

${parseFloat(item.unitPrice).toFixed(2)} each

{localQuantities[item.cartItemId] ?? item.quantity}

${(parseFloat(item.unitPrice) * (localQuantities[item.cartItemId] ?? item.quantity)).toFixed(2)}

))}
)}
); }