Spaces:
Build error
Build error
| 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; |