153 lines
4.7 KiB
TypeScript
153 lines
4.7 KiB
TypeScript
/**
|
|
* User Dropdown Component
|
|
* Reusable header dropdown with user information and navigation
|
|
*
|
|
* @author David Valera Melendez <david@valera-melendez.de>
|
|
* @created 2025-08-07
|
|
* @location Made in Germany 🇩🇪
|
|
*/
|
|
|
|
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
import { User, FileText, ChevronDown, Settings, LogOut } from 'lucide-react';
|
|
|
|
interface UserDropdownProps {
|
|
/** Current page identifier to highlight in dropdown */
|
|
currentPage?: 'dashboard' | 'settings';
|
|
/** Whether to show the logo icon */
|
|
showLogo?: boolean;
|
|
/** Custom CSS classes */
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* UserDropdown Component - Reusable header dropdown
|
|
*
|
|
* Professional user dropdown component with user information display
|
|
* and navigation options. Can be customized for different pages.
|
|
*
|
|
* Features:
|
|
* - User information display (name + email)
|
|
* - Navigation menu with current page highlighting
|
|
* - Settings and logout functionality
|
|
* - Optional logo display
|
|
* - Responsive design
|
|
*
|
|
* @param currentPage - Current page to highlight in dropdown
|
|
* @param showLogo - Whether to display the logo icon
|
|
* @param className - Additional CSS classes
|
|
* @returns Reusable user dropdown component
|
|
*/
|
|
export function UserDropdown({
|
|
currentPage,
|
|
showLogo = false,
|
|
className = '',
|
|
}: UserDropdownProps) {
|
|
const router = useRouter();
|
|
const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
|
|
|
|
/**
|
|
* Handles navigation to settings page
|
|
*/
|
|
const handleAccountSettings = () => {
|
|
setIsUserMenuOpen(false);
|
|
router.push('/settings');
|
|
};
|
|
|
|
/**
|
|
* Handles logout functionality
|
|
*/
|
|
const handleLogout = () => {
|
|
setIsUserMenuOpen(false);
|
|
// Here you would typically clear user session/tokens
|
|
console.log('Logging out...');
|
|
// Redirect to login or home page
|
|
router.push('/');
|
|
};
|
|
|
|
/**
|
|
* Closes dropdown when clicking outside
|
|
*/
|
|
const handleDropdownToggle = () => {
|
|
setIsUserMenuOpen(!isUserMenuOpen);
|
|
};
|
|
|
|
return (
|
|
<div className={`flex items-center gap-3 ${className}`}>
|
|
{/* Optional Logo */}
|
|
{showLogo && (
|
|
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-gradient-to-br from-primary-600 to-primary-700 shadow-sm">
|
|
<FileText className="h-6 w-6 text-white" />
|
|
</div>
|
|
)}
|
|
|
|
{/* User Info Display */}
|
|
<div className="text-right">
|
|
<h1 className="text-lg font-bold text-primary-700">
|
|
David Valera Melendez
|
|
</h1>
|
|
<p className="text-xs text-gray-500">david@valera-melendez.de</p>
|
|
</div>
|
|
|
|
{/* User Dropdown */}
|
|
<div className="relative">
|
|
<button
|
|
onClick={handleDropdownToggle}
|
|
className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-100"
|
|
aria-label="User menu"
|
|
aria-expanded={isUserMenuOpen}
|
|
>
|
|
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-br from-primary-100 to-primary-200">
|
|
<User className="h-4 w-4 text-primary-600" />
|
|
</div>
|
|
<ChevronDown className="h-4 w-4" />
|
|
</button>
|
|
|
|
{/* Dropdown Menu */}
|
|
{isUserMenuOpen && (
|
|
<>
|
|
{/* Backdrop for mobile */}
|
|
<div
|
|
className="fixed inset-0 z-40 lg:hidden"
|
|
onClick={() => setIsUserMenuOpen(false)}
|
|
/>
|
|
|
|
<div className="absolute right-0 top-full z-50 mt-2 w-56 rounded-lg border border-gray-200 bg-white shadow-lg">
|
|
<div className="py-1">
|
|
{/* Settings Option */}
|
|
<button
|
|
onClick={handleAccountSettings}
|
|
className={`flex w-full items-center gap-2 px-4 py-2 text-left text-sm transition-colors ${
|
|
currentPage === 'settings'
|
|
? 'bg-primary-50 text-primary-600'
|
|
: 'text-gray-700 hover:bg-gray-50'
|
|
}`}
|
|
>
|
|
<Settings className="h-4 w-4" />
|
|
Konto-Einstellungen
|
|
</button>
|
|
|
|
{/* Divider */}
|
|
<div className="mx-1 my-1 border-t border-gray-100" />
|
|
|
|
{/* Logout Option */}
|
|
<button
|
|
onClick={handleLogout}
|
|
className="flex w-full items-center gap-2 px-4 py-2 text-left text-sm text-red-600 transition-colors hover:bg-red-50"
|
|
>
|
|
<LogOut className="h-4 w-4" />
|
|
Abmelden
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default UserDropdown;
|