diff --git a/changelog/fix-7473-accept-dispute-loading-state-ui b/changelog/fix-7473-accept-dispute-loading-state-ui new file mode 100644 index 00000000000..90961cf931e --- /dev/null +++ b/changelog/fix-7473-accept-dispute-loading-state-ui @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Show loading state when accepting a dispute from the transaction details screen. diff --git a/client/payment-details/dispute-details/dispute-awaiting-response-details.tsx b/client/payment-details/dispute-details/dispute-awaiting-response-details.tsx index 07882870f2b..ac90232316d 100644 --- a/client/payment-details/dispute-details/dispute-awaiting-response-details.tsx +++ b/client/payment-details/dispute-details/dispute-awaiting-response-details.tsx @@ -82,10 +82,14 @@ interface AcceptDisputeProps { /** * Disputes and Inquiries have different text for buttons and the modal. * They also have different icons and tracks events. This function returns the correct props. - * - * @param dispute */ -function getAcceptDisputeProps( dispute: Dispute ): AcceptDisputeProps { +function getAcceptDisputeProps( { + dispute, + isDisputeAcceptRequestPending, +}: { + dispute: Dispute; + isDisputeAcceptRequestPending: boolean; +} ): AcceptDisputeProps { if ( isInquiry( dispute ) ) { return { acceptButtonLabel: __( 'Issue refund', 'woocommerce-payments' ), @@ -146,7 +150,9 @@ function getAcceptDisputeProps( dispute: Dispute ): AcceptDisputeProps { ), }, ], - modalButtonLabel: __( 'Accept dispute', 'woocommerce-payments' ), + modalButtonLabel: isDisputeAcceptRequestPending + ? __( 'Accepting…', 'woocommerce-payments' ) + : __( 'Accept dispute', 'woocommerce-payments' ), modalButtonTracksEvent: wcpayTracks.events.DISPUTE_ACCEPT_CLICK, }; } @@ -157,7 +163,10 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { chargeCreated, orderUrl, } ) => { - const { doAccept, isLoading } = useDisputeAccept( dispute ); + const { + doAccept, + isLoading: isDisputeAcceptRequestPending, + } = useDisputeAccept( dispute ); const [ isModalOpen, setModalOpen ] = useState( false ); const now = moment(); @@ -170,7 +179,11 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { featureFlags: { isDisputeIssuerEvidenceEnabled }, } = useContext( WCPaySettingsContext ); - const onModalClose = () => { + const handleModalClose = () => { + // Don't allow the user to close the modal if the accept request is in progress. + if ( isDisputeAcceptRequestPending ) { + return; + } setModalOpen( false ); }; @@ -188,7 +201,10 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { ); }; - const disputeAcceptAction = getAcceptDisputeProps( dispute ); + const disputeAcceptAction = getAcceptDisputeProps( { + dispute, + isDisputeAcceptRequestPending, + } ); const challengeButtonDefaultText = isInquiry( dispute ) ? __( 'Submit evidence', 'woocommerce-payments' ) @@ -239,7 +255,7 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { = ( { { wcpayTracks.recordEvent( wcpayTracks.events @@ -275,7 +291,7 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { { wcpayTracks.recordEvent( @@ -295,7 +311,7 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { { isModalOpen && ( @@ -326,7 +342,10 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { > { __( 'Cancel', @@ -335,6 +354,12 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { { wcpayTracks.recordEvent( @@ -346,7 +371,7 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { 'transaction_details', } ); - setModalOpen( false ); + /** * Handle the primary modal action. * If it's an inquiry, redirect to the order page; otherwise, continue with the default dispute acceptance. diff --git a/client/payment-details/dispute-details/style.scss b/client/payment-details/dispute-details/style.scss index e51559f4fcd..60773396b54 100644 --- a/client/payment-details/dispute-details/style.scss +++ b/client/payment-details/dispute-details/style.scss @@ -104,7 +104,9 @@ } } .transaction-details-dispute-accept-modal { - max-width: 600px; + &.components-modal__frame { + max-width: 600px; + } .components-modal__content { padding-top: $grid-unit-30;
@@ -326,7 +342,10 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { > { __( 'Cancel', @@ -335,6 +354,12 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { { wcpayTracks.recordEvent( @@ -346,7 +371,7 @@ const DisputeAwaitingResponseDetails: React.FC< Props > = ( { 'transaction_details', } ); - setModalOpen( false ); + /** * Handle the primary modal action. * If it's an inquiry, redirect to the order page; otherwise, continue with the default dispute acceptance. diff --git a/client/payment-details/dispute-details/style.scss b/client/payment-details/dispute-details/style.scss index e51559f4fcd..60773396b54 100644 --- a/client/payment-details/dispute-details/style.scss +++ b/client/payment-details/dispute-details/style.scss @@ -104,7 +104,9 @@ } } .transaction-details-dispute-accept-modal { - max-width: 600px; + &.components-modal__frame { + max-width: 600px; + } .components-modal__content { padding-top: $grid-unit-30;