import { Button, Notice } from '@wordpress/components'; import { __, sprintf, _n } from '@wordpress/i18n'; import { useCallback, useState } from '@wordpress/element'; import { Icon, check, error as errorIcon, external } from '@wordpress/icons'; import { formatCurrency, getCurrencyObject, } from 'components/label-purchase/design-next/utils'; import { BulkPrintDialog, type BulkPrintDialogPrintResult, } from '../bulk-print-dialog'; import type { FailedRow, SettledRow, SucceededRow } from './types'; import { BATCH_INTERRUPTED_ERROR_CODE, BATCH_TRANSPORT_ERROR_CODE, } from './types'; import { failedRows, formatFailureMessage, getEditOrderUrl, orderLabel, } from './helpers'; /** * Batch-level error codes mark per-row failures that were not caused by * the order itself (server unreachable, merchant aborted mid-progress). * Opening the order edit page for those does not help the merchant fix * anything, so the per-row "Fix and retry" affordance is suppressed and * a top-level hint is shown instead. */ const isBatchLevelFailure = ( row: FailedRow ): boolean => row.error_code === BATCH_TRANSPORT_ERROR_CODE || row.error_code === BATCH_INTERRUPTED_ERROR_CODE; interface ResultsViewProps { rows: SettledRow[]; onClose: () => void; autoPrintSuccessfulLabels?: boolean; } const getResultsTitle = ( hasSucceeded: boolean, hasFailed: boolean ): string => { if ( hasSucceeded && hasFailed ) { return __( 'Some labels need attention', 'woocommerce-shipping' ); } if ( hasSucceeded ) { return __( 'All labels created', 'woocommerce-shipping' ); } return __( 'No labels were created', 'woocommerce-shipping' ); }; /** * Per-order print error state. Keyed by `order_id` so a second print * attempt on a different row doesn't stomp the error from the first. * The `Print all labels` button uses the synthetic `__all__` key so * its error doesn't collide with a single-row retry. */ type PrintErrorMap = Record< string, string >; const PRINT_ALL_KEY = '__all__'; export const ResultsView = ( { rows, onClose, autoPrintSuccessfulLabels = false, }: ResultsViewProps ) => { const succeeded = rows.filter( ( r ): r is SucceededRow => r.status === 'succeeded' ); const failed = failedRows( rows ); const allLabelRefs = succeeded.flatMap( ( r ) => r.label_refs ); const hasSucceeded = succeeded.length > 0; const hasFailed = failed.length > 0; const [ printErrors, setPrintErrors ] = useState< PrintErrorMap >( {} ); const clearPrintError = useCallback( ( key: string ) => { setPrintErrors( ( prev ) => { if ( ! ( key in prev ) ) { return prev; } const next = { ...prev }; delete next[ key ]; return next; } ); }, [] ); const handlePrintResult = useCallback( ( key: string, result: BulkPrintDialogPrintResult ) => { if ( result.ok ) { clearPrintError( key ); return; } setPrintErrors( ( prev ) => ( { ...prev, [ key ]: result.messages[ 0 ], } ) ); }, [ clearPrintError ] ); const currency = getCurrencyObject().code; const printAllError = printErrors[ PRINT_ALL_KEY ]; return (