import React from 'react'; import { NavLink, useLocation } from 'react-router-dom'; import { LayoutDashboard, Calendar, Mail, Archive, BarChart3, Settings, X, Palette, FileText, HardDrive, Users, Tags } from 'lucide-react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { settingsService } from '../../services/settings.service'; import { VersionInfo } from './VersionInfo'; import { usePermissions } from '../../contexts/PermissionsContext'; interface AdminSidebarProps { isOpen: boolean; onClose: () => void; } interface NavItem { nameKey: string; href: string; icon: React.ComponentType<{ className?: string }>; permission?: string; } const navigation: NavItem[] = [ { nameKey: 'navigation.dashboard', href: '/admin/dashboard', icon: LayoutDashboard }, { nameKey: 'navigation.events', href: '/admin/events', icon: Calendar, permission: 'events.view' }, { nameKey: 'navigation.archives', href: '/admin/archives', icon: Archive, permission: 'archives.view' }, { nameKey: 'admin.analytics', href: '/admin/analytics', icon: BarChart3, permission: 'analytics.view' }, { nameKey: 'navigation.emailSettings', href: '/admin/email', icon: Mail, permission: 'email.view' }, { nameKey: 'navigation.branding', href: '/admin/branding', icon: Palette, permission: 'branding.view' }, { nameKey: 'navigation.settings', href: '/admin/settings', icon: Settings, permission: 'settings.view' }, { nameKey: 'navigation.eventTypes', href: '/admin/event-types', icon: Tags, permission: 'settings.view' }, { nameKey: 'navigation.backup', href: '/admin/backup', icon: HardDrive, permission: 'backup.view' }, { nameKey: 'navigation.cmsPages', href: '/admin/cms', icon: FileText, permission: 'cms.view' }, { nameKey: 'navigation.users', href: '/admin/users', icon: Users, permission: 'users.view' }, ]; export const AdminSidebar: React.FC = ({ isOpen, onClose }) => { const location = useLocation(); const { t } = useTranslation(); const { hasPermission } = usePermissions(); // Filter navigation items based on permissions const filteredNavigation = navigation.filter(item => { if (!item.permission) return true; return hasPermission(item.permission); }); return (
{/* Brand */}
{t('admin.title')}
{/* Navigation */} {/* Bottom section - sticky to bottom (only for users with settings.view permission) */} {hasPermission('settings.view') && (
{/* Version Info */} {/* Storage Info */}
)}
); }; const StorageInfo: React.FC = () => { const { t } = useTranslation(); const { data: storageInfo } = useQuery({ queryKey: ['storage-info'], queryFn: () => settingsService.getStorageInfo(), refetchInterval: 60000 // Refresh every minute }); // Don't render anything while loading or if data failed to load if (!storageInfo) { return null; } const limitInUse = storageInfo.storage_soft_limit || storageInfo.storage_limit || 1; const usagePercent = limitInUse ? Math.round((storageInfo.total_used / limitInUse) * 100) : 0; const isOverSoftLimit = limitInUse && storageInfo.total_used >= limitInUse; const progressBarClass = isOverSoftLimit ? 'bg-red-600' : 'bg-primary-600'; const containerClass = isOverSoftLimit ? 'bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800' : 'bg-neutral-100 dark:bg-neutral-800'; const softLimitDisplay = settingsService.formatBytes(limitInUse); return (
{t('admin.storageUsed')} {settingsService.formatBytes(storageInfo.total_used)}

{t('admin.storagePercent', { percent: usagePercent, limit: softLimitDisplay })}

); };