| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- import React, { useState, useRef, useEffect } from 'react';
- import { useNavigate } from 'react-router-dom';
- interface Message {
- id: number;
- text: string;
- sender: 'user' | 'clone';
- }
- const CloneChatPage: React.FC = () => {
- const navigate = useNavigate();
- const [messages, setMessages] = useState<Message[]>([
- { id: 1, text: "Hello! You can start training me by talking to me. What's on your mind?", sender: 'clone' }
- ]);
- const [inputValue, setInputValue] = useState('');
- const [isTyping, setIsTyping] = useState(false);
- const messagesEndRef = useRef<HTMLDivElement>(null);
- const scrollToBottom = () => {
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
- };
- useEffect(scrollToBottom, [messages, isTyping]);
- const handleSendMessage = (e: React.FormEvent) => {
- e.preventDefault();
- if (inputValue.trim() === '') return;
- const userMessage: Message = {
- id: Date.now(),
- text: inputValue,
- sender: 'user',
- };
- setMessages(prev => [...prev, userMessage]);
- setInputValue('');
- setIsTyping(true);
- // Simulate clone response
- setTimeout(() => {
- const cloneResponse: Message = {
- id: Date.now() + 1,
- text: `That's an interesting point. It reminds me of how you once said... (simulated response based on your persona).`,
- sender: 'clone',
- };
- setIsTyping(false);
- setMessages(prev => [...prev, cloneResponse]);
- }, 1500 + Math.random() * 1000);
- };
- return (
- <div className="flex flex-col h-[calc(100vh-60px)] max-w-3xl mx-auto bg-white rounded-2xl overflow-hidden border border-slate-200">
- {/* Header */}
- <header className="flex items-center justify-between p-4 border-b border-slate-200 bg-slate-50 flex-shrink-0">
- <h1 className="text-xl font-bold text-slate-800">Train My Digital Clone</h1>
- <button
- onClick={() => navigate('/edit')}
- className="px-4 py-2 text-sm font-medium text-slate-700 bg-white border border-slate-300 rounded-md hover:bg-slate-100"
- >
- Back to Edit
- </button>
- </header>
- {/* Chat Area */}
- <main className="flex-1 overflow-y-auto p-6 space-y-4">
- {messages.map(msg => (
- <div key={msg.id} className={`flex items-end gap-2 ${msg.sender === 'user' ? 'justify-end' : 'justify-start'}`}>
- {msg.sender === 'clone' && (
- <div className="w-8 h-8 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex-shrink-0"></div>
- )}
- <div className={`max-w-xs md:max-w-md lg:max-w-lg px-4 py-2 rounded-2xl ${msg.sender === 'user' ? 'bg-blue-600 text-white rounded-br-none' : 'bg-slate-200 text-slate-800 rounded-bl-none'}`}>
- <p className="text-sm leading-relaxed">{msg.text}</p>
- </div>
- </div>
- ))}
- {isTyping && (
- <div className="flex items-end gap-2 justify-start">
- <div className="w-8 h-8 rounded-full bg-gradient-to-br from-indigo-500 to-purple-600 flex-shrink-0"></div>
- <div className="px-4 py-2 rounded-2xl bg-slate-200 rounded-bl-none">
- <div className="flex items-center justify-center space-x-1">
- <span className="w-1.5 h-1.5 bg-slate-500 rounded-full animate-bounce [animation-delay:-0.3s]"></span>
- <span className="w-1.5 h-1.5 bg-slate-500 rounded-full animate-bounce [animation-delay:-0.15s]"></span>
- <span className="w-1.5 h-1.5 bg-slate-500 rounded-full animate-bounce"></span>
- </div>
- </div>
- </div>
- )}
- <div ref={messagesEndRef} />
- </main>
- {/* Input Form */}
- <footer className="p-4 border-t border-slate-200 bg-slate-50 flex-shrink-0">
- <form onSubmit={handleSendMessage} className="flex items-center gap-3">
- <input
- type="text"
- value={inputValue}
- onChange={e => setInputValue(e.target.value)}
- placeholder="Talk to your clone..."
- className="flex-1 w-full px-4 py-2 bg-white border border-slate-300 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500"
- autoComplete="off"
- />
- <button
- type="submit"
- aria-label="Send message"
- className="w-10 h-10 flex-shrink-0 bg-blue-600 text-white rounded-full flex items-center justify-center hover:bg-blue-700 disabled:bg-blue-300 transition-colors"
- disabled={inputValue.trim() === ''}
- >
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" className="w-5 h-5">
- <path d="M3.105 2.289a.75.75 0 00-.826.95l1.414 4.925A1.5 1.5 0 005.135 9.25h6.115a.75.75 0 010 1.5H5.135a1.5 1.5 0 00-1.442 1.086L2.279 16.76a.75.75 0 00.826.95l14.433-6.414a.75.75 0 000-1.392L3.105 2.289z" />
- </svg>
- </button>
- </form>
- </footer>
- </div>
- );
- };
- export default CloneChatPage;
|