inspiren-sem-tool/resources/js/layouts/settings/layout.tsx
brian-inspiren 221d3f8173
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
feat: sem codebase
2026-05-21 11:28:03 +08:00

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>
);
}