import { useCallback, useState, useRef } from "react"; import { LogOut, Shield, PanelLeftClose, PanelLeftOpen, Menu, X } from "lucide-react"; import { QuestionBubble } from "./QuestionBubble"; import { AnswerBubble } from "./AnswerBubble"; import { ToolBubble } from "./ToolBubble"; import { MessageInput } from "./MessageInput"; import { ConversationList } from "./ConversationList"; import { AdminPanel } from "./AdminPanel"; import { cn } from "../lib/utils"; import { useConversations } from "../hooks/useConversations"; import { useChat } from "../hooks/useChat"; import catIcon from "../assets/cat.png"; type ChatScreenProps = { setAuthenticated: (isAuth: boolean) => void; isAdmin: boolean; }; export const ChatScreen = ({ setAuthenticated, isAdmin }: ChatScreenProps) => { const [query, setQuery] = useState(""); const [simbaMode, setSimbaMode] = useState(false); const [showConversations, setShowConversations] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [showAdminPanel, setShowAdminPanel] = useState(false); const messagesEndRef = useRef(null); const isLoadingRef = useRef(false); const scrollToBottom = useCallback(() => { requestAnimationFrame(() => { messagesEndRef.current?.scrollIntoView({ behavior: isLoadingRef.current ? "instant" : "smooth", }); }); }, []); const { conversations, selectedConversation, selectConversation, createConversation, refreshConversations, } = useConversations(); const onSessionExpired = useCallback(() => setAuthenticated(false), [setAuthenticated]); const { messages, setMessages, isLoading, pendingImage, setPendingImage, sendMessage, } = useChat({ selectedConversation, createConversation, refreshConversations, onSessionExpired, scrollToBottom, }); // Keep ref in sync for scrollToBottom behavior isLoadingRef.current = isLoading; const handleSelectConversation = useCallback( async (conversation: { title: string; id: string }) => { setShowConversations(false); const loaded = await selectConversation(conversation); setMessages(loaded); }, [selectConversation, setMessages], ); const handleCreateNewConversation = useCallback(async () => { await createConversation(); setMessages([]); }, [createConversation, setMessages]); const handleQuestionSubmit = useCallback(() => { sendMessage(query, simbaMode); setQuery(""); }, [query, simbaMode, sendMessage]); const handleQueryChange = useCallback((event: React.ChangeEvent) => { setQuery(event.target.value); }, []); const handleKeyDown = useCallback((event: React.ChangeEvent) => { const kev = event as unknown as React.KeyboardEvent; if (kev.key === "Enter" && !kev.shiftKey) { kev.preventDefault(); handleQuestionSubmit(); } }, [handleQuestionSubmit]); const handleImageSelect = useCallback((file: File) => setPendingImage(file), [setPendingImage]); const handleClearImage = useCallback(() => setPendingImage(null), [setPendingImage]); const handleLogout = () => { localStorage.removeItem("access_token"); localStorage.removeItem("refresh_token"); setAuthenticated(false); }; return (
{/* Desktop Sidebar */} {showAdminPanel && setShowAdminPanel(false)} />}
Simba

asksimba

{messages.length === 0 ? (
{showConversations && (
)}
Simba

Ask me anything

) : ( <>
{showConversations && (
)} {messages.map((msg, index) => { if (msg.speaker === "tool") return ; if (msg.speaker === "simba") return ; return ; })} {isLoading && }
)}
); };