feat: add configurable sidebar and top navigation layout modes commit

This commit is contained in:
mengstabketemaw
2026-06-19 16:17:01 +03:00
parent ddd91b6125
commit 1f27a36b90
6 changed files with 196 additions and 67 deletions

View File

@@ -26,6 +26,8 @@ import {
IconCircleCheckFilled,
IconDeviceDesktop,
IconDeviceFloppy,
IconLayoutNavbar,
IconLayoutSidebar,
IconLock,
IconMail,
IconMoon,
@@ -46,6 +48,8 @@ import { setUser } from '@ema-platform/auth';
import type { AuthUser } from '@ema-platform/auth';
import { SUPPORTED_LANGUAGES, type AppLanguage } from '../../../i18n/config';
import { useAppDispatch, useAppSelector } from '../../../store/hooks';
import { setLayoutMode } from '../../../store/preferences.slice';
import type { LayoutMode } from '../../../store/preferences.slice';
import classes from './ProfilePage.module.css';
function getInitials(name: string, fallback: string) {
@@ -72,6 +76,7 @@ export function ProfilePage() {
const dispatch = useAppDispatch();
const user = useAppSelector((state) => state.auth.user);
const { colorScheme, setColorScheme } = useMantineColorScheme();
const layoutMode = useAppSelector((state) => state.preferences.layoutMode);
const [updateTrigger] = useApiMutation<AuthUser>();
const [meTrigger] = useApiMutation<AuthUser>();
@@ -572,6 +577,48 @@ export function ProfilePage() {
<Divider />
<div>
<Title order={5}>{t('profile.layout.title')}</Title>
<Text size="sm" c="dimmed" mb="md">
{t('profile.layout.subtitle')}
</Text>
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
{([{ value: 'top', label: t('profile.layout.top'), icon: IconLayoutNavbar }, { value: 'sidebar', label: t('profile.layout.sidebar'), icon: IconLayoutSidebar }] as const).map(({ value, label, icon: Icon }) => {
const active = layoutMode === value;
return (
<UnstyledButton
key={value}
onClick={() => dispatch(setLayoutMode(value))}
className={`${classes.choice} ${active ? classes.choiceActive : ''}`}
p="md"
>
<Group wrap="nowrap">
<Icon
size={20}
color={
active
? 'var(--mantine-color-emaPrimary-6)'
: 'var(--mantine-color-gray-6)'
}
/>
<Text fw={600} size="sm" style={{ flex: 1 }}>
{label}
</Text>
{active && (
<IconCircleCheckFilled
size={18}
color="var(--mantine-color-emaPrimary-6)"
/>
)}
</Group>
</UnstyledButton>
);
})}
</SimpleGrid>
</div>
<Divider />
<Group align="flex-start" justify="space-between" wrap="nowrap">
<Group gap="sm" wrap="nowrap">
<IconBell size={20} color="var(--mantine-color-gray-6)" />