Advertisement
raffaelegriecoit

Untitled

Dec 17th, 2024
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.89 KB | None | 0 0
  1. import { useState, useEffect, useRef } from 'react';
  2. import userServices from '../services/userServices';
  3.  
  4. const ChatAdmin = () => {
  5. const [socket, setSocket] = useState(null);
  6. const [messages, setMessages] = useState({});
  7. const [messageInputs, setMessageInputs] = useState({});
  8. const [typingStatus, setTypingStatus] = useState({});
  9. const { getAllUsers } = userServices;
  10. const [allUsers, setAllUsers] = useState([]);
  11. const typingTimeout = useRef({});
  12.  
  13. useEffect(() => {
  14. const jwt = localStorage.getItem('token');
  15. const ws = new WebSocket(`ws://localhost:8003/ws/chat/?token=${jwt}`);
  16.  
  17. // Quando la connessione è aperta, settiamo il socket nello stato
  18. ws.onopen = () => {
  19. setSocket(ws);
  20. };
  21.  
  22. ws.onmessage = (event) => {
  23. const data = JSON.parse(event.data);
  24.  
  25. switch (data.type) {
  26. case 'message_read':
  27. setMessages((prev) => ({
  28. ...prev,
  29. [data.user_id]: [
  30. ...(prev[data.user_id] || []),
  31. { message: "Message read", sender_role: "system" },
  32. ],
  33. }));
  34. break;
  35.  
  36. case 'message':
  37. setMessages((prev) => ({
  38. ...prev,
  39. [data.user_id]: [...(prev[data.user_id] || []), data],
  40. }));
  41.  
  42. // Invia una notifica di lettura al client solo se il socket è ancora aperto
  43. if (ws && ws.readyState === WebSocket.OPEN) {
  44. ws.send(JSON.stringify({
  45. type: 'message_read',
  46. client_id: data.user_id,
  47. }));
  48. } else {
  49. console.log('errore message_read send');
  50. }
  51. break;
  52.  
  53. case 'typing':
  54. setTypingStatus((prev) => ({
  55. ...prev,
  56. [data.user_id]: 'Client is typing...',
  57. }));
  58.  
  59. if (typingTimeout.current[data.user_id]) {
  60. clearTimeout(typingTimeout.current[data.user_id]);
  61. }
  62. typingTimeout.current[data.user_id] = setTimeout(() => {
  63. setTypingStatus((prev) => ({
  64. ...prev,
  65. [data.user_id]: '',
  66. }));
  67. }, 3000);
  68. break;
  69.  
  70. default:
  71. console.error("Unknown message type:", data.type);
  72. }
  73. };
  74.  
  75. // Non impostiamo più qui setSocket(ws), lo facciamo in onopen
  76. return () => ws.close();
  77. }, [getAllUsers]);
  78.  
  79. useEffect(() => {
  80. const fetchData = async () => {
  81. try {
  82. const response = await getAllUsers();
  83. const clients = response.filter((user) => user.role === 'client');
  84. setAllUsers(clients);
  85.  
  86. const initialInputs = {};
  87. clients.forEach((client) => {
  88. initialInputs[client.id] = '';
  89. });
  90. setMessageInputs(initialInputs);
  91. } catch (error) {
  92. console.error("Error fetching users:", error);
  93. }
  94. };
  95.  
  96. fetchData();
  97. }, [getAllUsers]);
  98.  
  99. const sendMessage = (clientId) => {
  100. // Controllo se il socket è aperto prima di inviare
  101. if (socket && socket.readyState === WebSocket.OPEN && messageInputs[clientId].trim()) {
  102. socket.send(
  103. JSON.stringify({
  104. type: 'message',
  105. message: messageInputs[clientId],
  106. client_id: clientId,
  107. })
  108. );
  109.  
  110. setMessages((prev) => ({
  111. ...prev,
  112. [clientId]: [
  113. ...(prev[clientId] || []),
  114. { message: messageInputs[clientId], sender_role: 'admin' },
  115. ],
  116. }));
  117.  
  118. setMessageInputs((prev) => ({ ...prev, [clientId]: '' }));
  119. }
  120. };
  121.  
  122. const handleInputChange = (clientId, value) => {
  123. setMessageInputs((prev) => ({ ...prev, [clientId]: value }));
  124.  
  125. // Controllo se il socket è aperto prima di inviare "typing"
  126. if (socket && socket.readyState === WebSocket.OPEN) {
  127. socket.send(
  128. JSON.stringify({
  129. type: 'typing',
  130. client_id: clientId,
  131. })
  132. );
  133. }
  134. };
  135.  
  136. return (
  137. <div>
  138. <h1>Admin Chat</h1>
  139. <div>
  140. {allUsers.map((user) => (
  141. <div
  142. key={user.id}
  143. className="chat-box"
  144. style={{ border: '1px solid #ccc', margin: '10px', padding: '10px' }}
  145. >
  146. <h4>{`Chat with Client ${user.username}`}</h4>
  147. <div className="messages" style={{ height: '150px', overflowY: 'auto' }}>
  148. {messages[user.id]?.map((msg, index) => (
  149. <p key={index}>
  150. {msg.sender_role === "system" ? (
  151. <span style={{ fontStyle: "italic", color: "gray" }}>
  152. {msg.message}
  153. </span>
  154. ) : (
  155. <strong>
  156. {msg.sender_role === "client" ? "Client" : "You"}: {msg.message}
  157. </strong>
  158. )}
  159. </p>
  160. ))}
  161. {typingStatus[user.id] && (
  162. <p style={{ fontStyle: "italic", color: "blue" }}>
  163. {typingStatus[user.id]}
  164. </p>
  165. )}
  166. </div>
  167. <input
  168. type="text"
  169. value={messageInputs[user.id] || ''}
  170. onChange={(e) => handleInputChange(user.id, e.target.value)}
  171. placeholder="Type your message"
  172. style={{ width: '80%', marginRight: '5px' }}
  173. />
  174. <button onClick={() => sendMessage(user.id)}>Send</button>
  175. </div>
  176. ))}
  177. </div>
  178. </div>
  179. );
  180. };
  181.  
  182. export default ChatAdmin;
  183.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement