aboutsummaryrefslogtreecommitdiff
path: root/src/components/metrics/MetricsTable.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/metrics/MetricsTable.tsx')
-rw-r--r--src/components/metrics/MetricsTable.tsx95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/components/metrics/MetricsTable.tsx b/src/components/metrics/MetricsTable.tsx
new file mode 100644
index 0000000..e99bd21
--- /dev/null
+++ b/src/components/metrics/MetricsTable.tsx
@@ -0,0 +1,95 @@
+import { Grid, Icon, Row, Text } from '@umami/react-zen';
+import { useEffect, useMemo } from 'react';
+import { LinkButton } from '@/components/common/LinkButton';
+import { LoadingPanel } from '@/components/common/LoadingPanel';
+import { useMessages, useNavigation, useWebsiteMetricsQuery } from '@/components/hooks';
+import { Maximize } from '@/components/icons';
+import { MetricLabel } from '@/components/metrics/MetricLabel';
+import { percentFilter } from '@/lib/filters';
+import { ListTable, type ListTableProps } from './ListTable';
+
+export interface MetricsTableProps extends ListTableProps {
+ websiteId: string;
+ type: string;
+ dataFilter?: (data: any) => any;
+ limit?: number;
+ showMore?: boolean;
+ filterLink?: boolean;
+ params?: Record<string, any>;
+ onDataLoad?: (data: any) => void;
+}
+
+export function MetricsTable({
+ websiteId,
+ type,
+ dataFilter,
+ limit,
+ showMore = false,
+ filterLink = true,
+ params,
+ onDataLoad,
+ ...props
+}: MetricsTableProps) {
+ const { updateParams } = useNavigation();
+ const { formatMessage, labels } = useMessages();
+ const { data, isLoading, isFetching, error } = useWebsiteMetricsQuery(websiteId, {
+ type,
+ limit,
+ ...params,
+ });
+
+ const filteredData = useMemo(() => {
+ if (data) {
+ let items = data as any[];
+
+ if (dataFilter) {
+ if (Array.isArray(dataFilter)) {
+ items = dataFilter.reduce((arr, filter) => {
+ return filter(arr);
+ }, items);
+ } else {
+ items = dataFilter(items);
+ }
+ }
+
+ items = percentFilter(items);
+
+ return items.map(({ x, y, z, ...props }) => ({ label: x, count: y, percent: z, ...props }));
+ }
+ return [];
+ }, [data, dataFilter, limit, type]);
+
+ useEffect(() => {
+ if (data) {
+ onDataLoad?.(data);
+ }
+ }, [data]);
+
+ const renderLabel = (row: any) => {
+ return filterLink ? <MetricLabel type={type} data={row} /> : row.label;
+ };
+
+ return (
+ <LoadingPanel
+ data={data}
+ isFetching={isFetching}
+ isLoading={isLoading}
+ error={error}
+ minHeight="400px"
+ >
+ <Grid>
+ {data && <ListTable {...props} data={filteredData} renderLabel={renderLabel} />}
+ {showMore && limit && (
+ <Row justifyContent="center" alignItems="flex-end">
+ <LinkButton href={updateParams({ view: type })} variant="quiet">
+ <Icon size="sm">
+ <Maximize />
+ </Icon>
+ <Text>{formatMessage(labels.more)}</Text>
+ </LinkButton>
+ </Row>
+ )}
+ </Grid>
+ </LoadingPanel>
+ );
+}