304 lines
10 KiB
TypeScript
304 lines
10 KiB
TypeScript
'use client';
|
|
|
|
import Link from 'next/link';
|
|
import { usePathname } from 'next/navigation';
|
|
import { clsx } from 'clsx';
|
|
import { useStore } from '@/lib/store';
|
|
import { isAdmin } from '@/lib/auth';
|
|
import {
|
|
Home,
|
|
Image,
|
|
Video,
|
|
Mic,
|
|
FileText,
|
|
History,
|
|
Settings,
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
Sparkles,
|
|
Maximize,
|
|
Eraser,
|
|
Captions,
|
|
Volume2,
|
|
Type,
|
|
Wand2,
|
|
ImagePlus,
|
|
Film,
|
|
Shield,
|
|
Users,
|
|
TrendingUp,
|
|
Clock,
|
|
FolderOpen,
|
|
AudioLines,
|
|
Network,
|
|
FileCode,
|
|
FileType,
|
|
FileEdit,
|
|
Scissors,
|
|
} from 'lucide-react';
|
|
|
|
const modules = [
|
|
{
|
|
category: 'Image',
|
|
icon: Image,
|
|
items: [
|
|
{ name: 'Generate', href: '/image/generate', icon: ImagePlus },
|
|
{ name: 'Nano Edit', href: '/image/edit-pro', icon: Sparkles },
|
|
{ name: 'Upscale', href: '/image/upscale', icon: Maximize },
|
|
{ name: 'Remove Background', href: '/image/remove-bg', icon: Eraser },
|
|
],
|
|
},
|
|
{
|
|
category: 'Video',
|
|
icon: Video,
|
|
items: [
|
|
{ name: 'Generate', href: '/video/generate', icon: Film },
|
|
{ name: 'Upscale', href: '/video/upscale', icon: Maximize },
|
|
{ name: 'Frame Extractor', href: '/video/extract', icon: Scissors },
|
|
{ name: 'Subtitles', href: '/video/subtitles', icon: Captions },
|
|
],
|
|
},
|
|
{
|
|
category: 'Audio',
|
|
icon: Mic,
|
|
items: [
|
|
{ name: 'Text to Speech', href: '/audio/text-to-speech', icon: Volume2 },
|
|
{ name: 'Voice to Text', href: '/audio/voice-to-text', icon: Type },
|
|
{ name: 'Sound Effects', href: '/audio/sound-effects', icon: AudioLines },
|
|
],
|
|
},
|
|
{
|
|
category: 'Text',
|
|
icon: FileText,
|
|
items: [
|
|
{ name: 'Prompt Studio', href: '/text/prompt-studio', icon: Wand2 },
|
|
{ name: 'Alt Text Generator', href: '/text/alt-text', icon: FileText },
|
|
{ name: 'Mermaid Generator', href: '/text/mermaid-generator', icon: Network },
|
|
{ name: 'Mermaid Renderer', href: '/text/mermaid-renderer', icon: FileCode },
|
|
{ name: 'Markdown Converter', href: '/text/markdown-converter', icon: FileType },
|
|
{ name: 'Markdown Generator', href: '/text/markdown-generator', icon: FileEdit },
|
|
],
|
|
},
|
|
];
|
|
|
|
export default function Sidebar() {
|
|
const pathname = usePathname();
|
|
const { user, sidebarCollapsed, toggleSidebar } = useStore();
|
|
const userIsAdmin = isAdmin(user as any);
|
|
|
|
return (
|
|
<aside
|
|
className={clsx(
|
|
'bg-forge-dark border-r border-gray-800 flex flex-col transition-all duration-300',
|
|
sidebarCollapsed ? 'w-20' : 'w-64'
|
|
)}
|
|
>
|
|
{/* Logo */}
|
|
<div className="p-4 border-b border-gray-800">
|
|
<Link href="/" className="flex items-center gap-3">
|
|
<div className="w-10 h-10 flex items-center justify-center">
|
|
<img src="/THE_FORGE_LOGO.png" alt="Forge AI" className="w-full h-full object-contain" />
|
|
</div>
|
|
{!sidebarCollapsed && (
|
|
<span className="text-xl font-bold text-white">FORGE AI</span>
|
|
)}
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<nav className="flex-1 overflow-y-auto py-4">
|
|
{/* Dashboard */}
|
|
<Link
|
|
href="/"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-3 mx-2 rounded-lg transition-colors',
|
|
pathname === '/'
|
|
? 'bg-forge-yellow/10 text-forge-yellow'
|
|
: 'text-gray-400 hover:text-white hover:bg-forge-gray'
|
|
)}
|
|
>
|
|
<Home className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Dashboard</span>}
|
|
</Link>
|
|
|
|
{/* Modules */}
|
|
{modules.map((module) => (
|
|
<div key={module.category} className="mt-4">
|
|
{!sidebarCollapsed && (
|
|
<div className="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider">
|
|
{module.category}
|
|
</div>
|
|
)}
|
|
{sidebarCollapsed && (
|
|
<div className="px-4 py-2 flex justify-center">
|
|
<module.icon className="w-4 h-4 text-gray-500" />
|
|
</div>
|
|
)}
|
|
{module.items.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === item.href
|
|
? 'bg-forge-yellow/10 text-forge-yellow'
|
|
: 'text-gray-400 hover:text-white hover:bg-forge-gray'
|
|
)}
|
|
>
|
|
<item.icon className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>{item.name}</span>}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
))}
|
|
|
|
{/* My Files */}
|
|
<div className="mt-6 pt-6 border-t border-gray-800">
|
|
<Link
|
|
href="/files"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-3 mx-2 rounded-lg transition-colors',
|
|
pathname === '/files'
|
|
? 'bg-forge-yellow/10 text-forge-yellow'
|
|
: 'text-gray-400 hover:text-white hover:bg-forge-gray'
|
|
)}
|
|
>
|
|
<FolderOpen className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>My Files</span>}
|
|
</Link>
|
|
</div>
|
|
|
|
{/* History & Settings */}
|
|
<div className="mt-4">
|
|
<Link
|
|
href="/history"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-3 mx-2 rounded-lg transition-colors',
|
|
pathname === '/history'
|
|
? 'bg-forge-yellow/10 text-forge-yellow'
|
|
: 'text-gray-400 hover:text-white hover:bg-forge-gray'
|
|
)}
|
|
>
|
|
<History className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>History</span>}
|
|
</Link>
|
|
<Link
|
|
href="/settings"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-3 mx-2 rounded-lg transition-colors',
|
|
pathname === '/settings'
|
|
? 'bg-forge-yellow/10 text-forge-yellow'
|
|
: 'text-gray-400 hover:text-white hover:bg-forge-gray'
|
|
)}
|
|
>
|
|
<Settings className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Settings</span>}
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Admin Section - Only visible to admins */}
|
|
{userIsAdmin && (
|
|
<div className="mt-4 pt-4 border-t border-red-900/50">
|
|
{!sidebarCollapsed && (
|
|
<div className="px-4 py-2 text-xs font-semibold text-red-400 uppercase tracking-wider">
|
|
Admin
|
|
</div>
|
|
)}
|
|
{sidebarCollapsed && (
|
|
<div className="px-4 py-2 flex justify-center">
|
|
<Shield className="w-4 h-4 text-red-400" />
|
|
</div>
|
|
)}
|
|
<Link
|
|
href="/admin"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<Shield className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Dashboard</span>}
|
|
</Link>
|
|
<Link
|
|
href="/admin/users"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin/users'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<Users className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Users</span>}
|
|
</Link>
|
|
<Link
|
|
href="/admin/reports"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin/reports'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<TrendingUp className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Reports</span>}
|
|
</Link>
|
|
<Link
|
|
href="/admin/usage"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin/usage'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<History className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Usage Search</span>}
|
|
</Link>
|
|
<Link
|
|
href="/admin/logs"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin/logs'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<Clock className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Audit Logs</span>}
|
|
</Link>
|
|
<Link
|
|
href="/admin/voices"
|
|
className={clsx(
|
|
'flex items-center gap-3 px-4 py-2.5 mx-2 rounded-lg transition-colors',
|
|
pathname === '/admin/voices'
|
|
? 'bg-red-900/20 text-red-400'
|
|
: 'text-gray-400 hover:text-red-400 hover:bg-red-900/10'
|
|
)}
|
|
>
|
|
<Mic className="w-5 h-5 flex-shrink-0" />
|
|
{!sidebarCollapsed && <span>Voices</span>}
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</nav>
|
|
|
|
{/* Collapse Toggle */}
|
|
<button
|
|
onClick={toggleSidebar}
|
|
className="p-4 border-t border-gray-800 text-gray-400 hover:text-white transition-colors"
|
|
>
|
|
{sidebarCollapsed ? (
|
|
<ChevronRight className="w-5 h-5 mx-auto" />
|
|
) : (
|
|
<div className="flex items-center gap-2">
|
|
<ChevronLeft className="w-5 h-5" />
|
|
<span>Collapse</span>
|
|
</div>
|
|
)}
|
|
</button>
|
|
</aside>
|
|
);
|
|
}
|