Fixed nav menus.

This commit is contained in:
Mike Cao 2025-11-28 00:33:53 -08:00
parent dcc1ae1864
commit d7fd22645c
9 changed files with 62 additions and 7 deletions

48
pnpm-lock.yaml generated
View file

@ -328,7 +328,44 @@ importers:
specifier: ^5.9.3 specifier: ^5.9.3
version: 5.9.3 version: 5.9.3
dist: {} dist:
dependencies:
chart.js:
specifier: ^4.5.0
version: 4.5.1
chartjs-adapter-date-fns:
specifier: ^3.0.0
version: 3.0.0(chart.js@4.5.1)(date-fns@2.30.0)
colord:
specifier: ^2.9.2
version: 2.9.3
jsonwebtoken:
specifier: ^9.0.2
version: 9.0.2
lucide-react:
specifier: ^0.542.0
version: 0.542.0(react@19.2.0)
pure-rand:
specifier: ^7.0.1
version: 7.0.1
react-simple-maps:
specifier: ^2.3.0
version: 2.3.0(prop-types@15.8.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
react-use-measure:
specifier: ^2.0.4
version: 2.1.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
react-window:
specifier: ^1.8.6
version: 1.8.11(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
serialize-error:
specifier: ^12.0.0
version: 12.0.0
thenby:
specifier: ^1.3.4
version: 1.3.4
uuid:
specifier: ^11.1.0
version: 11.1.0
packages: packages:
@ -5152,6 +5189,11 @@ packages:
peerDependencies: peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
lucide-react@0.542.0:
resolution: {integrity: sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
lucide-react@0.543.0: lucide-react@0.543.0:
resolution: {integrity: sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==} resolution: {integrity: sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==}
peerDependencies: peerDependencies:
@ -12921,6 +12963,10 @@ snapshots:
dependencies: dependencies:
react: 19.2.0 react: 19.2.0
lucide-react@0.542.0(react@19.2.0):
dependencies:
react: 19.2.0
lucide-react@0.543.0(react@19.2.0): lucide-react@0.543.0(react@19.2.0):
dependencies: dependencies:
react: 19.2.0 react: 19.2.0

View file

@ -21,6 +21,7 @@ export function AdminLayout({ children }: { children: ReactNode }) {
border="right" border="right"
backgroundColor backgroundColor
marginRight="2" marginRight="2"
padding="3"
> >
<AdminNav /> <AdminNav />
</Column> </Column>

View file

@ -50,7 +50,7 @@ export function UserEditForm({ userId, onSave }: { userId: string; onSave?: () =
label={formatMessage(labels.role)} label={formatMessage(labels.role)}
rules={{ required: formatMessage(labels.required) }} rules={{ required: formatMessage(labels.required) }}
> >
<Select defaultSelectedKey={user.role}> <Select defaultValue={user.role}>
<ListItem id={ROLES.viewOnly} data-test="dropdown-item-viewOnly"> <ListItem id={ROLES.viewOnly} data-test="dropdown-item-viewOnly">
{formatMessage(labels.viewOnly)} {formatMessage(labels.viewOnly)}
</ListItem> </ListItem>

View file

@ -14,6 +14,7 @@ export function SettingsLayout({ children }: { children: ReactNode }) {
border="right" border="right"
backgroundColor backgroundColor
marginRight="2" marginRight="2"
padding="3"
> >
<SettingsNav /> <SettingsNav />
</Column> </Column>

View file

@ -3,7 +3,7 @@ import { SettingsLayout } from './SettingsLayout';
export default function ({ children }) { export default function ({ children }) {
if (process.env.cloudMode) { if (process.env.cloudMode) {
//return null; return null;
} }
return <SettingsLayout>{children}</SettingsLayout>; return <SettingsLayout>{children}</SettingsLayout>;

View file

@ -51,7 +51,7 @@ export function SideMenu({
}; };
return ( return (
<Column gap overflowY="auto" justifyContent="space-between"> <Column gap overflowY="auto" justifyContent="space-between" position="sticky" top="20px">
{title && ( {title && (
<Row padding> <Row padding>
<Heading size="1">{title}</Heading> <Heading size="1">{title}</Heading>

View file

@ -1,10 +1,11 @@
import { useToast } from '@umami/react-zen'; import { useToast } from '@umami/react-zen';
import type { ApiError } from '@/lib/types';
import { useApi } from '../useApi'; import { useApi } from '../useApi';
import { useModified } from '../useModified'; import { useModified } from '../useModified';
export function useUpdateQuery(path: string, params?: Record<string, any>) { export function useUpdateQuery(path: string, params?: Record<string, any>) {
const { post, useMutation } = useApi(); const { post, useMutation } = useApi();
const query = useMutation({ const query = useMutation<any, ApiError, Record<string, any>>({
mutationFn: (data: Record<string, any>) => post(path, { ...data, ...params }), mutationFn: (data: Record<string, any>) => post(path, { ...data, ...params }),
}); });
const { touch } = useModified(); const { touch } = useModified();

View file

@ -1,5 +1,6 @@
import { FormattedMessage, type MessageDescriptor, useIntl } from 'react-intl'; import { FormattedMessage, type MessageDescriptor, useIntl } from 'react-intl';
import { labels, messages } from '@/components/messages'; import { labels, messages } from '@/components/messages';
import type { ApiError } from '@/lib/types';
type FormatMessage = ( type FormatMessage = (
descriptor: MessageDescriptor, descriptor: MessageDescriptor,
@ -12,7 +13,7 @@ interface UseMessages {
messages: typeof messages; messages: typeof messages;
labels: typeof labels; labels: typeof labels;
getMessage: (id: string) => string; getMessage: (id: string) => string;
getErrorMessage: (error: unknown) => string | undefined; getErrorMessage: (error: ApiError) => string | undefined;
FormattedMessage: typeof FormattedMessage; FormattedMessage: typeof FormattedMessage;
} }
@ -25,7 +26,7 @@ export function useMessages(): UseMessages {
return message ? formatMessage(message) : id; return message ? formatMessage(message) : id;
}; };
const getErrorMessage = (error: unknown) => { const getErrorMessage = (error: ApiError) => {
if (!error) { if (!error) {
return undefined; return undefined;
} }

View file

@ -136,3 +136,8 @@ export interface RealtimeData {
urls: Record<string, number>; urls: Record<string, number>;
visitors: any[]; visitors: any[];
} }
export interface ApiError extends Error {
code?: string;
message: string;
}