/** * 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 ); }