PaperStack / components /ChatBot.tsx
Akhil-Theerthala's picture
Upload 14 files
6fe3275 verified
import React, { useState, useEffect, useRef } from 'react';
import { MessageSquare, X, Send, Loader2 } from 'lucide-react';
import { ChatMessage } from '../types';
interface Props {
isOpen: boolean;
onClose: () => void;
messages: ChatMessage[];
onSendMessage: (text: string) => void;
isProcessing: boolean;
}
const ChatBot: React.FC<Props> = ({ isOpen, onClose, messages, onSendMessage, isProcessing }) => {
const [input, setInput] = useState('');
const scrollRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (scrollRef.current) {
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
}
}, [messages, isOpen]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim() || isProcessing) return;
onSendMessage(input);
setInput('');
};
if (!isOpen) return null;
return (
<div className="fixed bottom-6 right-6 w-80 md:w-96 h-[500px] glass-panel rounded-2xl shadow-2xl flex flex-col z-50 overflow-hidden border border-gray-200 dark:border-gray-700 animate-in fade-in slide-in-from-bottom-10">
{/* Header */}
<div className="p-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center bg-gray-50/50 dark:bg-gray-900/50">
<div className="flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
<h3 className="font-bold text-sm">Paper Assistant</h3>
</div>
<button onClick={onClose} className="hover:bg-gray-200 dark:hover:bg-gray-700 p-1 rounded">
<X size={16} />
</button>
</div>
{/* Messages */}
<div ref={scrollRef} className="flex-grow overflow-y-auto p-4 space-y-4 bg-white/50 dark:bg-black/20">
{messages.length === 0 && (
<div className="text-center text-xs opacity-50 mt-10">
Ask me anything about the paper!
</div>
)}
{messages.map((msg) => (
<div
key={msg.id}
className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div
className={`
max-w-[80%] p-3 rounded-2xl text-sm shadow-sm
${msg.role === 'user'
? 'bg-brand-600 text-white rounded-br-none'
: 'bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-bl-none'}
`}
>
{msg.text}
</div>
</div>
))}
{isProcessing && (
<div className="flex justify-start">
<div className="bg-white dark:bg-gray-800 p-3 rounded-2xl rounded-bl-none border border-gray-100 dark:border-gray-700">
<Loader2 className="animate-spin w-4 h-4 opacity-50" />
</div>
</div>
)}
</div>
{/* Input */}
<form onSubmit={handleSubmit} className="p-3 border-t border-gray-200 dark:border-gray-700 bg-gray-50/50 dark:bg-gray-900/50">
<div className="relative">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a question..."
className="w-full bg-white dark:bg-black/30 border border-gray-200 dark:border-gray-700 rounded-xl pl-4 pr-10 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500/50"
/>
<button
type="submit"
disabled={!input.trim() || isProcessing}
className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 rounded-lg bg-brand-500 text-white hover:bg-brand-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<Send size={14} />
</button>
</div>
</form>
</div>
);
};
export default ChatBot;