diff --git a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx index 3696b786..df476e79 100644 --- a/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsiteNav.tsx @@ -1,14 +1,5 @@ import { Text } from '@umami/react-zen'; -import { - Eye, - User, - Clock, - Sheet, - Tag, - ChartPie, - UserPlus, - GitCompareArrows, -} from '@/components/icons'; +import { Eye, User, Clock, Ungroup, Tag, ChartPie, UserPlus, GitCompare } from '@/components/icons'; import { Lightning, Path, Money, Target, Funnel, Magnet, Network } from '@/components/svg'; import { useMessages, useNavigation } from '@/components/hooks'; import { SideMenu } from '@/components/common/SideMenu'; @@ -56,13 +47,13 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) { { id: 'compare', label: formatMessage(labels.compare), - icon: , + icon: , path: renderPath('/compare'), }, { id: 'breakdown', label: formatMessage(labels.breakdown), - icon: , + icon: , path: renderPath('/breakdown'), }, ], diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx similarity index 97% rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx rename to src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx index 4ed55427..4dcf08b4 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionActivity.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx @@ -47,7 +47,7 @@ export function SessionActivity({ return ( - {showHeader && {formatTimezoneDate(createdAt, 'PPPP')}} + {showHeader && {formatTimezoneDate(createdAt, 'PPPP')}} {formatTimezoneDate(createdAt, 'pp')} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionData.tsx similarity index 100% rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionData.tsx rename to src/app/(main)/websites/[websiteId]/sessions/SessionData.tsx diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx similarity index 93% rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx rename to src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx index 4ebb462c..c2127cf5 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionInfo.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionInfo.tsx @@ -1,5 +1,5 @@ import { ReactNode } from 'react'; -import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen'; +import { Icon, TextField, Column, Row, Label } from '@umami/react-zen'; import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks'; import { TypeIcon } from '@/components/common/TypeIcon'; import { KeyRound, Calendar } from '@/components/icons'; @@ -15,7 +15,7 @@ export function SessionInfo({ data }) { return ( - + }> @@ -83,7 +83,7 @@ const Info = ({ {icon && {icon}} - {children || '—'} + {children || '—'} ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx similarity index 58% rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx rename to src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx index 86e3cdbf..bdbfbc58 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionDetailsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProfile.tsx @@ -1,37 +1,52 @@ -'use client'; -import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel } from '@umami/react-zen'; +import { Grid, Row, Column, Tabs, TabList, Tab, TabPanel, Icon, Button } from '@umami/react-zen'; import { Avatar } from '@/components/common/Avatar'; import { LoadingPanel } from '@/components/common/LoadingPanel'; +import { X } from '@/components/icons'; import { useMessages, useWebsiteSessionQuery } from '@/components/hooks'; import { SessionActivity } from './SessionActivity'; import { SessionData } from './SessionData'; import { SessionInfo } from './SessionInfo'; import { SessionStats } from './SessionStats'; -import { Panel } from '@/components/common/Panel'; -export function SessionDetailsPage({ +export function SessionProfile({ websiteId, sessionId, + onClose, }: { websiteId: string; sessionId: string; + onClose?: () => void; }) { const { data, isLoading, error } = useWebsiteSessionQuery(websiteId, sessionId); const { formatMessage, labels } = useMessages(); return ( - + {data && ( - - - - - - - - - - + + + + + + + + + + + + + + {formatMessage(labels.activity)} @@ -49,9 +64,9 @@ export function SessionDetailsPage({ - - - + + + )} ); diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx index ea4b5f03..e66302ad 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionProperties.tsx @@ -1,5 +1,5 @@ import { useMemo, useState } from 'react'; -import { Select, ListItem, Grid } from '@umami/react-zen'; +import { Select, ListItem, Grid, Column } from '@umami/react-zen'; import { useMessages, useSessionDataPropertiesQuery, @@ -24,25 +24,26 @@ export function SessionProperties({ websiteId }: { websiteId: string }) { data={data} error={error} minHeight="300px" - gap="6" > - {data && ( - - - - )} - {propertyName && } + + {data && ( + + + + )} + {propertyName && } + ); } @@ -84,7 +85,6 @@ const SessionValues = ({ websiteId, propertyName }) => { data={data} error={error} minHeight="300px" - gap="6" > {data && ( diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionStats.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionStats.tsx similarity index 100% rename from src/app/(main)/websites/[websiteId]/sessions/[sessionId]/SessionStats.tsx rename to src/app/(main)/websites/[websiteId]/sessions/SessionStats.tsx diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx index 68eef29c..ae0d4104 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsPage.tsx @@ -1,18 +1,35 @@ 'use client'; import { Key, useState } from 'react'; -import { TabList, Tab, Tabs, TabPanel, Column } from '@umami/react-zen'; +import { TabList, Tab, Tabs, TabPanel, Column, Modal, Dialog } from '@umami/react-zen'; import { SessionsDataTable } from './SessionsDataTable'; import { SessionProperties } from './SessionProperties'; -import { useMessages } from '@/components/hooks'; +import { useMessages, useNavigation } from '@/components/hooks'; import { Panel } from '@/components/common/Panel'; import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls'; import { getItem, setItem } from '@/lib/storage'; +import { SessionProfile } from '@/app/(main)/websites/[websiteId]/sessions/SessionProfile'; const KEY_NAME = 'umami.sessions.tab'; export function SessionsPage({ websiteId }) { const [tab, setTab] = useState(getItem(KEY_NAME) || 'activity'); const { formatMessage, labels } = useMessages(); + const { + router, + query: { session }, + updateParams, + } = useNavigation(); + + const handleClose = (close: () => void) => { + router.push(updateParams({ session: undefined })); + close(); + }; + + const handleOpenChange = (isOpen: boolean) => { + if (!isOpen) { + router.push(updateParams({ session: undefined })); + } + }; const handleSelect = (value: Key) => { setItem(KEY_NAME, value); @@ -36,6 +53,26 @@ export function SessionsPage({ websiteId }) { + + + {({ close }) => { + return ( + handleClose(close)} + /> + ); + }} + + ); } diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx index fa3be6c7..391c57f4 100644 --- a/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx +++ b/src/app/(main)/websites/[websiteId]/sessions/SessionsTable.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; import { DataColumn, DataTable } from '@umami/react-zen'; -import { useFormat, useMessages } from '@/components/hooks'; +import { useFormat, useMessages, useNavigation } from '@/components/hooks'; import { Avatar } from '@/components/common/Avatar'; import { TypeIcon } from '@/components/common/TypeIcon'; import { DateDistance } from '@/components/common/DateDistance'; @@ -8,12 +8,13 @@ import { DateDistance } from '@/components/common/DateDistance'; export function SessionsTable({ data = [] }: { data: any[]; showDomain?: boolean }) { const { formatMessage, labels } = useMessages(); const { formatValue } = useFormat(); + const { updateParams } = useNavigation(); return ( {(row: any) => ( - + )} diff --git a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx b/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx deleted file mode 100644 index 8d85a7c7..00000000 --- a/src/app/(main)/websites/[websiteId]/sessions/[sessionId]/page.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { SessionDetailsPage } from './SessionDetailsPage'; -import { Metadata } from 'next'; - -export default async function WebsitePage({ - params, -}: { - params: Promise<{ websiteId: string; sessionId: string }>; -}) { - const { websiteId, sessionId } = await params; - - return ; -} - -export const metadata: Metadata = { - title: 'Websites', -}; diff --git a/src/components/common/LoadingPanel.tsx b/src/components/common/LoadingPanel.tsx index a0159a02..b3ff7a09 100644 --- a/src/components/common/LoadingPanel.tsx +++ b/src/components/common/LoadingPanel.tsx @@ -29,25 +29,31 @@ export function LoadingPanel({ }: LoadingPanelProps) { const empty = isEmpty ?? checkEmpty(data); - return ( - <> - {/* Show loading spinner only if no data exists */} - {(isLoading || isFetching) && ( - - - - )} + // Show loading spinner only if no data exists + if (isLoading || isFetching) { + return ( + + + + ); + } - {/* Show error */} - {error && } + // Show error + if (error) { + return ; + } - {/* Show empty state (once loaded) */} - {!error && !isLoading && !isFetching && empty && renderEmpty()} + // Show empty state (once loaded) + if (!error && !isLoading && !isFetching && empty) { + return renderEmpty(); + } - {/* Show main content when data exists */} - {!isLoading && !isFetching && !error && !empty && children} - - ); + // Show main content when data exists + if (!isLoading && !isFetching && !error && !empty) { + return children; + } + + return null; } function checkEmpty(data: any) { diff --git a/src/components/hooks/queries/useWebsiteSessionQuery.ts b/src/components/hooks/queries/useWebsiteSessionQuery.ts index 053dae31..21e94911 100644 --- a/src/components/hooks/queries/useWebsiteSessionQuery.ts +++ b/src/components/hooks/queries/useWebsiteSessionQuery.ts @@ -8,5 +8,6 @@ export function useWebsiteSessionQuery(websiteId: string, sessionId: string) { queryFn: () => { return get(`/websites/${websiteId}/sessions/${sessionId}`); }, + enabled: Boolean(websiteId && sessionId), }); } diff --git a/src/components/hooks/useDateRange.ts b/src/components/hooks/useDateRange.ts index 0b8db7ce..b5d967ed 100644 --- a/src/components/hooks/useDateRange.ts +++ b/src/components/hooks/useDateRange.ts @@ -6,7 +6,7 @@ import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants'; export function useDateRange(options: { ignoreOffset?: boolean } = {}) { const { - query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev', all }, + query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev' }, } = useNavigation(); const { locale } = useLocale(); @@ -24,7 +24,7 @@ export function useDateRange(options: { ignoreOffset?: boolean } = {}) { date, offset, compare, - isAllTime: !!all, + isAllTime: date.endsWith(`:all`), isCustomRange: date.startsWith('range:'), dateRange, dateCompare, diff --git a/src/components/input/DateFilter.tsx b/src/components/input/DateFilter.tsx index cd016491..44c725cf 100644 --- a/src/components/input/DateFilter.tsx +++ b/src/components/input/DateFilter.tsx @@ -99,11 +99,13 @@ export function DateFilter({ ); }; + const selectedValue = value.endsWith(':all') ? 'all' : value; + return ( <> , + style: { maxHeight: '400px' }, }} > {({ id, name }: any) => {name}}