Decoder2704/python-chatbot-jay
0
1import MessageBubble from "./MessageBubble.jsx";2import SampleQuestions from "./SampleQuestions.jsx";3import { useChatSession } from "../hooks/useChatSession.js";4import "./ChatWindow.css";5 6export default function ChatWindow() {7 const {8 messages,9 input,10 setInput,11 loading,12 error,13 runSend,14 handleSubmit,15 handleClear,16 bottomRef,17 } = useChatSession();18 19 return (20 <div className="chat-window">21 <header className="chat-window__header">22 <div>23 <h1 className="chat-window__title">PyBot</h1>24 <p className="chat-window__subtitle">Python Q&A — powered by your FastAPI backend</p>25 </div>26 <button type="button" className="chat-window__clear" onClick={handleClear}>27 Clear chat28 </button>29 </header>30 31 <div className="chat-window__body">32 {messages.length === 0 && !loading && (33 <p className="chat-window__empty">Ask a Python question below, or pick a sample.</p>34 )}35 <div className="chat-window__messages">36 {messages.map((m) => (37 <MessageBubble38 key={m.id}39 role={m.role}40 text={m.text}41 meta={m.meta}42 />43 ))}44 {loading && (45 <div className="chat-window__loading" aria-live="polite">46 <span className="chat-window__spinner" aria-hidden />47 Thinking…48 </div>49 )}50 <div ref={bottomRef} />51 </div>52 </div>53 54 {error && <p className="chat-window__error">{error}</p>}55 56 <SampleQuestions onSelect={(q) => runSend(q)} disabled={loading} />57 58 <form className="chat-window__form" onSubmit={handleSubmit}>59 <input60 type="text"61 className="chat-window__input"62 placeholder="Type your Python question…"63 value={input}64 onChange={(e) => setInput(e.target.value)}65 disabled={loading}66 autoComplete="off"67 aria-label="Message"68 />69 <button type="submit" className="chat-window__send" disabled={loading || !input.trim()}>70 Send71 </button>72 </form>73 </div>74 );75}76 