/** * Order progress: paid → booked (P2G) → fulfilled (WC complete). * Uses WordPress/WooCommerce components only; progress bar uses role="progressbar" and inline width. */ import { __ } from '@wordpress/i18n'; import { useMemo } from '@wordpress/element'; import { Card, CardBody, Flex, FlexItem, Notice } from '@wordpress/components'; import { Badge } from '.'; export interface OrderProgressProps { paid: boolean; booked: boolean; fulfilled: boolean; attempts?: number; orderReference?: string | number | null; contactName?: string; contactEmail?: string; orderLineCount?: number; bookedOrderLineCount?: number; } export default function OrderProgress({ paid, booked, fulfilled, attempts = 0, orderReference, contactName = '', contactEmail = '', orderLineCount = 1, bookedOrderLineCount = 0, }: OrderProgressProps) { const progress = useMemo(() => { // Progress calculation focused on booking stage movement if (fulfilled) return 100; if (booked) { let bookedProgress = 80; if (orderLineCount > 0) { const itemCompletionRate = bookedOrderLineCount / orderLineCount; bookedProgress += itemCompletionRate * 15; // Up to 15% for item completion } const attemptProgress = Math.min((attempts / 30) * 4, 4); // Up to 4% from attempts return Math.min(bookedProgress + attemptProgress, 99); // Cap just before 100% } if (paid) { let paidProgress = 30; if (orderLineCount > 0) { const bookingRate = bookedOrderLineCount / orderLineCount; paidProgress += bookingRate * 35; // Up to 35% for partial bookings } const attemptProgress = Math.min((attempts / 30) * 15, 15); // Up to 15% from attempts return Math.min(paidProgress + attemptProgress, 79); // Cap before booked stage } const baseProgress = 25; const attemptProgress = Math.min((attempts / 30) * 4, 4); // Minimal progress from attempts return Math.min(baseProgress + attemptProgress, 29); // Cap before payment }, [ paid, booked, fulfilled, attempts, orderLineCount, bookedOrderLineCount, ]); const currentStep = useMemo(() => { if (fulfilled) return 4; if (booked) return 4; if (paid) return 3; return 2; }, [paid, booked, fulfilled]); const steps = useMemo( () => [ { label: __('Order placed', 'parcel2go-shipping'), completed: true, description: __( 'Your order has been received.', 'parcel2go-shipping' ), }, { label: __('Payment confirmed', 'parcel2go-shipping'), completed: paid, description: __( 'Payment has been processed.', 'parcel2go-shipping' ), }, { label: __('Booking confirmed', 'parcel2go-shipping'), completed: booked, description: booked ? orderLineCount > 1 ? `${bookedOrderLineCount} ${__('of', 'parcel2go-shipping')} ${orderLineCount} ${__('orders booked with Parcel2Go.', 'parcel2go-shipping')}` : __( 'Your shipment has been booked with Parcel2Go.', 'parcel2go-shipping' ) : orderLineCount > 1 ? `${__('We are working on booking your shipments.', 'parcel2go-shipping')} (${bookedOrderLineCount}/${orderLineCount})` : `${__('We are working on booking your shipment.', 'parcel2go-shipping')} (${bookedOrderLineCount}/${orderLineCount})`, }, { label: __('Order fulfilled', 'parcel2go-shipping'), completed: fulfilled, description: __( 'Your order is on its way.', 'parcel2go-shipping' ), }, ], [paid, booked, fulfilled, orderLineCount, bookedOrderLineCount] ); const statusMessage = useMemo(() => { if (fulfilled) return __( 'Your order has been fulfilled and is on its way!', 'parcel2go-shipping' ); if (booked) { const itemStatus = orderLineCount > 0 && bookedOrderLineCount < orderLineCount ? ` ${bookedOrderLineCount}/${orderLineCount} ${__('items ready.', 'parcel2go-shipping')}` : ''; return __( "Your shipment has been confirmed and we're preparing for fulfillment.", 'parcel2go-shipping' ).concat(itemStatus); } if (paid) return __( "Payment confirmed! We're working on booking your shipment.", 'parcel2go-shipping' ); return __( "We've received your order and are processing it now.", 'parcel2go-shipping' ); }, [fulfilled, booked, paid, orderLineCount, bookedOrderLineCount]); const attemptsBadgeTone = useMemo(() => { if (attempts >= 30) return 'error'; if (attempts > 15) return 'warning'; return 'default'; }, [attempts]); return (

{__('Order progress', 'parcel2go-shipping')} {orderReference != null && orderReference !== '' ? ` ${orderReference}` : ''}

{attempts > 15 && ( {attempts >= 30 ? __( 'Processing delayed', 'parcel2go-shipping' ) : __( 'Taking longer', 'parcel2go-shipping' )} )}
{/* Progress bar: semantic progress, fill width is the only dynamic value */}
{__( 'Step %1$d of 4', 'parcel2go-shipping' ).replace('%1$d', String(currentStep))} {Math.round(progress)}%{' '} {__('complete', 'parcel2go-shipping')} {statusMessage}

{__('Order timeline', 'parcel2go-shipping')}

{steps.map((step, index) => ( {step.completed ? '✓' : '○'} {step.label} {step.completed && ( {__( 'Complete', 'parcel2go-shipping' )} )} {!step.completed && index + 1 === currentStep && ( {__( 'In progress', 'parcel2go-shipping' )} )}

{step.description}

))}
{attempts > 15 && attempts < 30 && ( {__( "We're still processing your order, but it's taking longer than expected. Our team is actively working on it.", 'parcel2go-shipping' )}{' '} {__('Contact Us:', 'parcel2go-shipping')}{' '} {__('Live Chat', 'parcel2go-shipping')} )} {attempts >= 30 && ( {__( "We're experiencing delays with your order. Our support team has been notified and will contact you shortly.", 'parcel2go-shipping' )}{' '} {__('Contact Us:', 'parcel2go-shipping')}{' '} {__('Live Chat', 'parcel2go-shipping')} )} ); }