Updated layout. Fixed properties rendering.

This commit is contained in:
Mike Cao 2025-07-18 00:22:06 -07:00
parent 01bfd7f52e
commit 876f4c883e
18 changed files with 214 additions and 176 deletions

View file

@ -12,7 +12,7 @@ export function WebsiteHeader() {
const website = useWebsite();
return (
<PageHeader title={website.name} icon={<Favicon domain={website.domain} />}>
<PageHeader title={website.name} icon={<Favicon domain={website.domain} />} marginBottom="3">
<Row alignItems="center" gap="6">
<ActiveUsers websiteId={website.id} />
<Row alignItems="center" gap>

View file

@ -1,25 +1,17 @@
'use client';
import { ReactNode } from 'react';
import { Column, Grid } from '@umami/react-zen';
import { Column } from '@umami/react-zen';
import { WebsiteProvider } from './WebsiteProvider';
import { PageBody } from '@/components/common/PageBody';
import { WebsiteHeader } from './WebsiteHeader';
import { WebsiteNav } from '@/app/(main)/websites/[websiteId]/WebsiteNav';
export function WebsiteLayout({ websiteId, children }: { websiteId: string; children: ReactNode }) {
return (
<WebsiteProvider websiteId={websiteId}>
<Grid columns="200px 1fr" gap width="100%">
<Column padding>
<WebsiteNav websiteId={websiteId} />
</Column>
<PageBody>
<Column gap>
<WebsiteHeader />
<Column>{children}</Column>
</Column>
</PageBody>
</Grid>
<PageBody gap>
<WebsiteHeader />
<Column>{children}</Column>
</PageBody>
</WebsiteProvider>
);
}

View file

@ -1,4 +1,4 @@
import { Icon, Text, Row, NavMenu, NavMenuItem, NavMenuGroup } from '@umami/react-zen';
import { Icon, Text, Row, NavMenu, NavMenuItem, NavMenuGroup, Column } from '@umami/react-zen';
import {
Eye,
Lightning,
@ -12,6 +12,8 @@ import {
Tag,
Money,
Network,
UserPlus,
ChartPie,
} from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks';
import Link from 'next/link';
@ -22,7 +24,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
const links = [
{
label: formatMessage(labels.core),
label: formatMessage(labels.traffic),
items: [
{
id: 'overview',
@ -88,6 +90,18 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
icon: <Sheet />,
path: '/breakdown',
},
{
id: 'segments',
label: formatMessage(labels.segments),
icon: <ChartPie />,
path: '/segments',
},
{
id: 'cohorts',
label: formatMessage(labels.cohorts),
icon: <UserPlus />,
path: '/cohorts',
},
],
},
{
@ -120,27 +134,29 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
'overview';
return (
<NavMenu highlightColor="3" style={{ position: 'sticky', top: 'var(--spacing-2)' }}>
{links.map(({ label, items }) => {
return (
<NavMenuGroup title={label} key={label} gap="2">
{items.map(({ id, label, icon, path }) => {
const isSelected = selected === id;
<Column gap padding width="240px" border="left">
<NavMenu highlightColor="2">
{links.map(({ label, items }) => {
return (
<NavMenuGroup title={label} key={label} gap="1">
{items.map(({ id, label, icon, path }) => {
const isSelected = selected === id;
return (
<Link key={id} href={renderUrl(`/websites/${websiteId}${path}`)}>
<NavMenuItem isSelected={isSelected}>
<Row alignItems="center" gap>
<Icon>{icon}</Icon>
<Text>{label}</Text>
</Row>
</NavMenuItem>
</Link>
);
})}
</NavMenuGroup>
);
})}
</NavMenu>
return (
<Link key={id} href={renderUrl(`/websites/${websiteId}${path}`)}>
<NavMenuItem isSelected={isSelected}>
<Row alignItems="center" gap>
<Icon>{icon}</Icon>
<Text>{label}</Text>
</Row>
</NavMenuItem>
</Link>
);
})}
</NavMenuGroup>
);
})}
</NavMenu>
</Column>
);
}

View file

@ -28,41 +28,43 @@ export function EventProperties({ websiteId }: { websiteId: string }) {
return (
<LoadingPanel
data={data}
isLoading={isLoading}
isFetching={isFetching}
data={data}
error={error}
minHeight="300px"
gap="6"
>
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" gap>
<Select
label={formatMessage(labels.event)}
value={eventName}
onChange={setEventName}
placeholder=""
>
{events?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
<Select
label={formatMessage(labels.property)}
value={propertyName}
onChange={setPropertyName}
isDisabled={!eventName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
{propertyName && (
{data && (
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" gap>
<Select
label={formatMessage(labels.event)}
value={eventName}
onChange={setEventName}
placeholder=""
>
{events?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
<Select
label={formatMessage(labels.property)}
value={propertyName}
onChange={setPropertyName}
isDisabled={!eventName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
)}
{eventName && propertyName && (
<EventValues websiteId={websiteId} eventName={eventName} propertyName={propertyName} />
)}
</LoadingPanel>
@ -113,10 +115,12 @@ const EventValues = ({ websiteId, eventName, propertyName }) => {
minHeight="300px"
gap="6"
>
<Grid columns="1fr 1fr" gap>
{values && <ListTable title={propertyName} data={tableData} />}
<PieChart key={propertyName + eventName} type="doughnut" chartData={chartData} />
</Grid>
{values && (
<Grid columns="1fr 1fr" gap>
<ListTable title={propertyName} data={tableData} />
<PieChart type="doughnut" chartData={chartData} />
</Grid>
)}
</LoadingPanel>
);
};

View file

@ -26,20 +26,22 @@ export function SessionProperties({ websiteId }: { websiteId: string }) {
minHeight="300px"
gap="6"
>
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" gap>
<Select
label={formatMessage(labels.event)}
value={propertyName}
onChange={setPropertyName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
{data && (
<Grid columns="repeat(auto-fill, minmax(300px, 1fr))" gap>
<Select
label={formatMessage(labels.event)}
value={propertyName}
onChange={setPropertyName}
placeholder=""
>
{properties?.map(p => (
<ListItem key={p} id={p}>
{p}
</ListItem>
))}
</Select>
</Grid>
)}
{propertyName && <SessionValues websiteId={websiteId} propertyName={propertyName} />}
</LoadingPanel>
);
@ -84,10 +86,12 @@ const SessionValues = ({ websiteId, propertyName }) => {
minHeight="300px"
gap="6"
>
<Grid columns="1fr 1fr" gap>
{data && <ListTable title={propertyName} data={tableData} />}
<PieChart key={propertyName} type="doughnut" chartData={chartData} />
</Grid>
{data && (
<Grid columns="1fr 1fr" gap>
<ListTable title={propertyName} data={tableData} />
<PieChart type="doughnut" chartData={chartData} />
</Grid>
)}
</LoadingPanel>
);
};