ChandimaPrabath commited on
Commit
1ca0bed
·
1 Parent(s): 695b887

update. added session token.

Browse files
frontend/app/Auth.js CHANGED
@@ -15,7 +15,7 @@ const Auth = ({
15
  setIsSignup,
16
  ws,
17
  status,
18
- setSessionToken, // Added to handle session token
19
  }) => {
20
  const [usernameValid, setUsernameValid] = useState(false);
21
  const [passwordValid, setPasswordValid] = useState(false);
 
15
  setIsSignup,
16
  ws,
17
  status,
18
+ setSessionToken,
19
  }) => {
20
  const [usernameValid, setUsernameValid] = useState(false);
21
  const [passwordValid, setPasswordValid] = useState(false);
frontend/app/Sidebar.js CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import { useState, useEffect } from 'react';
2
  import Image from 'next/image';
3
 
@@ -10,6 +12,7 @@ export default function Sidebar({
10
  }) {
11
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
12
  const [me, setMe] = useState('');
 
13
 
14
  useEffect(() => {
15
  // Retrieve 'me' from localStorage
@@ -17,6 +20,17 @@ export default function Sidebar({
17
  if (storedMe) {
18
  setMe(storedMe);
19
  }
 
 
 
 
 
 
 
 
 
 
 
20
  }, []);
21
 
22
  const toggleSidebar = () => {
@@ -27,8 +41,12 @@ export default function Sidebar({
27
  const query = e.target.value;
28
  setSearchQuery(query);
29
 
30
- const servicesUrl = process.env.NEXT_PUBLIC_SERVICES_URL;
 
 
 
31
 
 
32
  if (!servicesUrl) {
33
  console.error('Environment variable NEXT_PUBLIC_SERVICES_URL is not defined.');
34
  return;
@@ -38,9 +56,10 @@ export default function Sidebar({
38
  try {
39
  const response = await fetch(`${servicesUrl}/search?query=${query}`);
40
  const data = await response.json();
41
- setFilteredUsers(data);
42
  } catch (error) {
43
  console.error('Error fetching search results:', error);
 
44
  }
45
  } else {
46
  setFilteredUsers([]);
@@ -95,45 +114,97 @@ export default function Sidebar({
95
  style={searchInputStyle}
96
  />
97
 
98
- <ul style={{ listStyleType: 'none', padding: 0 }}>
99
- {filteredUsers.map((recipient, index) => (
100
- <li
101
- key={index}
102
- style={{
103
- color: '#fff',
104
- cursor: 'pointer',
105
- marginBottom: '15px',
106
- display: 'flex',
107
- alignItems: 'center',
108
- }}
109
- onClick={() => handleUserSelect(recipient)}
110
- >
111
- {/* Profile Picture */}
112
- <div
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  style={{
114
- width: '40px',
115
- height: '40px',
116
- position: 'relative',
117
- marginRight: '10px',
 
118
  }}
 
119
  >
120
- <Image
121
- src={`https://ui-avatars.com/api/?background=random&name=${encodeURIComponent(
122
- recipient
123
- )}`}
124
- alt={`${recipient}'s avatar`}
125
- layout="fill"
126
- objectFit="cover"
127
- style={{ borderRadius: '50%' }}
128
- />
129
- </div>
130
- {/* Username */}
131
- <span style={{ textDecoration: 'none', color: '#fff', fontSize: '16px' }}>
132
- {recipient} {recipient === me ? '(Me)' : ''}
133
- </span>
134
- </li>
135
- ))}
136
- </ul>
 
 
 
 
 
 
 
 
 
 
137
  </div>
138
  </>
139
  );
 
1
+ 'use client';
2
+
3
  import { useState, useEffect } from 'react';
4
  import Image from 'next/image';
5
 
 
12
  }) {
13
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
14
  const [me, setMe] = useState('');
15
+ const [allChats, setAllChats] = useState([]);
16
 
17
  useEffect(() => {
18
  // Retrieve 'me' from localStorage
 
20
  if (storedMe) {
21
  setMe(storedMe);
22
  }
23
+
24
+ // Retrieve all chats stored in localStorage
25
+ const allKeys = Object.keys(localStorage);
26
+ const chats = allKeys.filter((key) => key !== 'me' && key !== 'sessionToken' && key !== 'ally-supports-cache').map((key) => {
27
+ return {
28
+ username: key,
29
+ chatData: JSON.parse(localStorage.getItem(key)),
30
+ };
31
+ });
32
+
33
+ setAllChats(chats);
34
  }, []);
35
 
36
  const toggleSidebar = () => {
 
41
  const query = e.target.value;
42
  setSearchQuery(query);
43
 
44
+ if (!query) {
45
+ setFilteredUsers([]); // No search query, show nothing in search results
46
+ return;
47
+ }
48
 
49
+ const servicesUrl = process.env.NEXT_PUBLIC_SERVICES_URL;
50
  if (!servicesUrl) {
51
  console.error('Environment variable NEXT_PUBLIC_SERVICES_URL is not defined.');
52
  return;
 
56
  try {
57
  const response = await fetch(`${servicesUrl}/search?query=${query}`);
58
  const data = await response.json();
59
+ setFilteredUsers(Array.isArray(data) ? data : []); // Ensure that filteredUsers is always an array
60
  } catch (error) {
61
  console.error('Error fetching search results:', error);
62
+ setFilteredUsers([]); // In case of error, clear filteredUsers
63
  }
64
  } else {
65
  setFilteredUsers([]);
 
114
  style={searchInputStyle}
115
  />
116
 
117
+ <div style={{ marginBottom: '20px' }}>
118
+ {/* Display search results */}
119
+ {searchQuery && (
120
+ <div>
121
+ <h4 style={{ color: '#fff', marginBottom: '10px' }}>Search Results</h4>
122
+ <ul style={{ listStyleType: 'none', padding: 0 }}>
123
+ {Array.isArray(filteredUsers) && filteredUsers.map((recipient, index) => (
124
+ <li
125
+ key={index}
126
+ style={{
127
+ color: '#fff',
128
+ cursor: 'pointer',
129
+ marginBottom: '15px',
130
+ display: 'flex',
131
+ alignItems: 'center',
132
+ }}
133
+ onClick={() => handleUserSelect(recipient)}
134
+ >
135
+ {/* Profile Picture */}
136
+ <div
137
+ style={{
138
+ width: '40px',
139
+ height: '40px',
140
+ position: 'relative',
141
+ marginRight: '10px',
142
+ }}
143
+ >
144
+ <Image
145
+ src={`https://ui-avatars.com/api/?background=random&name=${encodeURIComponent(
146
+ recipient
147
+ )}`}
148
+ alt={`${recipient}'s avatar`}
149
+ layout="fill"
150
+ objectFit="cover"
151
+ style={{ borderRadius: '50%' }}
152
+ />
153
+ </div>
154
+ {/* Username */}
155
+ <span style={{ textDecoration: 'none', color: '#fff', fontSize: '16px' }}>
156
+ {recipient} {recipient === me ? '(Me)' : ''}
157
+ </span>
158
+ </li>
159
+ ))}
160
+ </ul>
161
+ </div>
162
+ )}
163
+ </div>
164
+
165
+ <div>
166
+ {/* Display localStorage chats */}
167
+ <h4 style={{ color: '#fff', marginBottom: '10px' }}>Chats</h4>
168
+ <ul style={{ listStyleType: 'none', padding: 0 }}>
169
+ {allChats.map((chat, index) => (
170
+ <li
171
+ key={index}
172
  style={{
173
+ color: '#fff',
174
+ cursor: 'pointer',
175
+ marginBottom: '15px',
176
+ display: 'flex',
177
+ alignItems: 'center',
178
  }}
179
+ onClick={() => handleUserSelect(chat.username)}
180
  >
181
+ {/* Profile Picture */}
182
+ <div
183
+ style={{
184
+ width: '40px',
185
+ height: '40px',
186
+ position: 'relative',
187
+ marginRight: '10px',
188
+ }}
189
+ >
190
+ <Image
191
+ src={`https://ui-avatars.com/api/?background=random&name=${encodeURIComponent(
192
+ chat.username
193
+ )}`}
194
+ alt={`${chat.username}'s avatar`}
195
+ layout="fill"
196
+ objectFit="cover"
197
+ style={{ borderRadius: '50%' }}
198
+ />
199
+ </div>
200
+ {/* Username */}
201
+ <span style={{ textDecoration: 'none', color: '#fff', fontSize: '16px' }}>
202
+ {chat.username} {chat.username === me ? '(Me)' : ''}
203
+ </span>
204
+ </li>
205
+ ))}
206
+ </ul>
207
+ </div>
208
  </div>
209
  </>
210
  );
frontend/app/layout.js CHANGED
@@ -16,7 +16,8 @@ export default function RootLayout({ children }) {
16
  const [searchQuery, setSearchQuery] = useState('');
17
  const [filteredUsers, setFilteredUsers] = useState([]);
18
  const [isLoggedIn, setIsLoggedIn] = useState(false);
19
- const [isSignup, setIsSignup] = useState(false);
 
20
 
21
  useEffect(() => {
22
  // Check if there's a valid session token in localStorage
@@ -52,6 +53,8 @@ export default function RootLayout({ children }) {
52
  setIsLoggedIn={setIsLoggedIn}
53
  isSignup={isSignup}
54
  setIsSignup={setIsSignup}
 
 
55
  >
56
  {children}
57
  </WebSocketLayout>
@@ -82,6 +85,8 @@ function WebSocketLayout({
82
  setIsLoggedIn,
83
  isSignup,
84
  setIsSignup,
 
 
85
  children,
86
  }) {
87
  const { ws, status } = useWebSocket();
@@ -103,6 +108,7 @@ function WebSocketLayout({
103
  setRecipientList(data.recipients || []);
104
  localStorage.setItem('me', username);
105
  localStorage.setItem('sessionToken', data.token); // Store session token
 
106
  } else if (data.status === 'error') {
107
  setError(data.message);
108
  setIsLoading(false);
@@ -141,6 +147,7 @@ function WebSocketLayout({
141
  setIsSignup={setIsSignup}
142
  ws={ws}
143
  status={status}
 
144
  />
145
  </div>
146
  )}
 
16
  const [searchQuery, setSearchQuery] = useState('');
17
  const [filteredUsers, setFilteredUsers] = useState([]);
18
  const [isLoggedIn, setIsLoggedIn] = useState(false);
19
+ const [isSignup, setIsSignup] = useState('');
20
+ const [sessionToken, setSessionToken] = useState(''); // Initialize sessionToken state
21
 
22
  useEffect(() => {
23
  // Check if there's a valid session token in localStorage
 
53
  setIsLoggedIn={setIsLoggedIn}
54
  isSignup={isSignup}
55
  setIsSignup={setIsSignup}
56
+ sessionToken={sessionToken} // Pass sessionToken down to WebSocketLayout
57
+ setSessionToken={setSessionToken} // Pass setSessionToken down to WebSocketLayout
58
  >
59
  {children}
60
  </WebSocketLayout>
 
85
  setIsLoggedIn,
86
  isSignup,
87
  setIsSignup,
88
+ sessionToken,
89
+ setSessionToken, // Receive setSessionToken
90
  children,
91
  }) {
92
  const { ws, status } = useWebSocket();
 
108
  setRecipientList(data.recipients || []);
109
  localStorage.setItem('me', username);
110
  localStorage.setItem('sessionToken', data.token); // Store session token
111
+ setSessionToken(data.token); // Update sessionToken state
112
  } else if (data.status === 'error') {
113
  setError(data.message);
114
  setIsLoading(false);
 
147
  setIsSignup={setIsSignup}
148
  ws={ws}
149
  status={status}
150
+ setSessionToken={setSessionToken} // Pass setSessionToken to Auth
151
  />
152
  </div>
153
  )}
frontend/app/page.js CHANGED
@@ -1,18 +1,30 @@
1
- "use client";
2
 
3
- import { useState } from "react";
4
 
5
  export default function ChatPage() {
 
 
 
 
 
 
 
 
 
 
 
 
6
  return (
7
- <div style={{ width: "100%", padding: "20px", backgroundColor: "rgb(28, 28, 47)", minHeight: "100vh" }}>
8
  <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', height: '100%', width: '100%' }}>
9
  <div style={{ textAlign: 'center' }}>
10
- <h1 style={{ color: "#4a4a4a", fontSize: "24px", marginBottom: "20px" }}>Welcome to Nexus</h1>
11
- <p style={{ color: "#7d7d7d", fontSize: "16px", marginBottom: "20px" }}>
12
- Open the sidebar to find and start conversations with your contacts.
13
  </p>
14
- <div style={{ fontSize: "14px", color: "#aaa" }}>
15
- <p>No chats selected yet. Choose a conversation from the sidebar.</p>
16
  </div>
17
  </div>
18
  </div>
 
1
+ 'use client';
2
 
3
+ import { useState, useEffect } from 'react';
4
 
5
  export default function ChatPage() {
6
+ const [me, setMe] = useState('');
7
+
8
+ useEffect(() => {
9
+ // Retrieve 'me' from localStorage because who doesn't like remembering things?
10
+ const storedMe = localStorage.getItem('me');
11
+ if (storedMe) {
12
+ setMe(storedMe);
13
+ } else {
14
+ console.warn("Hey, there's no 'me' in localStorage. Are you sure you're logged in?");
15
+ }
16
+ }, []);
17
+
18
  return (
19
+ <div style={{ width: '100%', padding: '20px', backgroundColor: 'rgb(28, 28, 47)', minHeight: '100vh' }}>
20
  <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', height: '100%', width: '100%' }}>
21
  <div style={{ textAlign: 'center' }}>
22
+ <h1 style={{ color: '#4a4a4a', fontSize: '24px', marginBottom: '20px' }}>Welcome, {me || 'Stranger'} to Nexus!</h1>
23
+ <p style={{ color: '#7d7d7d', fontSize: '16px', marginBottom: '20px' }}>
24
+ Open the sidebar to find and start conversations with your contacts (or your future best friends).
25
  </p>
26
+ <div style={{ fontSize: '14px', color: '#aaa' }}>
27
+ <p>{me ? 'No chats selected yet. Choose a conversation from the sidebar to get started.' : 'Log in to start chatting!'}</p>
28
  </div>
29
  </div>
30
  </div>
frontend/app/u/[recipientusername]/page.js CHANGED
@@ -13,8 +13,15 @@ export default function ChatPage() {
13
  const { ws } = useWebSocket();
14
 
15
  const [me, setMe] = useState("");
 
16
  const router = useRouter(); // Hook to navigate
17
 
 
 
 
 
 
 
18
  useEffect(() => {
19
  // Retrieve 'me' from localStorage
20
  const storedMe = localStorage.getItem("me");
@@ -31,16 +38,30 @@ export default function ChatPage() {
31
 
32
  useEffect(() => {
33
  if (recipient) {
34
- const storedMessages = JSON.parse(localStorage.getItem(recipient)) || [];
35
- setChatLog(formatMessages(storedMessages));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
- }, [recipient]);
38
 
39
  useEffect(() => {
40
  const interval = setInterval(() => {
41
  if (recipient) {
42
- const updatedMessages =
43
- JSON.parse(localStorage.getItem(recipient)) || [];
44
  setChatLog(formatMessages(updatedMessages));
45
  }
46
  }, 2000);
@@ -78,7 +99,8 @@ export default function ChatPage() {
78
  };
79
 
80
  const formatMessages = (messages) => {
81
- return messages.map(formatMessage);
 
82
  };
83
 
84
  const formatMessage = (message) => {
@@ -103,152 +125,160 @@ export default function ChatPage() {
103
  }}
104
  >
105
  {recipient ? (
106
- <>
107
- {/* Chat Header */}
108
- <div
109
- style={{
110
- backgroundColor: "#170f3f",
111
- padding: "10px",
112
- display: "flex",
113
- alignItems: "center",
114
- gap: "10px",
115
- position: "relative",
116
- }}
117
- >
118
- <Image
119
- src={`https://ui-avatars.com/api/?name=${encodeURIComponent(
120
- recipient
121
- )}&background=random`}
122
- alt={`${recipient}'s avatar`}
123
- width={40}
124
- height={40}
125
- style={{ borderRadius: "50%", marginLeft: "40px" }}
126
- />
127
- <h1 style={{ margin: 0, fontSize: "20px" }}>
128
- {recipient === me ? `${recipient} (Me)` : recipient}
129
- </h1>
130
-
131
- {/* Close Button */}
132
- <button
133
- onClick={handleCloseChat}
134
  style={{
135
- position: "absolute",
136
- right: "10px",
137
- background: "transparent",
138
- border: "none",
139
- color: "#fff",
140
- fontSize: "30px",
141
- cursor: "pointer",
142
  }}
143
  >
144
- &times;
145
- </button>
146
- </div>
 
 
 
 
 
 
 
 
 
147
 
148
- {/* Chat Log */}
149
- <div
150
- style={{
151
- flex: 1,
152
- overflowY: "auto",
153
- padding: "20px",
154
- backgroundColor: "#1c1c2f",
155
- display: "flex",
156
- flexDirection: "column",
157
- gap: "10px",
158
- borderTop: "1px solid #3d3d6b",
159
- }}
160
- >
161
- {chatLog.map((entry, index) => (
162
- <div
163
- key={index}
164
  style={{
165
- display: "flex",
166
- alignItems: "flex-end",
167
- flexDirection: entry.from === "You" ? "row-reverse" : "row",
168
- gap: "10px",
 
 
 
169
  }}
170
  >
171
- {/* Avatar */}
172
- <Image
173
- src={
174
- entry.from === "You"
175
- ? `https://ui-avatars.com/api/?name=${encodeURIComponent(
176
- me
177
- )}&background=random`
178
- : `https://ui-avatars.com/api/?name=${encodeURIComponent(
179
- recipient
180
- )}&background=random`
181
- }
182
- alt={`${entry.from}'s avatar`}
183
- width={30}
184
- height={30}
185
- style={{ borderRadius: "50%" }}
186
- />
187
-
188
- {/* Message */}
189
- <div
190
- style={{
191
- backgroundColor:
192
- entry.from === "You" ? "#3b2e83" : "#3d446b",
193
- color: "#fff",
194
- padding: "10px",
195
- borderRadius: "10px",
196
- maxWidth: "70%",
197
- wordWrap: "break-word",
198
- }}
199
- >
200
- <p style={{ margin: 0, fontWeight: "bold" }}>{entry.from}</p>
201
- <p style={{ margin: "5px 0" }}>{entry.message}</p>
202
- <small style={{ fontSize: "12px", color: "#a1a1c7" }}>
203
- {entry.timestamp}
204
- </small>
205
- </div>
206
- </div>
207
- ))}
208
- </div>
209
 
210
- {/* Message Input */}
211
- <div
212
- style={{
213
- backgroundColor: "#171927",
214
- borderTop: "1px solid rgb(95, 38, 207)",
215
- padding: "10px",
216
- display: "flex",
217
- gap: "10px",
218
- }}
219
- >
220
- <input
221
- type="text"
222
- placeholder="Type your message..."
223
- value={message}
224
- onChange={(e) => setMessage(e.target.value)}
225
  style={{
226
  flex: 1,
227
- padding: "10px",
228
- borderRadius: "5px",
229
- border: "1px solid #4b2e83",
230
- fontSize: "16px",
231
- backgroundColor: "#2e2e4f",
232
- color: "#fff",
 
233
  }}
234
- />
235
- <button
236
- onClick={handleSendMessage}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  style={{
238
- padding: "10px 20px",
239
- backgroundColor: "#3b2e83",
240
- color: "#fff",
241
- border: "none",
242
- borderRadius: "5px",
243
- fontSize: "16px",
244
- cursor: "pointer",
245
- transition: "background-color 0.3s",
246
  }}
247
  >
248
- Send
249
- </button>
250
- </div>
251
- </>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  ) : (
253
  <p>Loading recipient...</p>
254
  )}
 
13
  const { ws } = useWebSocket();
14
 
15
  const [me, setMe] = useState("");
16
+ const [recipientExists, setRecipientExists] = useState(true);
17
  const router = useRouter(); // Hook to navigate
18
 
19
+ const servicesUrl = process.env.NEXT_PUBLIC_SERVICES_URL;
20
+ if (!servicesUrl) {
21
+ console.error('Environment variable NEXT_PUBLIC_SERVICES_URL is not defined.');
22
+ return;
23
+ }
24
+
25
  useEffect(() => {
26
  // Retrieve 'me' from localStorage
27
  const storedMe = localStorage.getItem("me");
 
38
 
39
  useEffect(() => {
40
  if (recipient) {
41
+ // Check if recipient exists by making an API request to the server
42
+ const checkUserExistence = async () => {
43
+ try {
44
+ const response = await fetch(`${servicesUrl}/api/user/${recipient}`);
45
+ if (response.ok) {
46
+ setRecipientExists(true);
47
+ const storedMessages = JSON.parse(localStorage.getItem(recipient)) || [];
48
+ setChatLog(formatMessages(storedMessages));
49
+ } else {
50
+ setRecipientExists(false);
51
+ }
52
+ } catch (error) {
53
+ console.error("Error checking user existence:", error);
54
+ setRecipientExists(false);
55
+ }
56
+ };
57
+ checkUserExistence();
58
  }
59
+ }, [recipient, servicesUrl]);
60
 
61
  useEffect(() => {
62
  const interval = setInterval(() => {
63
  if (recipient) {
64
+ const updatedMessages = JSON.parse(localStorage.getItem(recipient)) || [];
 
65
  setChatLog(formatMessages(updatedMessages));
66
  }
67
  }, 2000);
 
99
  };
100
 
101
  const formatMessages = (messages) => {
102
+ // Ensure that messages is an array before calling map
103
+ return Array.isArray(messages) ? messages.map(formatMessage) : [];
104
  };
105
 
106
  const formatMessage = (message) => {
 
125
  }}
126
  >
127
  {recipient ? (
128
+ recipientExists ? (
129
+ <>
130
+ {/* Chat Header */}
131
+ <div
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  style={{
133
+ backgroundColor: "#170f3f",
134
+ padding: "10px",
135
+ display: "flex",
136
+ alignItems: "center",
137
+ gap: "10px",
138
+ position: "relative",
 
139
  }}
140
  >
141
+ <Image
142
+ src={`https://ui-avatars.com/api/?name=${encodeURIComponent(
143
+ recipient
144
+ )}&background=random`}
145
+ alt={`${recipient}'s avatar`}
146
+ width={40}
147
+ height={40}
148
+ style={{ borderRadius: "50%", marginLeft: "40px" }}
149
+ />
150
+ <h1 style={{ margin: 0, fontSize: "20px" }}>
151
+ {recipient === me ? `${recipient} (Me)` : recipient}
152
+ </h1>
153
 
154
+ {/* Close Button */}
155
+ <button
156
+ onClick={handleCloseChat}
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  style={{
158
+ position: "absolute",
159
+ right: "10px",
160
+ background: "transparent",
161
+ border: "none",
162
+ color: "#fff",
163
+ fontSize: "30px",
164
+ cursor: "pointer",
165
  }}
166
  >
167
+ &times;
168
+ </button>
169
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ {/* Chat Log */}
172
+ <div
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  style={{
174
  flex: 1,
175
+ overflowY: "auto",
176
+ padding: "20px",
177
+ backgroundColor: "#1c1c2f",
178
+ display: "flex",
179
+ flexDirection: "column",
180
+ gap: "10px",
181
+ borderTop: "1px solid #3d3d6b",
182
  }}
183
+ >
184
+ {chatLog.length > 0 ? (
185
+ chatLog.map((entry, index) => (
186
+ <div
187
+ key={index}
188
+ style={{
189
+ display: "flex",
190
+ alignItems: "flex-end",
191
+ flexDirection: entry.from === "You" ? "row-reverse" : "row",
192
+ gap: "10px",
193
+ }}
194
+ >
195
+ {/* Avatar */}
196
+ <Image
197
+ src={
198
+ entry.from === "You"
199
+ ? `https://ui-avatars.com/api/?name=${encodeURIComponent(
200
+ me
201
+ )}&background=random`
202
+ : `https://ui-avatars.com/api/?name=${encodeURIComponent(
203
+ recipient
204
+ )}&background=random`
205
+ }
206
+ alt={`${entry.from}'s avatar`}
207
+ width={30}
208
+ height={30}
209
+ style={{ borderRadius: "50%" }}
210
+ />
211
+
212
+ {/* Message */}
213
+ <div
214
+ style={{
215
+ backgroundColor:
216
+ entry.from === "You" ? "#3b2e83" : "#3d446b",
217
+ color: "#fff",
218
+ padding: "10px",
219
+ borderRadius: "10px",
220
+ maxWidth: "70%",
221
+ wordWrap: "break-word",
222
+ }}
223
+ >
224
+ <p style={{ margin: 0, fontWeight: "bold" }}>{entry.from}</p>
225
+ <p style={{ margin: "5px 0" }}>{entry.message}</p>
226
+ <small style={{ fontSize: "12px", color: "#a1a1c7" }}>
227
+ {entry.timestamp}
228
+ </small>
229
+ </div>
230
+ </div>
231
+ ))
232
+ ) : (
233
+ <p>No messages yet</p>
234
+ )}
235
+ </div>
236
+
237
+ {/* Message Input */}
238
+ <div
239
  style={{
240
+ backgroundColor: "#171927",
241
+ borderTop: "1px solid rgb(95, 38, 207)",
242
+ padding: "10px",
243
+ display: "flex",
244
+ gap: "10px",
 
 
 
245
  }}
246
  >
247
+ <input
248
+ type="text"
249
+ placeholder="Type your message..."
250
+ value={message}
251
+ onChange={(e) => setMessage(e.target.value)}
252
+ style={{
253
+ flex: 1,
254
+ padding: "10px",
255
+ borderRadius: "5px",
256
+ border: "1px solid #4b2e83",
257
+ fontSize: "16px",
258
+ backgroundColor: "#2e2e4f",
259
+ color: "#fff",
260
+ }}
261
+ />
262
+ <button
263
+ onClick={handleSendMessage}
264
+ style={{
265
+ padding: "10px 20px",
266
+ backgroundColor: "#3b2e83",
267
+ color: "#fff",
268
+ border: "none",
269
+ borderRadius: "5px",
270
+ fontSize: "16px",
271
+ cursor: "pointer",
272
+ transition: "background-color 0.3s",
273
+ }}
274
+ >
275
+ Send
276
+ </button>
277
+ </div>
278
+ </>
279
+ ) : (
280
+ <p>User does not exist.</p>
281
+ )
282
  ) : (
283
  <p>Loading recipient...</p>
284
  )}