/** * WordPress dependencies */ import { Button, ExternalLink, Tooltip } from '@safe-wordpress/components'; import { useDispatch, useSelect } from '@safe-wordpress/data'; import { useState } from '@safe-wordpress/element'; import { _x, sprintf } from '@safe-wordpress/i18n'; import { addQueryArgs } from '@safe-wordpress/url'; /** * External dependencies */ import clsx from 'clsx'; import { isFunction, noop } from 'lodash'; import { ConfirmationDialog, FancyIcon, Preview } from '@nab/components'; import { store as NAB_DATA, usePluginSetting } from '@nab/data'; import { store as NAB_EXPERIMENTS } from '@nab/experiments'; import { getLetter, isExperimentTooOldToHaveHeatmaps } from '@nab/utils'; import type { Alternative, AlternativeTrackingData, ECommercePlugin, Experiment, ExperimentId, GoalId, } from '@nab/types'; /** * Internal dependencies */ import { getAlternativeName, getMoneyLabel, getNumberLabel, getPercentageLabel, getImprovementLabel, } from '../utils'; export type AlternativeContainerProps = { readonly index: number; readonly alternative: Alternative; readonly areResultsUnique: boolean; readonly isPublicView: boolean; readonly ecommerce?: ECommercePlugin; readonly experimentId: ExperimentId; readonly experimentStatus: Experiment[ 'status' ]; readonly goal: GoalId; readonly result?: AlternativeTrackingData; readonly controlRevenue?: number; readonly controlArpc?: number; readonly isWinner?: boolean; readonly pageViews?: number; }; export const AlternativeContainer = ( props: AlternativeContainerProps ): JSX.Element => { const [ isApplyDialogOpen, openApplyDialog ] = useState( false ); const minSampleSize = usePluginSetting( 'minSampleSize' ); const { homeUrl, alternativeBeingApplied, endDate, supportsAlternativeApplication, supportsAlternativePreviewDialog, } = useAttributes( props ) || {}; const { applyAlternative, viewAlternative } = useAlternativeActions( props ); const { index, experimentId, alternative: { isLastApplied, attributes: { name }, links: { heatmap, preview }, }, areResultsUnique: isUnique, isPublicView, result: { visits: allVisits, conversions: allConversions = {}, conversionRates: allConvRates = {}, values: allValues = {}, improvementFactors: allImprovFactors = {}, uniqueVisits: uniqVisits, uniqueConversions: uniqConversions = {}, uniqueConversionRates: uniqConvRates = {}, uniqueValues: uniqValues = {}, uniqueImprovementFactors: uniqImprovFactors = {}, } = {}, ecommerce, experimentStatus, goal, controlRevenue, controlArpc, isWinner, pageViews = 0, } = props; const visits = isUnique ? uniqVisits : allVisits; const conversions = isUnique ? uniqConversions : allConversions; const conversionRates = isUnique ? uniqConvRates : allConvRates; const revenues = isUnique ? uniqValues : allValues; const improvementFactors = isUnique ? uniqImprovFactors : allImprovFactors; const revenue = revenues[ goal ] || 0; const revenuePerView = revenue / ( visits || 1 ); const revenueImprovement = ! controlRevenue ? 0 : Math.round( ( ( revenue - controlRevenue ) / controlRevenue ) * 1000 ) / 10; const conv = conversions[ goal ] ?? 0; const arpc = conversions[ goal ] ? revenue / conv : 0; const arpcImprovement = ! controlArpc ? 0 : Math.round( ( ( arpc - controlArpc ) / controlArpc ) * 1000 ) / 10; const screenshot = preview; const alternativeName = getAlternativeName( index, name ); const showHeatmapButton = !! heatmap && ! isExperimentTooOldToHaveHeatmaps( endDate ); const showApplyButton = experimentStatus === 'finished' && !! supportsAlternativeApplication && !! applyAlternative; const showPreviewInDialog = !! supportsAlternativePreviewDialog; const isClearWinner = isWinner && minSampleSize <= pageViews; const heatmapResultPageUrl = isPublicView ? addQueryArgs( homeUrl, { 'nab-result': true, experiment: experimentId, heatmap: index, preview: '', } ) : addQueryArgs( 'admin.php', { page: 'nelio-ab-testing-experiment-view', experiment: experimentId, heatmap: index, } ); return (