Updated session and events queries. Added sessions page.

This commit is contained in:
Mike Cao 2024-07-08 01:45:54 -07:00
parent 082a751ffe
commit db36c37d32
39 changed files with 376 additions and 180 deletions

View file

@ -0,0 +1,26 @@
.container {
display: grid;
grid-template-columns: 1fr 1fr;
justify-content: space-between;
align-items: center;
padding: 10px 0;
min-height: 90px;
margin-bottom: 20px;
background: var(--base50);
z-index: var(--z-index-above);
}
.actions {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
flex: 1;
}
@media only screen and (max-width: 992px) {
.container {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
}
}

View file

@ -0,0 +1,37 @@
import { useApi, useDateRange, useMessages } from 'components/hooks';
import MetricCard from 'components/metrics/MetricCard';
import WebsiteDateFilter from 'components/input/WebsiteDateFilter';
import MetricsBar from 'components/metrics/MetricsBar';
import styles from './EventDataMetricsBar.module.css';
export function EventDataMetricsBar({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages();
const { get, useQuery } = useApi();
const { dateRange } = useDateRange(websiteId);
const { startDate, endDate } = dateRange;
const { data, error, isLoading, isFetched } = useQuery({
queryKey: ['event-data:stats', { websiteId, startDate, endDate }],
queryFn: () =>
get(`/event-data/stats`, {
websiteId,
startAt: +startDate,
endAt: +endDate,
}),
});
return (
<div className={styles.container}>
<MetricsBar isLoading={isLoading} isFetched={isFetched} error={error}>
<MetricCard label={formatMessage(labels.events)} value={data?.events} />
<MetricCard label={formatMessage(labels.fields)} value={data?.fields} />
<MetricCard label={formatMessage(labels.totalRecords)} value={data?.records} />
</MetricsBar>
<div className={styles.actions}>
<WebsiteDateFilter websiteId={websiteId} />
</div>
</div>
);
}
export default EventDataMetricsBar;

View file

@ -0,0 +1,12 @@
'use client';
import WebsiteHeader from '../WebsiteHeader';
import WebsiteEventData from './WebsiteEventData';
export default function EventDataPage({ websiteId }) {
return (
<>
<WebsiteHeader websiteId={websiteId} />
<WebsiteEventData websiteId={websiteId} />
</>
);
}

View file

@ -0,0 +1,37 @@
import Link from 'next/link';
import { GridTable, GridColumn } from 'react-basics';
import { useMessages, useNavigation } from 'components/hooks';
import Empty from 'components/common/Empty';
import { DATA_TYPES } from 'lib/constants';
export function EventDataTable({ data = [] }) {
const { formatMessage, labels } = useMessages();
const { renderUrl } = useNavigation();
if (data.length === 0) {
return <Empty />;
}
return (
<GridTable data={data}>
<GridColumn name="eventName" label={formatMessage(labels.event)}>
{row => (
<Link href={renderUrl({ event: row.eventName })} shallow={true}>
{row.eventName}
</Link>
)}
</GridColumn>
<GridColumn name="fieldName" label={formatMessage(labels.field)}>
{row => row.fieldName}
</GridColumn>
<GridColumn name="dataType" label={formatMessage(labels.type)}>
{row => DATA_TYPES[row.dataType]}
</GridColumn>
<GridColumn name="total" label={formatMessage(labels.totalRecords)}>
{({ total }) => total.toLocaleString()}
</GridColumn>
</GridTable>
);
}
export default EventDataTable;

View file

@ -0,0 +1,30 @@
import { GridTable, GridColumn } from 'react-basics';
import { useMessages } from 'components/hooks';
import PageHeader from 'components/layout/PageHeader';
import Empty from 'components/common/Empty';
import { DATA_TYPES } from 'lib/constants';
export function EventDataValueTable({ data = [], event }: { data: any[]; event: string }) {
const { formatMessage, labels } = useMessages();
return (
<>
<PageHeader title={event} />
{data.length <= 0 && <Empty />}
{data.length > 0 && (
<GridTable data={data}>
<GridColumn name="fieldName" label={formatMessage(labels.field)} />
<GridColumn name="dataType" label={formatMessage(labels.type)}>
{row => DATA_TYPES[row.dataType]}
</GridColumn>
<GridColumn name="fieldValue" label={formatMessage(labels.value)} />
<GridColumn name="total" label={formatMessage(labels.totalRecords)} width="200px">
{({ total }) => total.toLocaleString()}
</GridColumn>
</GridTable>
)}
</>
);
}
export default EventDataValueTable;

View file

@ -0,0 +1,7 @@
.container a {
color: var(--font-color100);
}
.container a:hover {
color: var(--primary400);
}

View file

@ -0,0 +1,41 @@
import { Flexbox, Loading } from 'react-basics';
import EventDataTable from './EventDataTable';
import EventDataValueTable from './EventDataValueTable';
import { EventDataMetricsBar } from './EventDataMetricsBar';
import { useDateRange, useApi, useNavigation } from 'components/hooks';
import styles from './WebsiteEventData.module.css';
function useData(websiteId: string, event: string) {
const { dateRange } = useDateRange(websiteId);
const { startDate, endDate } = dateRange;
const { get, useQuery } = useApi();
const { data, error, isLoading } = useQuery({
queryKey: ['event-data:events', { websiteId, startDate, endDate, event }],
queryFn: () =>
get('/event-data/events', {
websiteId,
startAt: +startDate,
endAt: +endDate,
event,
}),
enabled: !!(websiteId && startDate && endDate),
});
return { data, error, isLoading };
}
export default function WebsiteEventData({ websiteId }) {
const {
query: { event },
} = useNavigation();
const { data, isLoading } = useData(websiteId, event);
return (
<Flexbox className={styles.container} direction="column" gap={20}>
<EventDataMetricsBar websiteId={websiteId} />
{!event && <EventDataTable data={data} />}
{isLoading && <Loading position="page" />}
{event && data && <EventDataValueTable event={event} data={data} />}
</Flexbox>
);
}

View file

@ -0,0 +1,10 @@
import { Metadata } from 'next';
import EventDataPage from './EventDataPage';
export default async function ({ params: { websiteId } }) {
return <EventDataPage websiteId={websiteId} />;
}
export const metadata: Metadata = {
title: 'Event Data',
};