-
Notifications
You must be signed in to change notification settings - Fork 69
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 steps to resolve to the transaction details page. #7206
Changes from 12 commits
bb6ba35
3088de5
284243f
18f2fa5
5a3cbe5
53c6679
f9c94f9
45e25fa
63bd71f
6fe270b
d28219e
04ee3f6
e94f356
a7ddf94
116a8db
ad54e79
6e2b7ff
d9d006e
e8a83fe
f9126c5
d105ead
19545bd
973a63c
64556a1
0b768b3
6a55603
3d35ecc
787b8d9
341ef80
0498f7a
4a10c2a
9275269
71a3349
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Significance: patch | ||
Type: dev | ||
Comment: This work is part of a UI improvements to increase disputes response that is behind a feature flag. A changelog entry will be added to represent the work as a whole. | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
/** @format **/ | ||
|
||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import { __, _n, sprintf } from '@wordpress/i18n'; | ||
import { createInterpolateElement } from '@wordpress/element'; | ||
import { dateI18n } from '@wordpress/date'; | ||
import moment from 'moment'; | ||
import HelpOutlineIcon from 'gridicons/dist/help-outline'; | ||
import classNames from 'classnames'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import type { Dispute } from 'wcpay/types/disputes'; | ||
import { ChargeBillingDetails } from 'wcpay/types/charges'; | ||
import { formatExplicitCurrency } from 'utils/currency'; | ||
import { ClickTooltip } from 'wcpay/components/tooltip'; | ||
|
||
interface Props { | ||
dispute: Dispute; | ||
customer: ChargeBillingDetails | null; | ||
chargeCreated: number; | ||
daysRemaining: number; | ||
} | ||
|
||
const DisputeSteps: React.FC< Props > = ( { | ||
dispute, | ||
customer, | ||
chargeCreated, | ||
daysRemaining, | ||
} ) => { | ||
let emailLink; | ||
if ( customer?.email ) { | ||
const chargeDate = dateI18n( | ||
'Y-m-d', | ||
moment( chargeCreated * 1000 ).toISOString() | ||
); | ||
const disputeDate = dateI18n( | ||
'Y-m-d', | ||
moment( dispute.created * 1000 ).toISOString() | ||
); | ||
const emailSubject = `Problem with your purchase from ${ wcpaySettings.storeName } on ${ chargeDate }?`; | ||
const emailBody = | ||
`Hello ${ customer?.name }\n\n` + | ||
shendy-a8c marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`We noticed that on ${ disputeDate }, you disputed a ${ formatExplicitCurrency( | ||
dispute.amount, | ||
dispute.currency | ||
) } from ${ chargeDate }. We wanted to contact you to make sure everything was all right with your purchase and see if there's anything else we can do to resolve any problems you might have had.\n\n` + | ||
`Alternatively, if the dispute was a mistake, you could easily withdraw it by calling the number on the back of your card. Thank you so much - we appreciate your business and look forward to working with you.`; | ||
|
||
emailLink = `mailto:${ customer.email }?subject=${ encodeURIComponent( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wanted to use querystring.strinfigy() but I don't see it's used at all in the codebase, so I just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Has anyone tested clicking the link correctly works with at least one email client? If there's any issue with escaping or protocol then that would catch it! I have this behaviour disabled on my mac (because I use GMail), so wasn't able to test. Noting so we can test in our test swarm today e.g. on mobile or if someone has |
||
emailSubject | ||
) }&body=${ encodeURIComponent( emailBody ) }`; | ||
} | ||
|
||
const respondByDate = dispute.evidence_details?.due_by | ||
? dateI18n( | ||
'M j, Y, g:ia', | ||
moment( dispute.evidence_details?.due_by * 1000 ).toISOString() | ||
) | ||
: '–'; | ||
|
||
return ( | ||
<div className="dispute-steps"> | ||
<div className="dispute-steps__header"> | ||
{ __( 'Steps to resolve:', 'woocommercts' ) } | ||
</div> | ||
<ol className="dispute-steps__steps"> | ||
<li> | ||
{ | ||
// TODO: add link to the issuer evidence files link. See https://github.com/Automattic/woocommerce-payments/pull/7192. | ||
Jinksi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
__( | ||
"Review the claim issued by the cardholder's bank.", | ||
'woocommerce-payments' | ||
) | ||
} | ||
</li> | ||
<li> | ||
{ customer?.email | ||
? createInterpolateElement( | ||
__( | ||
'<a>Email the customer</a> to address their concerns.', | ||
'woocommerce-payments' | ||
), | ||
{ | ||
a: ( | ||
// eslint-disable-next-line jsx-a11y/anchor-has-content | ||
<a | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
href={ emailLink } | ||
/> | ||
), | ||
} | ||
) | ||
: __( | ||
'Email the customer to address their concerns.', | ||
'woocommerce-payments' | ||
) } | ||
</li> | ||
<li> | ||
{ | ||
// TODO: link 'guidance on dispute withdrawal' to the docs when it's ready. | ||
shendy-a8c marked this conversation as resolved.
Show resolved
Hide resolved
|
||
__( | ||
'Provide guidance on dispute withdrawal if the customer agrees.', | ||
'woocommerce-payments' | ||
) | ||
} | ||
</li> | ||
<li> | ||
{ createInterpolateElement( | ||
__( | ||
'Challenge <challengeicon/> or accept <accepticon/> the dispute by <disputeduedate/>.', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I found these inline icon tooltips a bit weird, they break the flow of the sentence. It's functioning well though and super clear and usable so not a blocker. Maybe that info could be in a single help popup, nearer the action buttons. Thinking out loud – @nikkivias is our UX expert here. |
||
'woocommerce-payments' | ||
), | ||
{ | ||
challengeicon: ( | ||
<ClickTooltip | ||
buttonIcon={ <HelpOutlineIcon /> } | ||
buttonLabel={ __( | ||
'Challenge the dispute', | ||
'woocommerce-payments' | ||
) } | ||
content={ __( | ||
"Challenge the dispute if you consider the claim invalid. You'll need to provide evidence to back your claim. Keep in mind that challenging doesn't ensure a resolution in your favor.", | ||
'woocommerce-payments' | ||
) } | ||
/> | ||
), | ||
accepticon: ( | ||
<ClickTooltip | ||
buttonIcon={ <HelpOutlineIcon /> } | ||
buttonLabel={ __( | ||
'Accept the dispute', | ||
'woocommerce-payments' | ||
) } | ||
content={ sprintf( | ||
// Translators: %s is a formatted currency amount, eg $10.00. | ||
__( | ||
`Accepting this dispute will automatically close it. Your account will be charged a %s fee, and the disputed amount will be refunded to the cardholder.`, | ||
'woocommerce-payments' | ||
), | ||
// TODO: use getDisputeFee() from https://github.com/Automattic/woocommerce-payments/pull/7118. | ||
Jinksi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'' | ||
) } | ||
/> | ||
), | ||
disputeduedate: ( | ||
<span className="dispute-steps__steps__response-date"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I copied this from DisputeSummaryRow's so it looks consistent. One doubt I have is that in the design paJDYF-9Ip-p2, when due date is still more than 7-day away, it does not show the but I see in |
||
{ respondByDate } | ||
<span | ||
className={ classNames( { | ||
'dispute-steps__steps__response-date--urgent': | ||
daysRemaining < 3, | ||
'dispute-steps__steps__response-date--warning': | ||
daysRemaining < 7 && | ||
daysRemaining > 2, | ||
} ) } | ||
> | ||
{ daysRemaining === 0 | ||
? __( | ||
'(Last day today)', | ||
'woocommerce-payments' | ||
) | ||
: sprintf( | ||
// Translators: %s is the number of days left to respond to the dispute. | ||
_n( | ||
'(%s day left to respond)', | ||
'(%s days left to respond)', | ||
daysRemaining, | ||
'woocommerce-payments' | ||
), | ||
daysRemaining | ||
) } | ||
</span> | ||
</span> | ||
), | ||
} | ||
) } | ||
</li> | ||
</ol> | ||
</div> | ||
); | ||
}; | ||
|
||
export default DisputeSteps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally do not translate the email subject and body because it is a bit weird to translate a content that is for the customer who might not speak the same language as merchant.
What do you think @souravdebnath1986 @nikkivias? Should we send this email as merchant's language or in English? Or maybe both as I've seen that practice (sending in 2 languages in one email) a lot, but if so, what about the subject?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we keep it simple? This is site content, so it should be translatable. Just like content on pages, buttons, or in site emails.
The merchant has control of all of this. The default experience should not have mixed languages IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note – this will not send an email, just generate a draft email in merchant's email client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, if a multilingual merchant wants to send a localised "is everything ok with your purchase" email, they can edit in their mail client of choice or use another mailing solution such as MailPoet etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made the email subject and body translatable in 787b8d9 to let the merchant decide what language to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think to default to the merchant's language is better than to suddenly see English if they have localized configuration.