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 ( + <> +
+
{formatDate(new Date(data.date))}
+
+ +
+
+
+
{metric.title}
+
+
+ {number.formatWithUnit(data[metric.key])} + {!!data[`prev_${metric.key}`] && ( + + ({number.formatWithUnit(data[`prev_${metric.key}`])}) + + )} +
+ + +
+
+
+ + + ); +});