aboutsummaryrefslogtreecommitdiff
path: root/src/components/metrics/EventsChart.tsx
blob: 3a53ba9a68de2d1f4318b05a1eecc5a416b2fcee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { colord } from 'colord';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { BarChart, type BarChartProps } from '@/components/charts/BarChart';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import {
  useDateRange,
  useLocale,
  useTimezone,
  useWebsiteEventsSeriesQuery,
} from '@/components/hooks';
import { renderDateLabels } from '@/lib/charts';
import { CHART_COLORS } from '@/lib/constants';
import { generateTimeSeries } from '@/lib/date';

export interface EventsChartProps extends BarChartProps {
  websiteId: string;
  focusLabel?: string;
}

export function EventsChart({ websiteId, focusLabel }: EventsChartProps) {
  const { timezone } = useTimezone();
  const {
    dateRange: { startDate, endDate, unit },
  } = useDateRange({ timezone: timezone });
  const { locale, dateLocale } = useLocale();
  const { data, isLoading, error } = useWebsiteEventsSeriesQuery(websiteId);
  const [label, setLabel] = useState<string>(focusLabel);

  const chartData: any = useMemo(() => {
    if (!data) return;

    const map = (data as any[]).reduce((obj, { x, t, y }) => {
      if (!obj[x]) {
        obj[x] = [];
      }

      obj[x].push({ x: t, y });

      return obj;
    }, {});

    if (!map || Object.keys(map).length === 0) {
      return {
        datasets: [
          {
            data: generateTimeSeries([], startDate, endDate, unit, dateLocale),
            lineTension: 0,
            borderWidth: 1,
          },
        ],
      };
    } else {
      return {
        datasets: Object.keys(map).map((key, index) => {
          const color = colord(CHART_COLORS[index % CHART_COLORS.length]);
          return {
            label: key,
            data: generateTimeSeries(map[key], startDate, endDate, unit, dateLocale),
            lineTension: 0,
            backgroundColor: color.alpha(0.6).toRgbString(),
            borderColor: color.alpha(0.7).toRgbString(),
            borderWidth: 1,
          };
        }),
        focusLabel,
      };
    }
  }, [data, startDate, endDate, unit, focusLabel]);

  useEffect(() => {
    if (label !== focusLabel) {
      setLabel(focusLabel);
    }
  }, [focusLabel]);

  const renderXLabel = useCallback(renderDateLabels(unit, locale), [unit, locale]);

  return (
    <LoadingPanel isLoading={isLoading} error={error} minHeight="400px">
      {chartData && (
        <BarChart
          chartData={chartData}
          minDate={startDate}
          maxDate={endDate}
          unit={unit}
          stacked={true}
          renderXLabel={renderXLabel}
          height="400px"
        />
      )}
    </LoadingPanel>
  );
}