Files
Event-Management-System/RIT-EMS-main/frontend/src/components/Sidebar.tsx
2026-06-22 12:16:30 +05:30

108 lines
4.3 KiB
TypeScript

import React, { useState } from 'react';
import {
LayoutGrid,
ClipboardList,
CheckSquare,
History as HistoryIcon,
Zap,
BookOpen,
PlusCircle,
ChevronRight,
ShieldCheck,
Users,
Calendar,
HelpCircle,
ExternalLink,
CheckCircle,
Bell
} from 'lucide-react';
import { cn } from '../lib/utils';
import { motion } from 'framer-motion';
import ritLogo from '../assets/images/college-logo.png';
import { useAuth } from '../context/AuthContext';
interface SidebarProps {
activeItem: string;
onItemClick: (id: string) => void;
}
export const Sidebar: React.FC<SidebarProps> = ({ activeItem, onItemClick }) => {
const { user } = useAuth();
const isClubAuthorized = user?.isClubCoordinator || user?.role === 'ADMIN';
const menuItems = [
{ icon: LayoutGrid, label: 'Dashboard', id: 'dashboard' },
...((user?.role === 'HOD' || user?.role === 'PRINCIPAL') ? [{ icon: CheckCircle, label: 'Approvals', id: 'approvals' }] : []),
...(isClubAuthorized ? [{ icon: ShieldCheck, label: 'Clubs', id: 'clubs' }] : []),
{ icon: ClipboardList, label: 'All Events', id: 'events' },
{ icon: CheckSquare, label: 'Checklist', id: 'checklist' },
{ icon: HistoryIcon, label: 'History', id: 'history' },
...((user?.role === 'ADMIN' || user?.role === 'PRINCIPAL' || user?.role === 'HOD') ? [{ icon: Zap, label: 'Automation', id: 'automation' }] : []),
...(user?.role === 'ADMIN' ? [{ icon: BookOpen, label: 'Classes', id: 'classes' }] : []),
...(user?.role === 'ADMIN' ? [{ icon: Users, label: 'Manage Users', id: 'user-management' }] : []),
...(user?.role === 'ADMIN' ? [{ icon: Bell, label: 'Manage Notices', id: 'manage-notices' }] : []),
...((user?.role === 'FACULTY' || user?.role === 'HOD' || user?.role === 'ADMIN') ? [{ icon: Users, label: 'Student Hub', id: 'student-registrations' }] : [])
];
return (
<aside className="floating-sidebar">
{/* Logo */}
<div className="flex items-center gap-3 mb-8 px-2">
<img src={ritLogo} alt="College Logo" className="h-14 w-auto object-contain" />
</div>
{/* Navigation */}
<nav className="flex-1 space-y-1.5 overflow-y-auto custom-scrollbar pr-1">
<p className="px-4 text-[10px] font-black uppercase tracking-widest text-slate-400 mb-4">Main Menu</p>
{menuItems.map((item) => (
<motion.div
key={item.id}
whileHover={{ x: 4 }}
whileTap={{ scale: 0.98 }}
onClick={() => onItemClick(item.id)}
className={cn(
"sidebar-item group relative",
activeItem === item.id && "sidebar-item-active"
)}
>
<div className={cn(
"p-2 rounded-xl transition-all",
activeItem === item.id ? "bg-white shadow-sm" : "bg-transparent group-hover:bg-white/50"
)}>
<item.icon className="w-4.5 h-4.5" strokeWidth={2.5} />
</div>
<span className="flex-1 text-sm">{item.label}</span>
{activeItem === item.id && (
<div className="w-1.5 h-1.5 rounded-full bg-brand-indigo" />
)}
</motion.div>
))}
</nav>
{/* Footer Build Info */}
<div className="mt-auto px-4 pt-6 border-t border-slate-50">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-1.5 px-3 py-1 bg-brand-glow text-brand-indigo rounded-full border border-brand-indigo/10 backdrop-blur-sm group/beta hover:bg-brand-indigo hover:text-white transition-all duration-300 cursor-default">
<div className="w-1 h-1 bg-brand-indigo rounded-full group-hover/beta:bg-white animate-pulse" />
<span className="text-[9px] font-black uppercase tracking-[0.2em]">Beta</span>
</div>
<span className="text-[9px] font-black uppercase tracking-[0.2em] text-slate-300">
v0.1.5
</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-1.5">
<div className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse" />
<span className="text-[9px] font-black uppercase tracking-[0.2em] text-emerald-500/70">
Live Systems
</span>
</div>
</div>
</div>
</aside>
);
};