import React from "react"; import classNames from "classnames"; import { Tooltip } from '../../util/tooltip' import numberFormatter, { durationFormatter } from '../../util/number-formatter' import { METRIC_MAPPING } from './graph-util' export default class TopStats extends React.Component { renderComparison(name, comparison) { const formattedComparison = numberFormatter(Math.abs(comparison)) if (comparison > 0) { const color = name === 'Bounce rate' ? 'text-red-400' : 'text-green-500' return {formattedComparison}% } else if (comparison < 0) { const color = name === 'Bounce rate' ? 'text-green-500' : 'text-red-400' return {formattedComparison}% } else if (comparison === 0) { return 〰 0% } } topStatNumberShort(stat) { if (['visit duration', 'time on page'].includes(stat.name.toLowerCase())) { return durationFormatter(stat.value) } else if (['bounce rate', 'conversion rate'].includes(stat.name.toLowerCase())) { return stat.value + '%' } else { return numberFormatter(stat.value) } } topStatNumberLong(stat) { if (['visit duration', 'time on page'].includes(stat.name.toLowerCase())) { return durationFormatter(stat.value) } else if (['bounce rate', 'conversion rate'].includes(stat.name.toLowerCase())) { return stat.value + '%' } else { return stat.value.toLocaleString() } } topStatTooltip(stat) { let statName = stat.name.toLowerCase() statName = stat.value === 1 ? statName.slice(0, -1) : statName return (
{this.topStatNumberLong(stat)} {statName}
{this.canMetricBeGraphed(stat) &&
{this.titleFor(stat)}
}
) } titleFor(stat) { const isClickable = this.canMetricBeGraphed(stat) if (isClickable && this.props.metric === METRIC_MAPPING[stat.name]) { return "Click to hide" } else if (isClickable) { return "Click to show" } else { return null } } canMetricBeGraphed(stat) { const isTotalUniqueVisitors = this.props.query.filters.goal && stat.name === 'Unique visitors' const isKnownMetric = Object.keys(METRIC_MAPPING).includes(stat.name) return isKnownMetric && !isTotalUniqueVisitors } maybeUpdateMetric(stat) { if (this.canMetricBeGraphed(stat)) { this.props.updateMetric(METRIC_MAPPING[stat.name]) } } renderStat(stat) { return ( {this.topStatNumberShort(stat)} {this.renderComparison(stat.name, stat.change)} ) } render() { const { metric, topStatData, query } = this.props const stats = topStatData && topStatData.top_stats.map((stat, index) => { const isSelected = metric === METRIC_MAPPING[stat.name] const [statDisplayName, statExtraName] = stat.name.split(/(\(.+\))/g) const className = classNames('px-4 md:px-6 w-1/2 my-4 lg:w-auto group select-none', { 'cursor-pointer': this.canMetricBeGraphed(stat), 'lg:border-l border-gray-300': index > 0, 'border-r lg:border-r-0': index % 2 === 0 }) return ( { this.maybeUpdateMetric(stat) }} boundary={this.props.tooltipBoundary}>
{statDisplayName} {statExtraName && {statExtraName}}
{this.topStatNumberShort(stat)} {this.renderComparison(stat.name, stat.change)}
) }) if (query && query.period === 'realtime') { stats.push(
) } return stats } }