"use client"; import { useState, useEffect, useCallback } from "react"; import Link from "next/link"; import { useCart } from "@/context/CartContext"; import StorefrontHeader from "@/components/storefront/StorefrontHeader"; import StorefrontFooter from "@/components/storefront/StorefrontFooter"; import { getPublicStopsForBrand, checkStopProductAvailability, type PublicStop } from "@/actions/checkout"; type Stop = PublicStop; export default function CartClient() { const { cart, subtotal, selectedStop, cartBrandId, setSelectedStop, increaseQuantity, decreaseQuantity, removeFromCart, } = useCart(); const [stops, setStops] = useState([]); const [loadingStops, setLoadingStops] = useState(false); const [showStopPicker, setShowStopPicker] = useState(false); const [incompatibleItems, setIncompatibleItems] = useState([]); const [stopBrandMismatch, setStopBrandMismatch] = useState(false); const [availabilityError, setAvailabilityError] = useState(false); const hasPickupItems = cart.some((i) => i.fulfillment === "pickup"); const hasShedPickupItems = cart.some((i) => i.fulfillment === "pickup" && i.pickup_type === "shed"); const hasStopPickupItems = cart.some((i) => i.fulfillment === "pickup" && i.pickup_type !== "shed"); // Check brand mismatch useEffect(() => { if (selectedStop?.brand_id && cartBrandId && selectedStop.brand_id !== cartBrandId) { // eslint-disable-next-line react-hooks/set-state-in-effect setStopBrandMismatch(true); } else { setStopBrandMismatch(false); } }, [selectedStop, cartBrandId]); // Fetch stops when picker is open useEffect(() => { if (hasPickupItems && showStopPicker && cartBrandId) { // eslint-disable-next-line react-hooks/set-state-in-effect setLoadingStops(true); getPublicStopsForBrand(cartBrandId) .then((data) => setStops(data ?? [])) .catch(() => setStops([])) .finally(() => setLoadingStops(false)); } }, [hasPickupItems, showStopPicker, cartBrandId]); const handleStopSelect = useCallback((stop: Stop) => { setSelectedStop(stop); setStopBrandMismatch(false); setShowStopPicker(false); setAvailabilityError(false); setIncompatibleItems([]); if (hasPickupItems) { const pickupProductIds = cart.filter((i) => i.fulfillment === "pickup").map((i) => i.id); checkStopProductAvailability(stop.id, pickupProductIds) .then((data) => { const unavailable = (data ?? []) .filter((row) => row.is_available === false) .map((row) => row.product_id); setIncompatibleItems(unavailable); }) .catch(() => { setAvailabilityError(true); setIncompatibleItems([]); }); } }, [cart, hasPickupItems, setSelectedStop]); const handleCheckoutClick = useCallback(() => { if (cart.length === 0) return; if (stopBrandMismatch) { setSelectedStop(null); return; } if (hasStopPickupItems && !selectedStop) { setShowStopPicker(true); return; } if (incompatibleItems.length > 0) { return; } window.location.href = "/checkout"; }, [cart.length, stopBrandMismatch, hasStopPickupItems, selectedStop, incompatibleItems]); return (
{/* Background */}