Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dispute Challenge and Accept buttons to Transaction Details #7093

Merged
merged 63 commits into from
Sep 19, 2023

Conversation

Jinksi
Copy link
Member

@Jinksi Jinksi commented Aug 30, 2023

Fixes #6926

Note
This PR is behind feature flag _wcpay_feature_dispute_on_transaction_page

Changes proposed in this Pull Request

  • Adds dispute action buttons to the Transaction Details screen for disputes awaiting a response (not inquiries), enabling the merchant to Accept the dispute or begin/continue a Challenge from this screen.
  • Adds a test suite for the DisputeDetails component
  • Introduces code quality improvements – updated and annotated some TS interfaces.

Note: this PR won't handle CTA buttons for inquiries – this will be handled in issue #7193.

Screenshots

Action buttons:

dispute-actions

Accept modal:

image

Snackbar on successful accept:

Wide buttons on mobile (see design: RiEQmaKRI7u9USAI3lyZz0VX-fi-7430_30973):

The below video demonstrates:
→ clicking the Challenge button
→ staging evidence via the challenge form
→ returning to the dispute details
→ opening the accept dispute modal
→ accepting the dispute

dispute-actions.mov

Testing instructions

  • Create a disputed transaction using the card 4000000000000259 at checkout.
  • Navigate to the disputed Transaction (Transactions → click the disputed transaction)
  • Click Challenge dispute → You should be taken to the Dispute challenge screen.
  • Click Accept dispute → A modal will be shown. Confirm the text and styles are correct as per the design (RiEQmaKRI7u9USAI3lyZz0VX-fi-6974_70994).
    • Click Cancel to close the modal
    • Disable network / go offline in devtools (to force a network error)
    • Click Accept dispute
      • On error, a snackbar will show an error message in the bottom-left corner.
    • Re-enable network
    • Click Accept dispute
      • The modal should close
      • The dispute should be accepted
      • A snackbar will show a success message in the bottom-left corner
      • The Transaction Details screen will be hydrated with new data (Disputed: Lost status chip).
      • The dispute actions should no longer be available.
  • View a dispute of any other status (won, lost, under review)
    • The dispute actions should not be visible
  • View a disputed transaction for a dispute where a challenge has been staged (click "Save for Later" on the dispute challenge form.
    • The Challenge button should be labelled Continue with challenge

  • Run npm run changelog to add a changelog file, choose patch to leave it empty if the change is not significant. You can add multiple changelog files in one PR by running this command a few times.
  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Post merge

@@ -56,6 +69,7 @@ export interface Dispute {
currency: string;
created: number;
balance_transactions: BalanceTransaction[];
payment_intent: string;
Copy link
Member Author

@Jinksi Jinksi Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was missing from the Dispute TS interface, but is a property of the Stripe API dispute object: https://stripe.com/docs/api/disputes/object#dispute_object-payment_intent.

This PR uses dispute.payment_intent to refresh the payment_intent data for the Transaction Details when a dispute is accepted.

// This function handles the dispute acceptance flow from the Transaction Details screen.
// It will become the default acceptDispute function once the feature flag
// '_wcpay_feature_dispute_on_transaction_page' is enabled by default.
export function* acceptTransactionDetailsDispute( dispute ) {
Copy link
Member Author

@Jinksi Jinksi Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than modify the existing acceptDispute action (used on the Dispute → Details screen), I've created a new one since there are some differences in the approach:

  1. The existing action will force a redirect to Payments → Disputes.
  2. This new action requires fetching and updating the payment intent to refresh the current Transaction Details page.

Once the feature flag is lifted, _wcpay_feature_dispute_on_transaction_page, we can remove and replace the previous action with the new one.

I've left a TODO item on #6883 to make this change.

@botwoo
Copy link
Collaborator

botwoo commented Aug 30, 2023

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 7093 or branch name fix/6926-transaction-dispute-details-actions in your-test.site/wp-admin/admin.php?page=jetpack-beta&plugin=woocommerce-payments

Option 2. Jurassic Ninja - available for logged-in A12s

🚀 Launch a JN site with this branch 🚀

ℹ️ Install this Tampermonkey script to get more options.


Build info:

  • Latest commit: eb23605
  • Build time: 2023-09-19 23:24:27 UTC

Note: the build is updated when a new commit is pushed to this PR.

client/types/disputes.d.ts Outdated Show resolved Hide resolved
@Jinksi Jinksi changed the title Add Challenge and Accept buttons to Transaction Dispute Details screen Add Challenge and Accept buttons to Transaction Details → Dispute Details Aug 30, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Aug 30, 2023

Size Change: +2 kB (0%)

Total Size: 1.41 MB

Filename Size Change
release/woocommerce-payments/dist/blocks-checkout.js 73.7 kB +46 B (0%)
release/woocommerce-payments/dist/checkout.js 28.7 kB +42 B (0%)
release/woocommerce-payments/dist/index-rtl.css 36.2 kB +81 B (0%)
release/woocommerce-payments/dist/index.css 36.2 kB +81 B (0%)
release/woocommerce-payments/dist/index.js 281 kB +953 B (0%)
release/woocommerce-payments/dist/multi-currency-switcher-block.js 60.1 kB +105 B (0%)
release/woocommerce-payments/dist/multi-currency.js 54.7 kB +113 B (0%)
release/woocommerce-payments/dist/order.js 40.9 kB +121 B (0%)
release/woocommerce-payments/dist/payment-gateways.js 38.4 kB +116 B (0%)
release/woocommerce-payments/dist/settings.js 231 kB +113 B (0%)
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 20.3 kB +38 B (0%)
release/woocommerce-payments/dist/subscriptions-empty-state.js 19.4 kB +36 B (0%)
release/woocommerce-payments/dist/tos.js 21.9 kB +36 B (0%)
release/woocommerce-payments/dist/upe_with_deferred_intent_creation_checkout.js 36.6 kB +43 B (0%)
release/woocommerce-payments/dist/woopay-express-button.js 50.6 kB +36 B (0%)
release/woocommerce-payments/dist/woopay.js 71.6 kB +38 B (0%)
ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.03 kB
release/woocommerce-payments/assets/css/success.css 158 B
release/woocommerce-payments/dist/blocks-checkout-rtl.css 1.51 kB
release/woocommerce-payments/dist/blocks-checkout.css 1.51 kB
release/woocommerce-payments/dist/checkout-rtl.css 440 B
release/woocommerce-payments/dist/checkout.css 441 B
release/woocommerce-payments/dist/multi-currency-analytics.js 1.05 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 2.88 kB
release/woocommerce-payments/dist/multi-currency.css 2.88 kB
release/woocommerce-payments/dist/order-rtl.css 676 B
release/woocommerce-payments/dist/order.css 679 B
release/woocommerce-payments/dist/payment-gateways-rtl.css 690 B
release/woocommerce-payments/dist/payment-gateways.css 692 B
release/woocommerce-payments/dist/payment-request-rtl.css 146 B
release/woocommerce-payments/dist/payment-request.css 146 B
release/woocommerce-payments/dist/payment-request.js 11.6 kB
release/woocommerce-payments/dist/product-details.js 789 B
release/woocommerce-payments/dist/settings-rtl.css 8.9 kB
release/woocommerce-payments/dist/settings.css 8.91 kB
release/woocommerce-payments/dist/subscription-edit-page.js 669 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 519 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 519 B
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 693 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 117 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 117 B
release/woocommerce-payments/dist/tos-rtl.css 230 B
release/woocommerce-payments/dist/tos.css 231 B
release/woocommerce-payments/dist/upe_checkout-rtl.css 440 B
release/woocommerce-payments/dist/upe_checkout.css 441 B
release/woocommerce-payments/dist/upe_checkout.js 34 kB
release/woocommerce-payments/dist/upe_split_checkout-rtl.css 440 B
release/woocommerce-payments/dist/upe_split_checkout.css 441 B
release/woocommerce-payments/dist/upe_split_checkout.js 34.6 kB
release/woocommerce-payments/dist/upe-blocks-checkout-rtl.css 1.51 kB
release/woocommerce-payments/dist/upe-blocks-checkout.css 1.51 kB
release/woocommerce-payments/dist/upe-blocks-checkout.js 39.5 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout-rtl.css 1.51 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout.css 1.51 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout.js 41 kB
release/woocommerce-payments/dist/woopay-express-button-rtl.css 146 B
release/woocommerce-payments/dist/woopay-express-button.css 146 B
release/woocommerce-payments/dist/woopay-rtl.css 3.85 kB
release/woocommerce-payments/dist/woopay.css 3.85 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 633 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 720 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.43 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.01 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 522 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 581 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/babel.config.js 160 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.css 2.32 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.js 13.8 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.rtl.css 2.32 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.2 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 291 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 403 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.56 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 299 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 742 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 572 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 411 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 544 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin.js 9.63 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.js 6.8 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.83 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 544 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.1 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.6 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/payment-method-restrictions.js 1.29 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/wcs-meta-boxes-order.js 502 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 355 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 429 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/view-subscription.js 1.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/wcs-cart.js 781 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.1 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.27 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 392 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.06 kB

compressed-size-action

client/types/disputes.d.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@brucealdridge brucealdridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Challenge dispute → Dispute challenge screen ✅
Accept dispute → A modal will be shown. ✅
On error, a snackbar will show an error message in the bottom-left corner. ✅
The dispute should be accepted ✅
The Transaction Details screen will be hydrated with new data (Disputed: Lost status chip). ✅
The dispute actions should no longer be available. ❌
The dispute actions should not be visible when won, lost or under review. ❌
View a disputed transaction for a dispute where a challenge has been staged (click "Save for Later" on the dispute challenge form.) ✅

When testing I was able to see the buttons after the dispute was lost or won.
Screenshot 2023-09-19 at 3 59 02 PM

@Jinksi
Copy link
Member Author

Jinksi commented Sep 19, 2023

The dispute actions should no longer be available. ❌
The dispute actions should not be visible when won, lost or under review. ❌

This surprises me, since the parent won't render the component at all if the isAwaitingResponse return false.

{ isAwaitingResponse( charge.dispute.status ) ? (
<DisputeAwaitingResponseDetails
dispute={ charge.dispute }
/>
) : (

I'll have a look. Thanks for testing @brucealdridge !

Comment on lines +95 to +108
<Link
href={
// Prevent the user navigating to the challenge screen if the accept request is in progress.
isLoading
? ''
: getAdminUrl( {
page: 'wc-admin',
path:
'/payments/disputes/challenge',
id: dispute.id,
} )
}
>
<Button
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for a button inside a link here? Would it be better to just have a button with a href attribute on it?

There is the wcTracks event on the <Button> and the href on the <Link>

Can we combine these so there are two actions on the one element, rather than two actions over two elements?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeh this pattern came out of the discussion here: #7047 (comment).

We want the client-side routing AND native browser navigation via href when CMD+clicking. Link offers this, whereas Button doesn't – but we want the Button UI.

I'll consider if there's another way, perhaps there is a component that I don't know about.

Copy link
Member Author

@Jinksi Jinksi Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've attempted a compromise in 3709cc0 by using a Link with a span child for the button styles.

<Link
	href={ getAdminUrl( ... ) }
	onClick={ () => { wcpayTracks.recordEvent( ... ); } }
>
	<span className="components-button is-primary">
		I am styled like a Button

One risk with this approach is that we're using classNames for styling components-button detached from the Button component.

I'm curious to get your thoughts on this problem, @haszari, as you noticed this issue in a recent PR: #7047 (comment).

If I'm thinking about the project goals, getting this button right is critical. Using client-side routing is desirable, IMO, since the merchant will see the challenge form more quickly and smoothly → more challenges being initiated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm thinking about the project goals, getting this button right is critical. Using client-side routing is desirable, IMO, since the merchant will see the challenge form more quickly and smoothly → more challenges being initiated.

💯 totally agree. If we can speed up state transitions, that should improve "conversions" (responses to disputes), and of course make merchants' lives easier and more efficient.

One risk with this approach is that we're using classNames for styling components-button detached from the Button component.

I don't think using a raw <span> is much leaner than using a <button>. I'd lean towards using components as is (not borrowing classes or other hackery), and if there's a gap in the library, follow up by logging issues (and submitting PRs?) so the component library meets our needs. So personally I prefer the original `

This reveals a potential UX/design issue – we might be using Button inappropriately when we should be using Link.

A bigger topic really, might be a good discussion on P2 e.g. codep2 or with other front end experts :)

Copy link
Member Author

@Jinksi Jinksi Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your feedback @haszari and @brucealdridge.

Based on this discussion, I'm going to proceed with the <Link><Button /></Link> pattern to get this PR shipped (203f161 & 163514b).

I'll log a follow-up issue and move this conversation elsewhere.

sprintf(
/* translators: %s: dispute fee, <em>: emphasis HTML element. */
__(
'Accepting the dispute marks it as <em>Lost</em>. The disputed amount will be returned to the cardholder, with a %s dispute fee deducted from your account.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to review this language. This implies the fee will only be deducted if they accept the dispute. When the fee has already been deducted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll log a follow-up issue to allow this PR to be shipped and we can iterate on the wording.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New issue for this: #7254

@brucealdridge
Copy link
Contributor

This surprises me, since the parent won't render the component at all if the isAwaitingResponse return false.

Hmmmm, I'm sure I did a pull just before testing. Doing a pull again says I was running be9ff75. False alarm sorry, all working as expected.

Copy link
Contributor

@brucealdridge brucealdridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retested after confirming I was checking an old commit :doh!:
All cases working as expected.

@Jinksi Jinksi enabled auto-merge September 19, 2023 23:19
@Jinksi Jinksi added this pull request to the merge queue Sep 19, 2023
Merged via the queue into develop with commit ae45522 Sep 19, 2023
27 checks passed
@Jinksi Jinksi deleted the fix/6926-transaction-dispute-details-actions branch September 19, 2023 23:45
@Jinksi Jinksi mentioned this pull request Oct 4, 2023
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Transaction Details > Dispute Details > Dispute CTA buttons and Accept dispute modal
4 participants