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

266 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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 }>
{ __(
'Youve 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 }
</>
);
};