/* ═══════════════════════════════════════════════════════════════════════════ * IMPHNEN Sidebar — Navigation command center * Minimal, collapsed by default, dengan Mascot yang playful. * Fokus: Guild Moderation Watcher untuk komunitas IMPHNEN. * ═══════════════════════════════════════════════════════════════════════════ */ import { motion } from "framer-motion"; import { LayoutDashboard, MessageSquare, Radio, } from "lucide-react"; import type { MessageRecord } from "../entities/message/types.js"; import type { DashboardTab } from "../entities/ui/types.js"; import { useMascotChat } from "../shared/hooks/useMascotChat"; import { cn } from "../shared/lib/utils"; import { MascotChatbot } from "./mascot/MascotChatbot"; import { MascotImage } from "./mascot/MascotImage"; const navItems: Array<{ id: DashboardTab; label: string; icon: typeof Radio; badge?: string; }> = [ { id: "messages", label: "Pesan & Moderasi", icon: MessageSquare, badge: "Live", }, { id: "live", label: "Voice & Media", icon: Radio, }, { id: "dashboard", label: "Dashboard Guild", icon: LayoutDashboard, }, ]; interface SidebarProps { activeTab: DashboardTab; onTabChange: (tab: DashboardTab) => void; collapsed?: boolean; recentMessages?: MessageRecord[]; guildId?: string; channelId?: string; flaggedCount?: number; } export function Sidebar({ activeTab, onTabChange, collapsed = false, recentMessages = [], guildId, channelId, flaggedCount = 0, }: SidebarProps) { const mascotChat = useMascotChat({ messageCount: recentMessages.length, activeParticipants: new Set( recentMessages.map((message) => message.user_id), ).size, lastActivity: recentMessages.length > 0 ? "Aktif" : "Idle", topicsDiscussed: ["Pesan", "Moderasi"], guildId, channelId, }); return ( <> {/* ── Brand Icon ────────────────────────────────────────────── */} {/* Logo */} {/* Live indicator dot */} {/* Brand text when expanded */} {!collapsed && ( IMPHNEN Guild Watcher )} {/* Mascot — only when expanded */} {!collapsed && ( mascotChat.setIsOpen(!mascotChat.isOpen)} /> )} {/* ── Navigation Items ──────────────────────────────────────── */} {navItems.map((item) => { const Icon = item.icon; const isActive = activeTab === item.id; return ( onTabChange(item.id)} title={collapsed ? item.label : undefined} className={cn( "group relative flex items-center rounded-xl p-2.5", "font-sans text-sm font-medium", "transition-all duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", collapsed ? "justify-center" : "gap-3", isActive ? "bg-[#e1f0fd] text-[#23a1eb] ring-1 ring-[#23a1eb]/20" : "text-[#666666] hover:bg-[#e1f0fd]/50 hover:text-[#23a1eb]/70", )} > {/* Flagged dot indicator */} {item.id === "messages" && flaggedCount > 0 && ( )} {!collapsed && ( {item.label} {item.badge && ( {item.badge} )} )} ); })} {/* ── Bottom: Mascot Chat Button ────────────────────────────── */} mascotChat.setIsOpen(!mascotChat.isOpen)} className={cn( "relative z-50 rounded-xl p-1.5", "transition-all duration-200 hover:scale-105", "focus:outline-none focus:ring-2 focus:ring-[#23a1eb]/40", mascotChat.isOpen && "bg-[#e1f0fd] ring-1 ring-[#23a1eb]/30", )} title="Chat dengan Mascot" > {mascotChat.isOpen && ( )} {/* ── Mascot Chatbot Panel ────────────────────────────────────── */} mascotChat.setIsOpen(false)} onSendMessage={mascotChat.handleSendMessage} mascotName="Mascot IMPHNEN" className="fixed bottom-[170px] left-[80px] z-[9999]" /> > ); }
Guild Watcher