import { Spinner } from '@woocommerce/components'; import { Button, Card, CardBody, Flex, FlexItem, Notice, TextControl, } from '@wordpress/components'; import { close } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; import { useCallback, useMemo, useState } from 'react'; import { ValidationResponse, CheckoutApiError } from '../../../types'; import { sanitizeDiscountCode } from '../utils/sanitizeDiscountCode'; import { formatCurrency } from '../../../shared/utils'; import { CheckoutErrorNotice } from '../../../shared/components'; interface PriceSectionProps { validationResult: ValidationResponse | null; isValidating: boolean; fullAmount: number; initialExtras: string[]; selectedExtras?: string[]; discountCode: string; createOrderError: string | null; setDiscountCode: (code: string) => void; onApplyDiscount: (currentExtras: string[], code: string) => void; onCancelDiscount: (currentExtras: string[]) => void; } const PriceSection = ({ validationResult, isValidating, fullAmount, initialExtras, selectedExtras = [], onApplyDiscount, onCancelDiscount, createOrderError, discountCode, setDiscountCode, }: PriceSectionProps) => { const [showDiscountInput, setShowDiscountInput] = useState(false); const handleDiscountChange = useCallback((value: string | undefined) => { setDiscountCode(sanitizeDiscountCode(value ?? '')); }, []); const handleApplyDiscount = useCallback(() => { const sanitized = sanitizeDiscountCode(discountCode); if (sanitized) onApplyDiscount(initialExtras.concat(selectedExtras), sanitized); }, [discountCode, initialExtras, selectedExtras, onApplyDiscount]); const handleCloseDiscountInput = useCallback(() => { setShowDiscountInput(false); setDiscountCode(''); }, []); const handleRemoveDiscount = useCallback(() => { setShowDiscountInput(false); setDiscountCode(''); onCancelDiscount(initialExtras.concat(selectedExtras)); }, [initialExtras, selectedExtras, onCancelDiscount]); const hasAppliedDiscount = validationResult?.success && (validationResult?.price?.discount ?? 0) > 0; /* Price breakdown */ const validationBreakdown = useMemo(() => { const basePrices = validationResult?.price?.breakdown?.filter((b) => b.name?.startsWith('Base Price') ) ?? []; const subTotal = validationResult?.price?.net ?? 0; const ddpItems = validationResult?.price?.breakdown?.filter((b) => b.name.startsWith('DDP') ) || []; const dutyAndTaxItems = ddpItems.filter( (b) => b.name.includes('DDP Duty') || b.name.includes('DDP Tax') ); const otherDdpItems = ddpItems.filter( (b) => !b.name.includes('DDP Duty') && !b.name.includes('DDP Tax') ); const dutyAndTaxTotal = dutyAndTaxItems.reduce( (sum, item) => sum + item.amount, 0 ); return { basePrices, subTotal, dutyAndTaxItems, otherDdpItems, dutyAndTaxTotal, }; }, [validationResult]); return ( {validationResult?.warnings?.length > 0 && ( {validationResult?.warnings[0].title} )}

{__('Price', 'parcel2go-shipping')}

{hasAppliedDiscount ? ( {__('Discount code', 'parcel2go-shipping')}:{' '} {discountCode} ) : ( {__('Discount code', 'parcel2go-shipping')} )} {hasAppliedDiscount && ( {__( 'Discount code applied successfully.', 'parcel2go-shipping' )} )} {/* Price breakdown */} {isValidating && !validationResult ? ( {__('Calculating price...', 'parcel2go-shipping')} ) : validationResult?.error ? ( ) : validationResult ? ( <> {validationBreakdown.basePrices.map((price) => { if (price.amount !== validationBreakdown.subTotal) { return ( {price.metadata?.name ?? price.name} {formatCurrency(price.amount / 100)} ); } return null; })} {validationBreakdown.dutyAndTaxItems?.length > 0 && ( {__( 'Duty and Local Tax', 'parcel2go-shipping' )} {formatCurrency( validationBreakdown.dutyAndTaxTotal / 100 )} )} {validationBreakdown.otherDdpItems?.map((item) => ( {item.metadata?.name ?? item.name} {formatCurrency(item.amount / 100)} ))} {validationResult.price?.tax > 0 && ( {__('VAT', 'parcel2go-shipping')} {formatCurrency( validationResult.price.tax / 100 )} )} {validationResult.price?.discount > 0 && ( {__( 'Discount applied', 'parcel2go-shipping' )} - {formatCurrency( validationResult.price.discount / 100 )} )} {__('Total', 'parcel2go-shipping')} {formatCurrency(fullAmount)} ) : null} {createOrderError && ( {createOrderError} )} ); }; export default PriceSection;