woocommerce/plugins/woocommerce-admin/client/task-lists/setup-task-list/components/task-list-completed-header.tsx

266 lines
6.9 KiB
TypeScript

/**
* External dependencies
*/
import clsx from 'clsx';
import { useEffect, useState } from '@wordpress/element';
import { EllipsisMenu } from '@woocommerce/components';
import { recordEvent } from '@woocommerce/tracks';
import { useDispatch, useSelect } from '@wordpress/data';
import { OPTIONS_STORE_NAME, WCDataSelector, WEEK } from '@woocommerce/data';
import { Button, Card, CardHeader } from '@wordpress/components';
import { Text } from '@woocommerce/experimental';
import {
ADMIN_INSTALL_TIMESTAMP_OPTION_NAME,
ALLOW_TRACKING_OPTION_NAME,
CustomerFeedbackModal,
CustomerFeedbackSimple,
SHOWN_FOR_ACTIONS_OPTION_NAME,
} from '@woocommerce/customer-effort-score';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import './task-list-completed-header.scss';
import HeaderImage from '../assets/completed-celebration-header.svg';
type TaskListCompletedHeaderProps = {
hideTasks: () => void;
keepTasks: () => void;
customerEffortScore: boolean;
};
const CUSTOMER_EFFORT_SCORE_ACTION = 'store_setup';
function getStoreAgeInWeeks( adminInstallTimestamp: number ) {
if ( adminInstallTimestamp === 0 ) {
return null;
}
// Date.now() is ms since Unix epoch, adminInstallTimestamp is in
// seconds since Unix epoch.
const storeAgeInMs = Date.now() - adminInstallTimestamp * 1000;
const storeAgeInWeeks = Math.round( storeAgeInMs / WEEK );
return storeAgeInWeeks;
}
export const TaskListCompletedHeader: React.FC<
TaskListCompletedHeaderProps
> = ( { hideTasks, keepTasks, customerEffortScore } ) => {
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
const [ showCesModal, setShowCesModal ] = useState( false );
const [ hasSubmittedScore, setHasSubmittedScore ] = useState( false );
const [ score, setScore ] = useState( NaN );
const [ hideCustomerEffortScore, setHideCustomerEffortScore ] =
useState( false );
const { storeAgeInWeeks, cesShownForActions, canShowCustomerEffortScore } =
useSelect( ( select: WCDataSelector ) => {
const { getOption, hasFinishedResolution } =
select( OPTIONS_STORE_NAME );
if ( customerEffortScore ) {
const allowTracking = getOption( ALLOW_TRACKING_OPTION_NAME );
const adminInstallTimestamp: number =
getOption( ADMIN_INSTALL_TIMESTAMP_OPTION_NAME ) || 0;
const cesActions = getOption< string[] >(
SHOWN_FOR_ACTIONS_OPTION_NAME
);
const loadingOptions =
! hasFinishedResolution( 'getOption', [
SHOWN_FOR_ACTIONS_OPTION_NAME,
] ) ||
! hasFinishedResolution( 'getOption', [
ADMIN_INSTALL_TIMESTAMP_OPTION_NAME,
] );
return {
storeAgeInWeeks: getStoreAgeInWeeks(
adminInstallTimestamp
),
cesShownForActions: cesActions,
canShowCustomerEffortScore:
! loadingOptions &&
allowTracking &&
! ( cesActions || [] ).includes( 'store_setup' ),
loading: loadingOptions,
};
}
return {};
} );
useEffect( () => {
if ( hasSubmittedScore ) {
setTimeout( () => {
setHideCustomerEffortScore( true );
}, 1200 );
}
}, [ hasSubmittedScore ] );
const submitScore = ( {
firstScore,
secondScore,
comments,
}: {
firstScore: number;
secondScore?: number;
comments?: string;
} ) => {
recordEvent( 'ces_feedback', {
action: CUSTOMER_EFFORT_SCORE_ACTION,
score: firstScore,
score_second_question: secondScore ?? null,
score_combined: firstScore + ( secondScore ?? 0 ),
comments: comments || '',
store_age: storeAgeInWeeks,
} );
updateOptions( {
[ SHOWN_FOR_ACTIONS_OPTION_NAME ]: [
CUSTOMER_EFFORT_SCORE_ACTION,
...( cesShownForActions || [] ),
],
} );
setHasSubmittedScore( true );
};
const recordScore = ( recordedScore: number ) => {
if ( recordedScore > 2 ) {
setScore( recordedScore );
submitScore( { firstScore: recordedScore } );
} else {
setScore( recordedScore );
setShowCesModal( true );
recordEvent( 'ces_view', {
action: CUSTOMER_EFFORT_SCORE_ACTION,
store_age: storeAgeInWeeks,
} );
}
};
const recordModalScore = (
firstScore: number,
secondScore: number,
comments: string
) => {
setShowCesModal( false );
submitScore( { firstScore, secondScore, comments } );
};
return (
<>
<div
className={ clsx(
'woocommerce-task-dashboard__container setup-task-list'
) }
>
<Card
size="large"
className="woocommerce-task-card woocommerce-homescreen-card completed"
>
<CardHeader size="medium">
<div className="woocommerce-task-card__header">
<img
src={ HeaderImage }
alt="Completed"
className="woocommerce-task-card__finished-header-image"
/>
<Text size="title" as="h2" lineHeight={ 1.4 }>
{ __(
"You've completed store setup",
'woocommerce'
) }
</Text>
<Text
variant="subtitle.small"
as="p"
size="13"
lineHeight="16px"
className="woocommerce-task-card__header-subtitle"
>
{ __(
'Congratulations! Take a moment to celebrate and look out for the first sale.',
'woocommerce'
) }
</Text>
<div className="woocommerce-task-card__header-menu">
<EllipsisMenu
label={ __(
'Task List Options',
'woocommerce'
) }
renderContent={ () => (
<div className="woocommerce-task-card__section-controls">
<Button
onClick={ () => keepTasks() }
>
{ __(
'Show setup task list',
'woocommerce'
) }
</Button>
<Button
onClick={ () => hideTasks() }
>
{ __(
'Hide this',
'woocommerce'
) }
</Button>
</div>
) }
/>
</div>
</div>
</CardHeader>
{ canShowCustomerEffortScore &&
! hideCustomerEffortScore &&
! hasSubmittedScore && (
<CustomerFeedbackSimple
label={ __(
'How was your experience?',
'woocommerce'
) }
onSelect={ recordScore }
/>
) }
{ hasSubmittedScore && ! hideCustomerEffortScore && (
<div className="woocommerce-task-card__header-ces-feedback">
<Text
variant="subtitle.small"
as="p"
size="13"
lineHeight="16px"
>
🙌{ ' ' }
{ __(
'We appreciate your feedback!',
'woocommerce'
) }
</Text>
</div>
) }
</Card>
</div>
{ showCesModal ? (
<CustomerFeedbackModal
title={ __( 'How was your experience?', 'woocommerce' ) }
firstQuestion={ __(
'The store setup is easy to complete.',
'woocommerce'
) }
secondQuestion={ __(
'The store setup process meets my needs.',
'woocommerce'
) }
defaultScore={ score }
recordScoreCallback={ recordModalScore }
onCloseModal={ () => {
setScore( NaN );
setShowCesModal( false );
} }
/>
) : null }
</>
);
};