| function UserMessage({ content }) { |
| return ( |
| <div className="msg-row msg-row--user"> |
| <div className="bubble bubble--user">{content}</div> |
| <div className="avatar avatar--user">You</div> |
| </div> |
| ); |
| } |
|
|
| function ConfirmationMessage({ content, onConfirm, onDecline }) { |
| return ( |
| <div className="msg-row msg-row--assistant"> |
| <div className="avatar avatar--bot">J</div> |
| <div className="assistant-content"> |
| <div className="bubble bubble--assistant">{content}</div> |
| {onConfirm && onDecline && ( |
| <div className="confirm-actions"> |
| <button className="confirm-btn confirm-btn--yes" onClick={onConfirm}>Yes</button> |
| <button className="confirm-btn confirm-btn--no" onClick={onDecline}>No</button> |
| </div> |
| )} |
| </div> |
| </div> |
| ); |
| } |
|
|
| function AssistantMessage({ content, sources, error }) { |
| const uniqueSources = sources ? [...new Set(sources.filter(Boolean))] : []; |
|
|
| return ( |
| <div className="msg-row msg-row--assistant"> |
| <div className="avatar avatar--bot">J</div> |
| <div className="assistant-content"> |
| <div className={`bubble bubble--assistant ${error ? 'bubble--error' : ''}`}> |
| {content} |
| </div> |
| {uniqueSources.length > 0 && ( |
| <div className="sources"> |
| <span className="sources-label">Sources</span> |
| <div className="sources-list"> |
| {uniqueSources.map((src, i) => ( |
| <span key={i} className="source-tag"> |
| <span className="source-icon">📄</span> |
| {src} |
| </span> |
| ))} |
| </div> |
| </div> |
| )} |
| </div> |
| </div> |
| ); |
| } |
|
|
| export default function ChatMessage({ message, onConfirm, onDecline }) { |
| if (message.role === 'user') { |
| return <UserMessage content={message.content} />; |
| } |
| if (message.type === 'confirmation') { |
| return <ConfirmationMessage content={message.content} onConfirm={onConfirm} onDecline={onDecline} />; |
| } |
| return ( |
| <AssistantMessage |
| content={message.content} |
| sources={message.sources} |
| error={message.error} |
| /> |
| ); |
| } |
|
|