import React, { useMemo, useState } from 'react'
import {
Box,
Button,
Grid,
GridItem,
Heading,
NumberInput,
NumberInputInput,
Stat,
StatHelpText,
StatLabel,
StatValueText,
Text,
VStack,
} from '@chakra-ui/react'
import type { ABTestMetrics } from '../../__data__/types'
import { compareVariants } from '../../utils/analytics'
interface VariantFormState {
submissionRate: number
completionRate: number
retryRate: number
timeToFirstSubmission: number
sessionDuration: number
satisfactionScore?: number
}
const createVariantState = (): VariantFormState => ({
submissionRate: 0,
completionRate: 0,
retryRate: 0,
timeToFirstSubmission: 0,
sessionDuration: 0,
satisfactionScore: undefined,
})
const buildMetrics = (variant: 'A' | 'B', state: VariantFormState): ABTestMetrics => ({
variant,
submissionRate: state.submissionRate,
completionRate: state.completionRate,
retryRate: state.retryRate,
timeToFirstSubmission: state.timeToFirstSubmission,
sessionDuration: state.sessionDuration,
satisfactionScore: state.satisfactionScore,
})
const MetricInput = ({
label,
value,
onChange,
suffix,
}: {
label: string
value: number
onChange: (value: number) => void
suffix?: string
}) => (
{label}
onChange(Number.isNaN(val) ? 0 : val)}>
{suffix && (
{suffix}
)}
)
export const ABTestPanel = () => {
const [variantA, setVariantA] = useState(createVariantState)
const [variantB, setVariantB] = useState(createVariantState)
const [comparison, setComparison] = useState | null>(null)
const handleCompare = () => {
const metricsA = buildMetrics('A', variantA)
const metricsB = buildMetrics('B', variantB)
setComparison(compareVariants(metricsA, metricsB))
}
const hasData = useMemo(
() =>
Object.values(variantA).some((value) => value !== 0) ||
Object.values(variantB).some((value) => value !== 0),
[variantA, variantB],
)
return (
A/B тест: сравнение вариантов
Вариант A
setVariantA((prev) => ({ ...prev, submissionRate: value }))}
suffix="Процент пользователей, отправивших хотя бы одно решение"
/>
setVariantA((prev) => ({ ...prev, completionRate: value }))}
/>
setVariantA((prev) => ({ ...prev, retryRate: value }))}
/>
setVariantA((prev) => ({ ...prev, timeToFirstSubmission: value }))}
/>
setVariantA((prev) => ({ ...prev, sessionDuration: value }))}
/>
Вариант B
setVariantB((prev) => ({ ...prev, submissionRate: value }))}
/>
setVariantB((prev) => ({ ...prev, completionRate: value }))}
/>
setVariantB((prev) => ({ ...prev, retryRate: value }))}
/>
setVariantB((prev) => ({ ...prev, timeToFirstSubmission: value }))}
/>
setVariantB((prev) => ({ ...prev, sessionDuration: value }))}
/>
{comparison && (
Результат сравнения
Δ Submission Rate
{comparison.submissionRateDiff.toFixed(1)}%
Положительное значение — рост у варианта B
Δ Completion Rate
{comparison.completionRateDiff.toFixed(1)}%
Положительное значение — рост у варианта B
Победитель
Вариант {comparison.winner}
Основано на сравнении коэффициента завершения
)}
)
}