xpeditis2.0/apps/frontend/src/components/admin/AdminPanelDropdown.tsx
2025-12-18 15:33:55 +01:00

136 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState, useRef, useEffect } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
interface AdminMenuItem {
name: string;
href: string;
icon: string;
description: string;
}
const adminMenuItems: AdminMenuItem[] = [
{
name: 'Users',
href: '/dashboard/admin/users',
icon: '👥',
description: 'Manage users and permissions',
},
{
name: 'Organizations',
href: '/dashboard/admin/organizations',
icon: '🏢',
description: 'Manage organizations and companies',
},
{
name: 'Bookings',
href: '/dashboard/admin/bookings',
icon: '📦',
description: 'View and manage all bookings',
},
{
name: 'Documents',
href: '/dashboard/admin/documents',
icon: '📄',
description: 'Manage organization documents',
},
{
name: 'CSV Rates',
href: '/dashboard/admin/csv-rates',
icon: '📊',
description: 'Upload and manage CSV rates',
},
];
export default function AdminPanelDropdown() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const pathname = usePathname();
// Close dropdown when clicking outside
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
}
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen]);
// Close dropdown when route changes
useEffect(() => {
setIsOpen(false);
}, [pathname]);
const isActiveRoute = adminMenuItems.some(item => pathname.startsWith(item.href));
return (
<div className="relative" ref={dropdownRef}>
{/* Trigger Button */}
<button
onClick={() => setIsOpen(!isOpen)}
className={`flex items-center w-full px-4 py-3 text-sm font-medium rounded-lg transition-colors ${
isActiveRoute
? 'bg-blue-50 text-blue-700'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
<span className="mr-3 text-xl"></span>
<span className="flex-1 text-left">Admin Panel</span>
<svg
className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
{/* Dropdown Menu */}
{isOpen && (
<div className="absolute left-0 right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 z-50 overflow-hidden">
<div className="py-2">
{adminMenuItems.map(item => {
const isActive = pathname.startsWith(item.href);
return (
<Link
key={item.name}
href={item.href}
className={`flex items-start px-4 py-3 hover:bg-gray-50 transition-colors ${
isActive ? 'bg-blue-50' : ''
}`}
>
<span className="text-2xl mr-3 mt-0.5">{item.icon}</span>
<div className="flex-1">
<div className={`text-sm font-medium ${isActive ? 'text-blue-700' : 'text-gray-900'}`}>
{item.name}
</div>
<div className="text-xs text-gray-500 mt-0.5">
{item.description}
</div>
</div>
</Link>
);
})}
</div>
</div>
)}
</div>
);
}