Abdalkaderdev's picture
Initial ORA deployment
5e0532d
'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>
);
}