import { useAnalytics } from '@automattic/jetpack-shared-extension-utils'; import { curveMonotoneX } from '@visx/curve'; import { LegendOrdinal } from '@visx/legend'; import { ParentSize } from '@visx/responsive'; import { scaleOrdinal } from '@visx/scale'; import { Axis, Grid, LineSeries, Tooltip, XYChart, buildChartTheme } from '@visx/xychart'; import { useEffect } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { SERIES_COLORS, SERIES_LABELS, TRACKS_EVENT_NAME_PREFIX } from '../constants'; import { calcLeftAxisMargin, formatAxisTickDate, formatDate, formatNumber, getXAxisTickValues, transformData, } from '../helpers'; import type { SubscriberTotalsByDate, ChartSubscriptionDataPoint } from '../types'; import type { RenderTooltipGlyphProps, RenderTooltipParams, } from '@visx/xychart/lib/components/Tooltip'; // Create a scale for the legend const legendScale = scaleOrdinal( { domain: [ 'all', 'paid' ], range: [ SERIES_COLORS.all, SERIES_COLORS.paid ], } ); const chartTheme = buildChartTheme( { backgroundColor: 'white', colors: [ SERIES_COLORS.all, SERIES_COLORS.paid ], gridColor: '#e0e0e0', gridColorDark: '#e0e0e0', tickLength: 0, gridStyles: { strokeWidth: 1, }, svgLabelSmall: { fill: '#1e1e1e', fontSize: 13, fontWeight: 400, }, } ); // Chart accessors const getDate = ( d: ChartSubscriptionDataPoint ) => d.date; const getAllSubscribers = ( d: ChartSubscriptionDataPoint ) => d.all; const getPaidSubscribers = ( d: ChartSubscriptionDataPoint ) => d.paid; const getLineColor = ( k: string ) => SERIES_COLORS[ k ]; const getLegendLabel = ( k: string ) => SERIES_LABELS[ k ]; // Custom rendering for tooltip glyphs to match the line colors const renderGlyph = ( { key, color, x, y, }: RenderTooltipGlyphProps< ChartSubscriptionDataPoint > ) => { const fillColor = SERIES_COLORS[ key ] || color; return ( ); }; const renderTooltip = ( { tooltipData }: RenderTooltipParams< ChartSubscriptionDataPoint > ) => { if ( ! tooltipData?.nearestDatum ) return null; const datum = tooltipData.nearestDatum.datum; const date = getDate( datum ); return ( <>
{ formatDate( date, 'full' ) }
{ sprintf( // translators: %s is the total number of subscribers. __( 'All: %s', 'jetpack' ), formatNumber( getAllSubscribers( datum ) ) ) }
{ sprintf( // translators: %s is the number of paid subscribers. __( 'Paid: %s', 'jetpack' ), formatNumber( getPaidSubscribers( datum ) ) ) }
); }; interface SubscribersChartProps { subscriberTotalsByDate: SubscriberTotalsByDate; } export const SubscribersChart = ( { subscriberTotalsByDate }: SubscribersChartProps ) => { const { tracks } = useAnalytics(); useEffect( () => { tracks.recordEvent( `${ TRACKS_EVENT_NAME_PREFIX }chart_view` ); }, [ tracks ] ); if ( Object.keys( subscriberTotalsByDate ).length === 0 ) { return
{ __( 'No data available', 'jetpack' ) }
; } const data = transformData( subscriberTotalsByDate ); return ( <>
{ ( { width, height } ) => { if ( ! width || ! height ) return null; return ( showVerticalCrosshair showSeriesGlyphs className="subscribers-chart__tooltip" renderTooltip={ renderTooltip } renderGlyph={ renderGlyph } /> ); } }
); };