@pubuduth-aplicy/chat-ui 2.1.94 → 2.1.96

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubuduth-aplicy/chat-ui",
3
- "version": "2.1.94",
3
+ "version": "2.1.96",
4
4
  "description": "This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -6,9 +6,10 @@ const SystemNotice = () => (
6
6
  margin: "1rem",
7
7
  backgroundColor: "#f9f9f9",
8
8
  fontSize: "14px",
9
+ textAlign: "center",
9
10
  }}>
10
11
  <strong style={{ display: "block", marginBottom: "0.5rem", textAlign:"center", fontSize:"smaller" }}>🛡 WE HAVE YOUR BACK</strong>
11
- <p style={{fontSize:"x-small"}}>For added safety and your protection, keep payments and communications within Hirepanther.
12
+ <p style={{fontSize:"x-small", textAlign:"center"}}>For added safety and your protection, keep payments and communications within Hirepanther.
12
13
  {/* <a href="#">Learn more</a> */}
13
14
  </p>
14
15
  </div>
@@ -29,9 +29,6 @@ const VirtualizedChatList = ({ conversations }: Props) => {
29
29
  overflow: "auto",
30
30
  }}
31
31
  >
32
- {/* {virtualizer.getVirtualItems().map((item) => {
33
- const conversation = conversations[item.index];
34
- return ( */}
35
32
  <div
36
33
  // key={item.key}
37
34
  style={{
@@ -65,8 +62,6 @@ const VirtualizedChatList = ({ conversations }: Props) => {
65
62
  );
66
63
  })}
67
64
  </div>
68
- {/* ); */}
69
- {/* })} */}
70
65
  </div>
71
66
  );
72
67
  };
@@ -356,7 +356,7 @@ const Message = ({ message }: MessageProps) => {
356
356
  <div className="circular-progress-container">
357
357
  <div className="media-preview-background">
358
358
  <img
359
- src={`${`${cdnUrl}${media.url}`}`}
359
+ src={`${cdnUrl}${media.url}`}
360
360
  alt={media.name}
361
361
  className="blurred-preview"
362
362
  />
@@ -409,32 +409,13 @@ const Message = ({ message }: MessageProps) => {
409
409
  }
410
410
  />
411
411
  ) : media.type === "video" ? (
412
- <>
413
- <div
414
- className="video-file-preview"
415
- onClick={() =>
416
- window.open(`${cdnUrl}${media.url}`, "_blank")
417
- }
418
- >
419
- <div className="file-icon video-icon">🎥</div>
420
-
421
- <div className="file-info">
422
- <span className="file-name">{media.name}</span>
423
- <span className="file-size">
424
- {(media.size / 1024 / 1024).toFixed(1)} MB
425
- </span>
426
- </div>
427
-
428
- <div className="play-overlay">▶</div>
429
- </div>
430
- </>
412
+ <video controls className="media-content">
413
+ <source
414
+ src={`${cdnUrl}${media.url}`}
415
+ type={`video/${`${cdnUrl}${media.url}`.split(".").pop()}`}
416
+ />
417
+ </video>
431
418
  ) : (
432
- // <video controls className="media-content" preload="metadata">
433
- // <source
434
- // src={`${cdnUrl}${media.url}`}
435
- // type={`video/${`${cdnUrl}${media.url}`.split(".").pop()?.toLocaleLowerCase()}`}
436
- // />
437
- // </video>
438
419
  <div className="document-preview">
439
420
  <div className="file-icon">
440
421
  {media.type === "document" && "📄"}
@@ -455,7 +436,7 @@ const Message = ({ message }: MessageProps) => {
455
436
  cancelDownload();
456
437
  } else {
457
438
  handleDownload(
458
- `${cdnUrl}/${media.url}`,
439
+ `${cdnUrl}${media.url}`,
459
440
  media.name,
460
441
  index
461
442
  );
@@ -34,54 +34,52 @@ const Conversations = () => {
34
34
  }>({ personalChats: [], groupedServiceChats: {} });
35
35
 
36
36
  // Process fetched data
37
- useEffect(() => {
38
- if (!participantGroups) return;
39
- const processConversations = (groups: ParticipantGroup[]) => {
40
- const allPersonalChats: ConversationType[] = [];
41
- const allServiceChatsMap = new Map<string, GroupedServiceChats[string]>();
42
-
43
- groups.forEach((group) => {
44
-
45
- if (group.personalConversation) {
46
- allPersonalChats.push(group.personalConversation);
47
- }
48
-
49
- group.serviceConversations.forEach((serviceGroup) => {
50
- if (!allServiceChatsMap.has(serviceGroup.serviceId)) {
51
- allServiceChatsMap.set(serviceGroup.serviceId, {
52
- serviceTitle: serviceGroup.serviceTitle,
53
- conversations: [],
54
- });
37
+ useEffect(() => {
38
+ if (!participantGroups) return;
39
+ const processConversations = (groups: ParticipantGroup[]) => {
40
+ const allPersonalChats: ConversationType[] = [];
41
+ const allServiceChatsMap = new Map<string, GroupedServiceChats[string]>();
42
+
43
+ groups.forEach((group) => {
44
+ if (group.personalConversation) {
45
+ allPersonalChats.push(group.personalConversation);
55
46
  }
56
-
57
- const existing = allServiceChatsMap.get(serviceGroup.serviceId)!;
58
- existing.conversations.push(...serviceGroup.conversations);
47
+
48
+ group.serviceConversations.forEach((serviceGroup) => {
49
+ if (!allServiceChatsMap.has(serviceGroup.serviceId)) {
50
+ allServiceChatsMap.set(serviceGroup.serviceId, {
51
+ serviceTitle: serviceGroup.serviceTitle,
52
+ conversations: [],
53
+ });
54
+ }
55
+
56
+ const existing = allServiceChatsMap.get(serviceGroup.serviceId)!;
57
+ existing.conversations.push(...serviceGroup.conversations);
58
+ });
59
59
  });
60
- });
61
60
 
61
+ const sortConversations = (convos: ConversationType[]) =>
62
+ convos.sort(
63
+ (a, b) =>
64
+ new Date(b.lastMessage?.createdAt || b.updatedAt).getTime() -
65
+ new Date(a.lastMessage?.createdAt || a.updatedAt).getTime()
66
+ );
62
67
 
63
- const sortConversations = (convos: ConversationType[]) =>
64
- convos.sort(
65
- (a, b) =>
66
- new Date(b.lastMessage?.createdAt || b.updatedAt).getTime() -
67
- new Date(a.lastMessage?.createdAt || a.updatedAt).getTime()
68
- );
68
+ sortConversations(allPersonalChats);
69
+ allServiceChatsMap.forEach((value) => {
70
+ sortConversations(value.conversations);
71
+ });
69
72
 
70
- sortConversations(allPersonalChats);
71
- allServiceChatsMap.forEach((value) => {
72
- sortConversations(value.conversations);
73
- });
73
+ const result = {
74
+ personalChats: allPersonalChats,
75
+ groupedServiceChats: Object.fromEntries(allServiceChatsMap),
76
+ };
74
77
 
75
- const result = {
76
- personalChats: allPersonalChats,
77
- groupedServiceChats: Object.fromEntries(allServiceChatsMap),
78
+ return result;
78
79
  };
79
80
 
80
- return result;
81
- };
82
-
83
- setConversations(processConversations(participantGroups));
84
- }, [participantGroups]);
81
+ setConversations(processConversations(participantGroups));
82
+ }, [participantGroups]);
85
83
 
86
84
  // Real-time update listeners
87
85
  useEffect(() => {
@@ -111,7 +109,9 @@ const Conversations = () => {
111
109
 
112
110
  const personalIndex = personalChats.findIndex((c) => c._id === chatId);
113
111
  if (personalIndex >= 0) {
114
- personalChats[personalIndex] = updateRead(personalChats[personalIndex]);
112
+ personalChats[personalIndex] = updateRead(
113
+ personalChats[personalIndex]
114
+ );
115
115
  return { personalChats, groupedServiceChats };
116
116
  }
117
117
 
@@ -232,38 +232,41 @@ const Conversations = () => {
232
232
 
233
233
  const lowerSearch = searchTerm?.toLowerCase().trim();
234
234
 
235
- // Filter personal chats
236
- const filteredPersonalChats = !lowerSearch
237
- ? conversations.personalChats
238
- : conversations.personalChats.filter((convo) =>
239
- convo.participantDetails?.some((p: any) =>
240
- p?.name?.toLowerCase().includes(lowerSearch)
241
- )
242
- );
243
-
244
- // Filter service chats
245
- const filteredGroupedServiceChats: GroupedServiceChats = !lowerSearch
246
- ? conversations.groupedServiceChats
247
- : Object.fromEntries(
248
- Object.entries(conversations.groupedServiceChats)
249
- .map(([serviceId, group]) => {
250
- const filteredConvos = group.conversations.filter((convo) =>
251
- convo.participantDetails?.some((p: any) =>
252
- p?.name?.toLowerCase().includes(lowerSearch)
253
- ) ||
254
- group.serviceTitle?.toLowerCase().includes(lowerSearch) ||
255
- convo.serviceTitle?.toLowerCase().includes(lowerSearch)
256
- );
257
- return [serviceId, { ...group, conversations: filteredConvos }];
258
- })
259
- .filter(([_, group]) => group.conversations.length > 0)
260
- );
235
+ // Filter personal chats
236
+ const filteredPersonalChats = !lowerSearch
237
+ ? conversations.personalChats
238
+ : conversations.personalChats.filter((convo) =>
239
+ convo.participantDetails?.some((p: any) =>
240
+ p?.name?.toLowerCase().includes(lowerSearch)
241
+ )
242
+ );
261
243
 
262
- // Improved empty state logic
263
- const showPersonalTab = activeTab === "personal" && filteredPersonalChats.length > 0;
264
- const showServiceTab = activeTab === "service" && Object.keys(filteredGroupedServiceChats).length > 0;
265
- const isEmpty = !showPersonalTab && !showServiceTab;
266
-
244
+ // Filter service chats
245
+ const filteredGroupedServiceChats: GroupedServiceChats = !lowerSearch
246
+ ? conversations.groupedServiceChats
247
+ : Object.fromEntries(
248
+ Object.entries(conversations.groupedServiceChats)
249
+ .map(([serviceId, group]) => {
250
+ const filteredConvos = group.conversations.filter(
251
+ (convo) =>
252
+ convo.participantDetails?.some((p: any) =>
253
+ p?.name?.toLowerCase().includes(lowerSearch)
254
+ ) ||
255
+ group.serviceTitle?.toLowerCase().includes(lowerSearch) ||
256
+ convo.serviceTitle?.toLowerCase().includes(lowerSearch)
257
+ );
258
+ return [serviceId, { ...group, conversations: filteredConvos }];
259
+ })
260
+ .filter(([_, group]) => group.conversations.length > 0)
261
+ );
262
+
263
+ // Improved empty state logic
264
+ const showPersonalTab =
265
+ activeTab === "personal" && filteredPersonalChats.length > 0;
266
+ const showServiceTab =
267
+ activeTab === "service" &&
268
+ Object.keys(filteredGroupedServiceChats).length > 0;
269
+ const isEmpty = !showPersonalTab && !showServiceTab;
267
270
 
268
271
  // Calculate unread counts for tabs
269
272
  const personalUnreadCount = conversations.personalChats.reduce(
@@ -272,7 +275,7 @@ const isEmpty = !showPersonalTab && !showServiceTab;
272
275
  );
273
276
 
274
277
  const serviceUnreadCount = Object.values(conversations.groupedServiceChats)
275
- .flatMap(group => group.conversations)
278
+ .flatMap((group) => group.conversations)
276
279
  .reduce((total, convo) => total + (convo.unreadMessageCount || 0), 0);
277
280
 
278
281
  return (
@@ -312,41 +315,43 @@ const isEmpty = !showPersonalTab && !showServiceTab;
312
315
  </div>
313
316
 
314
317
  {/* Tab Content */}
315
- <div className="flex-1 overflow-auto">
318
+ <div className="flex-1 h-[550px] overflow-auto">
316
319
  {isEmpty ? (
317
320
  <div className="flex flex-col items-center justify-center p-8 text-center">
318
321
  <h3 className="text-xl font-semibold mb-1">No Conversations</h3>
319
322
  <p className="text-gray-500 text-sm mb-4">
320
- {activeTab === "personal"
321
- ? "You have no personal messages yet."
323
+ {activeTab === "personal"
324
+ ? "You have no personal messages yet."
322
325
  : "You have no service messages yet."}
323
326
  </p>
324
327
  </div>
325
328
  ) : (
326
329
  <>
327
- <div className="h-full overflow-auto">
328
- {activeTab === "personal" && filteredPersonalChats.length > 0 && (
329
- <VirtualizedChatList conversations={filteredPersonalChats} />
330
- )}
331
-
332
- {activeTab === "service" &&
333
- Object.entries(filteredGroupedServiceChats).length > 0 && (
334
- <div className="p-2">
335
- {Object.entries(filteredGroupedServiceChats).map(
336
- ([serviceId, { serviceTitle, conversations: serviceConvos }]) => (
337
- <CollapsibleSection
338
- key={serviceId}
339
- title={serviceTitle}
340
- defaultOpen={false}
341
- >
342
- <VirtualizedChatList conversations={serviceConvos} />
343
- </CollapsibleSection>
344
- )
330
+ <div className="h-full overflow-auto">
331
+ {activeTab === "personal" && filteredPersonalChats.length > 0 && (
332
+ <VirtualizedChatList conversations={filteredPersonalChats} />
333
+ )}
334
+
335
+ {activeTab === "service" &&
336
+ Object.entries(filteredGroupedServiceChats).length > 0 && (
337
+ <div className="p-2">
338
+ {Object.entries(filteredGroupedServiceChats).map(
339
+ ([
340
+ serviceId,
341
+ { serviceTitle, conversations: serviceConvos },
342
+ ]) => (
343
+ <CollapsibleSection
344
+ key={serviceId}
345
+ title={serviceTitle}
346
+ defaultOpen={false}
347
+ >
348
+ <VirtualizedChatList conversations={serviceConvos} />
349
+ </CollapsibleSection>
350
+ )
351
+ )}
352
+ </div>
345
353
  )}
346
- </div>
347
- )}
348
- </div>
349
-
354
+ </div>
350
355
  </>
351
356
  )}
352
357
  </div>
@@ -354,4 +359,4 @@ const isEmpty = !showPersonalTab && !showServiceTab;
354
359
  );
355
360
  };
356
361
 
357
- export default Conversations;
362
+ export default Conversations;