import React from 'react'
import { Tooltip } from '../../util/tooltip'
import { SecondsSinceLastLoad } from '../../util/seconds-since-last-load'
import classNames from 'classnames'
import * as storage from '../../util/storage'
import { formatDateRange } from '../../util/date'
import { useQueryContext } from '../../query-context'
import { useSiteContext } from '../../site-context'
import { useLastLoadContext } from '../../last-load-context'
import { ChangeArrow } from '../reports/change-arrow'
import {
MetricFormatterShort,
MetricFormatterLong
} from '../reports/metric-formatter'
function topStatNumberShort(metric, value) {
const formatter = MetricFormatterShort[metric]
return formatter(value)
}
function topStatNumberLong(metric, value) {
const formatter = MetricFormatterLong[metric]
return formatter(value)
}
export default function TopStats({
data,
onMetricUpdate,
tooltipBoundary,
graphableMetrics
}) {
const { query } = useQueryContext()
const lastLoadTimestamp = useLastLoadContext()
const site = useSiteContext()
const isComparison = query.comparison && data && data.comparing_from
function tooltip(stat) {
let statName = stat.name.toLowerCase()
const warning = warningText(stat.graph_metric, site)
statName = stat.value === 1 ? statName.slice(0, -1) : statName
return (
{isComparison && (
{topStatNumberLong(stat.graph_metric, stat.value)} vs.{' '}
{topStatNumberLong(stat.graph_metric, stat.comparison_value)}{' '}
{statName}
)}
{!isComparison && (
{topStatNumberLong(stat.graph_metric, stat.value)} {statName}
)}
{stat.name === 'Current visitors' && (
Last updated{' '}
s ago
)}
{warning ? (
* {warning}
) : null}
)
}
function warningText(metric) {
const warning = data.meta.metric_warnings?.[metric]
if (!warning) {
return null
}
if (
metric === 'scroll_depth' &&
warning.code === 'no_imported_scroll_depth'
) {
return 'Does not include imported data'
}
if (metric === 'time_on_page') {
return warning.message
}
return null
}
function canMetricBeGraphed(stat) {
return graphableMetrics.includes(stat.graph_metric)
}
function maybeUpdateMetric(stat) {
if (canMetricBeGraphed(stat)) {
storage.setItem(`metric__${site.domain}`, stat.graph_metric)
onMetricUpdate(stat.graph_metric)
}
}
function blinkingDot() {
return (
)
}
function getStoredMetric() {
return storage.getItem(`metric__${site.domain}`)
}
function renderStatName(stat) {
const isSelected = stat.graph_metric === getStoredMetric()
const [statDisplayName, statExtraName] = stat.name.split(/(\(.+\))/g)
const statDisplayNameClass = classNames(
'text-xs font-bold tracking-wide text-gray-500 uppercase dark:text-gray-400 whitespace-nowrap flex w-fit border-b',
{
'text-indigo-600 dark:text-indigo-500 border-indigo-600 dark:border-indigo-500':
isSelected,
'group-hover:text-indigo-700 dark:group-hover:text-indigo-500 border-transparent':
!isSelected
}
)
return (
{statDisplayName}
{statExtraName && (
{statExtraName}
)}
{warningText(stat.graph_metric) && (
*
)}
)
}
function renderStat(stat, index) {
const className = classNames(
'px-4 md:px-6 w-1/2 my-4 lg:w-auto group select-none',
{
'cursor-pointer': canMetricBeGraphed(stat),
'lg:border-l border-gray-300 dark:border-gray-700': index > 0,
'border-r lg:border-r-0': index % 2 === 0
}
)
return (
{
maybeUpdateMetric(stat)
}}
boundary={tooltipBoundary}
>
{renderStatName(stat)}
{topStatNumberShort(stat.graph_metric, stat.value)}
{!isComparison && stat.change != null ? (
) : null}
{isComparison ? (
{formatDateRange(site, data.from, data.to)}
) : null}
{isComparison ? (
{topStatNumberShort(stat.graph_metric, stat.comparison_value)}
{formatDateRange(site, data.comparing_from, data.comparing_to)}
) : null}
)
}
const stats =
data && data.top_stats.filter((stat) => stat.value !== null).map(renderStat)
if (stats && query.period === 'realtime') {
stats.push(blinkingDot())
}
return stats || null
}