diff --git a/dashboard/src/components/Layout.css b/dashboard/src/components/Layout.css index 0db1288f..90f6fd7d 100644 --- a/dashboard/src/components/Layout.css +++ b/dashboard/src/components/Layout.css @@ -184,6 +184,41 @@ overflow: hidden; } +.language-selector { + position: relative; +} + +.language-menu { + position: absolute; + bottom: calc(100% + 0.5rem); + inset-inline-start: 0; + min-width: 12rem; + background: var(--bg-white); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08); + z-index: 110; + overflow: hidden; +} + +.language-menu-item { + width: 100%; + display: block; + padding: 0.75rem 1rem; + text-align: left; + background: none; + border: none; + color: var(--text-primary); + font-size: 0.875rem; + cursor: pointer; + transition: background 0.2s ease; +} + +.language-menu-item:hover, +.language-menu-item.active { + background: var(--bg-light); +} + .sidebar.collapsed .theme-toggle-btn, .sidebar.collapsed .logout-btn { justify-content: center; diff --git a/dashboard/src/components/Layout.tsx b/dashboard/src/components/Layout.tsx index f2815bb8..f8696a74 100644 --- a/dashboard/src/components/Layout.tsx +++ b/dashboard/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { NavLink, Outlet } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { @@ -54,6 +54,8 @@ export function Layout({ onLogout, userRole }: LayoutProps) { const [isCollapsed, setIsCollapsed] = useState(false); const [isMobileOpen, setIsMobileOpen] = useState(false); const [isMobile, setIsMobile] = useState(window.innerWidth < 768); + const [isLanguageMenuOpen, setIsLanguageMenuOpen] = useState(false); + const languageMenuRef = useRef(null); useEffect(() => { const handleResize = () => { @@ -65,6 +67,17 @@ export function Layout({ onLogout, userRole }: LayoutProps) { return () => window.removeEventListener('resize', handleResize); }, []); + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (languageMenuRef.current && !languageMenuRef.current.contains(event.target as Node)) { + setIsLanguageMenuOpen(false); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, []); + const handleNavClick = () => { if (isMobile) setIsMobileOpen(false); }; @@ -80,12 +93,23 @@ export function Layout({ onLogout, userRole }: LayoutProps) { 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 languageLabels: Record = { + en: t('common.english'), + he: t('common.hebrew'), + te: t('common.telugu'), + fr: t('common.french'), + }; + const languageOptions = supportedLanguages.map(lang => ({ + value: lang, + label: languageLabels[lang], + })); + + const selectLanguage = (lang: SupportedLanguage) => { + setIsLanguageMenuOpen(false); + void i18n.changeLanguage(lang); }; - const languageLabel = currentLang === 'he' ? 'עברית' : 'EN'; + + const languageLabel = languageLabels[currentLang] ?? currentLang.toUpperCase(); const isRtl = currentLang === 'he'; return ( @@ -151,15 +175,36 @@ export function Layout({ onLogout, userRole }: LayoutProps) {
- +
+ + + {isLanguageMenuOpen && ( +
+ {languageOptions.map(({ value, label }) => ( + + ))} +
+ )} +