aboutsummaryrefslogtreecommitdiff
path: root/src/components/metrics/EventsChart.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/metrics/EventsChart.tsx')
-rw-r--r--src/components/metrics/EventsChart.tsx93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/components/metrics/EventsChart.tsx b/src/components/metrics/EventsChart.tsx
new file mode 100644
index 0000000..3a53ba9
--- /dev/null
+++ b/src/components/metrics/EventsChart.tsx
@@ -0,0 +1,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>
+ );
+}