Merge branch 'feature/pencil-design' of github.com:Tria-plc/emaui into feature/pencil-design

This commit is contained in:
mengstabketemaw
2026-06-15 13:32:05 +03:00
8 changed files with 15113 additions and 64 deletions

View File

@@ -9,9 +9,10 @@ export function BackofficeLayout() {
return (
<AppShell
header={{ height: 60 }}
navbar={{ width: 240, breakpoint: 'sm', collapsed: { mobile: !opened } }}
padding="md"
header={{ height: 64 }}
navbar={{ width: 264, breakpoint: 'sm', collapsed: { mobile: !opened } }}
padding="lg"
styles={{ main: { backgroundColor: '#f5f7fb' } }}
>
<AppShell.Header>
<AppHeader onToggle={toggle} />

View File

@@ -1,5 +1,22 @@
import { Group, Text, ActionIcon, Burger } from '@mantine/core';
import { IconLogout } from '@tabler/icons-react';
import {
Group,
Text,
ActionIcon,
Burger,
TextInput,
Avatar,
Menu,
Indicator,
UnstyledButton,
} from '@mantine/core';
import {
IconLogout,
IconBell,
IconSearch,
IconChevronDown,
IconUserCircle,
IconSettings,
} from '@tabler/icons-react';
import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { logout } from '@ema-platform/auth';
@@ -18,16 +35,54 @@ export function AppHeader({ onToggle }: AppHeaderProps) {
};
return (
<Group h="100%" px="md" justify="space-between">
<Group>
<Group h="100%" px="lg" justify="space-between">
<Group gap="sm">
<Burger onClick={onToggle} size="sm" hiddenFrom="sm" />
<Text fw={700} size="lg">
EMA Backoffice
</Text>
<TextInput
visibleFrom="sm"
w={320}
radius="md"
placeholder="Search users, roles..."
leftSection={<IconSearch size={16} />}
/>
</Group>
<Group gap="sm">
<Indicator color="red" size={8} offset={6} withBorder>
<ActionIcon variant="subtle" color="gray" radius="xl" size="lg" aria-label="Notifications">
<IconBell size={19} />
</ActionIcon>
</Indicator>
<Menu position="bottom-end" width={200} shadow="md">
<Menu.Target>
<UnstyledButton>
<Group gap="sm" wrap="nowrap">
<Avatar color="blue" radius="xl" size={36}>
AD
</Avatar>
<div style={{ lineHeight: 1.1 }}>
<Text size="sm" fw={600} visibleFrom="sm">
Amanuel D.
</Text>
<Text size="xs" c="dimmed" visibleFrom="sm">
Administrator
</Text>
</div>
<IconChevronDown size={14} />
</Group>
</UnstyledButton>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item leftSection={<IconUserCircle size={16} />}>Profile</Menu.Item>
<Menu.Item leftSection={<IconSettings size={16} />}>Settings</Menu.Item>
<Menu.Divider />
<Menu.Item color="red" leftSection={<IconLogout size={16} />} onClick={handleLogout}>
Logout
</Menu.Item>
</Menu.Dropdown>
</Menu>
</Group>
<ActionIcon variant="subtle" onClick={handleLogout} title="Logout">
<IconLogout size={18} />
</ActionIcon>
</Group>
);
}

View File

@@ -1,17 +1,15 @@
import { NavLink, Stack } from '@mantine/core';
import { Stack, Group, Text, NavLink, ThemeIcon, Button, Box } from '@mantine/core';
import {
IconDashboard,
IconBox,
IconLayoutDashboard,
IconUsers,
IconClipboardList,
IconShieldCheck,
IconLifebuoy,
} from '@tabler/icons-react';
import { useNavigate, useLocation } from 'react-router-dom';
const NAV_ITEMS = [
{ label: 'Dashboard', icon: IconDashboard, path: '/dashboard' },
{ label: 'Items', icon: IconBox, path: '/items' },
{ label: 'Dashboard', icon: IconLayoutDashboard, path: '/dashboard' },
{ label: 'User Management', icon: IconUsers, path: '/um' },
{ label: 'Audit Log', icon: IconClipboardList, path: '/audit-log' },
];
export function AppSidebar() {
@@ -19,16 +17,77 @@ export function AppSidebar() {
const { pathname } = useLocation();
return (
<Stack p="xs" gap={4}>
{NAV_ITEMS.map(({ label, icon: Icon, path }) => (
<NavLink
key={path}
label={label}
leftSection={<Icon size={18} />}
active={pathname.startsWith(path)}
onClick={() => navigate(path)}
/>
))}
<Stack h="100%" justify="space-between" p="md" gap="lg">
<Stack gap="lg">
{/* brand */}
<Group gap="sm" px={4} wrap="nowrap">
<ThemeIcon size={42} radius="md" variant="gradient" gradient={{ from: 'blue', to: 'indigo', deg: 135 }}>
<IconShieldCheck size={22} />
</ThemeIcon>
<div>
<Text fw={700} lh={1.1}>
EMA Admin
</Text>
<Text size="xs" c="dimmed">
Control Center
</Text>
</div>
</Group>
{/* menu */}
<div>
<Text size="xs" fw={700} c="dimmed" px="xs" mb={8} style={{ letterSpacing: 1 }}>
MENU
</Text>
<Stack gap={4}>
{NAV_ITEMS.map(({ label, icon: Icon, path }) => (
<NavLink
key={path}
label={label}
leftSection={<Icon size={19} />}
active={pathname.startsWith(path)}
onClick={() => navigate(path)}
variant="light"
color="blue"
styles={{ root: { borderRadius: 10 }, label: { fontWeight: 500 } }}
/>
))}
</Stack>
</div>
</Stack>
{/* help card */}
<Box
style={{
borderRadius: 16,
padding: 18,
color: '#fff',
background: 'linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%)',
}}
>
<Box
w={36}
h={36}
style={{
borderRadius: 10,
background: 'rgba(255,255,255,0.18)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<IconLifebuoy size={20} />
</Box>
<Text fw={700} mt="sm">
Need help?
</Text>
<Text size="xs" mt={4} style={{ opacity: 0.85 }}>
Browse guides or contact support.
</Text>
<Button fullWidth mt="md" size="xs" radius="md" variant="white" color="blue">
Open Help Center
</Button>
</Box>
</Stack>
);
}