@pubuduth-aplicy/chat-ui 2.1.79 → 2.1.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -17,28 +17,29 @@ type GroupedServiceChats = {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
type TabType = "personal" | "service";
|
|
21
|
+
|
|
20
22
|
const Conversations = () => {
|
|
21
23
|
const { userId, socket } = useChatContext();
|
|
22
24
|
const { data: participantGroups } = useGetConversations(userId);
|
|
23
25
|
const { searchTerm } = useChatUIStore();
|
|
26
|
+
const [activeTab, setActiveTab] = useState<TabType>("personal");
|
|
24
27
|
const [conversations, setConversations] = useState<{
|
|
25
|
-
|
|
28
|
+
personalChats: ConversationType[];
|
|
26
29
|
groupedServiceChats: GroupedServiceChats;
|
|
27
|
-
}>({
|
|
30
|
+
}>({ personalChats: [], groupedServiceChats: {} });
|
|
28
31
|
|
|
29
32
|
// Process fetched data
|
|
30
33
|
useEffect(() => {
|
|
31
34
|
if (!participantGroups) return;
|
|
32
35
|
|
|
33
36
|
const processConversations = (groups: ParticipantGroup[]) => {
|
|
34
|
-
const
|
|
37
|
+
const allPersonalChats: ConversationType[] = [];
|
|
35
38
|
const allServiceChatsMap = new Map<string, GroupedServiceChats[string]>();
|
|
36
39
|
|
|
37
40
|
groups.forEach((group) => {
|
|
38
|
-
// console.log("group", group.personalConversation);
|
|
39
|
-
|
|
40
41
|
if (group.personalConversation) {
|
|
41
|
-
|
|
42
|
+
allPersonalChats.push(group.personalConversation);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
group.serviceConversations.forEach((serviceGroup) => {
|
|
@@ -61,13 +62,13 @@ const Conversations = () => {
|
|
|
61
62
|
new Date(a.lastMessage?.createdAt || a.updatedAt).getTime()
|
|
62
63
|
);
|
|
63
64
|
|
|
64
|
-
sortConversations(
|
|
65
|
+
sortConversations(allPersonalChats);
|
|
65
66
|
allServiceChatsMap.forEach((value) =>
|
|
66
67
|
sortConversations(value.conversations)
|
|
67
68
|
);
|
|
68
69
|
|
|
69
70
|
return {
|
|
70
|
-
|
|
71
|
+
personalChats: allPersonalChats,
|
|
71
72
|
groupedServiceChats: Object.fromEntries(allServiceChatsMap),
|
|
72
73
|
};
|
|
73
74
|
};
|
|
@@ -86,7 +87,7 @@ const Conversations = () => {
|
|
|
86
87
|
const { chatId, messageIds } = data;
|
|
87
88
|
|
|
88
89
|
setConversations((prev) => {
|
|
89
|
-
const
|
|
90
|
+
const personalChats = [...prev.personalChats];
|
|
90
91
|
const groupedServiceChats = { ...prev.groupedServiceChats };
|
|
91
92
|
|
|
92
93
|
const updateRead = (convo: ConversationType) => {
|
|
@@ -101,10 +102,10 @@ const Conversations = () => {
|
|
|
101
102
|
};
|
|
102
103
|
};
|
|
103
104
|
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
return {
|
|
105
|
+
const personalIndex = personalChats.findIndex((c) => c._id === chatId);
|
|
106
|
+
if (personalIndex >= 0) {
|
|
107
|
+
personalChats[personalIndex] = updateRead(personalChats[personalIndex]);
|
|
108
|
+
return { personalChats, groupedServiceChats };
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
for (const serviceId in groupedServiceChats) {
|
|
@@ -117,7 +118,7 @@ const Conversations = () => {
|
|
|
117
118
|
...groupedServiceChats[serviceId],
|
|
118
119
|
conversations: updatedConvos,
|
|
119
120
|
};
|
|
120
|
-
return {
|
|
121
|
+
return { personalChats, groupedServiceChats };
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -129,7 +130,7 @@ const Conversations = () => {
|
|
|
129
130
|
if (!newMessage?.conversationId) return;
|
|
130
131
|
|
|
131
132
|
setConversations((prev) => {
|
|
132
|
-
const
|
|
133
|
+
const personalChats = [...prev.personalChats];
|
|
133
134
|
const groupedServiceChats = { ...prev.groupedServiceChats };
|
|
134
135
|
|
|
135
136
|
const updateConversation = (convo: ConversationType) => ({
|
|
@@ -146,14 +147,14 @@ const Conversations = () => {
|
|
|
146
147
|
: convo.unreadMessageCount || 0,
|
|
147
148
|
});
|
|
148
149
|
|
|
149
|
-
const
|
|
150
|
+
const personalIndex = personalChats.findIndex(
|
|
150
151
|
(c) => c._id === newMessage.conversationId
|
|
151
152
|
);
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
if (personalIndex >= 0) {
|
|
154
|
+
personalChats[personalIndex] = updateConversation(
|
|
155
|
+
personalChats[personalIndex]
|
|
155
156
|
);
|
|
156
|
-
return {
|
|
157
|
+
return { personalChats, groupedServiceChats };
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
for (const serviceId in groupedServiceChats) {
|
|
@@ -171,11 +172,11 @@ const Conversations = () => {
|
|
|
171
172
|
...groupedServiceChats[serviceId],
|
|
172
173
|
conversations: updatedConversations,
|
|
173
174
|
};
|
|
174
|
-
return {
|
|
175
|
+
return { personalChats, groupedServiceChats };
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
|
|
179
|
+
personalChats.push({
|
|
179
180
|
_id: newMessage.conversationId,
|
|
180
181
|
participants: [newMessage.senderId, newMessage.receiverId],
|
|
181
182
|
lastMessage: newMessage,
|
|
@@ -188,7 +189,7 @@ const Conversations = () => {
|
|
|
188
189
|
createdAt: new Date().toISOString(),
|
|
189
190
|
});
|
|
190
191
|
|
|
191
|
-
return {
|
|
192
|
+
return { personalChats, groupedServiceChats };
|
|
192
193
|
});
|
|
193
194
|
};
|
|
194
195
|
|
|
@@ -218,13 +219,14 @@ const Conversations = () => {
|
|
|
218
219
|
}, [socket, userId]);
|
|
219
220
|
|
|
220
221
|
const isEmpty =
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
activeTab === "personal"
|
|
223
|
+
? conversations.personalChats.length === 0
|
|
224
|
+
: Object.keys(conversations.groupedServiceChats).length === 0;
|
|
223
225
|
|
|
224
226
|
const lowerSearch = searchTerm?.toLowerCase().trim();
|
|
225
227
|
|
|
226
|
-
const
|
|
227
|
-
convo.participantDetails?.some((p:any) =>
|
|
228
|
+
const filteredPersonalChats = conversations.personalChats.filter((convo) =>
|
|
229
|
+
convo.participantDetails?.some((p: any) =>
|
|
228
230
|
typeof p === "string"
|
|
229
231
|
? p.toLowerCase().includes(lowerSearch)
|
|
230
232
|
: p.name?.toLowerCase().includes(lowerSearch)
|
|
@@ -235,7 +237,7 @@ const Conversations = () => {
|
|
|
235
237
|
Object.entries(conversations.groupedServiceChats)
|
|
236
238
|
.map(([serviceId, group]) => {
|
|
237
239
|
const filteredConvos = group.conversations.filter((convo) =>
|
|
238
|
-
convo.participants?.some((p:any) =>
|
|
240
|
+
convo.participants?.some((p: any) =>
|
|
239
241
|
typeof p === "string"
|
|
240
242
|
? p.toLowerCase().includes(lowerSearch)
|
|
241
243
|
: p.name?.toLowerCase().includes(lowerSearch)
|
|
@@ -246,48 +248,90 @@ const Conversations = () => {
|
|
|
246
248
|
.filter(([_, group]) => group.conversations.length > 0) // Remove empty groups
|
|
247
249
|
);
|
|
248
250
|
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
+
// Calculate unread counts for tabs
|
|
252
|
+
const personalUnreadCount = conversations.personalChats.reduce(
|
|
253
|
+
(total, convo) => total + (convo.unreadMessageCount || 0),
|
|
254
|
+
0
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
const serviceUnreadCount = Object.values(conversations.groupedServiceChats)
|
|
258
|
+
.flatMap(group => group.conversations)
|
|
259
|
+
.reduce((total, convo) => total + (convo.unreadMessageCount || 0), 0);
|
|
251
260
|
|
|
252
261
|
return (
|
|
253
262
|
<div className="chatSidebarConversations">
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
{/* Tab Navigation */}
|
|
264
|
+
<div className="flex border-b border-gray-200">
|
|
265
|
+
<button
|
|
266
|
+
className={`flex-1 py-3 px-4 text-sm font-medium text-center border-b-2 transition-colors ${
|
|
267
|
+
activeTab === "personal"
|
|
268
|
+
? "border-[#317490] message-text bg-blue-50"
|
|
269
|
+
: "border-transparent text-gray-500 hover:text-gray-700 hover:bg-gray-50"
|
|
270
|
+
}`}
|
|
271
|
+
onClick={() => setActiveTab("personal")}
|
|
272
|
+
>
|
|
273
|
+
Personal
|
|
274
|
+
{personalUnreadCount > 0 && (
|
|
275
|
+
<span className="ml-2 bg-blue-500 text-white text-xs rounded-full px-2 py-1 min-w-5 inline-flex justify-center">
|
|
276
|
+
{personalUnreadCount}
|
|
277
|
+
</span>
|
|
267
278
|
)}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
</CollapsibleSection>
|
|
283
|
-
)
|
|
284
|
-
)}
|
|
285
|
-
</CollapsibleSection>
|
|
279
|
+
</button>
|
|
280
|
+
<button
|
|
281
|
+
className={`flex-1 py-3 px-4 text-sm font-medium text-center border-b-2 transition-colors ${
|
|
282
|
+
activeTab === "service"
|
|
283
|
+
? "border-blue-500 text-blue-600 bg-blue-50"
|
|
284
|
+
: "border-transparent text-gray-500 hover:text-gray-700 hover:bg-gray-50"
|
|
285
|
+
}`}
|
|
286
|
+
onClick={() => setActiveTab("service")}
|
|
287
|
+
>
|
|
288
|
+
Service
|
|
289
|
+
{serviceUnreadCount > 0 && (
|
|
290
|
+
<span className="ml-2 bg-blue-500 text-white text-xs rounded-full px-2 py-1 min-w-5 inline-flex justify-center">
|
|
291
|
+
{serviceUnreadCount}
|
|
292
|
+
</span>
|
|
286
293
|
)}
|
|
287
|
-
|
|
288
|
-
|
|
294
|
+
</button>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
{/* Tab Content */}
|
|
298
|
+
<div className="flex-1 overflow-auto">
|
|
299
|
+
{isEmpty ? (
|
|
300
|
+
<div className="flex flex-col items-center justify-center p-8 text-center">
|
|
301
|
+
<h3 className="text-xl font-semibold mb-1">No Conversations</h3>
|
|
302
|
+
<p className="text-gray-500 text-sm mb-4">
|
|
303
|
+
{activeTab === "personal"
|
|
304
|
+
? "You have no personal messages yet."
|
|
305
|
+
: "You have no service messages yet."}
|
|
306
|
+
</p>
|
|
307
|
+
</div>
|
|
308
|
+
) : (
|
|
309
|
+
<>
|
|
310
|
+
{activeTab === "personal" && filteredPersonalChats.length > 0 && (
|
|
311
|
+
<VirtualizedChatList conversations={filteredPersonalChats} />
|
|
312
|
+
)}
|
|
313
|
+
|
|
314
|
+
{activeTab === "service" &&
|
|
315
|
+
Object.entries(filteredGroupedServiceChats).length > 0 && (
|
|
316
|
+
<div className="p-2">
|
|
317
|
+
{Object.entries(filteredGroupedServiceChats).map(
|
|
318
|
+
([serviceId, { serviceTitle, conversations: serviceConvos }]) => (
|
|
319
|
+
<CollapsibleSection
|
|
320
|
+
key={serviceId}
|
|
321
|
+
title={serviceTitle}
|
|
322
|
+
defaultOpen={false}
|
|
323
|
+
>
|
|
324
|
+
<VirtualizedChatList conversations={serviceConvos} />
|
|
325
|
+
</CollapsibleSection>
|
|
326
|
+
)
|
|
327
|
+
)}
|
|
328
|
+
</div>
|
|
329
|
+
)}
|
|
330
|
+
</>
|
|
331
|
+
)}
|
|
332
|
+
</div>
|
|
289
333
|
</div>
|
|
290
334
|
);
|
|
291
335
|
};
|
|
292
336
|
|
|
293
|
-
export default Conversations;
|
|
337
|
+
export default Conversations;
|