diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/page.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/page.tsx
index 95cd258b..67339ccc 100644
--- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/page.tsx
+++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/page.tsx
@@ -9,7 +9,7 @@ import OverviewTopPages from '@/components/overview/overview-top-pages';
import OverviewTopSources from '@/components/overview/overview-top-sources';
import { OverviewInterval } from '@/components/overview/overview-interval';
-import OverviewMetricsV2 from '@/components/overview/overview-metrics-v2';
+import OverviewMetrics from '@/components/overview/overview-metrics';
import { OverviewRange } from '@/components/overview/overview-range';
interface PageProps {
@@ -36,8 +36,7 @@ export default function Page({ params: { projectId } }: PageProps) {
- {/*
*/}
-
+
diff --git a/apps/dashboard/src/components/overview/overview-metrics-v2.tsx b/apps/dashboard/src/components/overview/overview-metrics-v2.tsx
deleted file mode 100644
index 888a1c76..00000000
--- a/apps/dashboard/src/components/overview/overview-metrics-v2.tsx
+++ /dev/null
@@ -1,258 +0,0 @@
-'use client';
-
-import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
-import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
-import { cn } from '@/utils/cn';
-
-import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
-import { useNumber } from '@/hooks/useNumerFormatter';
-import { type RouterOutputs, api } from '@/trpc/client';
-import { getChartColor } from '@/utils/theme';
-import { getPreviousMetric } from '@openpanel/common';
-import React from 'react';
-import {
- CartesianGrid,
- Line,
- LineChart,
- ResponsiveContainer,
- XAxis,
- YAxis,
-} from 'recharts';
-import { createChartTooltip } from '../charts/chart-tooltip';
-import { useXAxisProps, useYAxisProps } from '../report-chart/common/axis';
-import { PreviousDiffIndicatorPure } from '../report-chart/common/previous-diff-indicator';
-import { Skeleton } from '../skeleton';
-import { OverviewLiveHistogram } from './overview-live-histogram';
-import { OverviewMetricCard } from './overview-metric-card';
-
-interface OverviewMetricsProps {
- projectId: string;
-}
-
-const TITLES = [
- {
- title: 'Unique Visitors',
- key: 'unique_visitors',
- unit: '',
- inverted: false,
- },
- {
- title: 'Sessions',
- key: 'total_sessions',
- unit: '',
- inverted: false,
- },
- {
- title: 'Pageviews',
- key: 'total_screen_views',
- unit: '',
- inverted: false,
- },
- {
- title: 'Pages per session',
- key: 'views_per_session',
- unit: '',
- inverted: false,
- },
- {
- title: 'Bounce Rate',
- key: 'bounce_rate',
- unit: '%',
- inverted: true,
- },
- {
- title: 'Session Duration',
- key: 'avg_session_duration',
- unit: 'min',
- inverted: false,
- },
-] as const;
-
-export default function OverviewMetricsV2({ projectId }: OverviewMetricsProps) {
- const { range, interval, metric, setMetric, startDate, endDate } =
- useOverviewOptions();
- const [filters] = useEventQueryFilters();
-
- const activeMetric = TITLES[metric]!;
- const overviewQuery = api.overview.stats.useQuery({
- projectId,
- range,
- interval,
- filters,
- startDate,
- endDate,
- });
-
- const data =
- overviewQuery.data?.series?.map((item) => ({
- ...item,
- timestamp: new Date(item.date).getTime(),
- })) || [];
-
- const xAxisProps = useXAxisProps({ interval: 'day' });
- const yAxisProps = useYAxisProps();
-
- return (
- <>
-
-
- {TITLES.map((title, index) => (
-
setMetric(index)}
- label={title.title}
- metric={{
- current: overviewQuery.data?.metrics[title.key] ?? 0,
- previous: overviewQuery.data?.metrics[`prev_${title.key}`],
- }}
- unit={title.unit}
- data={data.map((item) => ({
- current: item[title.key],
- previous: item[`prev_${title.key}`],
- }))}
- active={metric === index}
- isLoading={overviewQuery.isLoading}
- />
- ))}
-
-
-
-
-
-
-
-
- {activeMetric.title}
-
-
- {overviewQuery.isLoading && }
-
-
-
-
-
-
-
-
-
- 90
- ? false
- : {
- stroke: 'hsl(var(--foreground) / 0.2)',
- fill: 'hsl(var(--def-100))',
- strokeWidth: 1.5,
- r: 3,
- }
- }
- activeDot={{
- stroke: 'hsl(var(--foreground) / 0.2)',
- fill: 'hsl(var(--def-100))',
- strokeWidth: 2,
- r: 4,
- }}
- />
-
- 90
- ? false
- : {
- stroke: getChartColor(0),
- fill: 'hsl(var(--def-100))',
- strokeWidth: 1.5,
- r: 3,
- }
- }
- activeDot={{
- stroke: getChartColor(0),
- fill: 'hsl(var(--def-100))',
- strokeWidth: 2,
- r: 4,
- }}
- />
-
-
-
-
-
-
- >
- );
-}
-
-const { Tooltip, TooltipProvider } = createChartTooltip<
- RouterOutputs['overview']['stats']['series'][number],
- {
- metric: (typeof TITLES)[number];
- }
->(({ context: { metric }, data }) => {
- const formatDate = useFormatDateInterval('day');
- const number = useNumber();
-
- return (
- <>
-
-
{formatDate(new Date(data.date))}
-
-
-
-
-
-
{metric.title}
-
-
- {number.formatWithUnit(data[metric.key])}
- {!!data[`prev_${metric.key}`] && (
-
- ({number.formatWithUnit(data[`prev_${metric.key}`])})
-
- )}
-
-
-
-
-
-
-
- >
- );
-});
diff --git a/apps/dashboard/src/components/overview/overview-metrics.tsx b/apps/dashboard/src/components/overview/overview-metrics.tsx
index f0fff42a..4eb82619 100644
--- a/apps/dashboard/src/components/overview/overview-metrics.tsx
+++ b/apps/dashboard/src/components/overview/overview-metrics.tsx
@@ -4,212 +4,118 @@ import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
import { cn } from '@/utils/cn';
-import type { IChartProps } from '@openpanel/validation';
-
-import { ReportChart } from '../report-chart';
+import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
+import { useNumber } from '@/hooks/useNumerFormatter';
+import { type RouterOutputs, api } from '@/trpc/client';
+import { getChartColor } from '@/utils/theme';
+import { getPreviousMetric } from '@openpanel/common';
+import React from 'react';
+import {
+ CartesianGrid,
+ Line,
+ LineChart,
+ ResponsiveContainer,
+ XAxis,
+ YAxis,
+} from 'recharts';
+import { createChartTooltip } from '../charts/chart-tooltip';
+import { useXAxisProps, useYAxisProps } from '../report-chart/common/axis';
+import { PreviousDiffIndicatorPure } from '../report-chart/common/previous-diff-indicator';
+import { Skeleton } from '../skeleton';
import { OverviewLiveHistogram } from './overview-live-histogram';
+import { OverviewMetricCard } from './overview-metric-card';
interface OverviewMetricsProps {
projectId: string;
}
+const TITLES = [
+ {
+ title: 'Unique Visitors',
+ key: 'unique_visitors',
+ unit: '',
+ inverted: false,
+ },
+ {
+ title: 'Sessions',
+ key: 'total_sessions',
+ unit: '',
+ inverted: false,
+ },
+ {
+ title: 'Pageviews',
+ key: 'total_screen_views',
+ unit: '',
+ inverted: false,
+ },
+ {
+ title: 'Pages per session',
+ key: 'views_per_session',
+ unit: '',
+ inverted: false,
+ },
+ {
+ title: 'Bounce Rate',
+ key: 'bounce_rate',
+ unit: '%',
+ inverted: true,
+ },
+ {
+ title: 'Session Duration',
+ key: 'avg_session_duration',
+ unit: 'min',
+ inverted: false,
+ },
+] as const;
+
export default function OverviewMetrics({ projectId }: OverviewMetricsProps) {
- const { previous, range, interval, metric, setMetric, startDate, endDate } =
+ const { range, interval, metric, setMetric, startDate, endDate } =
useOverviewOptions();
const [filters] = useEventQueryFilters();
- const isPageFilter = filters.find((filter) => filter.name === 'path');
- const reports = [
- {
- id: 'Visitors',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'user',
- filters,
- id: 'A',
- name: isPageFilter ? 'screen_view' : 'session_start',
- displayName: 'Visitors',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Visitors',
- range,
- previous,
- metric: 'sum',
- },
- {
- id: 'Sessions',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'session',
- filters,
- id: 'A',
- name: isPageFilter ? 'screen_view' : 'session_start',
- displayName: 'Sessions',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Sessions',
- range,
- previous,
- metric: 'sum',
- },
- {
- id: 'Pageviews',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'event',
- filters,
- id: 'A',
- name: 'screen_view',
- displayName: 'Pageviews',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Pageviews',
- range,
- previous,
- metric: 'sum',
- },
- {
- id: 'Views per session',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'user_average',
- filters,
- id: 'A',
- name: 'screen_view',
- displayName: 'Views per session',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Views per session',
- range,
- previous,
- metric: 'average',
- },
- {
- id: 'Bounce rate',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'event',
- filters: [
- {
- id: '1',
- name: 'properties.__bounce',
- operator: 'is',
- value: ['true'],
- },
- ...filters,
- ],
- id: 'A',
- name: 'session_end',
- displayName: 'Bounce rate',
- },
- {
- segment: 'event',
- filters: filters,
- id: 'B',
- name: 'session_end',
- displayName: 'Bounce rate',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Bounce rate',
- range,
- previous,
- previousIndicatorInverted: true,
- formula: 'A/B*100',
- metric: 'average',
- unit: '%',
- maxDomain: 100,
- },
- {
- id: 'Visit duration',
- projectId,
- startDate,
- endDate,
- events: [
- {
- segment: 'property_average',
- filters: [
- {
- name: 'duration',
- operator: 'isNot',
- value: ['0'],
- id: 'A',
- },
- ...filters,
- ],
- id: 'A',
- property: 'duration',
- name: isPageFilter ? 'screen_view' : 'session_end',
- displayName: isPageFilter ? 'Time on page' : 'Visit duration',
- },
- ],
- breakdowns: [],
- chartType: 'metric',
- lineType: 'monotone',
- interval,
- name: 'Visit duration',
- range,
- previous,
- formula: 'A/1000',
- metric: 'average',
- unit: 'min',
- },
- ] satisfies (IChartProps & { id: string; maxDomain?: number })[];
- const selectedMetric = reports[metric]!;
+ const activeMetric = TITLES[metric]!;
+ const overviewQuery = api.overview.stats.useQuery({
+ projectId,
+ range,
+ interval,
+ filters,
+ startDate,
+ endDate,
+ });
+
+ const data =
+ overviewQuery.data?.series?.map((item) => ({
+ ...item,
+ timestamp: new Date(item.date).getTime(),
+ })) || [];
+
+ const xAxisProps = useXAxisProps({ interval: 'day' });
+ const yAxisProps = useYAxisProps();
return (
<>
- {reports.map((report, index) => (
-
+ unit={title.unit}
+ data={data.map((item) => ({
+ current: item[title.key],
+ previous: item[`prev_${title.key}`],
+ }))}
+ active={metric === index}
+ isLoading={overviewQuery.isLoading}
+ />
))}
+
- {/*
-
-
*/}
+
+
+
+ {activeMetric.title}
+
+
+ {overviewQuery.isLoading && }
+
+
+
+
+
+
+
+
+
+ 90
+ ? false
+ : {
+ stroke: 'hsl(var(--foreground) / 0.2)',
+ fill: 'hsl(var(--def-100))',
+ strokeWidth: 1.5,
+ r: 3,
+ }
+ }
+ activeDot={{
+ stroke: 'hsl(var(--foreground) / 0.2)',
+ fill: 'hsl(var(--def-100))',
+ strokeWidth: 2,
+ r: 4,
+ }}
+ />
+
+ 90
+ ? false
+ : {
+ stroke: getChartColor(0),
+ fill: 'hsl(var(--def-100))',
+ strokeWidth: 1.5,
+ r: 3,
+ }
+ }
+ activeDot={{
+ stroke: getChartColor(0),
+ fill: 'hsl(var(--def-100))',
+ strokeWidth: 2,
+ r: 4,
+ }}
+ />
+
+
+
+
+
>
);
}
+
+const { Tooltip, TooltipProvider } = createChartTooltip<
+ RouterOutputs['overview']['stats']['series'][number],
+ {
+ metric: (typeof TITLES)[number];
+ }
+>(({ context: { metric }, data }) => {
+ const formatDate = useFormatDateInterval('day');
+ const number = useNumber();
+
+ return (
+ <>
+