import { ReactNode, useState, useEffect, useRef } from 'react';
import { Link, useLocation } from '@remix-run/react';
import { useFocusTrap } from '~/hooks/useFocusTrap';
import { designTokens } from '~/lib/design-tokens';
interface SidebarProps {
isCollapsed: boolean;
onToggle: () => void;
isMobile: boolean;
isOpen: boolean;
onClose: () => void;
userAuthLevel: number;
}
interface NavigationItem {
name: string;
href: string;
icon: ReactNode;
authLevel?: number; // Minimum auth level required
}
const navigationItems: NavigationItem[] = [
{
name: 'لوحة التحكم',
href: '/dashboard',
icon: (
),
},
{
name: 'العملاء',
href: '/customers',
icon: (
),
},
{
name: 'المركبات',
href: '/vehicles',
icon: (
),
},
{
name: 'زيارات الصيانة',
href: '/maintenance-visits',
icon: (
),
},
{
name: 'المصروفات',
href: '/expenses',
icon: (
),
authLevel: 2, // Admin and above
},
{
name: 'التقارير المالية',
href: '/financial-reports',
icon: (
),
authLevel: 2, // Admin and above
},
{
name: 'إدارة المستخدمين',
href: '/users',
icon: (
),
authLevel: 2, // Admin and above
},
{
name: 'إعدادات النظام',
href: '/settings',
icon: (
),
authLevel: 2, // Admin and above
},
];
export function Sidebar({ isCollapsed, onToggle, isMobile, isOpen, onClose, userAuthLevel }: SidebarProps) {
const location = useLocation();
const sidebarRef = useRef(null);
const [announcement, setAnnouncement] = useState('');
const [isClient, setIsClient] = useState(false);
// Set client-side flag
useEffect(() => {
setIsClient(true);
}, []);
// Filter navigation items based on user auth level
const filteredNavItems = navigationItems.filter(item =>
!item.authLevel || userAuthLevel <= item.authLevel
);
// Enable focus trap for mobile menu when open
useFocusTrap(sidebarRef, isOpen && isClient);
// Close sidebar on route change
useEffect(() => {
if (isOpen) {
onClose();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.pathname]);
// Handle Escape key to close mobile menu
useEffect(() => {
if (!isClient) return;
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isOpen) {
onClose();
setAnnouncement('القائمة مغلقة');
}
};
document.addEventListener('keydown', handleEscape);
return () => document.removeEventListener('keydown', handleEscape);
}, [isOpen, onClose, isClient]);
// Announce menu state changes for screen readers
useEffect(() => {
if (isOpen && isClient) {
setAnnouncement('القائمة مفتوحة');
}
}, [isOpen, isClient]);
// Render both mobile and desktop sidebars, use CSS to show/hide
return (
<>
{/* Screen reader announcement */}
{announcement}
{/* Mobile overlay - only show on mobile/tablet */}
{isOpen && (
)}
{/* Mobile Sidebar - hidden on desktop (md+) */}
{/* Desktop Sidebar - hidden on mobile/tablet (< md) */}
>
);
}