AI_Chat_With_Tools / components /ChatWindow.tsx
muhammad1707's picture
Move master code to main
8421ec4
Raw
History Blame Contribute Delete
8.11 kB
import React, { useRef, useEffect } from 'react';
import { Message, Chat } from '../types';
import ChatMessage from './ChatMessage';
import ChatInput from './ChatInput';
interface ChatWindowProps {
activeChat: Chat | null;
messages: Message[];
onSendMessage: (content: string) => void;
isSending: boolean;
isLoading: boolean;
}
const ChatWindow: React.FC<ChatWindowProps> = ({
activeChat,
messages,
onSendMessage,
isSending,
isLoading,
}) => {
const messagesEndRef = useRef<HTMLDivElement>(null);
// Auto-scroll to bottom when new messages arrive
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
return (
<div className="flex-1 flex flex-col bg-gray-50 h-full">
{/* Header */}
<header className="bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between shadow-sm">
<div className="flex items-center gap-3">
<div className="bg-gradient-to-br from-indigo-500 to-purple-600 p-2 rounded-xl shadow-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</div>
<div>
<h1 className="text-xl font-bold text-gray-900">
{activeChat ? activeChat.title : 'RAG Chat'}
</h1>
<p className="text-xs text-gray-500">Powered by AI + Document Retrieval</p>
</div>
</div>
{activeChat && (
<div className="flex items-center gap-2 text-xs text-gray-400">
<span className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></span>
Online
</div>
)}
</header>
{/* Messages Area */}
<div className="flex-1 overflow-y-auto px-6 py-6">
{!activeChat ? (
// No Chat Selected State
<div className="h-full flex flex-col items-center justify-center text-center">
<div className="bg-gradient-to-br from-indigo-100 to-purple-100 p-6 rounded-3xl mb-6">
<svg className="w-16 h-16 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</div>
<h2 className="text-2xl font-bold text-gray-800 mb-2">Welcome to RAG Chat</h2>
<p className="text-gray-500 max-w-md mb-6">
Start a new conversation or select an existing chat from the sidebar to continue your discussion.
</p>
<div className="flex flex-wrap justify-center gap-3 text-sm">
<div className="bg-white px-4 py-2 rounded-full border border-gray-200 text-gray-600">
💡 Ask questions about your documents
</div>
<div className="bg-white px-4 py-2 rounded-full border border-gray-200 text-gray-600">
📚 Context-aware responses
</div>
<div className="bg-white px-4 py-2 rounded-full border border-gray-200 text-gray-600">
💬 Conversation history
</div>
</div>
</div>
) : isLoading ? (
// Loading Messages
<div className="h-full flex items-center justify-center">
<div className="flex flex-col items-center gap-4">
<div className="relative">
<div className="w-12 h-12 border-4 border-indigo-200 rounded-full animate-spin border-t-indigo-600"></div>
</div>
<span className="text-gray-500 text-sm">Loading messages...</span>
</div>
</div>
) : messages.length === 0 ? (
// Empty Chat State
<div className="h-full flex flex-col items-center justify-center text-center">
<div className="bg-gradient-to-br from-emerald-100 to-teal-100 p-5 rounded-2xl mb-4">
<svg className="w-12 h-12 text-emerald-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-800 mb-1">Start the conversation</h3>
<p className="text-gray-500 text-sm max-w-sm">
Ask any question and I'll search through the documents to provide you with relevant answers.
</p>
</div>
) : (
// Messages List
<div className="max-w-4xl mx-auto space-y-6">
{messages.map((msg) => (
<ChatMessage key={msg.id} message={msg} />
))}
{/* Typing Indicator */}
{isSending && (
<div className="flex gap-4">
<div className="flex-shrink-0 w-10 h-10 rounded-full bg-gradient-to-br from-emerald-500 to-teal-600 flex items-center justify-center shadow-lg">
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" />
</svg>
</div>
<div className="bg-white border border-gray-100 px-4 py-3 rounded-2xl rounded-bl-md shadow-sm">
<div className="flex gap-1">
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }}></span>
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }}></span>
<span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }}></span>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
)}
</div>
{/* Input Area */}
<ChatInput
onSendMessage={onSendMessage}
isSending={isSending}
disabled={!activeChat}
/>
</div>
);
};
export default ChatWindow;