merge design protal and backoffice

This commit is contained in:
mengstabketemaw
2026-06-17 13:50:20 +03:00
parent 36234a2948
commit 85e070db33
25 changed files with 2618 additions and 847 deletions

View File

@@ -0,0 +1,83 @@
import { Menu, UnstyledButton, Text, rem } from '@mantine/core';
import { IconWorld, IconCheck, IconChevronDown } from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
interface LanguageSwitcherProps {
supportedLanguages: readonly string[];
/** `icon` renders a compact globe button; `button` shows the language label. */
variant?: 'icon' | 'button';
}
export function LanguageSwitcher({ supportedLanguages, variant = 'icon' }: LanguageSwitcherProps) {
const { t, i18n } = useTranslation();
const current = i18n.language;
const change = (lng: string) => {
if (lng !== current) i18n.changeLanguage(lng);
};
return (
<Menu shadow="md" width={160} position="bottom-end" withinPortal>
<Menu.Target>
<UnstyledButton
aria-label={t('language.label')}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: rem(4),
width: variant === 'icon' ? rem(38) : 'auto',
height: rem(38),
padding: variant === 'icon' ? 0 : '0 12px',
borderRadius: rem(12),
background: 'var(--mantine-color-body)',
color: 'var(--mantine-color-gray-6)',
boxShadow: '0 1px 3px rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.06)',
transition: 'all 150ms ease',
cursor: 'pointer',
border: 'none',
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = 'var(--mantine-color-primary-light)';
e.currentTarget.style.color = 'var(--mantine-color-primary-6)';
e.currentTarget.style.boxShadow =
'0 1px 3px rgba(0,0,0,0.04), 0 0 0 1px var(--mantine-color-primary-2)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'var(--mantine-color-body)';
e.currentTarget.style.color = 'var(--mantine-color-gray-6)';
e.currentTarget.style.boxShadow =
'0 1px 3px rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.06)';
}}
>
<IconWorld size={19} />
{variant !== 'icon' && (
<>
<Text size="sm" fw={500}>
{t(`language.${current}`)}
</Text>
<IconChevronDown size={14} />
</>
)}
</UnstyledButton>
</Menu.Target>
<Menu.Dropdown
style={{ borderRadius: rem(12), padding: rem(6) }}
>
<Menu.Label>{t('language.label')}</Menu.Label>
{supportedLanguages.map((lng) => (
<Menu.Item
key={lng}
onClick={() => change(lng)}
rightSection={
current === lng ? <IconCheck size={16} /> : undefined
}
style={{ borderRadius: rem(8) }}
>
{t(`language.${lng}`)}
</Menu.Item>
))}
</Menu.Dropdown>
</Menu>
);
}