diff --git a/web/components/analytics/charts.tsx b/web/components/analytics/charts.tsx index 131ce2a0..ad3b52fd 100644 --- a/web/components/analytics/charts.tsx +++ b/web/components/analytics/charts.tsx @@ -1,139 +1,77 @@ -import { Point, ResponsiveLine } from '@nivo/line' -import clsx from 'clsx' -import { formatPercent } from 'common/util/format' +import { useMemo } from 'react' +import { scaleTime, scaleLinear } from 'd3-scale' +import { min, max } from 'lodash' import dayjs from 'dayjs' -import { zip } from 'lodash' -import { useWindowSize } from 'web/hooks/use-window-size' -import { Col } from '../layout/col' -export function DailyCountChart(props: { - startDate: number - dailyCounts: number[] - small?: boolean -}) { - const { dailyCounts, startDate, small } = props - const { width } = useWindowSize() +import { formatPercent } from 'common/util/format' +import { Row } from '../layout/row' +import { + HistoryPoint, + SingleValueHistoryChart, +} from 'web/components/charts/generic-charts' +import { TooltipProps, MARGIN_X, MARGIN_Y } from 'web/components/charts/helpers' +import { SizedContainer } from 'web/components/sized-container' - const dates = dailyCounts.map((_, i) => - dayjs(startDate).add(i, 'day').toDate() - ) - - const points = zip(dates, dailyCounts).map(([date, betCount]) => ({ - x: date, - y: betCount, +const getPoints = (startDate: number, dailyValues: number[]) => { + const startDateDayJs = dayjs(startDate) + return dailyValues.map((y, i) => ({ + x: startDateDayJs.add(i, 'day').toDate(), + y: y, })) - const data = [{ id: 'Count', data: points, color: '#11b981' }] - - const bottomAxisTicks = width && width < 600 ? 6 : undefined +} +const DailyCountTooltip = (props: TooltipProps) => { + const { data, mouseX, xScale } = props + const d = xScale.invert(mouseX) return ( -
- dayjs(date).format('MMM DD'), - }} - colors={{ datum: 'color' }} - pointSize={0} - pointBorderWidth={1} - pointBorderColor="#fff" - enableSlices="x" - enableGridX={!!width && width >= 800} - enableArea - margin={{ top: 20, right: 28, bottom: 22, left: 40 }} - sliceTooltip={({ slice }) => { - const point = slice.points[0] - return - }} - /> -
+ + {dayjs(d).format('MMM DD')} + {data.y} + ) } -export function DailyPercentChart(props: { +const DailyPercentTooltip = (props: TooltipProps) => { + const { data, mouseX, xScale } = props + const d = xScale.invert(mouseX) + return ( + + {dayjs(d).format('MMM DD')} + {formatPercent(data.y)} + + ) +} + +export function DailyChart(props: { startDate: number - dailyPercent: number[] - small?: boolean + dailyValues: number[] excludeFirstDays?: number + pct?: boolean }) { - const { dailyPercent, startDate, small, excludeFirstDays } = props - const { width } = useWindowSize() + const { dailyValues, startDate, excludeFirstDays, pct } = props - const dates = dailyPercent.map((_, i) => - dayjs(startDate).add(i, 'day').toDate() + const data = useMemo( + () => getPoints(startDate, dailyValues).slice(excludeFirstDays ?? 0), + [startDate, dailyValues, excludeFirstDays] ) - - const points = zip(dates, dailyPercent) - .map(([date, percent]) => ({ - x: date, - y: percent, - })) - .slice(excludeFirstDays ?? 0) - const data = [{ id: 'Percent', data: points, color: '#11b981' }] - - const bottomAxisTicks = width && width < 600 ? 6 : undefined - + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const maxDate = max(data.map((d) => d.x))! + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const maxValue = max(data.map((d) => d.y))! return ( -
+ {(width, height) => ( + )} - > - dayjs(date).format('MMM DD'), - }} - colors={{ datum: 'color' }} - pointSize={0} - pointBorderWidth={1} - pointBorderColor="#fff" - enableSlices="x" - enableGridX={!!width && width >= 800} - enableArea - margin={{ top: 20, right: 28, bottom: 22, left: 40 }} - sliceTooltip={({ slice }) => { - const point = slice.points[0] - return - }} - /> -
- ) -} - -function Tooltip(props: { point: Point; isPercent?: boolean }) { - const { point, isPercent } = props - return ( - -
- {point.serieId}{' '} - {isPercent ? formatPercent(+point.data.y) : Math.round(+point.data.y)} -
-
{dayjs(point.data.x).format('MMM DD')}
- + ) } diff --git a/web/pages/stats.tsx b/web/pages/stats.tsx index 19fab509..fe0111bc 100644 --- a/web/pages/stats.tsx +++ b/web/pages/stats.tsx @@ -1,8 +1,5 @@ import { useEffect, useState } from 'react' -import { - DailyCountChart, - DailyPercentChart, -} from 'web/components/analytics/charts' +import { DailyChart } from 'web/components/analytics/charts' import { Col } from 'web/components/layout/col' import { Spacer } from 'web/components/layout/spacer' import { Tabs } from 'web/components/layout/tabs' @@ -96,40 +93,36 @@ export function CustomAnalytics(props: Stats) { { title: 'Daily', content: ( - ), }, { title: 'Daily (7d avg)', content: ( - ), }, { title: 'Weekly', content: ( - ), }, { title: 'Monthly', content: ( - ), }, @@ -149,44 +142,44 @@ export function CustomAnalytics(props: Stats) { { title: 'D1', content: ( - ), }, { title: 'D1 (7d avg)', content: ( - ), }, { title: 'W1', content: ( - ), }, { title: 'M1', content: ( - ), }, @@ -207,33 +200,33 @@ export function CustomAnalytics(props: Stats) { { title: 'ND1', content: ( - ), }, { title: 'ND1 (7d avg)', content: ( - ), }, { title: 'NW1', content: ( - ), }, @@ -249,41 +242,31 @@ export function CustomAnalytics(props: Stats) { { title: capitalize(PAST_BETS), content: ( - + ), }, { title: 'Markets created', content: ( - ), }, { title: 'Comments', content: ( - ), }, { title: 'Signups', content: ( - + ), }, ]} @@ -304,22 +287,22 @@ export function CustomAnalytics(props: Stats) { { title: 'Daily', content: ( - ), }, { title: 'Daily (7d avg)', content: ( - ), }, @@ -335,33 +318,33 @@ export function CustomAnalytics(props: Stats) { { title: 'Daily / Weekly', content: ( - ), }, { title: 'Daily / Monthly', content: ( - ), }, { title: 'Weekly / Monthly', content: ( - ), }, @@ -380,31 +363,19 @@ export function CustomAnalytics(props: Stats) { { title: 'Daily', content: ( - + ), }, { title: 'Weekly', content: ( - + ), }, { title: 'Monthly', content: ( - + ), }, ]}