2026-10-09 12:16:48 +05:30

128 lines
5.0 KiB
TypeScript

import { useEffect, useRef, useState } from 'react'
import { User } from '../types'
import { useT, toggleLang } from '../i18n'
interface Props {
user: User
sbUsers?: any[]
onLogout: () => void
onViewProfile?: () => void
}
const ROLE_COLOR: Record<string, string> = {
Manager: '#2563eb',
Auditor: '#d97706',
Employee: '#6b7280',
Admin: '#7c3aed',
'X-Auditor': '#0f766e',
Chairman: '#0f766e',
}
export default function UserMenu({ user, sbUsers = [], onLogout, onViewProfile }: Props) {
const [open, setOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
const t = useT()
useEffect(() => {
const handler = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)
}
document.addEventListener('mousedown', handler)
return () => document.removeEventListener('mousedown', handler)
}, [])
const sbUser = sbUsers.find(u => u.name === user.name || u.username === user.name)
const category = sbUser?.custom_category || user.role || 'User'
const initials = (user.full_name || user.name || 'U').charAt(0).toUpperCase()
const roleColor = ROLE_COLOR[user.role] || '#6b7280'
return (
<div ref={ref} style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 8 }}>
<button
onClick={() => setOpen(o => !o)}
style={{
display: 'flex', alignItems: 'center', gap: 7,
background: open ? '#f1f5f9' : 'transparent',
border: '1px solid transparent',
borderRadius: 20, padding: '4px 10px 4px 5px',
cursor: 'pointer', transition: 'background 0.15s',
}}>
<div style={{
width: 28, height: 28, borderRadius: '50%',
background: roleColor, color: 'white',
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 12, fontWeight: 700, flexShrink: 0,
boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
}}>
{initials}
</div>
<span style={{ fontSize: 12, fontWeight: 600, color: '#374151', whiteSpace: 'nowrap', maxWidth: 90, overflow: 'hidden', textOverflow: 'ellipsis' }}>
{user.full_name || user.name}
</span>
<span style={{ fontSize: 9, color: '#9ca3af' }}>{open ? '▲' : '▼'}</span>
</button>
{open && (
<div style={{
position: 'absolute', right: 0, top: 'calc(100% + 6px)',
width: 220, background: 'white', borderRadius: 10,
boxShadow: '0 8px 32px rgba(0,0,0,0.15)', zIndex: 10000,
border: '1px solid #e5e7eb', overflow: 'hidden',
}}>
<div style={{ padding: '14px 16px', borderBottom: '1px solid #f0f0f0', background: '#f8fafc', display: 'flex', alignItems: 'center', gap: 10 }}>
<div style={{
width: 36, height: 36, borderRadius: '50%', background: roleColor,
color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 700, flexShrink: 0,
}}>
{initials}
</div>
<div style={{ minWidth: 0 }}>
<div style={{ fontSize: 13, fontWeight: 700, color: '#1a2332', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{user.full_name || user.name}
</div>
<div style={{ fontSize: 10, color: '#888', marginTop: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{user.name}
</div>
<div style={{
display: 'inline-block', marginTop: 4, padding: '1px 8px',
background: roleColor + '18', color: roleColor,
fontSize: 10, fontWeight: 700, borderRadius: 8, border: '1px solid ' + roleColor + '44',
}}>
{category}
</div>
</div>
</div>
<div style={{ padding: '4px 0' }}>
<MenuRow icon="👤" label={t.myProfile} onClick={() => { onViewProfile?.(); setOpen(false) }} />
<MenuRow
icon="🌐"
label={t.switchLang}
onClick={() => { toggleLang(); setOpen(false) }}
/>
<div style={{ height: 1, background: '#f0f0f0', margin: '4px 8px' }} />
<MenuRow icon="↩" label={t.signOut} color="#ef4444" onClick={() => { onLogout(); setOpen(false) }} />
</div>
</div>
)}
</div>
)
}
function MenuRow({ icon, label, color = '#374151', onClick }: { icon: string; label: string; color?: string; onClick: () => void }) {
const [hover, setHover] = useState(false)
return (
<div onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
style={{
padding: '8px 14px', fontSize: 13, color, cursor: 'pointer',
display: 'flex', alignItems: 'center', gap: 9,
background: hover ? (color === '#ef4444' ? '#fef2f2' : '#f9fafb') : 'white',
transition: 'background 0.1s',
}}>
<span style={{ fontSize: 14, width: 18, textAlign: 'center' }}>{icon}</span>
{label}
</div>
)
}