From 16499926547cdb804b132811cc65ee01633cf737 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 12 Jun 2025 00:31:09 -0700 Subject: [PATCH] Updates session details page. --- .../[websiteId]/reports/revenue/Revenue.tsx | 1 + .../[sessionId]/SessionData.module.css | 38 ------ .../sessions/[sessionId]/SessionData.tsx | 40 +++--- .../[sessionId]/SessionDetailsPage.module.css | 47 ------- .../[sessionId]/SessionDetailsPage.tsx | 67 ++++----- .../[sessionId]/SessionInfo.module.css | 21 --- .../sessions/[sessionId]/SessionInfo.tsx | 127 +++++++++--------- src/components/hooks/useFormat.ts | 4 +- src/components/icons.ts | 1 + 9 files changed, 123 insertions(+), 223 deletions(-) delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.module.css delete mode 100644 src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.module.css diff --git a/src/app/(main)/websites/[websiteId]/reports/revenue/Revenue.tsx b/src/app/(main)/websites/[websiteId]/reports/revenue/Revenue.tsx index f9a8cb1c1..beac186b5 100644 --- a/src/app/(main)/websites/[websiteId]/reports/revenue/Revenue.tsx +++ b/src/app/(main)/websites/[websiteId]/reports/revenue/Revenue.tsx @@ -138,6 +138,7 @@ export function Revenue({ websiteId, startDate, endDate }: RevenueProps) { ({ x: name, y: value, diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.module.css b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.module.css deleted file mode 100644 index 4794803d2..000000000 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.module.css +++ /dev/null @@ -1,38 +0,0 @@ -.data { - display: flex; - flex-direction: column; - gap: 20px; - position: relative; -} - -.header { - font-weight: bold; - margin-bottom: 20px; -} - -.empty { - color: var(--font-color300); - text-align: center; -} - -.label { - display: flex; - align-items: center; - justify-content: space-between; -} - -.type { - font-size: 11px; - padding: 0 6px; - border-radius: 4px; - border: 1px solid var(--base400); -} - -.name { - color: var(--font-color200); - font-weight: bold; -} - -.value { - margin: 5px 0; -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx index d0e091e3d..70e1a1715 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx @@ -1,33 +1,33 @@ -import { Text } from '@umami/react-zen'; -import { useMessages, useSessionDataQuery } from '@/components/hooks'; +import { Text, Column, Row, Label, Box } from '@umami/react-zen'; +import { useSessionDataQuery } from '@/components/hooks'; import { Empty } from '@/components/common/Empty'; import { DATA_TYPES } from '@/lib/constants'; -import styles from './SessionData.module.css'; import { LoadingPanel } from '@/components/common/LoadingPanel'; export function SessionData({ websiteId, sessionId }: { websiteId: string; sessionId: string }) { - const { formatMessage, labels } = useMessages(); - const { data, ...query } = useSessionDataQuery(websiteId, sessionId); + const { data, isLoading, error } = useSessionDataQuery(websiteId, sessionId); + const isEmpty = !data?.length; return ( - <> -
{formatMessage(labels.properties)}
- - {!data?.length && } + + {!data?.length && } + {data?.map(({ dataKey, dataType, stringValue }) => { return ( -
-
-
- {dataKey} -
-
{DATA_TYPES[dataType]}
-
-
{stringValue}
-
+ + + + {stringValue} + + + {DATA_TYPES[dataType]} + + + + ); })} -
- + +
); } diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.module.css b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.module.css deleted file mode 100644 index 7058cd793..000000000 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.module.css +++ /dev/null @@ -1,47 +0,0 @@ -.page { - display: grid; - grid-template-columns: max-content 1fr max-content; - margin-bottom: 40px; - position: relative; -} - -.sidebar { - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - gap: 20px; - width: 300px; - padding-right: 20px; - border-right: 1px solid var(--base300); - position: relative; -} - -.content { - display: flex; - flex-direction: column; - gap: 30px; - padding: 0 20px; - position: relative; -} - -.data { - width: 300px; - border-left: 1px solid var(--base300); - padding-left: 20px; - position: relative; - transition: width 200ms ease-in-out; -} - -@media screen and (max-width: 992px) { - .page { - grid-template-columns: 1fr; - gap: 30px; - } - - .sidebar, - .data { - border: 0; - width: auto; - } -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx index 2aea2023a..27e058606 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx @@ -1,8 +1,8 @@ 'use client'; -import { Grid, Row, Column } from '@umami/react-zen'; +import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; import { Avatar } from '@/components/common/Avatar'; import { LoadingPanel } from '@/components/common/LoadingPanel'; -import { useWebsiteSessionQuery } from '@/components/hooks'; +import { useMessages, useWebsiteSessionQuery } from '@/components/hooks'; import { SessionActivity } from './SessionActivity'; import { SessionData } from './SessionData'; import { SessionInfo } from './SessionInfo'; @@ -16,38 +16,41 @@ export function SessionDetailsPage({ websiteId: string; sessionId: string; }) { - const { data, ...query } = useWebsiteSessionQuery(websiteId, sessionId); + const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId); + const { formatMessage, labels } = useMessages(); return ( - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + {formatMessage(labels.activity)} + {formatMessage(labels.properties)} + + + + + + + + + + ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.module.css b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.module.css deleted file mode 100644 index de6e796f7..000000000 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.module.css +++ /dev/null @@ -1,21 +0,0 @@ -.info { - display: grid; - gap: 10px; -} - -.info dl { - width: 100%; -} - -.info dt { - color: var(--font-color200); - font-weight: bold; -} - -.info dd { - display: flex; - gap: 10px; - align-items: center; - margin: 5px 0 28px; - text-align: left; -} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx index 2009bb35e..a3336fde3 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx @@ -1,7 +1,8 @@ -import { Icon, TextField, Column, Row, Label, Box, Text } from '@umami/react-zen'; +import { ReactNode } from 'react'; +import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen'; import { useFormat, useLocale, useMessages, useRegionNames, useTimezone } from '@/components/hooks'; import { TypeIcon } from '@/components/common/TypeIcon'; -import { Location } from '@/components/icons'; +import { Location, KeyRound, Calendar } from '@/components/icons'; export function SessionInfo({ data }) { const { locale } = useLocale(); @@ -12,77 +13,77 @@ export function SessionInfo({ data }) { return ( - - + - + - - - {data?.distinctId} - + }> + {data?.distinctId} + - - - {formatTimezoneDate(data?.lastAt, 'PPPPpp')} - + }> + {formatTimezoneDate(data?.lastAt, 'PPPPpp')} + - - - {formatTimezoneDate(data?.firstAt, 'PPPPpp')} - + }> + {formatTimezoneDate(data?.firstAt, 'PPPPpp')} + - - - - - {formatValue(data?.country, 'country')} - - + } + > + {formatValue(data?.country, 'country')} + - - - - - - - {getRegionName(data?.region)} - - + }> + {getRegionName(data?.region)} + - - - - - - - {data?.city} - - + }> + {data?.city} + - - - - - {formatValue(data?.os, 'os')} - - + } + > + {formatValue(data?.os, 'os')} + - - - - - {formatValue(data?.device, 'device')} - - + } + > + {formatValue(data?.device, 'device')} + - - - - - {formatValue(data?.browser, 'browser')} - - + } + > + {formatValue(data?.browser, 'browser')} + ); } + +const Info = ({ + label, + icon, + children, +}: { + label: string; + icon?: ReactNode; + children: ReactNode; +}) => { + return ( + + + + {icon && {icon}} + {children || '—'} + + + ); +}; diff --git a/src/components/hooks/useFormat.ts b/src/components/hooks/useFormat.ts index fb36ae880..6f0b436fb 100644 --- a/src/components/hooks/useFormat.ts +++ b/src/components/hooks/useFormat.ts @@ -24,7 +24,7 @@ export function useFormat() { }; const formatCountry = (value: string): string => { - return countryNames[value] || value || labels.unknown; + return countryNames[value] || value; }; const formatRegion = (value?: string): string => { @@ -57,7 +57,7 @@ export function useFormat() { case 'language': return formatLanguage(value); default: - return value; + return typeof value === 'string' ? value : undefined; } }; diff --git a/src/components/icons.ts b/src/components/icons.ts index 232a781d7..56b71869f 100644 --- a/src/components/icons.ts +++ b/src/components/icons.ts @@ -14,6 +14,7 @@ export { File, Globe, Grid2X2, + KeyRound, LayoutDashboard, Link, ListFilter,