@@ -3,57 +3,67 @@ import { useParams } from "react-router-dom";
33import axios from "axios" ;
44
55function ChatInterface ( ) {
6- const { projectId } = useParams ( ) ; // Treating projectId as group_id
6+ const { projectId } = useParams ( ) ;
77 const [ chatId , setChatId ] = useState ( null ) ;
88 const [ messages , setMessages ] = useState ( [ ] ) ;
99 const [ newMessage , setNewMessage ] = useState ( "" ) ;
1010 const [ isSocketReady , setIsSocketReady ] = useState ( false ) ;
11+ const [ memberNames , setMemberNames ] = useState ( { } ) ;
1112 const ws = useRef ( null ) ;
12- const messagesEndRef = useRef ( null ) ; // Reference for the auto-scroll container
13+ const messagesEndRef = useRef ( null ) ;
1314
1415 const user = JSON . parse ( localStorage . getItem ( "user" ) ) || { } ;
15- // const { email: userEmail, name: userName, token: authToken } = user;
16-
1716 const userEmail = user [ "email" ] ;
1817 const userName = user [ "name" ] ;
1918 const authToken = user [ "token" ] ;
2019
21- // Helper function to check if projectId is a valid ObjectId-like string
2220 const isValidObjectId = ( id ) => / ^ [ a - f \d ] { 24 } $ / i. test ( id ) ;
2321
2422 useEffect ( ( ) => {
25- const fetchChat = async ( ) => {
23+ const fetchChatAndGroup = async ( ) => {
2624 if ( ! isValidObjectId ( projectId ) ) {
27- console . warn (
28- "Invalid group_id format (must be 24-character hex):" ,
29- projectId
30- ) ;
25+ console . warn ( "Invalid chat ID:" , projectId ) ;
3126 return ;
3227 }
3328
3429 try {
35- const response = await axios . get (
30+ const chatRes = await axios . get (
3631 `https://group-grade-backend-5f919d63857a.herokuapp.com/api/chat/${ projectId } ` ,
3732 {
38- headers : {
39- Authorization : `Bearer ${ authToken } ` ,
40- } ,
33+ headers : { Authorization : `Bearer ${ authToken } ` } ,
4134 }
4235 ) ;
4336
44- const chatData = response . data . data ;
37+ const chatData = chatRes . data . data ;
4538 setChatId ( chatData . _id ) ;
4639 setMessages ( chatData . chat_history || [ ] ) ;
47- } catch ( error ) {
48- console . error (
49- "Failed to fetch chat:" ,
50- error . response ?. data || error . message
40+
41+ const groupId = chatData . group_id ;
42+
43+ const groupRes = await axios . get (
44+ "https://group-grade-backend-5f919d63857a.herokuapp.com/api/group" ,
45+ {
46+ headers : { Authorization : `Bearer ${ authToken } ` } ,
47+ }
5148 ) ;
49+
50+ const groupList = groupRes . data . data ;
51+ const currentGroup = groupList . find ( ( g ) => g . id === groupId ) ;
52+
53+ if ( ! currentGroup ) {
54+ console . warn ( "Group not found with ID:" , groupId ) ;
55+ return ;
56+ }
57+
58+ setMemberNames ( currentGroup . member_names || { } ) ;
59+ localStorage . setItem ( "memberNames" , JSON . stringify ( currentGroup . member_names ) ) ;
60+ } catch ( error ) {
61+ console . error ( "Error fetching chat or group:" , error . response ?. data || error . message ) ;
5262 }
5363 } ;
5464
5565 if ( projectId && authToken ) {
56- fetchChat ( ) ;
66+ fetchChatAndGroup ( ) ;
5767 }
5868 } , [ projectId , authToken ] ) ;
5969
@@ -63,35 +73,56 @@ function ChatInterface() {
6373 const wsUrl = `wss://group-grade-backend-5f919d63857a.herokuapp.com/ws/chat/${ chatId } /${ userEmail } ` ;
6474 ws . current = new WebSocket ( wsUrl ) ;
6575
66- ws . current . onopen = ( ) => {
67- console . log ( "WebSocket connected" ) ;
68- setIsSocketReady ( true ) ;
69- } ;
76+ ws . current . onopen = ( ) => setIsSocketReady ( true ) ;
7077
7178 ws . current . onmessage = ( event ) => {
7279 const data = JSON . parse ( event . data ) ;
80+ if ( data . is_heartbeat_msg || data . message === "Health ping received!" ) return ;
7381 setMessages ( ( prev ) => [ ...prev , data ] ) ;
74- scrollToBottom ( ) ; // Scroll to bottom on new message
82+ scrollToBottom ( ) ;
7583 } ;
7684
7785 ws . current . onclose = ( ) => setIsSocketReady ( false ) ;
78- ws . current . onerror = ( error ) => setIsSocketReady ( false ) ;
86+ ws . current . onerror = ( ) => setIsSocketReady ( false ) ;
7987
8088 return ( ) => {
8189 if ( ws . current ) ws . current . close ( ) ;
8290 } ;
8391 } , [ chatId , userEmail ] ) ;
8492
8593 useEffect ( ( ) => {
86- scrollToBottom ( ) ; // Scroll to bottom when the component mounts
94+ const HEARTBEAT_INTERVAL = 15000 ;
95+ let heartbeatInterval ;
96+
97+ if ( isSocketReady && ws . current ) {
98+ heartbeatInterval = setInterval ( ( ) => {
99+ if ( ws . current . readyState === WebSocket . OPEN ) {
100+ ws . current . send (
101+ JSON . stringify ( {
102+ message : "" ,
103+ sender_name : userName ,
104+ sender_email : userEmail ,
105+ is_heartbeat_msg : true ,
106+ close_connection : false ,
107+ } )
108+ ) ;
109+ }
110+ } , HEARTBEAT_INTERVAL ) ;
111+ }
112+
113+ return ( ) => {
114+ if ( heartbeatInterval ) clearInterval ( heartbeatInterval ) ;
115+ } ;
116+ } , [ isSocketReady , userName , userEmail ] ) ;
117+
118+ useEffect ( ( ) => {
119+ scrollToBottom ( ) ;
87120 } , [ messages ] ) ;
88121
89122 useEffect ( ( ) => {
90- const user = JSON . parse ( localStorage . getItem ( "user" ) ) ;
91- if ( user && user . name ) {
92- console . log ( "Loaded User Name:" , user . name ) ;
93- } else {
94- console . log ( "No User Name Found in Local Storage" ) ;
123+ const cached = localStorage . getItem ( "memberNames" ) ;
124+ if ( cached ) {
125+ setMemberNames ( JSON . parse ( cached ) ) ;
95126 }
96127 } , [ ] ) ;
97128
@@ -123,15 +154,13 @@ function ChatInterface() {
123154
124155 const formatIrishTime = ( date ) => {
125156 const dt = new Date ( date ) ;
126-
127157 const formatter = new Intl . DateTimeFormat ( "en-IE" , {
128158 hour : "numeric" ,
129159 minute : "2-digit" ,
130160 hour12 : true ,
131161 timeZone : "Europe/Dublin" ,
132162 } ) ;
133163 dt . setHours ( dt . getHours ( ) + ( dt . getTimezoneOffset ( ) < 0 ? 1 : 0 ) ) ;
134-
135164 return formatter . format ( dt ) ;
136165 } ;
137166
@@ -145,11 +174,13 @@ function ChatInterface() {
145174 { messages . map ( ( msg , index ) => (
146175 < li
147176 key = { index }
148- className = { `message-item ${
149- msg . sender === userEmail ? "mine" : "theirs"
150- } `}
177+ className = { `message-item ${ msg . sender === userEmail ? "mine" : "theirs" } ` }
151178 >
152- < div className = "sender-name" > { msg . sender_name || "No Name" } </ div >
179+ < div className = "sender-name" >
180+ { msg . sender === userEmail
181+ ? "You"
182+ : memberNames [ msg . sender ] || msg . sender }
183+ </ div >
153184 { msg . message }
154185 < span className = "timestamp" >
155186 { formatIrishTime ( msg . delivered_time ) }
@@ -176,3 +207,4 @@ function ChatInterface() {
176207}
177208
178209export default ChatInterface ;
210+
0 commit comments