desk_agent_2.0 / components /ChatInterface.tsx
harvesthealth's picture
Upload folder using huggingface_hub
c2ebec8 verified
import React, { useState, useRef, useEffect } from 'react';
import { Message, AgentType } from '../types';
import { Send, User, Bot, Loader2 } from 'lucide-react';
interface ChatInterfaceProps {
messages: Message[];
onSendMessage: (content: string) => void;
isProcessing: boolean;
}
const ChatInterface: React.FC<ChatInterfaceProps> = ({ messages, onSendMessage, isProcessing }) => {
const [input, setInput] = useState('');
const messagesEndRef = useRef<HTMLDivElement>(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim() || isProcessing) return;
onSendMessage(input);
setInput('');
};
const renderMessageIcon = (sender: string) => {
if (sender === 'User') return <User className="w-5 h-5 text-gray-300" />;
return <Bot className="w-5 h-5 text-blue-400" />;
};
return (
<div className="flex flex-col h-full bg-gray-950 rounded-xl overflow-hidden shadow-2xl border border-gray-800">
{/* Header */}
<div className="p-4 border-b border-gray-800 bg-gray-900/50 backdrop-blur">
<h2 className="text-lg font-semibold text-white">Orchestration Chat</h2>
<p className="text-xs text-gray-400">Interacting with Orchestrator Agent (Memory Active)</p>
</div>
{/* Messages */}
<div className="flex-1 overflow-y-auto p-4 space-y-6">
{messages.map((msg) => (
<div
key={msg.id}
className={`flex gap-3 ${msg.sender === 'User' ? 'flex-row-reverse' : 'flex-row'}`}
>
<div className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${
msg.sender === 'User' ? 'bg-gray-700' : 'bg-blue-900/30'
}`}>
{renderMessageIcon(msg.sender)}
</div>
<div className={`max-w-[80%] rounded-lg p-3 text-sm leading-relaxed ${
msg.sender === 'User'
? 'bg-gray-800 text-white'
: 'bg-blue-900/10 text-gray-200 border border-blue-900/30'
}`}>
<div className="flex items-center gap-2 mb-1">
<span className="font-bold text-xs opacity-70">{msg.sender}</span>
<span className="text-[10px] opacity-40">{msg.timestamp.toLocaleTimeString()}</span>
</div>
<div className="whitespace-pre-wrap">{msg.content}</div>
</div>
</div>
))}
{isProcessing && (
<div className="flex items-center gap-2 text-gray-500 text-sm pl-12">
<Loader2 className="w-4 h-4 animate-spin" />
<span>Orchestrator is delegating...</span>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Input */}
<div className="p-4 bg-gray-900 border-t border-gray-800">
<form onSubmit={handleSubmit} className="relative">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Describe your task (e.g., 'Plan a new health app' or 'Ask Jules to fix the bug')..."
className="w-full bg-gray-800 border-gray-700 text-white rounded-lg pl-4 pr-12 py-3 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:border-transparent placeholder-gray-500"
/>
<button
type="submit"
disabled={!input.trim() || isProcessing}
className="absolute right-2 top-2 p-1.5 bg-blue-600 hover:bg-blue-500 text-white rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<Send className="w-5 h-5" />
</button>
</form>
</div>
</div>
);
};
export default ChatInterface;