import { Card, CardContent, CardHeader, CardTitle } from '@components/common/ui/Card.js'; import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from '@components/common/ui/Item.js'; import { Label } from '@components/common/ui/Label.js'; import { RadioGroup, RadioGroupItem } from '@components/common/ui/RadioGroup.js'; import { useCheckout } from '@components/frontStore/checkout/CheckoutContext.js'; import { _ } from '@evershop/evershop/lib/locale/translate/_'; import { CustomerAddressGraphql } from '@evershop/evershop/types/customerAddress'; import { Package } from 'lucide-react'; import React from 'react'; interface ShippingMethod { code: string; name: string; cost?: { value: number; text: string; }; description?: string; isSelected?: boolean; } // Skeleton component for loading state function ShippingMethodSkeleton() { return (
{[1, 2, 3, 4].map((index) => (
))}
); } export function ShippingMethods({ methods, shippingAddress, isLoading, onSelect }: { methods: ShippingMethod[]; shippingAddress?: CustomerAddressGraphql; isLoading?: boolean; onSelect?: (method: ShippingMethod) => Promise | boolean; }) { const { form } = useCheckout(); const { formState, setValue, watch } = form; const [isProcessing, setIsProcessing] = React.useState(false); const currentValue = watch('shippingMethod'); const handleMethodSelect = async (method: ShippingMethod) => { if (!onSelect) { // If no onSelect function provided, allow normal behavior setValue('shippingMethod', method.code); return; } if (isProcessing || formState.disabled) { return; } try { setIsProcessing(true); const result = await Promise.resolve(onSelect(method)); if (result) { // Only update the form value if onSelect returns true setValue('shippingMethod', method.code); } // If result is false, keep the current selection } catch (error) { // Keep the current selection on error } finally { setIsProcessing(false); } }; return (
{_('Shipping Method')}
{isLoading ? ( ) : ( <>
{methods?.length === 0 ? (
{!shippingAddress?.country || !shippingAddress?.province ? (
{_( 'Available shipping methods will appear once you provide your address details' )}
) : (
{_('No shipping methods available')}
{_( 'No shipping options are available for your location' )}
)}
) : ( { const method = methods.find((m) => m.code === value); if (method) { handleMethodSelect(method); } else { setValue('shippingMethod', value); } }} > {methods.map((method: ShippingMethod) => (
{ !isProcessing && handleMethodSelect(method); }} disabled={isProcessing} />
{method.description && ( {method.description} )}
{method.cost ? ( <> {method.cost.value > 0 ? (
{method.cost.text}
) : ( <>
{method.cost.text}
{_('FREE')}
)} ) : (
{_('Contact for pricing')}
)}
))}
)}
{formState.errors.shippingMethod && (
{formState.errors.shippingMethod?.message?.toString() || _('Please select a shipping method')}
)} )}
); }