107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
import { isSameUrl } from '@/lib/utils';
|
|
import { edit } from '@/routes/profile';
|
|
import { Link } from '@inertiajs/react';
|
|
import { type InertiaLinkProps } from '@inertiajs/react';
|
|
import { Box, Button, Stack, Text, Title } from '@mantine/core';
|
|
import { IconUserCircle, type IconProps } from '@tabler/icons-react';
|
|
import { type FC, type PropsWithChildren } from 'react';
|
|
|
|
type SettingsNavItem = {
|
|
title: string;
|
|
href: NonNullable<InertiaLinkProps['href']>;
|
|
icon: FC<IconProps>;
|
|
};
|
|
|
|
const sidebarNavItems: SettingsNavItem[] = [
|
|
{
|
|
title: 'Profile',
|
|
href: edit(),
|
|
icon: IconUserCircle,
|
|
},
|
|
];
|
|
|
|
export default function SettingsLayout({ children }: PropsWithChildren) {
|
|
if (typeof window === 'undefined') {
|
|
return null;
|
|
}
|
|
|
|
const currentPath = window.location.pathname;
|
|
|
|
return (
|
|
<Stack spacing="xl">
|
|
<Stack spacing={4}>
|
|
<Title order={2} size="h3">
|
|
Settings
|
|
</Title>
|
|
<Text size="sm" color="dimmed">
|
|
Manage your profile and account settings.
|
|
</Text>
|
|
</Stack>
|
|
|
|
<Box
|
|
sx={(theme) => ({
|
|
display: 'flex',
|
|
alignItems: 'flex-start',
|
|
gap: theme.spacing.xl,
|
|
|
|
[theme.fn.smallerThan('sm')]: {
|
|
flexDirection: 'column',
|
|
},
|
|
})}
|
|
>
|
|
<Box
|
|
sx={(theme) => ({
|
|
width: 180,
|
|
flexShrink: 0,
|
|
|
|
[theme.fn.smallerThan('sm')]: {
|
|
width: '100%',
|
|
},
|
|
})}
|
|
>
|
|
<Stack spacing="xs">
|
|
{sidebarNavItems.map((item) => {
|
|
const Icon = item.icon;
|
|
const active = isSameUrl(currentPath, item.href);
|
|
|
|
return (
|
|
<Button
|
|
key={item.title}
|
|
component={Link}
|
|
href={item.href}
|
|
variant={active ? 'light' : 'subtle'}
|
|
color={active ? 'blue' : 'gray'}
|
|
leftIcon={Icon ? <Icon size={18} /> : null}
|
|
fullWidth
|
|
styles={{
|
|
inner: {
|
|
justifyContent: 'flex-start',
|
|
},
|
|
}}
|
|
>
|
|
{item.title}
|
|
</Button>
|
|
);
|
|
})}
|
|
</Stack>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={(theme) => ({
|
|
flex: 1,
|
|
minWidth: 0,
|
|
maxWidth: 640,
|
|
|
|
[theme.fn.smallerThan('sm')]: {
|
|
maxWidth: '100%',
|
|
width: '100%',
|
|
},
|
|
})}
|
|
>
|
|
{children}
|
|
</Box>
|
|
</Box>
|
|
</Stack>
|
|
);
|
|
}
|