Spaces:
Sleeping
Sleeping
| 'use client'; | |
| import { useState } from 'react'; | |
| import Link from 'next/link'; | |
| import { usePathname } from 'next/navigation'; | |
| import { | |
| MessageSquare, | |
| BookOpen, | |
| Heart, | |
| Brain, | |
| History, | |
| Settings, | |
| Sparkles, | |
| ChevronLeft, | |
| ChevronRight, | |
| Home, | |
| PenTool, | |
| Compass, | |
| Flame, | |
| } from 'lucide-react'; | |
| interface NavItem { | |
| icon: typeof MessageSquare; | |
| label: string; | |
| href: string; | |
| badge?: string; | |
| color?: string; | |
| } | |
| const mainNav: NavItem[] = [ | |
| { icon: MessageSquare, label: 'Chat', href: '/dashboard', color: 'purple' }, | |
| { icon: BookOpen, label: 'Bible Study', href: '/dashboard/bible', color: 'blue' }, | |
| { icon: PenTool, label: 'Journal', href: '/dashboard/journal', color: 'amber' }, | |
| { icon: Heart, label: 'Prayer', href: '/dashboard/prayer', color: 'rose' }, | |
| ]; | |
| const secondaryNav: NavItem[] = [ | |
| { icon: History, label: 'Memory', href: '/dashboard/memory', color: 'violet' }, | |
| { icon: Brain, label: 'Insights', href: '/dashboard/insights', color: 'emerald' }, | |
| { icon: Compass, label: 'Explore', href: '/dashboard/explore', color: 'cyan' }, | |
| ]; | |
| const colorClasses: Record<string, { bg: string; border: string; text: string; hover: string }> = { | |
| purple: { bg: 'bg-purple-500/10', border: 'border-purple-500/30', text: 'text-purple-400', hover: 'hover:bg-purple-500/20' }, | |
| blue: { bg: 'bg-blue-500/10', border: 'border-blue-500/30', text: 'text-blue-400', hover: 'hover:bg-blue-500/20' }, | |
| amber: { bg: 'bg-amber-500/10', border: 'border-amber-500/30', text: 'text-amber-400', hover: 'hover:bg-amber-500/20' }, | |
| rose: { bg: 'bg-rose-500/10', border: 'border-rose-500/30', text: 'text-rose-400', hover: 'hover:bg-rose-500/20' }, | |
| violet: { bg: 'bg-violet-500/10', border: 'border-violet-500/30', text: 'text-violet-400', hover: 'hover:bg-violet-500/20' }, | |
| emerald: { bg: 'bg-emerald-500/10', border: 'border-emerald-500/30', text: 'text-emerald-400', hover: 'hover:bg-emerald-500/20' }, | |
| cyan: { bg: 'bg-cyan-500/10', border: 'border-cyan-500/30', text: 'text-cyan-400', hover: 'hover:bg-cyan-500/20' }, | |
| }; | |
| export default function Sidebar() { | |
| const [collapsed, setCollapsed] = useState(false); | |
| const pathname = usePathname(); | |
| const NavLink = ({ item, isActive }: { item: NavItem; isActive: boolean }) => { | |
| const colors = colorClasses[item.color || 'purple']; | |
| return ( | |
| <Link | |
| href={item.href} | |
| className={` | |
| flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all duration-200 | |
| ${isActive | |
| ? `${colors.bg} ${colors.border} border ${colors.text}` | |
| : `text-neutral-400 hover:text-white ${colors.hover}` | |
| } | |
| ${collapsed ? 'justify-center' : ''} | |
| `} | |
| title={collapsed ? item.label : undefined} | |
| > | |
| <item.icon className={`w-5 h-5 shrink-0 ${isActive ? colors.text : ''}`} /> | |
| {!collapsed && ( | |
| <> | |
| <span className="text-sm font-medium">{item.label}</span> | |
| {item.badge && ( | |
| <span className={`ml-auto text-[10px] px-1.5 py-0.5 rounded-full ${colors.bg} ${colors.text}`}> | |
| {item.badge} | |
| </span> | |
| )} | |
| </> | |
| )} | |
| </Link> | |
| ); | |
| }; | |
| return ( | |
| <aside | |
| className={` | |
| h-screen sticky top-0 flex flex-col | |
| bg-[#0a0a0a]/80 backdrop-blur-xl | |
| border-r border-white/5 | |
| transition-all duration-300 | |
| ${collapsed ? 'w-[72px]' : 'w-[240px]'} | |
| `} | |
| > | |
| {/* Logo */} | |
| <div className={`p-4 border-b border-white/5 ${collapsed ? 'px-3' : ''}`}> | |
| <Link href="/" className="flex items-center gap-3"> | |
| <div className="w-10 h-10 rounded-xl bg-gradient-to-br from-purple-600 to-purple-800 flex items-center justify-center shadow-lg shadow-purple-500/20"> | |
| <Sparkles className="w-5 h-5 text-white" /> | |
| </div> | |
| {!collapsed && ( | |
| <div> | |
| <span className="text-lg font-bold text-white tracking-tight">ORA</span> | |
| <span className="block text-[10px] text-purple-400 -mt-0.5">Spiritual Companion</span> | |
| </div> | |
| )} | |
| </Link> | |
| </div> | |
| {/* Main Navigation */} | |
| <nav className="flex-1 p-3 space-y-1 overflow-y-auto"> | |
| <div className={`${collapsed ? '' : 'mb-4'}`}> | |
| {!collapsed && ( | |
| <span className="px-3 text-[10px] font-medium text-neutral-600 uppercase tracking-wider"> | |
| Main | |
| </span> | |
| )} | |
| <div className="mt-2 space-y-1"> | |
| {mainNav.map((item) => ( | |
| <NavLink | |
| key={item.href} | |
| item={item} | |
| isActive={pathname === item.href} | |
| /> | |
| ))} | |
| </div> | |
| </div> | |
| <div className={`pt-4 border-t border-white/5 ${collapsed ? '' : ''}`}> | |
| {!collapsed && ( | |
| <span className="px-3 text-[10px] font-medium text-neutral-600 uppercase tracking-wider"> | |
| Knowledge | |
| </span> | |
| )} | |
| <div className="mt-2 space-y-1"> | |
| {secondaryNav.map((item) => ( | |
| <NavLink | |
| key={item.href} | |
| item={item} | |
| isActive={pathname === item.href} | |
| /> | |
| ))} | |
| </div> | |
| </div> | |
| </nav> | |
| {/* Bottom Section */} | |
| <div className="p-3 border-t border-white/5 space-y-2"> | |
| {/* Settings */} | |
| <Link | |
| href="/dashboard/settings" | |
| className={` | |
| flex items-center gap-3 px-3 py-2.5 rounded-xl | |
| text-neutral-400 hover:text-white hover:bg-white/5 | |
| transition-all duration-200 | |
| ${collapsed ? 'justify-center' : ''} | |
| `} | |
| > | |
| <Settings className="w-5 h-5" /> | |
| {!collapsed && <span className="text-sm">Settings</span>} | |
| </Link> | |
| {/* Collapse Toggle */} | |
| <button | |
| onClick={() => setCollapsed(!collapsed)} | |
| className={` | |
| w-full flex items-center gap-3 px-3 py-2.5 rounded-xl | |
| text-neutral-500 hover:text-white hover:bg-white/5 | |
| transition-all duration-200 | |
| ${collapsed ? 'justify-center' : ''} | |
| `} | |
| > | |
| {collapsed ? ( | |
| <ChevronRight className="w-5 h-5" /> | |
| ) : ( | |
| <> | |
| <ChevronLeft className="w-5 h-5" /> | |
| <span className="text-sm">Collapse</span> | |
| </> | |
| )} | |
| </button> | |
| </div> | |
| {/* Status Indicator */} | |
| {!collapsed && ( | |
| <div className="p-4 border-t border-white/5"> | |
| <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-emerald-500/10 border border-emerald-500/20"> | |
| <span className="relative flex h-2 w-2"> | |
| <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75" /> | |
| <span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-500" /> | |
| </span> | |
| <span className="text-xs text-emerald-400">ORA Online</span> | |
| </div> | |
| </div> | |
| )} | |
| </aside> | |
| ); | |
| } | |