@pubuduth-aplicy/chat-ui 2.1.83 → 2.1.85
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
|
@@ -102,7 +102,7 @@ const MessageContainer = () => {
|
|
|
102
102
|
<div className="chatMessageContainerOutterDiv">
|
|
103
103
|
{selectedConversation.type === "service" ? (
|
|
104
104
|
<>
|
|
105
|
-
<p className="chatMessageContainerOutterDiv_name">
|
|
105
|
+
<p className="chatMessageContainerOutterDiv_name truncate xs:line-clamp-1">
|
|
106
106
|
{selectedConversation.serviceTitle}
|
|
107
107
|
</p>
|
|
108
108
|
<p className="text-sm">
|
|
@@ -38,7 +38,7 @@ interface Attachment {
|
|
|
38
38
|
|
|
39
39
|
const MessageInput = () => {
|
|
40
40
|
const apiClient = getApiClient();
|
|
41
|
-
const {role} = getChatConfig();
|
|
41
|
+
const { role } = getChatConfig();
|
|
42
42
|
const { socket, sendMessage, userId } = useChatContext();
|
|
43
43
|
const { selectedConversation, setMessages } = useChatUIStore();
|
|
44
44
|
const [message, setMessage] = useState("");
|
|
@@ -60,7 +60,9 @@ const MessageInput = () => {
|
|
|
60
60
|
`temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
61
61
|
// Join chat room when conversation is selected
|
|
62
62
|
|
|
63
|
-
const participantDetails = Array.isArray(
|
|
63
|
+
const participantDetails = Array.isArray(
|
|
64
|
+
selectedConversation?.participantDetails
|
|
65
|
+
)
|
|
64
66
|
? selectedConversation?.participantDetails
|
|
65
67
|
: [selectedConversation?.participantDetails].filter(Boolean);
|
|
66
68
|
|
|
@@ -78,7 +80,7 @@ const MessageInput = () => {
|
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
}, [selectedConversation?._id, socket, sendMessage]);
|
|
81
|
-
|
|
83
|
+
|
|
82
84
|
useEffect(() => {
|
|
83
85
|
// Clear all input state when conversation changes
|
|
84
86
|
setMessage("");
|
|
@@ -203,7 +205,7 @@ const MessageInput = () => {
|
|
|
203
205
|
const response = await apiClient.post(`${Path.preSignUrl}`, {
|
|
204
206
|
fileName: file.name,
|
|
205
207
|
fileType: file.type,
|
|
206
|
-
conversationId: selectedConversation?._id
|
|
208
|
+
conversationId: selectedConversation?._id,
|
|
207
209
|
});
|
|
208
210
|
|
|
209
211
|
const { signedUrl, fileUrl } = await response.data;
|
|
@@ -237,8 +239,6 @@ const MessageInput = () => {
|
|
|
237
239
|
});
|
|
238
240
|
};
|
|
239
241
|
|
|
240
|
-
|
|
241
|
-
|
|
242
242
|
// const otherParticipant = selectedConversation?.participantDetails?.find(
|
|
243
243
|
// (p:any) => p._id !== userId
|
|
244
244
|
// );
|
|
@@ -355,7 +355,7 @@ const MessageInput = () => {
|
|
|
355
355
|
? selectedConversation?.serviceId
|
|
356
356
|
: undefined,
|
|
357
357
|
senderRole: role,
|
|
358
|
-
receiverRole: role ===
|
|
358
|
+
receiverRole: role === "customer" ? "provider" : "customer",
|
|
359
359
|
},
|
|
360
360
|
{
|
|
361
361
|
onSuccess: (data) => {
|
|
@@ -704,27 +704,29 @@ const MessageInput = () => {
|
|
|
704
704
|
}}
|
|
705
705
|
/>
|
|
706
706
|
|
|
707
|
-
<
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
<svg
|
|
713
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
714
|
-
className="icon"
|
|
715
|
-
width="14"
|
|
716
|
-
height="14"
|
|
717
|
-
viewBox="0 0 24 24"
|
|
718
|
-
fill="none"
|
|
719
|
-
stroke="#ffffff"
|
|
720
|
-
stroke-width="2"
|
|
721
|
-
stroke-linecap="round"
|
|
722
|
-
stroke-linejoin="round"
|
|
707
|
+
<div>
|
|
708
|
+
<button
|
|
709
|
+
type="submit"
|
|
710
|
+
className="chatMessageInputSubmit"
|
|
711
|
+
disabled={!!inputError || isSending}
|
|
723
712
|
>
|
|
724
|
-
<
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
713
|
+
<svg
|
|
714
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
715
|
+
className="icon"
|
|
716
|
+
width="14"
|
|
717
|
+
height="14"
|
|
718
|
+
viewBox="0 0 24 24"
|
|
719
|
+
fill="none"
|
|
720
|
+
stroke="#ffffff"
|
|
721
|
+
stroke-width="2"
|
|
722
|
+
stroke-linecap="round"
|
|
723
|
+
stroke-linejoin="round"
|
|
724
|
+
>
|
|
725
|
+
<line x1="22" y1="2" x2="11" y2="13"></line>
|
|
726
|
+
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
|
|
727
|
+
</svg>
|
|
728
|
+
</button>
|
|
729
|
+
</div>
|
|
728
730
|
</div>
|
|
729
731
|
|
|
730
732
|
{typingUser &&
|
|
@@ -30,51 +30,54 @@ const Conversations = () => {
|
|
|
30
30
|
}>({ personalChats: [], groupedServiceChats: {} });
|
|
31
31
|
|
|
32
32
|
// Process fetched data
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!participantGroups) return;
|
|
35
|
+
const processConversations = (groups: ParticipantGroup[]) => {
|
|
36
|
+
const allPersonalChats: ConversationType[] = [];
|
|
37
|
+
const allServiceChatsMap = new Map<string, GroupedServiceChats[string]>();
|
|
38
|
+
|
|
39
|
+
groups.forEach((group, groupIndex) => {
|
|
40
|
+
|
|
41
|
+
if (group.personalConversation) {
|
|
42
|
+
allPersonalChats.push(group.personalConversation);
|
|
43
|
+
}
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
|
|
45
|
+
group.serviceConversations.forEach((serviceGroup, serviceIndex) => {
|
|
46
|
+
if (!allServiceChatsMap.has(serviceGroup.serviceId)) {
|
|
47
|
+
allServiceChatsMap.set(serviceGroup.serviceId, {
|
|
48
|
+
serviceTitle: serviceGroup.serviceTitle,
|
|
49
|
+
conversations: [],
|
|
50
|
+
});
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
allServiceChatsMap.set(serviceGroup.serviceId, {
|
|
48
|
-
serviceTitle: serviceGroup.serviceTitle,
|
|
49
|
-
conversations: [],
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
allServiceChatsMap
|
|
53
|
-
.get(serviceGroup.serviceId)!
|
|
54
|
-
.conversations.push(...serviceGroup.conversations);
|
|
55
|
-
});
|
|
52
|
+
|
|
53
|
+
const existing = allServiceChatsMap.get(serviceGroup.serviceId)!;
|
|
54
|
+
existing.conversations.push(...serviceGroup.conversations);
|
|
56
55
|
});
|
|
56
|
+
});
|
|
57
57
|
|
|
58
|
-
const sortConversations = (convos: ConversationType[]) =>
|
|
59
|
-
convos.sort(
|
|
60
|
-
(a, b) =>
|
|
61
|
-
new Date(b.lastMessage?.createdAt || b.updatedAt).getTime() -
|
|
62
|
-
new Date(a.lastMessage?.createdAt || a.updatedAt).getTime()
|
|
63
|
-
);
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
const sortConversations = (convos: ConversationType[]) =>
|
|
60
|
+
convos.sort(
|
|
61
|
+
(a, b) =>
|
|
62
|
+
new Date(b.lastMessage?.createdAt || b.updatedAt).getTime() -
|
|
63
|
+
new Date(a.lastMessage?.createdAt || a.updatedAt).getTime()
|
|
68
64
|
);
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
sortConversations(allPersonalChats);
|
|
67
|
+
allServiceChatsMap.forEach((value, key) => {
|
|
68
|
+
sortConversations(value.conversations);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const result = {
|
|
72
|
+
personalChats: allPersonalChats,
|
|
73
|
+
groupedServiceChats: Object.fromEntries(allServiceChatsMap),
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
}
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
setConversations(processConversations(participantGroups));
|
|
80
|
+
}, [participantGroups]);
|
|
78
81
|
|
|
79
82
|
// Real-time update listeners
|
|
80
83
|
useEffect(() => {
|
|
@@ -218,35 +221,45 @@ const Conversations = () => {
|
|
|
218
221
|
return () => socket.removeEventListener("message", messageListener);
|
|
219
222
|
}, [socket, userId]);
|
|
220
223
|
|
|
221
|
-
const isEmpty =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
224
|
+
// const isEmpty =
|
|
225
|
+
// activeTab === "personal"
|
|
226
|
+
// ? conversations.personalChats.length === 0
|
|
227
|
+
// : Object.keys(conversations.groupedServiceChats).length === 0;
|
|
225
228
|
|
|
226
229
|
const lowerSearch = searchTerm?.toLowerCase().trim();
|
|
227
230
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
231
|
+
// Filter personal chats
|
|
232
|
+
const filteredPersonalChats = !lowerSearch
|
|
233
|
+
? conversations.personalChats
|
|
234
|
+
: conversations.personalChats.filter((convo) =>
|
|
235
|
+
convo.participantDetails?.some((p: any) =>
|
|
236
|
+
p?.name?.toLowerCase().includes(lowerSearch)
|
|
237
|
+
)
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// Filter service chats
|
|
241
|
+
const filteredGroupedServiceChats: GroupedServiceChats = !lowerSearch
|
|
242
|
+
? conversations.groupedServiceChats
|
|
243
|
+
: Object.fromEntries(
|
|
244
|
+
Object.entries(conversations.groupedServiceChats)
|
|
245
|
+
.map(([serviceId, group]) => {
|
|
246
|
+
const filteredConvos = group.conversations.filter((convo) =>
|
|
247
|
+
convo.participantDetails?.some((p: any) =>
|
|
248
|
+
p?.name?.toLowerCase().includes(lowerSearch)
|
|
249
|
+
) ||
|
|
250
|
+
group.serviceTitle?.toLowerCase().includes(lowerSearch) ||
|
|
251
|
+
convo.serviceTitle?.toLowerCase().includes(lowerSearch)
|
|
252
|
+
);
|
|
253
|
+
return [serviceId, { ...group, conversations: filteredConvos }];
|
|
254
|
+
})
|
|
255
|
+
.filter(([_, group]) => group.conversations.length > 0)
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
// Improved empty state logic
|
|
259
|
+
const showPersonalTab = activeTab === "personal" && filteredPersonalChats.length > 0;
|
|
260
|
+
const showServiceTab = activeTab === "service" && Object.keys(filteredGroupedServiceChats).length > 0;
|
|
261
|
+
const isEmpty = !showPersonalTab && !showServiceTab;
|
|
262
|
+
|
|
250
263
|
|
|
251
264
|
// Calculate unread counts for tabs
|
|
252
265
|
const personalUnreadCount = conversations.personalChats.reduce(
|
package/src/lib/api/apiClient.ts
CHANGED