File size: 2,395 Bytes
fca46f5
 
 
 
15926a2
fca46f5
 
 
 
 
 
 
 
 
203dbbc
15926a2
fca46f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4da3586
fca46f5
 
 
 
 
 
 
 
 
 
 
203dbbc
fca46f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15926a2
 
 
fca46f5
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import React, { useEffect, useRef } from 'react';
import { useChat } from '../../hooks/useChat';
import MessageBubble from './MessageBubble';
import MessageInput from './MessageInput';
import StepSequencePanel from './StepSequencePanel';
import './ChatWindow.css';

/**
 * ChatWindow — main chat container.
 *
 * - Full-height layout with scrollable message list above input
 * - Auto-scrolls to the latest message
 * - Shows "PC Pal is typing..." indicator
 */
function ChatWindow({ userId }) {
  const { messages, sendMessage, isConnected, isTyping, activeSequence } = useChat(userId);
  const bottomRef = useRef(null);

  // Auto-scroll to the newest message
  useEffect(() => {
    if (bottomRef.current) {
      bottomRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [messages, isTyping]);

  return (
    <div className="chat-window">
      {/* Connection status banner */}
      {!isConnected && (
        <div className="connection-banner" role="status">
          Connecting to PC Pal... please wait.
        </div>
      )}

      {/* Scrollable message list */}
      <div className="chat-messages" role="log" aria-live="polite" aria-label="Chat messages">
        {messages.length === 0 && (
          <div className="chat-empty">
            <p className="chat-empty__text">
              Hello! I'm PC Pal, your friendly tech helper.
              <br />
              Ask me anything about your computer!
            </p>
          </div>
        )}

        {messages.map((msg) => (
          <MessageBubble key={msg.id} message={msg} />
        ))}

        {/* Typing indicator */}
        {isTyping && (
          <div className="typing-indicator" aria-live="polite" role="status">
            <div className="typing-indicator__dots">
              <span></span>
              <span></span>
              <span></span>
            </div>
            <span className="typing-indicator__label">PC Pal is typing...</span>
          </div>
        )}

        {/* Invisible anchor to scroll to */}
        <div ref={bottomRef} aria-hidden="true" />
      </div>

      {/* Step sequence guidance panel — shown above input when active */}
      <StepSequencePanel activeSequence={activeSequence} onSendMessage={sendMessage} />

      {/* Input area */}
      <MessageInput onSend={sendMessage} isTyping={isTyping} />
    </div>
  );
}

export default ChatWindow;