diff --git a/dashboard/src/components/Layout.css b/dashboard/src/components/Layout.css index 0db1288..7555f1b 100644 --- a/dashboard/src/components/Layout.css +++ b/dashboard/src/components/Layout.css @@ -195,6 +195,77 @@ color: var(--text-primary); } +.language-btn { + display: flex; + align-items: center; + justify-content: flex-start; + gap: 0.75rem; + padding: 0.6rem 0.9rem; + color: var(--text-secondary); + background: none; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; + white-space: nowrap; + overflow: hidden; + width: 100%; + text-align: left; +} + +.sidebar.collapsed .language-btn { + justify-content: center; + padding: 0.6rem; +} + +.language-btn:hover { + background: var(--bg-light); + color: var(--text-primary); +} + +.language-dropdown { + position: absolute; + bottom: calc(100% + 4px); + left: 0; + right: 0; + z-index: 9999; + background: var(--bg-white); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + padding: 0.25rem; + min-width: 120px; +} + +[dir="rtl"] .language-dropdown { + left: 0; + right: 0; +} + +.language-option { + padding: 0.5rem 0.75rem; + border-radius: calc(var(--radius) / 2); + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + color: var(--text-secondary); + transition: all 0.15s; + white-space: nowrap; +} + +.language-option:hover { + background: var(--bg-light); + color: var(--text-primary); +} + +.language-option.active { + background: rgba(37, 211, 102, 0.1); + color: var(--primary); + font-weight: 600; +} + .logout-btn { display: flex; align-items: center; diff --git a/dashboard/src/components/Layout.tsx b/dashboard/src/components/Layout.tsx index f2815bb..b2f9400 100644 --- a/dashboard/src/components/Layout.tsx +++ b/dashboard/src/components/Layout.tsx @@ -22,7 +22,7 @@ import { } from 'lucide-react'; import { useTheme } from '../hooks/useTheme'; import { type UserRole } from '../hooks/useRole'; -import { supportedLanguages, type SupportedLanguage } from '../i18n'; +import { type SupportedLanguage } from '../i18n'; import './Layout.css'; interface LayoutProps { @@ -54,6 +54,7 @@ export function Layout({ onLogout, userRole }: LayoutProps) { const [isCollapsed, setIsCollapsed] = useState(false); const [isMobileOpen, setIsMobileOpen] = useState(false); const [isMobile, setIsMobile] = useState(window.innerWidth < 768); + const [showLangDropdown, setShowLangDropdown] = useState(false); useEffect(() => { const handleResize = () => { @@ -76,17 +77,34 @@ export function Layout({ onLogout, userRole }: LayoutProps) { }; }, [isMobileOpen]); + useEffect(() => { + if (!showLangDropdown) return; + const handleClick = (e: MouseEvent) => { + const target = e.target as HTMLElement; + if (!target.closest('.language-wrapper')) { + setShowLangDropdown(false); + } + }; + document.addEventListener('click', handleClick); + return () => document.removeEventListener('click', handleClick); + }, [showLangDropdown]); + const toggleCollapse = () => setIsCollapsed(!isCollapsed); const toggleMobile = () => setIsMobileOpen(!isMobileOpen); const currentLang = (i18n.resolvedLanguage || i18n.language || 'en').split('-')[0] as SupportedLanguage; - const cycleLanguage = () => { - const idx = supportedLanguages.indexOf(currentLang); - const next = supportedLanguages[(idx + 1) % supportedLanguages.length]; - void i18n.changeLanguage(next); + const handleLanguageChange = (lang: string) => { + void i18n.changeLanguage(lang); }; - const languageLabel = currentLang === 'he' ? 'עברית' : 'EN'; - const isRtl = currentLang === 'he'; + const languageLabels: Record = { + en: 'English', + ar: 'العربية', + he: 'עברית', + zh: '中文', + es: 'Español', + }; + const languageLabel = languageLabels[currentLang] ?? 'EN'; + const isRtl = currentLang === 'he' || currentLang === 'ar'; return (
@@ -151,15 +169,32 @@ export function Layout({ onLogout, userRole }: LayoutProps) {
- +
+ + {showLangDropdown && !isCollapsed && ( +
+ {(['en', 'ar', 'es', 'zh', 'he'] as SupportedLanguage[]).map(lang => ( +
{ + handleLanguageChange(lang); + setShowLangDropdown(false); + }} + > + {languageLabels[lang]} +
+ ))} +
+ )} +