"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"; type Stop = { id: string; city: string; state: string; date: string; time: string; location: string; brand_id: string; }; 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); fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/stops?active=eq.true&brand_id=eq.${cartBrandId}&select=id,city,state,date,time,location,brand_id&order=date`, { headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! } } ) .then((r) => r.json()) .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); fetch( `${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/check_stop_product_availability`, { method: "POST", headers: { apikey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ p_stop_id: stop.id, p_product_ids: pickupProductIds }), } ) .then((r) => r.json()) .then((data: { product_id: string; is_available: boolean }[]) => { 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 */}