|
import React from 'react'; |
|
import { FaRobot } from 'react-icons/fa'; |
|
import { FiUser, FiCpu, FiAlertTriangle, FiTerminal, FiInfo } from 'react-icons/fi'; |
|
import ReactMarkdown from 'react-markdown'; |
|
|
|
export type MessageType = 'user' | 'agent' | 'log' | 'error' | 'info'; |
|
|
|
export interface ChatMessage { |
|
id: string; |
|
type: MessageType; |
|
content: string; |
|
agentId?: string; |
|
timestamp: Date; |
|
} |
|
|
|
interface ChatMessageProps { |
|
message: ChatMessage; |
|
} |
|
|
|
|
|
const ChatMessageComponent: React.FC<ChatMessageProps> = ({ message }) => { |
|
|
|
if (message.type === 'log') { |
|
|
|
const logMatch = message.content.match(/\[Agent:([^\]]+)\] (.*)/); |
|
if (logMatch) { |
|
const [_, agentId, logContent] = logMatch; |
|
return ( |
|
<div className="text-xs text-gray-500 py-1 pl-8 border-l border-gray-700 my-1"> |
|
<span className="font-semibold text-gray-400">{agentId}:</span> {logContent} |
|
</div> |
|
); |
|
} |
|
return ( |
|
<div className="flex items-start space-x-2 text-xs text-gray-500 py-1"> |
|
<FiTerminal className="text-gray-500 mt-0.5 flex-shrink-0" size={12} /> |
|
<div>{message.content}</div> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
if (message.type === 'error') { |
|
return ( |
|
<div className="flex items-start space-x-2 my-2 p-2 bg-red-900/20 border-l-2 border-red-500 text-red-400 rounded"> |
|
<FiAlertTriangle className="text-red-500 mt-1 flex-shrink-0" /> |
|
<div> |
|
<p className="font-semibold text-red-400">Erro:</p> |
|
<p className="text-gray-300">{message.content}</p> |
|
</div> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
if (message.type === 'info') { |
|
return ( |
|
<div className="flex items-start space-x-2 my-2 p-2 bg-blue-900/20 border-l-2 border-blue-500 text-blue-400 rounded"> |
|
<FiInfo className="text-blue-500 mt-1 flex-shrink-0" /> |
|
<div> |
|
<p className="font-semibold text-blue-400">Informação:</p> |
|
<p className="text-gray-300 whitespace-pre-line">{message.content}</p> |
|
</div> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
if (message.type === 'user') { |
|
return ( |
|
<div className="flex items-start space-x-2 my-3"> |
|
<div className="bg-indigo-600 text-white p-2 rounded-full flex-shrink-0"> |
|
<FiUser /> |
|
</div> |
|
<div className="bg-gray-800 p-3 rounded-lg rounded-tl-none max-w-[calc(100%-50px)] text-gray-200"> |
|
{message.content} |
|
</div> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
const agentColor = getAgentColor(message.agentId || 'default'); |
|
|
|
return ( |
|
<div className="flex items-start space-x-2 my-3"> |
|
<div className={`${agentColor} text-white p-2 rounded-full flex-shrink-0`}> |
|
<FiCpu /> |
|
</div> |
|
<div className="bg-gray-900 p-3 rounded-lg rounded-tl-none max-w-[calc(100%-50px)] text-gray-200 border border-gray-800"> |
|
<MessageContent content={message.content} /> |
|
</div> |
|
</div> |
|
); |
|
}; |
|
|
|
|
|
const getAgentColor = (agentId: string): string => { |
|
switch (agentId) { |
|
case 'orchestrator': |
|
return 'bg-purple-600'; |
|
case 'mike': |
|
return 'bg-blue-600'; |
|
case 'alex': |
|
return 'bg-green-600'; |
|
case 'david': |
|
return 'bg-amber-600'; |
|
default: |
|
return 'bg-indigo-600'; |
|
} |
|
}; |
|
|
|
|
|
const MessageContent: React.FC<{ content: string }> = ({ content }) => { |
|
|
|
if (content.includes('<html') || content.includes('<!DOCTYPE')) { |
|
return ( |
|
<div> |
|
<div className="bg-gray-800 p-2 rounded mb-2 text-xs text-green-400"> |
|
<FiInfo className="inline mr-1" /> HTML gerado |
|
</div> |
|
<div className="text-gray-300 max-h-80 overflow-y-auto"> |
|
{content} |
|
</div> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
try { |
|
return ( |
|
<div className="prose prose-invert prose-sm max-w-none"> |
|
<ReactMarkdown>{content}</ReactMarkdown> |
|
</div> |
|
); |
|
} catch { |
|
|
|
return <div className="whitespace-pre-wrap">{content}</div>; |
|
} |
|
}; |
|
|
|
export default ChatMessageComponent; |