Keep score displayed if user cancels out of CES Modal
This commit is contained in:
parent
45dfda2b65
commit
b441a84d9d
|
@ -4,8 +4,7 @@
|
|||
import { createElement, useState, useEffect } from '@wordpress/element';
|
||||
import PropTypes from 'prop-types';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -23,16 +22,14 @@ const noop = () => {};
|
|||
* @param {Object} props Component props.
|
||||
* @param {Function} props.recordScoreCallback Function to call when the score should be recorded.
|
||||
* @param {string} props.label The label displayed in the modal.
|
||||
* @param {Function} props.createNotice Create a notice (snackbar).
|
||||
* @param {Function} props.onNoticeShownCallback Function to call when the notice is shown.
|
||||
* @param {Function} props.onNoticeDismissedCallback Function to call when the notice is dismissed.
|
||||
* @param {Function} props.onModalShownCallback Function to call when the modal is shown.
|
||||
* @param {Object} props.icon Icon (React component) to be shown on the notice.
|
||||
*/
|
||||
function CustomerEffortScoreComponent( {
|
||||
function CustomerEffortScore( {
|
||||
recordScoreCallback,
|
||||
label,
|
||||
createNotice,
|
||||
onNoticeShownCallback = noop,
|
||||
onNoticeDismissedCallback = noop,
|
||||
onModalShownCallback = noop,
|
||||
|
@ -40,6 +37,7 @@ function CustomerEffortScoreComponent( {
|
|||
} ) {
|
||||
const [ shouldCreateNotice, setShouldCreateNotice ] = useState( true );
|
||||
const [ visible, setVisible ] = useState( false );
|
||||
const { createNotice } = useDispatch( 'core/notices2' );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! shouldCreateNotice ) {
|
||||
|
@ -82,7 +80,7 @@ function CustomerEffortScoreComponent( {
|
|||
);
|
||||
}
|
||||
|
||||
CustomerEffortScoreComponent.propTypes = {
|
||||
CustomerEffortScore.propTypes = {
|
||||
/**
|
||||
* The function to call to record the score.
|
||||
*/
|
||||
|
@ -91,10 +89,6 @@ CustomerEffortScoreComponent.propTypes = {
|
|||
* The label displayed in the modal.
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
/**
|
||||
* Create a notice (snackbar).
|
||||
*/
|
||||
createNotice: PropTypes.func.isRequired,
|
||||
/**
|
||||
* The function to call when the notice is shown.
|
||||
*/
|
||||
|
@ -113,14 +107,4 @@ CustomerEffortScoreComponent.propTypes = {
|
|||
icon: PropTypes.element,
|
||||
};
|
||||
|
||||
const CustomerEffortScore = compose(
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices2' );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
};
|
||||
} )
|
||||
)( CustomerEffortScoreComponent );
|
||||
|
||||
export { CustomerEffortScore };
|
||||
|
|
|
@ -26,15 +26,19 @@ import { __ } from '@wordpress/i18n';
|
|||
* @param {Object} props Component props.
|
||||
* @param {Function} props.recordScoreCallback Function to call when the results are sent.
|
||||
* @param {string} props.label Question to ask the customer.
|
||||
* @param {string} props.defaultScore Default score.
|
||||
* @param {Function} props.onCloseModal Callback for when user closes modal by clicking cancel.
|
||||
*/
|
||||
function CustomerFeedbackModal( {
|
||||
recordScoreCallback,
|
||||
label,
|
||||
defaultScore = NaN,
|
||||
onCloseModal,
|
||||
}: {
|
||||
recordScoreCallback: ( score: number, comments: string ) => void;
|
||||
label: string;
|
||||
defaultScore?: number;
|
||||
onCloseModal?: () => void;
|
||||
} ): JSX.Element | null {
|
||||
const options = [
|
||||
{
|
||||
|
@ -64,7 +68,12 @@ function CustomerFeedbackModal( {
|
|||
const [ showNoScoreMessage, setShowNoScoreMessage ] = useState( false );
|
||||
const [ isOpen, setOpen ] = useState( true );
|
||||
|
||||
const closeModal = () => setOpen( false );
|
||||
const closeModal = () => {
|
||||
setOpen( false );
|
||||
if ( onCloseModal ) {
|
||||
onCloseModal();
|
||||
}
|
||||
};
|
||||
|
||||
const onRadioControlChange = ( value: string ) => {
|
||||
const valueAsInt = parseInt( value, 10 );
|
||||
|
@ -113,7 +122,7 @@ function CustomerFeedbackModal( {
|
|||
{ ( score === 1 || score === 2 ) && (
|
||||
<div className="woocommerce-customer-effort-score__comments">
|
||||
<TextareaControl
|
||||
label={ __( 'Comments (Optional)', 'woocommerce' ) }
|
||||
label={ __( 'Comments (optional)', 'woocommerce' ) }
|
||||
help={ __(
|
||||
'Your feedback will go to the WooCommerce development team',
|
||||
'woocommerce'
|
||||
|
@ -154,7 +163,8 @@ function CustomerFeedbackModal( {
|
|||
CustomerFeedbackModal.propTypes = {
|
||||
recordScoreCallback: PropTypes.func.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
score: PropTypes.number,
|
||||
defaultScore: PropTypes.number,
|
||||
onCloseModal: PropTypes.func,
|
||||
};
|
||||
|
||||
export { CustomerFeedbackModal };
|
||||
|
|
|
@ -7,7 +7,7 @@ import { createElement } from '@wordpress/element';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import CustomerFeedbackModal from '../index';
|
||||
import { CustomerFeedbackModal } from '../index';
|
||||
|
||||
const mockRecordScoreCallback = jest.fn();
|
||||
|
||||
|
@ -59,7 +59,7 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
await screen.findByRole( 'dialog' );
|
||||
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (Optional)' )
|
||||
screen.queryByLabelText( 'Comments (optional)' )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
|
@ -80,7 +80,7 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
fireEvent.click( screen.getByLabelText( labelText ) );
|
||||
|
||||
// Wait for comments field to show.
|
||||
await screen.findByLabelText( 'Comments (Optional)' );
|
||||
await screen.findByLabelText( 'Comments (optional)' );
|
||||
|
||||
// Select neutral score.
|
||||
fireEvent.click( screen.getByLabelText( 'Neutral' ) );
|
||||
|
@ -88,7 +88,7 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
// Wait for comments field to hide.
|
||||
await waitFor( () => {
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (Optional)' )
|
||||
screen.queryByLabelText( 'Comments (optional)' )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { __ } from '@wordpress/i18n';
|
|||
type CustomerFeedbackSimpleProps = {
|
||||
recordScoreCallback: ( score: number ) => void;
|
||||
label: string;
|
||||
feedbackScore?: number;
|
||||
showFeedback?: boolean;
|
||||
};
|
||||
|
||||
|
@ -32,12 +33,14 @@ type CustomerFeedbackSimpleProps = {
|
|||
* @param {Object} props Component props.
|
||||
* @param {Function} props.recordScoreCallback Function to call when the results are sent.
|
||||
* @param {string} props.label Question to ask the customer.
|
||||
* @param {string} props.showFeedback To show feedback message.
|
||||
* @param {number} props.feedbackScore Feedback score.
|
||||
* @param {boolean} props.showFeedback Show feedback.
|
||||
*/
|
||||
const CustomerFeedbackSimple: React.FC< CustomerFeedbackSimpleProps > = ( {
|
||||
recordScoreCallback,
|
||||
label,
|
||||
showFeedback = false,
|
||||
feedbackScore = NaN,
|
||||
showFeedback,
|
||||
} ) => {
|
||||
const options = [
|
||||
{
|
||||
|
@ -67,7 +70,13 @@ const CustomerFeedbackSimple: React.FC< CustomerFeedbackSimpleProps > = ( {
|
|||
},
|
||||
];
|
||||
|
||||
const [ score, setScore ] = useState( NaN );
|
||||
const [ score, setScore ] = useState( feedbackScore || NaN );
|
||||
|
||||
useEffect( () => {
|
||||
if ( feedbackScore !== score ) {
|
||||
setScore( feedbackScore );
|
||||
}
|
||||
}, [ feedbackScore ] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! isNaN( score ) ) {
|
||||
|
@ -77,7 +86,7 @@ const CustomerFeedbackSimple: React.FC< CustomerFeedbackSimpleProps > = ( {
|
|||
|
||||
return (
|
||||
<div className="customer-feedback-simple__container">
|
||||
{ isNaN( score ) && ! showFeedback ? (
|
||||
{ ! showFeedback ? (
|
||||
<Fragment>
|
||||
<Text
|
||||
variant="subtitle.small"
|
||||
|
@ -124,7 +133,6 @@ const CustomerFeedbackSimple: React.FC< CustomerFeedbackSimpleProps > = ( {
|
|||
CustomerFeedbackSimple.propTypes = {
|
||||
recordScoreCallback: PropTypes.func.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
showFeedback: PropTypes.bool,
|
||||
};
|
||||
|
||||
export { CustomerFeedbackSimple };
|
||||
|
|
|
@ -1,96 +1,27 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { createElement } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import CustomerFeedbackModal from '../index';
|
||||
import { CustomerFeedbackSimple } from '../index';
|
||||
|
||||
const mockRecordScoreCallback = jest.fn();
|
||||
|
||||
describe( 'CustomerFeedbackModal', () => {
|
||||
it( 'should close modal when cancel button pressed', async () => {
|
||||
describe( 'CustomerFeedbackSimple', () => {
|
||||
it( 'should trigger recordScoreCallback when item is selected', () => {
|
||||
render(
|
||||
<CustomerFeedbackModal
|
||||
<CustomerFeedbackSimple
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
/>
|
||||
);
|
||||
|
||||
// Wait for the modal to render.
|
||||
await screen.findByRole( 'dialog' );
|
||||
// Select the option.
|
||||
fireEvent.click( screen.getAllByText( '🙂' )[ 0 ] );
|
||||
|
||||
// Press cancel button.
|
||||
fireEvent.click( screen.getByRole( 'button', { name: /cancel/i } ) );
|
||||
|
||||
expect( screen.queryByRole( 'dialog' ) ).not.toBeInTheDocument();
|
||||
expect( mockRecordScoreCallback ).toHaveBeenCalledWith( 4 );
|
||||
} );
|
||||
|
||||
it( 'should halt with an error when submitting without a score', async () => {
|
||||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
/>
|
||||
);
|
||||
|
||||
await screen.findByRole( 'dialog' ); // Wait for the modal to render.
|
||||
|
||||
fireEvent.click( screen.getByRole( 'button', { name: /send/i } ) ); // Press send button.
|
||||
|
||||
// Wait for error message.
|
||||
await screen.findByRole( 'alert' );
|
||||
|
||||
expect( screen.getByRole( 'dialog' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should disable the comments field initially', async () => {
|
||||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
/>
|
||||
);
|
||||
|
||||
// Wait for the modal to render.
|
||||
await screen.findByRole( 'dialog' );
|
||||
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (Optional)' )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it.each( [ 'Very difficult', 'Somewhat difficult' ] )(
|
||||
'should toggle the comments field when %s is selected',
|
||||
async ( labelText ) => {
|
||||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
/>
|
||||
);
|
||||
|
||||
// Wait for the modal to render.
|
||||
await screen.findByRole( 'dialog' );
|
||||
|
||||
// Select the option.
|
||||
fireEvent.click( screen.getByLabelText( labelText ) );
|
||||
|
||||
// Wait for comments field to show.
|
||||
await screen.findByLabelText( 'Comments (Optional)' );
|
||||
|
||||
// Select neutral score.
|
||||
fireEvent.click( screen.getByLabelText( 'Neutral' ) );
|
||||
|
||||
// Wait for comments field to hide.
|
||||
await waitFor( () => {
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (Optional)' )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*/
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { createElement } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -11,14 +12,28 @@ import { CustomerEffortScore } from '../customer-effort-score';
|
|||
|
||||
const noop = () => {};
|
||||
|
||||
jest.mock( '@wordpress/data', () => {
|
||||
const originalModule = jest.requireActual( '@wordpress/data' );
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
useDispatch: jest.fn().mockReturnValue( {
|
||||
createNotice: jest.fn(),
|
||||
} ),
|
||||
};
|
||||
} );
|
||||
|
||||
describe( 'CustomerEffortScore', () => {
|
||||
it( 'should call createNotice with appropriate parameters', async () => {
|
||||
const mockCreateNotice = jest.fn();
|
||||
useDispatch.mockReturnValue( {
|
||||
createNotice: mockCreateNotice,
|
||||
} );
|
||||
const icon = <span>icon</span>;
|
||||
|
||||
render(
|
||||
<CustomerEffortScore
|
||||
createNotice={ mockCreateNotice }
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
onNoticeDismissedCallback={ noop }
|
||||
|
@ -41,6 +56,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
|
||||
it( 'should not call createNotice on rerender', async () => {
|
||||
const mockCreateNotice = jest.fn();
|
||||
useDispatch.mockReturnValue( {
|
||||
createNotice: mockCreateNotice,
|
||||
} );
|
||||
|
||||
const { rerender } = render(
|
||||
<CustomerEffortScore
|
||||
|
@ -53,7 +71,6 @@ describe( 'CustomerEffortScore', () => {
|
|||
// Simulate rerender by changing label prop.
|
||||
rerender(
|
||||
<CustomerEffortScore
|
||||
createNotice={ mockCreateNotice }
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label2' }
|
||||
/>
|
||||
|
@ -65,7 +82,6 @@ describe( 'CustomerEffortScore', () => {
|
|||
it( 'should not show dialog if no action is taken', async () => {
|
||||
render(
|
||||
<CustomerEffortScore
|
||||
createNotice={ noop }
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
/>
|
||||
|
@ -91,10 +107,12 @@ describe( 'CustomerEffortScore', () => {
|
|||
// Modal shown callback should also be called.
|
||||
expect( mockOnModalShownCallback ).toHaveBeenCalled();
|
||||
};
|
||||
useDispatch.mockReturnValue( {
|
||||
createNotice,
|
||||
} );
|
||||
|
||||
render(
|
||||
<CustomerEffortScore
|
||||
createNotice={ createNotice }
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
onModalShownCallback={ mockOnModalShownCallback }
|
||||
|
|
|
@ -34,6 +34,8 @@ const TYPES = {
|
|||
ACTION_TASK_REQUEST: 'ACTION_TASK_REQUEST',
|
||||
ACTION_TASK_SUCCESS: 'ACTION_TASK_SUCCESS',
|
||||
VISITED_TASK: 'VISITED_TASK',
|
||||
KEEP_COMPLETED_TASKS_REQUEST: 'KEEP_COMPLETED_TASKS_REQUEST',
|
||||
KEEP_COMPLETED_TASKS_SUCCESS: 'KEEP_COMPLETED_TASKS_SUCCESS',
|
||||
};
|
||||
|
||||
export default TYPES;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
import { controls } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -9,6 +10,7 @@ import { apiFetch } from '@wordpress/data-controls';
|
|||
import TYPES from './action-types';
|
||||
import { WC_ADMIN_NAMESPACE } from '../constants';
|
||||
import { DeprecatedTasks } from './deprecated-tasks';
|
||||
import { STORE_NAME as OPTIONS_STORE_NAME } from '../options/constants';
|
||||
|
||||
export function getFreeExtensionsError( error ) {
|
||||
return {
|
||||
|
@ -203,6 +205,14 @@ export function optimisticallyCompleteTaskRequest( taskId ) {
|
|||
};
|
||||
}
|
||||
|
||||
export function keepCompletedTaskListSuccess( taskListId, keepCompletedList ) {
|
||||
return {
|
||||
type: TYPES.KEEP_COMPLETED_TASKS_SUCCESS,
|
||||
taskListId,
|
||||
keepCompletedTaskList: keepCompletedList,
|
||||
};
|
||||
}
|
||||
|
||||
export function visitedTask( taskId ) {
|
||||
return {
|
||||
type: TYPES.VISITED_TASK,
|
||||
|
@ -260,6 +270,20 @@ export function getProductTypesError( error ) {
|
|||
};
|
||||
}
|
||||
|
||||
export function* keepCompletedTaskList( taskListId ) {
|
||||
const updateOptionsParams = {
|
||||
woocommerce_task_list_keep_completed: 'yes',
|
||||
};
|
||||
const response = yield controls.dispatch(
|
||||
OPTIONS_STORE_NAME,
|
||||
'updateOptions',
|
||||
updateOptionsParams
|
||||
);
|
||||
if ( response && response.success ) {
|
||||
yield keepCompletedTaskListSuccess( taskListId, 'yes' );
|
||||
}
|
||||
}
|
||||
|
||||
export function* updateProfileItems( items ) {
|
||||
yield setIsRequesting( 'updateProfileItems', true );
|
||||
yield setError( 'updateProfileItems', null );
|
||||
|
|
|
@ -72,6 +72,7 @@ const onboarding = (
|
|||
taskListId,
|
||||
taskList,
|
||||
taskLists,
|
||||
keepCompletedTaskList,
|
||||
}
|
||||
) => {
|
||||
switch ( type ) {
|
||||
|
@ -372,6 +373,17 @@ const onboarding = (
|
|||
[ taskListId ]: taskList,
|
||||
},
|
||||
};
|
||||
case TYPES.KEEP_COMPLETED_TASKS_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
taskLists: {
|
||||
...state.taskLists,
|
||||
[ taskListId ]: {
|
||||
...state.taskLists[ taskListId ],
|
||||
keepCompletedTaskList,
|
||||
},
|
||||
},
|
||||
};
|
||||
case TYPES.OPTIMISTICALLY_COMPLETE_TASK_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
.wooocommerce-task-card__header .wooocommerce-task-card__header-subtitle {
|
||||
color: $gray-700;
|
||||
margin-bottom: $gap-large;
|
||||
color: $gray-700;
|
||||
margin-bottom: $gap-large;
|
||||
}
|
||||
|
||||
.customer-feedback-simple__container {
|
||||
height: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.woocommerce-task-card__header-menu {
|
||||
position: absolute;
|
||||
right: $gap-large;
|
||||
top: $gap;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
|
@ -52,8 +52,8 @@ export const TaskListCompletedHeaderWithCES: React.FC< TaskListCompletedHeaderPr
|
|||
} ) => {
|
||||
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
|
||||
const [ showCesModal, setShowCesModal ] = useState( false );
|
||||
const [ submittedScore, setSubmittedScore ] = useState( false );
|
||||
const [ score, setScore ] = useState( NaN );
|
||||
const [ showFeedback, setShowFeedback ] = useState( false );
|
||||
const { storeAgeInWeeks, cesShownForActions } = useSelect( ( select ) => {
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
|
||||
|
@ -69,19 +69,26 @@ export const TaskListCompletedHeaderWithCES: React.FC< TaskListCompletedHeaderPr
|
|||
return {};
|
||||
} );
|
||||
|
||||
const submitScore = ( recordedScore: number, comments?: string ) => {
|
||||
recordEvent( 'ces_feedback', {
|
||||
action: CES_ACTION,
|
||||
score: recordedScore,
|
||||
comments: comments || '',
|
||||
store_age: storeAgeInWeeks,
|
||||
} );
|
||||
updateOptions( {
|
||||
[ SHOWN_FOR_ACTIONS_OPTION_NAME ]: [
|
||||
CES_ACTION,
|
||||
...cesShownForActions,
|
||||
],
|
||||
} );
|
||||
setSubmittedScore( true );
|
||||
};
|
||||
|
||||
const recordScore = ( recordedScore: number ) => {
|
||||
if ( recordedScore > 2 ) {
|
||||
recordEvent( 'ces_feedback', {
|
||||
action: CES_ACTION,
|
||||
score: recordedScore,
|
||||
store_age: storeAgeInWeeks,
|
||||
} );
|
||||
updateOptions( {
|
||||
[ SHOWN_FOR_ACTIONS_OPTION_NAME ]: [
|
||||
CES_ACTION,
|
||||
...cesShownForActions,
|
||||
],
|
||||
} );
|
||||
setScore( recordedScore );
|
||||
submitScore( recordedScore );
|
||||
} else {
|
||||
setScore( recordedScore );
|
||||
setShowCesModal( true );
|
||||
|
@ -94,19 +101,7 @@ export const TaskListCompletedHeaderWithCES: React.FC< TaskListCompletedHeaderPr
|
|||
|
||||
const recordModalScore = ( recordedScore: number, comments: string ) => {
|
||||
setShowCesModal( false );
|
||||
recordEvent( 'ces_feedback', {
|
||||
action: 'store_setup',
|
||||
score: recordedScore,
|
||||
comments: comments || '',
|
||||
store_age: storeAgeInWeeks,
|
||||
} );
|
||||
updateOptions( {
|
||||
[ SHOWN_FOR_ACTIONS_OPTION_NAME ]: [
|
||||
CES_ACTION,
|
||||
...cesShownForActions,
|
||||
],
|
||||
} );
|
||||
setShowFeedback( true );
|
||||
submitScore( recordedScore, comments );
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -178,8 +173,9 @@ export const TaskListCompletedHeaderWithCES: React.FC< TaskListCompletedHeaderPr
|
|||
'How was your experience?',
|
||||
'woocommerce'
|
||||
) }
|
||||
showFeedback={ submittedScore }
|
||||
recordScoreCallback={ recordScore }
|
||||
showFeedback={ showFeedback }
|
||||
feedbackScore={ score }
|
||||
/>
|
||||
) }
|
||||
</Card>
|
||||
|
@ -189,6 +185,10 @@ export const TaskListCompletedHeaderWithCES: React.FC< TaskListCompletedHeaderPr
|
|||
label={ __( 'How was your experience?', 'woocommerce' ) }
|
||||
defaultScore={ score }
|
||||
recordScoreCallback={ recordModalScore }
|
||||
onCloseModal={ () => {
|
||||
setScore( NaN );
|
||||
setShowCesModal( false );
|
||||
} }
|
||||
/>
|
||||
) : null }
|
||||
</>
|
||||
|
|
|
@ -24,6 +24,7 @@ import { TaskListProps } from '~/tasks/task-list';
|
|||
import { ProgressHeader } from '~/task-lists/progress-header';
|
||||
import { SectionPanelTitle } from './section-panel-title';
|
||||
import { TaskListItem } from './task-list-item';
|
||||
import { TaskListCompletedHeaderWithCES } from './completed-header-with-ces';
|
||||
|
||||
type PanelBodyProps = Omit< PanelBody.Props, 'title' | 'onToggle' > & {
|
||||
title: string | React.ReactNode | undefined;
|
||||
|
@ -40,6 +41,8 @@ export const SectionedTaskList: React.FC< TaskListProps > = ( {
|
|||
isComplete,
|
||||
sections,
|
||||
displayProgressHeader,
|
||||
cesHeader = true,
|
||||
showCESFeedback = false,
|
||||
} ) => {
|
||||
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
|
||||
const { profileItems } = useSelect( ( select ) => {
|
||||
|
@ -115,14 +118,22 @@ export const SectionedTaskList: React.FC< TaskListProps > = ( {
|
|||
return <div className="woocommerce-task-dashboard__container"></div>;
|
||||
}
|
||||
|
||||
if ( isComplete && ! keepCompletedTaskList ) {
|
||||
if ( isComplete && keepCompletedTaskList !== 'yes' ) {
|
||||
return (
|
||||
<>
|
||||
<TaskListCompleted
|
||||
hideTasks={ hideTasks }
|
||||
keepTasks={ keepTasks }
|
||||
twoColumns={ false }
|
||||
/>
|
||||
{ cesHeader ? (
|
||||
<TaskListCompletedHeaderWithCES
|
||||
hideTasks={ hideTasks }
|
||||
keepTasks={ keepTasks }
|
||||
showCES={ showCESFeedback }
|
||||
/>
|
||||
) : (
|
||||
<TaskListCompleted
|
||||
hideTasks={ hideTasks }
|
||||
keepTasks={ keepTasks }
|
||||
twoColumns={ false }
|
||||
/>
|
||||
) }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,11 @@ export const TaskList: React.FC< TaskListProps > = ( {
|
|||
profileItems: getProfileItems(),
|
||||
};
|
||||
} );
|
||||
const { hideTaskList, visitedTask } = useDispatch( ONBOARDING_STORE_NAME );
|
||||
const {
|
||||
hideTaskList,
|
||||
visitedTask,
|
||||
keepCompletedTaskList: keepCompletedTasks,
|
||||
} = useDispatch( ONBOARDING_STORE_NAME );
|
||||
const userPreferences = useUserPreferences();
|
||||
const [ headerData, setHeaderData ] = useState< {
|
||||
task?: TaskType;
|
||||
|
@ -115,13 +119,14 @@ export const TaskList: React.FC< TaskListProps > = ( {
|
|||
};
|
||||
|
||||
const keepTasks = () => {
|
||||
const updateOptionsParams = {
|
||||
woocommerce_task_list_keep_completed: 'yes',
|
||||
};
|
||||
keepCompletedTasks( id );
|
||||
// const updateOptionsParams = {
|
||||
// woocommerce_task_list_keep_completed: 'yes',
|
||||
// };
|
||||
|
||||
updateOptions( {
|
||||
...updateOptionsParams,
|
||||
} );
|
||||
// updateOptions( {
|
||||
// ...updateOptionsParams,
|
||||
// } );
|
||||
};
|
||||
|
||||
const renderMenu = () => {
|
||||
|
|
Loading…
Reference in New Issue