111 lines
4.2 KiB
JavaScript
111 lines
4.2 KiB
JavaScript
import React, { useState, useRef, useEffect } from 'react';
|
|
import { User, LogOut, ChevronDown, Shield, Clock } from 'lucide-react';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
|
|
export default function UserMenu({ onManageUsers, onAuditLog }) {
|
|
const { user, logout, isAdmin } = useAuth();
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const menuRef = useRef(null);
|
|
|
|
// Close menu when clicking outside
|
|
useEffect(() => {
|
|
function handleClickOutside(event) {
|
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
setIsOpen(false);
|
|
}
|
|
}
|
|
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
}, []);
|
|
|
|
const getRoleBadgeColor = (role) => {
|
|
switch (role) {
|
|
case 'admin':
|
|
return 'bg-red-100 text-red-800';
|
|
case 'editor':
|
|
return 'bg-blue-100 text-blue-800';
|
|
default:
|
|
return 'bg-gray-100 text-gray-800';
|
|
}
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
setIsOpen(false);
|
|
await logout();
|
|
};
|
|
|
|
const handleManageUsers = () => {
|
|
setIsOpen(false);
|
|
if (onManageUsers) {
|
|
onManageUsers();
|
|
}
|
|
};
|
|
|
|
const handleAuditLog = () => {
|
|
setIsOpen(false);
|
|
if (onAuditLog) {
|
|
onAuditLog();
|
|
}
|
|
};
|
|
|
|
if (!user) return null;
|
|
|
|
return (
|
|
<div className="relative" ref={menuRef}>
|
|
<button
|
|
onClick={() => setIsOpen(!isOpen)}
|
|
className="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-gray-100 transition-colors"
|
|
>
|
|
<div className="w-8 h-8 bg-[#0476D9] rounded-full flex items-center justify-center">
|
|
<User className="w-4 h-4 text-white" />
|
|
</div>
|
|
<div className="text-left hidden sm:block">
|
|
<p className="text-sm font-medium text-gray-900">{user.username}</p>
|
|
<p className="text-xs text-gray-500 capitalize">{user.role}</p>
|
|
</div>
|
|
<ChevronDown className={`w-4 h-4 text-gray-500 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
|
|
</button>
|
|
|
|
{isOpen && (
|
|
<div className="absolute right-0 mt-2 w-64 bg-white rounded-lg shadow-lg border border-gray-200 py-2 z-50">
|
|
<div className="px-4 py-3 border-b border-gray-100">
|
|
<p className="text-sm font-medium text-gray-900">{user.username}</p>
|
|
<p className="text-sm text-gray-500">{user.email}</p>
|
|
<span className={`inline-block mt-2 px-2 py-1 rounded text-xs font-medium ${getRoleBadgeColor(user.role)}`}>
|
|
{user.role.charAt(0).toUpperCase() + user.role.slice(1)}
|
|
</span>
|
|
</div>
|
|
|
|
{isAdmin() && (
|
|
<>
|
|
<button
|
|
onClick={handleManageUsers}
|
|
className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-3"
|
|
>
|
|
<Shield className="w-4 h-4" />
|
|
Manage Users
|
|
</button>
|
|
<button
|
|
onClick={handleAuditLog}
|
|
className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 flex items-center gap-3"
|
|
>
|
|
<Clock className="w-4 h-4" />
|
|
Audit Log
|
|
</button>
|
|
</>
|
|
)}
|
|
|
|
<button
|
|
onClick={handleLogout}
|
|
className="w-full px-4 py-2 text-left text-sm text-red-600 hover:bg-red-50 flex items-center gap-3"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
Sign Out
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|