File size: 5,684 Bytes
7781557
 
 
 
902845d
 
 
 
 
 
 
 
 
 
 
7781557
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
902845d
 
 
 
7781557
 
 
 
 
 
 
 
 
 
 
 
 
902845d
 
 
 
7781557
 
 
 
 
 
902845d
7781557
 
 
 
 
 
902845d
7781557
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
902845d
 
 
 
7781557
 
 
902845d
7781557
 
 
3bb94b1
7781557
 
 
3bb94b1
902845d
7781557
 
902845d
7781557
 
902845d
 
 
7781557
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3bb94b1
 
 
 
 
 
 
 
 
 
 
7781557
 
 
 
 
 
 
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import React, { useState, useEffect, useRef } from 'react';
import { useAuth } from '../services/AuthContext';
import { useNavigate } from 'react-router-dom';

const processMessages = (messageObject) => {
  return (previousMessages) => {
    if (previousMessages.length > 0 && previousMessages[previousMessages.length - 1].sender === messageObject.sender) {
      const newMessage = {text:previousMessages[previousMessages.length - 1].text+ ' ' + messageObject.text, sender: messageObject.sender};
      return [...previousMessages.slice(0, -1), newMessage];
    } else {
      return [...previousMessages, messageObject];
    }
  }
}

const Chat = () => {
  const { token, logout } = useAuth();
  const navigate = useNavigate();
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [isConnected, setIsConnected] = useState(false);
  const [connectionAttempts, setConnectionAttempts] = useState(0);
  const [isReconnecting, setIsReconnecting] = useState(false);
  const websocket = useRef(null);
  const maxReconnectAttempts = 5;

  const connectWebSocket = () => {
    if (websocket.current?.readyState === WebSocket.OPEN) {
      console.log('WebSocket is already connected');
      return;
    }

    console.log('Attempting to connect WebSocket...');
    const ws = new WebSocket('ws://localhost:8000/ws');
    websocket.current = ws;

    ws.onopen = async () => {
      console.log('WebSocket connected, sending auth token...');
      // Send authentication token
      ws.send(JSON.stringify({
        type: 'authentication',
        token: token
      }));
    };

    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        console.log('Received message:', data);

        switch (data.type) {
          case 'connection_established':
            setIsConnected(true);
            setConnectionAttempts(0);
            setIsReconnecting(false);
            break;
          case 'message':
            setMessages(processMessages({
              text:data.message,
              sender: data.sender
            }));
            break;
          case 'error':
            console.error('Server error:', data.message);
            if (data.message.includes('Authentication failed')) {
              logout();
              navigate('/login');
            }
            break;
          default:
            console.log('Unhandled message type:', data.type);
        }
      } catch (error) {
        console.error('Error processing message:', error);
        setMessages(processMessages({
          text: event.data,
          sender: 'ai'
        }));
      }
    };

    ws.onclose = (event) => {
      console.log('WebSocket closed:', event);
      setIsConnected(false);

      if (event.code === 1008) {
        // Authentication failed
        console.error('WebSocket authentication failed');
        logout();
        navigate('/login');
      } else if (connectionAttempts < maxReconnectAttempts) {

        // Normal closure or error, attempt to reconnect
        setIsReconnecting(true);
        setConnectionAttempts(prev => prev + 1);
        setTimeout(connectWebSocket, 2000 * Math.min(connectionAttempts + 1, 5));
      }
    };

    ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };
  };

  useEffect(() => {
    connectWebSocket();

    return () => {
      if (websocket.current) {
        websocket.current.close();
      }
    };
  }, [token]);

  const sendMessage = (e) => {
    e.preventDefault();
    if (!input.trim() || !isConnected) return;

    const message = {
      type: 'message',
      content: input
    };

    setMessages(processMessages({
      text: input,
      sender: 'user'
    }));
    websocket.current.send(JSON.stringify(message));
    setInput('');
  };
  console.log('MESSAGES****', messages);
  // Rest of your component (file upload handler, UI rendering, etc.)
  return (
    <div className="flex flex-col h-screen bg-gray-100">
      

      {/* Messages area */}
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
      {isReconnecting && <span className="text-yellow-500">Reconnecting...</span>}
        {(messages || []).map((message, index) => (
          <div
            key={index}
            className={`p-3 rounded-lg max-w-[80%] ${message.sender === 'user'
                ? 'ml-auto bg-blue-500 text-white'
                : message.sender === 'ai'
                  ? 'bg-gray-200'
                  : 'bg-yellow-100 mx-auto'
              }`}
          >
            {message.text}
          </div>
        ))}
      </div>

      {/* Input area */}
      <div className="p-4 bg-white border-t">
        <form onSubmit={sendMessage} className="flex gap-4">
          <input
            type="text"
            value={input}
            onChange={(e) => setInput(e.target.value)}
            placeholder="Type your message..."
            className="flex-1 p-2 border rounded"
            disabled={!isConnected}
          />
          <button
            type="submit"
            className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-400"
            disabled={!isConnected}
          >
            Send
          </button>

          <button
            onClick={() => {
              logout();
              navigate('/login');
            }}
            className="px-4 py-2 text-white bg-red-500 rounded hover:bg-red-600"
          >
            Logout
          </button>
          <span className={`h-3 w-3 rounded-full ${isConnected ? 'bg-green-500' : 'bg-red-500'}`}></span>
        </form>
      </div>
    </div>
  );
};

export default Chat;