/** * The numbers and the chart, in one block: Visitors, Visits, Page views, * Bounce rate, Visit duration and Online, then the chart. A filter chip * narrows all of them, as it does the cards. Each number shows its change * against the window before (D2), except on Lifetime. The API sends raw * fractions and this file decides which direction reads as good, because * bounce rate is the one that inverts. */ import { __ } from '@wordpress/i18n'; import { useUi } from './ui-context'; import Timeseries from './chart'; import { useApi, numCompact } from './api'; import LoadError from './load-error'; function percent( fraction ) { return `${ Math.round( ( fraction || 0 ) * 100 ) }%`; } function duration( seconds ) { const s = seconds || 0; if ( s >= 3600 ) { return `${ Math.floor( s / 3600 ) }h ${ String( Math.floor( ( s % 3600 ) / 60 ) ).padStart( 2, '0' ) }m`; } return `${ Math.floor( s / 60 ) }m ${ String( s % 60 ).padStart( 2, '0' ) }s`; } // Rising is good everywhere except bounce rate, where a climb is the bad news. const LOWER_IS_BETTER = { bounce_rate: true }; /** * StatCard props for one number's change: nothing when there is no window * before, or it had no value to divide by (null delta). An absent change is * honest; "+100%" against zero is not. */ function change( deltas, key ) { const d = deltas?.[ key ]; if ( d === null || d === undefined ) { return {}; } const rounded = Math.abs( d * 100 ) < 0.05 ? 0 : d; const better = LOWER_IS_BETTER[ key ] ? rounded < 0 : rounded > 0; let tone = 'neutral'; if ( 0 !== rounded ) { tone = better ? 'success' : 'danger'; } return { delta: `${ rounded > 0 ? '+' : '' }${ ( rounded * 100 ).toFixed( 1 ) }%`, tone, }; } export default function Hero( { win, compare, filters } ) { const { Card, Skeleton, StatCard, StatGrid, StatusDot } = useUi(); const { data: cards, error, retry } = useApi( 'summary', { ...win, compare: compare || undefined, filters } ); const deltas = compare ? cards?.delta : null; const wait = ; const count = ( key, label ) => ( ); return (
{ error ? ( ) : ( { count( 'visitors', __( 'Visitors', 'saddle-analytics' ) ) } { count( 'visits', __( 'Visits', 'saddle-analytics' ) ) } { count( 'pageviews', __( 'Page views', 'saddle-analytics' ) ) } { cards ? duration( cards.duration ) : wait } } { ...change( deltas, 'duration' ) } /> { __( 'Online', 'saddle-analytics' ) } ) }
); }