/**
* WordPress dependencies
*/
import { Button } from '@safe-wordpress/components';
import { useSelect } from '@safe-wordpress/data';
import { createInterpolateElement } from '@safe-wordpress/element';
import { _x, _nx, sprintf } from '@safe-wordpress/i18n';
/**
* External dependencies
*/
import { clsx } from 'clsx';
import { store as NAB_EXPERIMENTS } from '@nab/experiments';
import { formatNumber } from '@nab/i18n';
import { getLetter } from '@nab/utils';
import type { RunningExperimentSummary } from '@nab/types';
/**
* Internal dependencies
*/
import './style.scss';
import { useResults } from '../../hooks';
import type { Results } from '../../hooks';
type RunningExperimentProps = {
readonly experiment: RunningExperimentSummary;
};
export function RunningExperiment( {
experiment,
}: RunningExperimentProps ): JSX.Element | null {
const experimentType = useSelect(
( select ) =>
select( NAB_EXPERIMENTS ).getExperimentType( experiment.type ),
[ experiment.type ]
);
const results = useResults( experiment.id );
if ( ! experimentType || 'error' === results.status ) {
return null;
}
const conversionRate =
'ready' === results.status && results.views > 0
? ( results.conversions / results.views ) * 100
: 0;
const Icon = experimentType.icon;
return (
{ experiment.name }
{ formatRelativeDate( experiment.startedAt ) }
{ createInterpolateElement(
sprintf(
/* translators: %s: Number of views. */
_x( '%s Views', 'text', 'nelio-ab-testing' ),
`${
'ready' === results.status
? formatNumber( results.views )
: '█'
}`
),
{
strong: (
),
}
) }
{ createInterpolateElement(
sprintf(
/* translators: %s: Number of conversions. */
_x( '%s Convs.', 'text', 'nelio-ab-testing' ),
`${
'ready' === results.status
? formatNumber( results.conversions )
: '█'
}`
),
{
strong: (
),
}
) }
{ createInterpolateElement(
sprintf(
/* translators: %s: Conversion rate. */
_x( '%s Conv. rate', 'text', 'nelio-ab-testing' ),
`${
'ready' === results.status
? conversionRate.toFixed( 1 ) + '%'
: '█'
}`
),
{
strong: (
),
}
) }
{ formatImprovement( results ) }
{ getLeaderLabel( results, experiment.alternativeCount ) }
);
}
function formatRelativeDate( value: string ): string {
const date = new Date( value );
const days = Math.max(
0,
Math.round( ( Date.now() - date.getTime() ) / 86400000 )
);
if ( ! days ) {
return _x( 'Started today', 'text', 'nelio-ab-testing' );
}
if ( 1 === days ) {
return _x( 'Started yesterday', 'text', 'nelio-ab-testing' );
}
if ( days < 30 ) {
return sprintf(
/* translators: %d: Number of days. */
_nx(
'Started %d day ago',
'Started %d days ago',
days,
'text',
'nelio-ab-testing'
),
days
);
}
if ( days < 90 ) {
const weeks = Math.round( days / 7 );
return sprintf(
/* translators: %d: Number of weeks. */
_nx(
'Started %d week ago',
'Started %d weeks ago',
weeks,
'text',
'nelio-ab-testing'
),
weeks
);
}
const months = Math.round( days / 30 );
return sprintf(
/* translators: %d: Number of months. */
_nx(
'Started %d month ago',
'Started %d months ago',
months,
'text',
'nelio-ab-testing'
),
months
);
}
function formatImprovement( results: Results ): string {
if ( 'ready' !== results.status ) {
return '█';
}
if ( undefined === results.currentLeader ) {
return '–';
}
const value = Math.abs( results.improvement );
const sign = 0 === results.currentLeader ? '↓' : '↑';
return `${ sign }${ value.toFixed( 1 ) }%`;
}
function getLeaderLabel( results: Results, alternativeCount: number ) {
if ( 'ready' !== results.status ) {
return '';
}
if ( undefined === results.currentLeader ) {
return _x( 'No clear leader yet', 'text', 'nelio-ab-testing' );
}
if ( ! results.currentLeader ) {
return alternativeCount > 2
? _x( 'All variants behind', 'text', 'nelio-ab-testing' )
: _x( 'Variant B behind', 'text', 'nelio-ab-testing' );
}
const letter = getLetter( results.currentLeader );
return sprintf(
/* translators: %s: Variant letter. */
_x( 'Variant %s ahead', 'text', 'nelio-ab-testing' ),
letter
);
}