"use client"; import { Alert, Button, Card, Separator, Spinner } from "@heroui/react"; import { useEffect, useRef } from "react"; import { useShippingRate } from "@/lib/checkout"; import type { CheckoutAddress, CheckoutValidationResult, CheckoutSelectedShippingRate, CheckoutShippingRateResult, } from "@/lib/checkout/types"; import { formatPrice } from "@repo/utils"; import { CheckoutLineItems } from "../content/CheckoutLineItems"; type OrderReviewStepProps = { addressId: string; addresses: CheckoutAddress[]; cartResult: CheckoutValidationResult; sessionId: string | undefined; onProceed: ( shipmentObjectId: string, shippingRate: CheckoutSelectedShippingRate, ) => void; onBack: () => void; }; function formatShippingAmount(amount: number, currency: string): string { return new Intl.NumberFormat("en-GB", { style: "currency", currency: currency || "GBP", minimumFractionDigits: 2, }).format(amount); } export function OrderReviewStep({ addressId, addresses, cartResult, sessionId, onProceed, onBack, }: OrderReviewStepProps) { const { result, isLoading, error, retry } = useShippingRate( addressId, sessionId, ); const prevSubtotalRef = useRef(cartResult.subtotal); useEffect(() => { if ( result && !isLoading && cartResult.subtotal !== result.cartSubtotal ) { prevSubtotalRef.current = cartResult.subtotal; retry(); } }, [cartResult.subtotal, result, isLoading, retry]); const selectedAddress = addresses.find((a) => a.id === addressId); const itemCount = cartResult.items.reduce((sum, i) => sum + i.quantity, 0); const canProceed = !!result && !isLoading && !error; const handleContinue = () => { if (!result) return; onProceed(result.shipmentObjectId, result.selectedRate); }; const loadingMessageId = "shipping-rate-loading"; const errorMessageId = "shipping-rate-error"; return (
{/* Left column: shipping rate + address + line items */}
{selectedAddress && (

Shipping address

)}

Items ({itemCount})

{/* Right column: sticky order summary */}
); } // ─── Shipping Rate Card ────────────────────────────────────────────────────── function ShippingRateCard({ result, isLoading, error, onRetry, loadingMessageId, errorMessageId, }: { result: CheckoutShippingRateResult | null; isLoading: boolean; error: string | null; onRetry: () => void; loadingMessageId: string; errorMessageId: string; }) { if (isLoading) { return (

Calculating best shipping rate…

); } if (error) { return (
Unable to calculate shipping {error}
); } if (!result) return null; const { selectedRate } = result; return (
{selectedRate.provider}
{formatShippingAmount(selectedRate.amount, selectedRate.currency)}

{selectedRate.serviceName} {selectedRate.durationTerms && ( · {selectedRate.durationTerms} )}

{selectedRate.estimatedDays > 0 && (

Est. {selectedRate.estimatedDays} business{" "} {selectedRate.estimatedDays === 1 ? "day" : "days"}

)}
); } // ─── Order Summary ─────────────────────────────────────────────────────────── function OrderSummary({ cartSubtotal, itemCount, result, isLoading, }: { cartSubtotal: number; itemCount: number; result: CheckoutShippingRateResult | null; isLoading: boolean; }) { const currency = result?.selectedRate.currency ?? "GBP"; const shippingAmount = result?.shippingTotal ?? null; const orderTotal = shippingAmount !== null ? cartSubtotal / 100 + shippingAmount : null; return (

Summary

Items ({itemCount})
{formatPrice(cartSubtotal)}
Shipping
{isLoading ? "Calculating…" : shippingAmount !== null ? formatShippingAmount(shippingAmount, currency) : "—"}
Total
{orderTotal !== null ? formatShippingAmount(orderTotal, currency) : "—"}
); } // ─── Address Preview ───────────────────────────────────────────────────────── function AddressPreview({ address }: { address: CheckoutAddress }) { return (

{address.fullName}

{address.addressLine1}

{address.additionalInformation &&

{address.additionalInformation}

}

{address.city}

{address.postalCode}

); } // ─── Icons ─────────────────────────────────────────────────────────────────── function TruckIcon() { return ( ); }