-
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 payment activity widget emoji survey #8506
Merged
Merged
Changes from 68 commits
Commits
Show all changes
77 commits
Select commit
Hold shift + click to select a range
90f6994
payments overview widget
e4027d0
add unicode emoji
2fdb2b3
add unit tests
2dd5b9a
ui tests
b0c9405
add changelog
53f7ec4
fix code reviews
7854b84
fix responsive component
4eaf649
hide feature under feature flag
85a3162
set more descriptive names for the ratings
bba57a2
separate external and internal dependencies
93f520a
adjust emoji size
1bb9d42
fix close button
7581bda
center emoji
4dcbec0
add text padding
eec84c4
remove ununsed var
da56928
add paddings
f6bef71
add close button on survey ends
c13b7bb
Remove duplicate var declaration post-merge
Jinksi 38c0f38
Reorder imports
Jinksi 0b807c8
Move survey to be child of PaymentActivity component
Jinksi 3c40202
Remove Card wrap
Jinksi 93b6d1a
Fix merge missing changes in survey controller
Jinksi 707f249
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 29c573e
Update snapshot tests
Jinksi 8ca2833
Update TS with Rating type etc
Jinksi 4e2fbf4
Rename plural to singular Emoticon
Jinksi 4e63d0e
Rename survey class to `wcpay-payments-activity__survey`
Jinksi e7ac70d
Update styles and markup
Jinksi 4f5ace7
Rename status -> responseStatus
Jinksi 16dc85d
Rename disclaimer class
Jinksi 38dab2c
Use WP icon for close button
Jinksi 0b69a97
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi f6d5318
Reduce to single call to context hook
Jinksi 4607805
Update survey text and alignment to match design
Jinksi 964ef07
Show error notice when survey post response fails
Jinksi b9034f3
Use a more descriptive option key for submitted survey
Jinksi 364f0cb
Refactor context TS
Jinksi ba26daa
Simplify css for both survey and confirmation message
Jinksi 4040dd9
Move CardFooter to Survey component
Jinksi da393e2
Update tests
Jinksi e7f8c09
Fix PaymentActivity test
Jinksi 477fec4
Refactor Emoticon onClick to consolidate logic
Jinksi 686da84
Prefer implicit types to improve readability
Jinksi e381c24
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 584b00f
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 22cba56
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 8915377
Render survey only when has at least one payment
Jinksi de06a8c
Submit WCPay version number with response
Jinksi aea55e1
Disable close button if submission in progress
Jinksi 5ffaa5b
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 64daee3
Update links to use the woocommerce.com domain (#8574)
vladolaru bdb09b2
Jetpack Connection Manager Updates (#8584)
dmallory42 9c32c43
Clear WP cache on writes inside Database_Cache (#8601)
marcinbot ea68a19
chore: remove unused code which confirmed payment in legacy UPE (#8577)
timur27 fec1630
Added support to Cartes Bancaires (#8568)
gpressutto5 197c0d2
Remove @wordpress/data dependency in the email input iframe file (#8561)
hsingyuc b4e6ff7
Adds check to see if WC()->session is set in WooPay_Utilities::should…
billrobbins 032d9f2
Add Multi-Currency Support to Page Caching via Cookies (#8534)
rafaelzaleski ba727d0
Reporting: Add UI for Payment Data Highlights tiles in Payment Activi…
nagpai 59332ad
Prevent WooPay order webhook from being registered if account is unde…
ricardo 09d274a
Fix account tools Finish setup button: point to Stripe KYC flow inste…
oaratovskyi 3f4cd6e
Revert account rejected check before registering WooPay order webhook…
ricardo c999d21
Ensure “Proceed to Checkout” Button’s Loading Spinner Doesn’t Affect …
lovo-h 207e0ca
Implement session cookie for WooPay checkout flow (#8570)
cesarcosta99 cc05f78
Fix tests after merge
Jinksi 1fdb16d
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi b41bd3a
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 3666e0d
Merge branch 'develop' into add/8484-payment-activity-widget-survey
ad76ea2
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi 152a819
Bring survey into new `payment-activity` dir
Jinksi 96d81d7
Fix missing jest mocks
Jinksi 8a912c3
Add survey integration tests for payment-activity component
Jinksi c20d8de
Use @include breakpoint for media query
Jinksi ce69a28
Add space above Emoticon declaration
Jinksi 824c8d9
Remove simplify inner container max-width styling
Jinksi 959210d
Define emoticons as React Elements rather than strings to avoid `dang…
Jinksi e046bc3
Merge branch 'develop' into add/8484-payment-activity-widget-survey
Jinksi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: minor | ||
Type: add | ||
|
||
Add User Satisfaction Survey for Payments Overview Widget |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React, { createContext, useState, useCallback, useContext } from 'react'; | ||
import apiFetch from '@wordpress/api-fetch'; | ||
import { useDispatch } from '@wordpress/data'; | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { NAMESPACE } from 'data/constants'; | ||
import type { OverviewSurveyFields } from './types'; | ||
|
||
type ResponseStatus = 'pending' | 'resolved' | 'error'; | ||
|
||
const useContextValue = ( initialState: OverviewSurveyFields = {} ) => { | ||
const [ surveySubmitted, setSurveySubmitted ] = useState( false ); | ||
const [ responseStatus, setResponseStatus ] = useState< ResponseStatus >( | ||
'resolved' | ||
); | ||
const [ surveyAnswers, setSurveyAnswers ] = useState( initialState ); | ||
|
||
const { createErrorNotice } = useDispatch( 'core/notices' ); | ||
|
||
const submitSurvey = useCallback( | ||
async ( answers: OverviewSurveyFields ) => { | ||
setResponseStatus( 'pending' ); | ||
try { | ||
await apiFetch( { | ||
path: `${ NAMESPACE }/upe_survey/payments-overview`, | ||
method: 'POST', | ||
data: answers, | ||
} ); | ||
setSurveySubmitted( true ); | ||
setResponseStatus( 'resolved' ); | ||
} catch ( e ) { | ||
setResponseStatus( 'error' ); | ||
setSurveySubmitted( false ); | ||
createErrorNotice( | ||
__( | ||
'An error occurred while submitting the survey. Please try again.', | ||
'woocommerce-payments' | ||
) | ||
); | ||
} | ||
}, | ||
[ setResponseStatus, setSurveySubmitted, createErrorNotice ] | ||
); | ||
|
||
return { | ||
setSurveySubmitted: submitSurvey, | ||
responseStatus, | ||
surveySubmitted, | ||
surveyAnswers, | ||
setSurveyAnswers, | ||
}; | ||
}; | ||
|
||
type ContextValue = ReturnType< typeof useContextValue >; | ||
|
||
const WcPayOverviewSurveyContext = createContext< ContextValue | null >( null ); | ||
|
||
export const WcPayOverviewSurveyContextProvider: React.FC< { | ||
initialData?: OverviewSurveyFields; | ||
} > = ( { children, initialData } ) => { | ||
return ( | ||
<WcPayOverviewSurveyContext.Provider | ||
value={ useContextValue( initialData ) } | ||
> | ||
{ children } | ||
</WcPayOverviewSurveyContext.Provider> | ||
); | ||
}; | ||
|
||
export const useOverviewSurveyContext = (): ContextValue => { | ||
const context = useContext( WcPayOverviewSurveyContext ); | ||
if ( ! context ) { | ||
throw new Error( 'An error occurred when using survey context' ); | ||
} | ||
return context; | ||
}; | ||
|
||
export default WcPayOverviewSurveyContext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import classNames from 'classnames'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import type { Rating } from './types'; | ||
|
||
const strings: Record< Rating, string > = { | ||
'very-unhappy': '😞', | ||
unhappy: '🫤', | ||
neutral: '😑', | ||
happy: '🙂', | ||
'very-happy': '😍', | ||
}; | ||
|
||
interface Props { | ||
rating: Rating; | ||
onClick: ( event: React.MouseEvent< HTMLButtonElement > ) => void; | ||
disabled: boolean; | ||
isSelected: boolean; | ||
} | ||
const Emoticon: React.FC< Props > = ( { | ||
Jinksi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
rating, | ||
onClick, | ||
disabled, | ||
isSelected, | ||
} ) => { | ||
return ( | ||
<button | ||
disabled={ disabled } | ||
type="button" | ||
onClick={ onClick } | ||
className={ classNames( 'components-button', 'has-icon', { | ||
selected: isSelected, | ||
} ) } | ||
> | ||
<span | ||
role="img" | ||
aria-label={ rating } | ||
// eslint-disable-next-line react/no-danger | ||
dangerouslySetInnerHTML={ { __html: strings[ rating ] } } | ||
Jinksi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/> | ||
</button> | ||
); | ||
}; | ||
|
||
export default Emoticon; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
/** @format **/ | ||
|
||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import { HorizontalRule } from '@wordpress/primitives'; | ||
import { Button, CardFooter, TextareaControl } from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { createInterpolateElement, useState } from '@wordpress/element'; | ||
import { Icon, closeSmall } from '@wordpress/icons'; | ||
|
||
/** | ||
* Internal dependencies. | ||
*/ | ||
import type { Rating } from './types'; | ||
import { useOverviewSurveyContext } from './context'; | ||
import Emoticon from './emoticon'; | ||
import './style.scss'; | ||
|
||
const Survey: React.FC = () => { | ||
const { | ||
responseStatus, | ||
surveySubmitted, | ||
surveyAnswers, | ||
setSurveyAnswers, | ||
setSurveySubmitted, | ||
} = useOverviewSurveyContext(); | ||
|
||
const [ showComponent, setShowComponent ] = useState( true ); | ||
|
||
const currentRating = surveyAnswers.rating; | ||
const ratingWithComment: Rating[] = [ | ||
'very-unhappy', | ||
'unhappy', | ||
'neutral', | ||
]; | ||
const ratings: Rating[] = [ | ||
'very-unhappy', | ||
'unhappy', | ||
'neutral', | ||
'happy', | ||
'very-happy', | ||
]; | ||
const showComment = | ||
currentRating && ratingWithComment.includes( currentRating ); | ||
const disableForm = 'pending' === responseStatus; | ||
|
||
const setReviewRating = function ( value?: Rating ) { | ||
const answers = { | ||
...surveyAnswers, | ||
rating: value, | ||
}; | ||
setSurveyAnswers( answers ); | ||
|
||
// If the user selects a rating that does not require a comment, submit the survey immediately. | ||
if ( value && ! ratingWithComment.includes( value ) ) { | ||
setSurveySubmitted( answers ); | ||
} | ||
}; | ||
|
||
if ( ! showComponent ) { | ||
return null; | ||
} | ||
|
||
if ( surveySubmitted ) { | ||
return ( | ||
<CardFooter size="small"> | ||
<div className="wcpay-payments-activity__survey"> | ||
<div className="survey_container"> | ||
<span role="img" aria-label="Thank you!"> | ||
🙌 | ||
</span> | ||
{ __( | ||
'We appreciate your feedback!', | ||
'woocommerce-payments' | ||
) } | ||
</div> | ||
|
||
<div className="close_container"> | ||
<button | ||
type="button" | ||
className="components-button has-icon" | ||
aria-label="Close dialog" | ||
onClick={ () => { | ||
setShowComponent( false ); | ||
} } | ||
> | ||
<Icon icon={ closeSmall } size={ 28 } /> | ||
</button> | ||
</div> | ||
</div> | ||
</CardFooter> | ||
); | ||
} | ||
|
||
return ( | ||
<CardFooter size="small"> | ||
<div className="wcpay-payments-activity__survey"> | ||
<div className="survey_container"> | ||
{ __( | ||
'Are those metrics helpful?', | ||
'woocommerce-payments' | ||
) } | ||
|
||
<div className="survey_container__emoticons"> | ||
{ ratings.map( ( rating ) => ( | ||
<Emoticon | ||
key={ rating } | ||
disabled={ disableForm } | ||
rating={ rating } | ||
onClick={ () => setReviewRating( rating ) } | ||
isSelected={ rating === currentRating } | ||
/> | ||
) ) } | ||
</div> | ||
</div> | ||
|
||
{ showComment && ( | ||
<> | ||
<div className="close_container"> | ||
<button | ||
type="button" | ||
className="components-button has-icon" | ||
aria-label="Close dialog" | ||
onClick={ () => { | ||
setReviewRating( undefined ); | ||
} } | ||
disabled={ disableForm } | ||
> | ||
<Icon icon={ closeSmall } size={ 28 } /> | ||
</button> | ||
</div> | ||
|
||
<HorizontalRule /> | ||
|
||
<div className="comment_container"> | ||
<TextareaControl | ||
label={ __( | ||
'Why do you feel that way? (optional)', | ||
'woocommerce-payments' | ||
) } | ||
onChange={ ( text ) => { | ||
setSurveyAnswers( ( prev ) => ( { | ||
...prev, | ||
comments: text, | ||
} ) ); | ||
} } | ||
value={ surveyAnswers.comments ?? '' } | ||
readOnly={ disableForm } | ||
/> | ||
<p className="comment_container__disclaimer"> | ||
{ createInterpolateElement( | ||
__( | ||
'Your feedback will be only be shared with WooCommerce and treated pursuant to our <a>privacy policy</a>.', | ||
'woocommerce-payments' | ||
), | ||
{ | ||
a: ( | ||
// eslint-disable-next-line jsx-a11y/anchor-has-content | ||
<a | ||
href="https://automattic.com/privacy/" | ||
target="_blank" | ||
rel="noreferrer" | ||
/> | ||
), | ||
} | ||
) } | ||
</p> | ||
</div> | ||
|
||
<div className="wcpay-confirmation-modal__footer"> | ||
<Button | ||
variant={ 'tertiary' } | ||
disabled={ disableForm } | ||
onClick={ () => { | ||
setReviewRating( undefined ); | ||
} } | ||
> | ||
{ __( 'Cancel', 'woocommerce-payments' ) } | ||
</Button> | ||
<Button | ||
variant={ 'primary' } | ||
isBusy={ disableForm } | ||
disabled={ disableForm } | ||
onClick={ () => | ||
setSurveySubmitted( surveyAnswers ) | ||
} | ||
> | ||
{ __( 'Send', 'woocommerce-payments' ) } | ||
</Button> | ||
</div> | ||
</> | ||
) } | ||
</div> | ||
</CardFooter> | ||
); | ||
}; | ||
export default Survey; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Love the implementation 🙌 though I am curious about the use of context for this feature, would love to know your thought process here.
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.
This was all carried over from the previous PR #8309. My thought process is that the Context approach works well, so there is no need to change it 😆