Spaces:
Sleeping
Sleeping
| import { useState, useRef, useEffect } from 'react' | |
| import './ChatBox.css' | |
| export default function ChatBox({ messages, onSendMessage, loading }) { | |
| const [inputValue, setInputValue] = useState('') | |
| const messagesEndRef = useRef(null) | |
| const inputRef = useRef(null) | |
| const scrollToBottom = () => { | |
| messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) | |
| } | |
| useEffect(() => { | |
| scrollToBottom() | |
| }, [messages]) | |
| const handleSend = () => { | |
| if (inputValue.trim() && !loading) { | |
| onSendMessage(inputValue) | |
| setInputValue('') | |
| setTimeout(() => inputRef.current?.focus(), 0) | |
| } | |
| } | |
| const handleKeyPress = (e) => { | |
| if (e.key === 'Enter' && !e.shiftKey && !loading) { | |
| e.preventDefault() | |
| handleSend() | |
| } | |
| } | |
| return ( | |
| <div className="chatbox"> | |
| <div className="messages"> | |
| {messages.length === 0 ? ( | |
| <div className="empty-state"> | |
| <div className="empty-icon">🤖</div> | |
| <h2>Willkommen!</h2> | |
| <p>Starte eine Unterhaltung mit dem Zephyr-7B Modell</p> | |
| <div className="suggestions"> | |
| <button | |
| className="suggestion-btn" | |
| onClick={() => { | |
| setInputValue('Was ist Machine Learning?') | |
| inputRef.current?.focus() | |
| }} | |
| > | |
| Was ist Machine Learning? | |
| </button> | |
| <button | |
| className="suggestion-btn" | |
| onClick={() => { | |
| setInputValue('Erkläre Quantencomputing') | |
| inputRef.current?.focus() | |
| }} | |
| > | |
| Erkläre Quantencomputing | |
| </button> | |
| <button | |
| className="suggestion-btn" | |
| onClick={() => { | |
| setInputValue('Schreibe einen Witz') | |
| inputRef.current?.focus() | |
| }} | |
| > | |
| Schreibe einen Witz | |
| </button> | |
| </div> | |
| </div> | |
| ) : ( | |
| messages.map((msg) => ( | |
| <div key={msg.id} className={`message ${msg.role} ${msg.isError ? 'error' : ''}`}> | |
| <div className="message-avatar"> | |
| {msg.role === 'user' ? '👤' : '🤖'} | |
| </div> | |
| <div className="message-content"> | |
| <div className="message-text">{msg.content}</div> | |
| {msg.stats && ( | |
| <div className="message-stats"> | |
| ⏱️ {msg.stats.time}s • 📊 {msg.stats.tokens} tokens | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| )) | |
| )} | |
| {loading && ( | |
| <div className="message assistant loading"> | |
| <div className="message-avatar">🤖</div> | |
| <div className="message-content"> | |
| <div className="typing-indicator"> | |
| <span></span> | |
| <span></span> | |
| <span></span> | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| <div ref={messagesEndRef} /> | |
| </div> | |
| <div className="input-area"> | |
| <textarea | |
| ref={inputRef} | |
| value={inputValue} | |
| onChange={(e) => setInputValue(e.target.value)} | |
| onKeyPress={handleKeyPress} | |
| placeholder="Schreibe deine Frage hier... (Shift+Enter für Zeilenumbruch)" | |
| disabled={loading} | |
| rows="3" | |
| /> | |
| <button | |
| className="send-btn" | |
| onClick={handleSend} | |
| disabled={loading || !inputValue.trim()} | |
| > | |
| {loading ? '⏳ Denke...' : '➤ Senden'} | |
| </button> | |
| </div> | |
| </div> | |
| ) | |
| } | |