mirror of
https://github.com/umami-software/umami.git
synced 2026-02-25 06:55:35 +01:00
add comparison to events page metric bar
Some checks are pending
Node.js CI / build (push) Waiting to run
Some checks are pending
Node.js CI / build (push) Waiting to run
This commit is contained in:
parent
530c21dac0
commit
99a328359b
3 changed files with 63 additions and 33 deletions
|
|
@ -1,12 +1,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
import { Column, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen';
|
||||||
import locale from 'date-fns/locale/af';
|
import { type Key, useState } from 'react';
|
||||||
import { type Key, useMemo, useState } from 'react';
|
|
||||||
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
|
import { SessionModal } from '@/app/(main)/websites/[websiteId]/sessions/SessionModal';
|
||||||
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
|
import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
|
||||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||||
import { Panel } from '@/components/common/Panel';
|
import { Panel } from '@/components/common/Panel';
|
||||||
import { useMessages } from '@/components/hooks';
|
import { useDateRange, useMessages } from '@/components/hooks';
|
||||||
import { useEventStatsQuery } from '@/components/hooks/queries/useEventStatsQuery';
|
import { useEventStatsQuery } from '@/components/hooks/queries/useEventStatsQuery';
|
||||||
import { EventsChart } from '@/components/metrics/EventsChart';
|
import { EventsChart } from '@/components/metrics/EventsChart';
|
||||||
import { MetricCard } from '@/components/metrics/MetricCard';
|
import { MetricCard } from '@/components/metrics/MetricCard';
|
||||||
|
|
@ -21,6 +20,7 @@ const KEY_NAME = 'umami.events.tab';
|
||||||
|
|
||||||
export function EventsPage({ websiteId }) {
|
export function EventsPage({ websiteId }) {
|
||||||
const [tab, setTab] = useState(getItem(KEY_NAME) || 'chart');
|
const [tab, setTab] = useState(getItem(KEY_NAME) || 'chart');
|
||||||
|
const { isAllTime } = useDateRange();
|
||||||
const { t, labels, getErrorMessage } = useMessages();
|
const { t, labels, getErrorMessage } = useMessages();
|
||||||
const { data, isLoading, isFetching, error } = useEventStatsQuery({
|
const { data, isLoading, isFetching, error } = useEventStatsQuery({
|
||||||
websiteId,
|
websiteId,
|
||||||
|
|
@ -31,34 +31,36 @@ export function EventsPage({ websiteId }) {
|
||||||
setTab(value);
|
setTab(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const metrics = useMemo(() => {
|
const { events, visitors, visits, uniqueEvents, comparison } = data || {};
|
||||||
if (!data) return [];
|
|
||||||
|
|
||||||
const { events, visitors, visits, uniqueEvents } = data || {};
|
const metrics = data
|
||||||
|
? [
|
||||||
return [
|
{
|
||||||
{
|
value: visitors,
|
||||||
value: visitors,
|
label: t(labels.visitors),
|
||||||
label: t(labels.visitors),
|
change: visitors - comparison.visitors,
|
||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: visits,
|
value: visits,
|
||||||
label: t(labels.visits),
|
label: t(labels.visits),
|
||||||
formatValue: formatLongNumber,
|
change: visits - comparison.visits,
|
||||||
},
|
formatValue: formatLongNumber,
|
||||||
{
|
},
|
||||||
value: events,
|
{
|
||||||
label: t(labels.events),
|
value: events,
|
||||||
formatValue: formatLongNumber,
|
label: t(labels.events),
|
||||||
},
|
change: events - comparison.events,
|
||||||
{
|
formatValue: formatLongNumber,
|
||||||
value: uniqueEvents,
|
},
|
||||||
label: t(labels.uniqueEvents),
|
{
|
||||||
formatValue: formatLongNumber,
|
value: uniqueEvents,
|
||||||
},
|
label: t(labels.uniqueEvents),
|
||||||
] as any;
|
change: uniqueEvents - comparison.uniqueEvents,
|
||||||
}, [data, locale]);
|
formatValue: formatLongNumber,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column gap="3">
|
<Column gap="3">
|
||||||
|
|
@ -71,8 +73,17 @@ export function EventsPage({ websiteId }) {
|
||||||
minHeight="136px"
|
minHeight="136px"
|
||||||
>
|
>
|
||||||
<MetricsBar>
|
<MetricsBar>
|
||||||
{metrics?.map(({ label, value, formatValue }) => {
|
{metrics?.map(({ label, value, change, formatValue }) => {
|
||||||
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
|
return (
|
||||||
|
<MetricCard
|
||||||
|
key={label}
|
||||||
|
value={value}
|
||||||
|
label={label}
|
||||||
|
change={change}
|
||||||
|
formatValue={formatValue}
|
||||||
|
showChange={!isAllTime}
|
||||||
|
/>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</MetricsBar>
|
</MetricsBar>
|
||||||
</LoadingPanel>
|
</LoadingPanel>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { getCompareDate } from '@/lib/date';
|
||||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||||
import { json, unauthorized } from '@/lib/response';
|
import { json, unauthorized } from '@/lib/response';
|
||||||
import { filterParams, withDateRange } from '@/lib/schema';
|
import { filterParams, withDateRange } from '@/lib/schema';
|
||||||
|
|
@ -28,5 +29,17 @@ export async function GET(
|
||||||
|
|
||||||
const data = await getWebsiteEventStats(websiteId, filters);
|
const data = await getWebsiteEventStats(websiteId, filters);
|
||||||
|
|
||||||
return json({ data });
|
const { startDate, endDate } = getCompareDate(
|
||||||
|
filters.compare ?? 'prev',
|
||||||
|
filters.startDate,
|
||||||
|
filters.endDate,
|
||||||
|
);
|
||||||
|
|
||||||
|
const comparison = await getWebsiteEventStats(websiteId, {
|
||||||
|
...filters,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
return json({ data: { ...data, comparison } });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ export interface EventStatsData {
|
||||||
visitors: number;
|
visitors: number;
|
||||||
visits: number;
|
visits: number;
|
||||||
uniqueEvents: number;
|
uniqueEvents: number;
|
||||||
|
comparison: {
|
||||||
|
events: number;
|
||||||
|
visitors: number;
|
||||||
|
visits: number;
|
||||||
|
uniqueEvents: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventStatsApiResponse = {
|
type EventStatsApiResponse = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue