@messenger-box/tailwind-ui-inbox 10.0.3-alpha.70 → 10.0.3-alpha.72

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.
Files changed (155) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/components/AIAgent/AIAgent.d.ts +14 -0
  3. package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
  4. package/lib/components/AIAgent/AIAgent.js +1148 -0
  5. package/lib/components/AIAgent/AIAgent.js.map +1 -0
  6. package/lib/components/AIAgent/index.d.ts +2 -0
  7. package/lib/components/AIAgent/index.d.ts.map +1 -0
  8. package/lib/components/InboxMessage/InputComponent.d.ts +9 -0
  9. package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
  10. package/lib/components/InboxMessage/InputComponent.js +210 -0
  11. package/lib/components/InboxMessage/InputComponent.js.map +1 -0
  12. package/lib/components/InboxMessage/LeftSidebar.d.ts +2 -0
  13. package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -1
  14. package/lib/components/InboxMessage/LeftSidebar.js +16 -5
  15. package/lib/components/InboxMessage/LeftSidebar.js.map +1 -1
  16. package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -1
  17. package/lib/components/InboxMessage/MessageInput.js +14 -10
  18. package/lib/components/InboxMessage/MessageInput.js.map +1 -1
  19. package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
  20. package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
  21. package/lib/components/InboxMessage/MessageInputComponent.js +173 -0
  22. package/lib/components/InboxMessage/MessageInputComponent.js.map +1 -0
  23. package/lib/components/InboxMessage/Messages.d.ts +3 -1
  24. package/lib/components/InboxMessage/Messages.d.ts.map +1 -1
  25. package/lib/components/InboxMessage/Messages.js +16 -60
  26. package/lib/components/InboxMessage/Messages.js.map +1 -1
  27. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
  28. package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
  29. package/lib/components/InboxMessage/MessagesBuilderUi.js +162 -0
  30. package/lib/components/InboxMessage/MessagesBuilderUi.js.map +1 -0
  31. package/lib/components/InboxMessage/UploadImageButton.d.ts +1 -0
  32. package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -1
  33. package/lib/components/InboxMessage/UploadImageButton.js +3 -3
  34. package/lib/components/InboxMessage/UploadImageButton.js.map +1 -1
  35. package/lib/components/InboxMessage/index.d.ts +3 -0
  36. package/lib/components/InboxMessage/index.d.ts.map +1 -1
  37. package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -1
  38. package/lib/components/InboxMessage/message-widgets/CommonMessage.js +11 -6
  39. package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -1
  40. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +14 -0
  41. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
  42. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1525 -0
  43. package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
  44. package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -1
  45. package/lib/components/InboxMessage/message-widgets/PlainMessage.js +6 -3
  46. package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -1
  47. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +2 -0
  48. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -1
  49. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +225 -26
  50. package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -1
  51. package/lib/components/InboxMessage/message-widgets/index.d.ts +1 -0
  52. package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -1
  53. package/lib/components/index.d.ts +2 -1
  54. package/lib/components/index.d.ts.map +1 -1
  55. package/lib/compute.d.ts.map +1 -1
  56. package/lib/compute.js +79 -3
  57. package/lib/compute.js.map +1 -1
  58. package/lib/config/env-config.d.ts +6 -0
  59. package/lib/config/env-config.d.ts.map +1 -1
  60. package/lib/config/env-config.js +19 -1
  61. package/lib/config/env-config.js.map +1 -1
  62. package/lib/container/AiInbox.d.ts +15 -0
  63. package/lib/container/AiInbox.d.ts.map +1 -0
  64. package/lib/container/AiInbox.js +1520 -0
  65. package/lib/container/AiInbox.js.map +1 -0
  66. package/lib/container/AiInboxWithLoader.d.ts +36 -0
  67. package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
  68. package/lib/container/AiInboxWithLoader.js +300 -0
  69. package/lib/container/AiInboxWithLoader.js.map +1 -0
  70. package/lib/container/AiLandingInput.d.ts +4 -0
  71. package/lib/container/AiLandingInput.d.ts.map +1 -0
  72. package/lib/container/AiLandingInput.js +164 -0
  73. package/lib/container/AiLandingInput.js.map +1 -0
  74. package/lib/container/Inbox.d.ts.map +1 -1
  75. package/lib/container/Inbox.js +177 -58
  76. package/lib/container/Inbox.js.map +1 -1
  77. package/lib/container/InboxAiMessagesLoader.d.ts +36 -0
  78. package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
  79. package/lib/container/InboxAiMessagesLoader.js +47 -0
  80. package/lib/container/InboxAiMessagesLoader.js.map +1 -0
  81. package/lib/container/InboxContainer.d.ts +12 -0
  82. package/lib/container/InboxContainer.d.ts.map +1 -0
  83. package/lib/container/InboxContainer.js +31 -0
  84. package/lib/container/InboxContainer.js.map +1 -0
  85. package/lib/container/InboxTemplate1.d.ts +15 -0
  86. package/lib/container/InboxTemplate1.d.ts.map +1 -0
  87. package/lib/container/InboxTemplate1.js +1375 -0
  88. package/lib/container/InboxTemplate1.js.map +1 -0
  89. package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
  90. package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
  91. package/lib/container/InboxTemplate2.d.ts +15 -0
  92. package/lib/container/InboxTemplate2.d.ts.map +1 -0
  93. package/lib/container/InboxTemplate2.js +1426 -0
  94. package/lib/container/InboxTemplate2.js.map +1 -0
  95. package/lib/container/InboxWithAiLoader.d.ts +15 -0
  96. package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
  97. package/lib/container/InboxWithAiLoader.js +56 -0
  98. package/lib/container/InboxWithAiLoader.js.map +1 -0
  99. package/lib/container/ServiceInbox.js +1 -1
  100. package/lib/container/ServiceInbox.js.map +1 -1
  101. package/lib/container/ThreadMessages.js +1 -1
  102. package/lib/container/ThreadMessages.js.map +1 -1
  103. package/lib/container/ThreadMessagesInbox.js +1 -1
  104. package/lib/container/ThreadMessagesInbox.js.map +1 -1
  105. package/lib/container/Threads.js +1 -1
  106. package/lib/container/Threads.js.map +1 -1
  107. package/lib/container/index.d.ts +4 -1
  108. package/lib/container/index.d.ts.map +1 -1
  109. package/lib/index.js +1 -1
  110. package/lib/machines/aiAgentMachine.d.ts +3 -0
  111. package/lib/machines/aiAgentMachine.d.ts.map +1 -0
  112. package/lib/machines/aiAgentMachine.js +1040 -0
  113. package/lib/machines/aiAgentMachine.js.map +1 -0
  114. package/lib/machines/types.d.ts +77 -0
  115. package/lib/machines/types.d.ts.map +1 -0
  116. package/lib/routes.json +40 -0
  117. package/lib/templates/InboxWithAi.d.ts +15 -0
  118. package/lib/templates/InboxWithAi.d.ts.map +1 -0
  119. package/lib/templates/InboxWithAi.js +405 -0
  120. package/lib/templates/InboxWithAi.js.map +1 -0
  121. package/lib/templates/InboxWithAi.tsx +502 -0
  122. package/package.json +7 -5
  123. package/src/components/AIAgent/AIAgent.tsx +1351 -0
  124. package/src/components/AIAgent/README.md +82 -0
  125. package/src/components/AIAgent/index.ts +1 -0
  126. package/src/components/InboxMessage/InputComponent.tsx +263 -0
  127. package/src/components/InboxMessage/LeftSidebar.tsx +14 -4
  128. package/src/components/InboxMessage/MessageInput.tsx +73 -66
  129. package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
  130. package/src/components/InboxMessage/Messages.tsx +24 -68
  131. package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
  132. package/src/components/InboxMessage/UploadImageButton.tsx +3 -2
  133. package/src/components/InboxMessage/index.ts +3 -0
  134. package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +39 -21
  135. package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1968 -0
  136. package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +6 -2
  137. package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +337 -53
  138. package/src/components/InboxMessage/message-widgets/index.ts +1 -0
  139. package/src/components/index.ts +4 -0
  140. package/src/compute.ts +83 -2
  141. package/src/config/env-config.ts +6 -0
  142. package/src/container/AiInbox.tsx +1796 -0
  143. package/src/container/AiInboxWithLoader.tsx +356 -0
  144. package/src/container/AiLandingInput.tsx +168 -0
  145. package/src/container/Inbox.tsx +280 -130
  146. package/src/container/InboxAiMessagesLoader.tsx +68 -0
  147. package/src/container/InboxContainer.tsx +35 -0
  148. package/src/container/InboxTemplate1.tsx +1542 -0
  149. package/src/container/InboxTemplate1WithLoader.tsx +338 -0
  150. package/src/container/InboxTemplate2.tsx +1606 -0
  151. package/src/container/InboxWithAiLoader.tsx +76 -0
  152. package/src/container/index.ts +15 -1
  153. package/src/machines/aiAgentMachine.ts +1248 -0
  154. package/src/machines/types.ts +59 -0
  155. package/src/templates/InboxWithAi.tsx +502 -0
@@ -8,10 +8,11 @@ import {
8
8
  } from 'common/graphql';
9
9
  import { useUploadFiles } from '@messenger-box/platform-client';
10
10
  import { IFileInfo, RoomType, PostTypeEnum } from 'common';
11
- import { useSelector } from 'react-redux';
11
+ import { useSelector, shallowEqual } from 'react-redux';
12
12
  import { useNavigate, useParams } from '@remix-run/react';
13
13
  import { LeftSidebar, MessageInput, Messages, RightSidebar } from '../components';
14
- import { userSelector } from '@adminide-stack/user-auth0-client';
14
+ import { Store, userSelector } from '@adminide-stack/user-auth0-client';
15
+ import { IUserState } from '@adminide-stack/core';
15
16
  import { config } from '../config';
16
17
  import { applyFooterStyles } from './apply-footer-styles';
17
18
  import { objectId } from '@messenger-box/core';
@@ -63,6 +64,32 @@ const useMediaQuery = (query: string) => {
63
64
  return matches;
64
65
  };
65
66
 
67
+ // Hook to get window dimensions
68
+ const useWindowDimensions = () => {
69
+ const [windowDimensions, setWindowDimensions] = React.useState({
70
+ width: typeof window !== 'undefined' ? window.innerWidth : 1024,
71
+ height: typeof window !== 'undefined' ? window.innerHeight : 768,
72
+ });
73
+
74
+ useEffect(() => {
75
+ if (typeof window === 'undefined') return;
76
+
77
+ const handleResize = () => {
78
+ setWindowDimensions({
79
+ width: window.innerWidth,
80
+ height: window.innerHeight,
81
+ });
82
+ };
83
+
84
+ window.addEventListener('resize', handleResize);
85
+ handleResize(); // Set initial dimensions
86
+
87
+ return () => window.removeEventListener('resize', handleResize);
88
+ }, []);
89
+
90
+ return windowDimensions;
91
+ };
92
+
66
93
  // Static components
67
94
  const Spinner = React.memo(({ className = '' }: { className?: string }) => (
68
95
  <div className={`animate-spin rounded-full border-4 border-gray-200 border-t-blue-500 ${className}`}>
@@ -76,10 +103,13 @@ const Drawer = React.memo(({ isOpen, onClose, children, title }: DrawerProps) =>
76
103
  return (
77
104
  <div className="fixed inset-0 z-50 overflow-hidden">
78
105
  <div className="absolute inset-0 bg-black bg-opacity-50" onClick={onClose} />
79
- <div className="absolute bottom-0 left-0 right-0 bg-white rounded-t-lg shadow-lg max-h-[80vh] overflow-hidden">
80
- <div className="flex items-center justify-between p-4 border-b border-gray-200">
81
- <h2 className="text-lg font-semibold">{title}</h2>
82
- <button onClick={onClose} className="p-1 hover:bg-gray-100 rounded-full transition-colors">
106
+ <div className="absolute bottom-0 left-0 right-0 bg-white rounded-t-lg shadow-lg max-h-[80vh] flex flex-col overflow-hidden">
107
+ <div className="flex items-center justify-between p-4 border-b border-gray-200 flex-shrink-0">
108
+ <h2 className="text-lg font-semibold truncate">{title}</h2>
109
+ <button
110
+ onClick={onClose}
111
+ className="p-1 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0 ml-2"
112
+ >
83
113
  <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
84
114
  <path
85
115
  strokeLinecap="round"
@@ -90,15 +120,17 @@ const Drawer = React.memo(({ isOpen, onClose, children, title }: DrawerProps) =>
90
120
  </svg>
91
121
  </button>
92
122
  </div>
93
- <div className="p-4 overflow-y-auto">{children}</div>
123
+ <div className="flex-1 p-4 overflow-y-auto" style={{ minHeight: 0 }}>
124
+ {children}
125
+ </div>
94
126
  </div>
95
127
  </div>
96
128
  );
97
129
  });
98
130
 
99
131
  const EmptyState = React.memo(() => (
100
- <div className="h-full flex items-center justify-center bg-gray-100 p-4 sm:p-6">
101
- <div className="text-center max-w-sm">
132
+ <div className="h-full flex items-center justify-center bg-gray-100 p-4 sm:p-6 overflow-hidden">
133
+ <div className="text-center max-w-sm mx-auto">
102
134
  <div className="text-3xl sm:text-4xl text-gray-400 mb-4">💬</div>
103
135
  <h3 className="text-lg sm:text-xl font-semibold text-gray-600 mb-2">Welcome to Messenger</h3>
104
136
  <p className="text-sm sm:text-base text-gray-500 leading-relaxed">
@@ -133,9 +165,17 @@ const Inbox = (props: InboxProps) => {
133
165
  mobilePreviewCTAText: false,
134
166
  });
135
167
 
136
- // Hooks
137
- const isMobileView = useMediaQuery('(max-width: 767px)');
138
- const auth = useSelector(userSelector);
168
+ // Hooks - improved responsive breakpoints with better granularity
169
+ const { width: windowWidth, height: windowHeight } = useWindowDimensions();
170
+ const isMobileView = useMediaQuery('(max-width: 640px)');
171
+ const isSmallTabletView = useMediaQuery('(min-width: 641px) and (max-width: 900px)');
172
+ const isTabletView = useMediaQuery('(min-width: 901px) and (max-width: 1024px)');
173
+ const isDesktopView = useMediaQuery('(min-width: 1025px)');
174
+ const isLargeDesktopView = useMediaQuery('(min-width: 1440px)');
175
+ const isSmallScreen = useMediaQuery('(max-width: 900px)');
176
+ // const auth = useSelector(userSelector);
177
+ const auth: any = useSelector<Store.Auth, IUserState>(userSelector, shallowEqual);
178
+ // const user = useSelector((state: any) => state.user, shallowEqual);
139
179
 
140
180
  // Data destructuring from Apollo queries
141
181
  const GetChannelsByUserQuery = data?.[0];
@@ -198,6 +238,13 @@ const Inbox = (props: InboxProps) => {
198
238
  return title || 'Direct Message';
199
239
  }
200
240
 
241
+ if (type === RoomType.Direct && members?.length === 1) {
242
+ if (members[0].user?.givenName && members[0]?.user?.familyName) {
243
+ return `${members[0].user?.givenName} ${members[0].user?.familyName}`;
244
+ }
245
+ return members[0].user?.givenName || members[0].user?.familyName || 'Direct Message';
246
+ }
247
+
201
248
  return title || 'Channel';
202
249
  }, [channels, pathChannelId, currentUser]);
203
250
 
@@ -268,6 +315,11 @@ const Inbox = (props: InboxProps) => {
268
315
  const detailSidebarOptions = useMemo(
269
316
  () => ({
270
317
  isMobileView,
318
+ isSmallTabletView,
319
+ isTabletView,
320
+ isDesktopView,
321
+ isLargeDesktopView,
322
+ isSmallScreen,
271
323
  setMobilePreviewCTAText: (v: string | ReactNode) =>
272
324
  localDispatch({ payload: { mobilePreviewCTAText: v }, type: 'update' }),
273
325
  setMobilePreviewText: (v: string | ReactNode) =>
@@ -275,17 +327,39 @@ const Inbox = (props: InboxProps) => {
275
327
  setMobilePreviewVisibility: (v: boolean) =>
276
328
  localDispatch({ payload: { mobilePreviewVisibility: v }, type: 'update' }),
277
329
  }),
278
- [isMobileView],
330
+ [isMobileView, isSmallTabletView, isTabletView, isDesktopView, isLargeDesktopView, isSmallScreen],
279
331
  );
280
332
 
281
333
  return (
282
- <div className="h-[100vh] border-t border-gray-300 flex overflow-hidden" style={{ height: '100vh ' }}>
334
+ <div
335
+ className="border-t border-gray-300 flex overflow-hidden"
336
+ style={{
337
+ height: `${windowHeight}px`,
338
+ maxHeight: '100vh',
339
+ }}
340
+ >
283
341
  {/* Left Sidebar - Responsive Design */}
284
342
  <div
285
343
  className={`
286
344
  flex-shrink-0 bg-gray-50 border-r border-gray-300 overflow-hidden transition-all duration-300 ease-in-out
287
- ${isMobileView && pathChannelId ? 'hidden' : 'w-80 lg:w-96 xl:w-[420px]'}
345
+ ${isMobileView && pathChannelId ? 'hidden' : ''}
288
346
  `}
347
+ style={{
348
+ width:
349
+ isMobileView && !pathChannelId
350
+ ? '100%'
351
+ : isMobileView && pathChannelId
352
+ ? '0px'
353
+ : isSmallTabletView
354
+ ? `${Math.min(288, windowWidth * 0.35)}px` // w-72 or 35% of window
355
+ : isTabletView
356
+ ? `${Math.min(320, windowWidth * 0.3)}px` // w-80 or 30% of window
357
+ : isLargeDesktopView
358
+ ? `${Math.min(384, windowWidth * 0.25)}px` // w-96 or 25% of window
359
+ : `${Math.min(320, windowWidth * 0.28)}px`, // w-80 or 28% of window
360
+ height: `${windowHeight}px`,
361
+ maxHeight: '100vh',
362
+ }}
289
363
  >
290
364
  <LeftSidebar
291
365
  currentUser={currentUser}
@@ -298,15 +372,23 @@ const Inbox = (props: InboxProps) => {
298
372
  getChannelsRefetch={getChannelsRefetch}
299
373
  role={channelRole}
300
374
  messagesQuery={data?.[1]}
375
+ windowHeight={windowHeight}
376
+ windowWidth={windowWidth}
301
377
  />
302
378
  </div>
303
379
 
304
380
  {/* Main Content Area - Responsive */}
305
381
  <div
306
382
  className={`
307
- flex-1 min-w-0 overflow-hidden transition-all duration-300 ease-in-out
308
- ${isMobileView && !pathChannelId ? 'hidden' : 'block'}
383
+ flex-1 min-w-0 flex flex-col overflow-hidden transition-all duration-300 ease-in-out
384
+ ${isMobileView && !pathChannelId ? 'hidden' : 'flex'}
309
385
  `}
386
+ style={{
387
+ minWidth: isSmallScreen ? '300px' : isDesktopView ? '500px' : '400px',
388
+ width: 'auto',
389
+ height: `${windowHeight}px`,
390
+ maxHeight: '100vh',
391
+ }}
310
392
  >
311
393
  {pathChannelId ? (
312
394
  <ContentComponent
@@ -315,6 +397,13 @@ const Inbox = (props: InboxProps) => {
315
397
  channelRole={channelRole}
316
398
  pathPrefix={props.pathPrefix}
317
399
  isMobileView={isMobileView}
400
+ isSmallTabletView={isSmallTabletView}
401
+ isTabletView={isTabletView}
402
+ isDesktopView={isDesktopView}
403
+ isLargeDesktopView={isLargeDesktopView}
404
+ isSmallScreen={isSmallScreen}
405
+ windowWidth={windowWidth}
406
+ windowHeight={windowHeight}
318
407
  mobilePreviewState={mobilePreviewState}
319
408
  detailSidebarOptions={detailSidebarOptions}
320
409
  isBottomDrawerOpen={isBottomDrawerOpen}
@@ -328,8 +417,17 @@ const Inbox = (props: InboxProps) => {
328
417
  </div>
329
418
 
330
419
  {/* Right Sidebar - Desktop Only */}
331
- {pathChannelId && data?.[1] && !isMobileView && (
332
- // <div className="w-80 xl:w-96 border-l border-gray-200 bg-white flex-shrink-0">
420
+ {pathChannelId && data?.[1] && isDesktopView && (
421
+ // <div
422
+ // className="border-l border-gray-200 bg-white flex-shrink-0 overflow-hidden"
423
+ // style={{
424
+ // width: isLargeDesktopView
425
+ // ? `${Math.min(384, windowWidth * 0.25)}px` // w-96 or 25% of window
426
+ // : `${Math.min(320, windowWidth * 0.22)}px`, // w-80 or 22% of window
427
+ // height: `${windowHeight}px`,
428
+ // maxHeight: '100vh'
429
+ // }}
430
+ // >
333
431
  <RightSidebarWrapper
334
432
  MessagesLoaderQuery={data?.[1]}
335
433
  selectedPost={null}
@@ -348,6 +446,13 @@ const ContentComponent = React.memo((props: any) => {
348
446
  pathPrefix,
349
447
  postId,
350
448
  isMobileView,
449
+ isSmallTabletView,
450
+ isTabletView,
451
+ isDesktopView,
452
+ isLargeDesktopView,
453
+ isSmallScreen,
454
+ windowWidth,
455
+ windowHeight,
351
456
  mobilePreviewState,
352
457
  detailSidebarOptions,
353
458
  isBottomDrawerOpen,
@@ -371,18 +476,22 @@ const ContentComponent = React.memo((props: any) => {
371
476
  }, [channelData]);
372
477
 
373
478
  return (
374
- <div className="flex h-full">
479
+ <div className="flex overflow-hidden" style={{ height: `${windowHeight}px`, maxHeight: '100vh' }}>
375
480
  {/* Main Chat Content */}
376
- <div className="flex-1 flex flex-col">
481
+ <div className="flex-1 flex flex-col min-w-0 overflow-hidden">
377
482
  {/* Channel Header */}
378
483
  {channelId && (
379
- <div className="px-4 sm:px-6 py-4 border-b border-gray-200 bg-white flex-shrink-0">
484
+ <div
485
+ className={`border-b border-gray-200 bg-white flex-shrink-0 z-10 ${
486
+ isSmallScreen ? 'px-3 py-3' : 'px-4 sm:px-6 py-4'
487
+ }`}
488
+ >
380
489
  <div className="flex items-center justify-between">
381
- <div className="flex items-center space-x-3">
382
- {/* Mobile Back Button */}
383
- {isMobileView && (
490
+ <div className="flex items-center space-x-2 min-w-0 flex-1">
491
+ {/* Mobile/Small Screen Back Button */}
492
+ {(isMobileView || isSmallTabletView) && (
384
493
  <button
385
- className="p-2 hover:bg-gray-100 rounded-full transition-colors lg:hidden"
494
+ className="p-2 hover:bg-gray-100 rounded-full transition-colors flex-shrink-0"
386
495
  onClick={() => window.history.back()}
387
496
  aria-label="Go back"
388
497
  >
@@ -401,11 +510,17 @@ const ContentComponent = React.memo((props: any) => {
401
510
  </svg>
402
511
  </button>
403
512
  )}
404
- <h2 className="text-lg font-semibold text-gray-800 truncate">{channelName}</h2>
513
+ <h2
514
+ className={`font-semibold text-gray-800 truncate ${
515
+ isSmallScreen ? 'text-base' : 'text-lg'
516
+ }`}
517
+ >
518
+ {channelName}
519
+ </h2>
405
520
  </div>
406
- {isMobileView && mobilePreviewState?.mobilePreviewVisibility && (
521
+ {(isMobileView || isSmallTabletView) && mobilePreviewState?.mobilePreviewVisibility && (
407
522
  <button
408
- className="text-sm px-3 py-1 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors"
523
+ className="text-sm px-3 py-1 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0"
409
524
  onClick={() => setBottomDrawer(true)}
410
525
  >
411
526
  {mobilePreviewState?.mobilePreviewCTAText}
@@ -416,13 +531,13 @@ const ContentComponent = React.memo((props: any) => {
416
531
  )}
417
532
 
418
533
  {/* Mobile Preview */}
419
- {isMobileView && channelId && mobilePreviewState?.mobilePreviewVisibility && (
420
- <div className="mx-4 mt-4">
534
+ {(isMobileView || isSmallTabletView) && channelId && mobilePreviewState?.mobilePreviewVisibility && (
535
+ <div className={`mt-4 ${isSmallScreen ? 'mx-3' : 'mx-4'}`}>
421
536
  <div className="mb-2">
422
- <div className="w-full flex justify-between mb-[5px]">
423
- <span>{mobilePreviewState?.mobilePreviewText}</span>
537
+ <div className="w-full flex justify-between items-center gap-2 mb-[5px]">
538
+ <span className="truncate flex-1 text-sm">{mobilePreviewState?.mobilePreviewText}</span>
424
539
  <button
425
- className="text-base px-4 py-2 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors"
540
+ className="text-sm px-3 py-2 bg-teal-500 hover:bg-teal-600 text-white rounded-md transition-colors flex-shrink-0"
426
541
  onClick={() => setBottomDrawer(true)}
427
542
  >
428
543
  {mobilePreviewState?.mobilePreviewCTAText}
@@ -434,45 +549,51 @@ const ContentComponent = React.memo((props: any) => {
434
549
  )}
435
550
 
436
551
  {/* Content based on postId */}
437
- {channelId && (
438
- <>
439
- {postId ? (
440
- postId === '1' ? (
441
- <ThreadsInbox
442
- channelId={channelId}
443
- role={channelRole}
444
- pathPrefix={pathPrefix}
445
- setChannelId={() => {}}
446
- setPostId={() => {}}
447
- setGoBack={() => {}}
448
- />
552
+ <div className="flex-1 flex flex-col min-h-0 overflow-hidden">
553
+ {channelId && (
554
+ <>
555
+ {postId ? (
556
+ postId === '1' ? (
557
+ <ThreadsInbox
558
+ channelId={channelId}
559
+ role={channelRole}
560
+ pathPrefix={pathPrefix}
561
+ setChannelId={() => {}}
562
+ setPostId={() => {}}
563
+ setGoBack={() => {}}
564
+ />
565
+ ) : (
566
+ <ThreadMessagesInbox
567
+ channelId={channelId}
568
+ postId={postId}
569
+ role={channelRole}
570
+ goBack={false}
571
+ pathPrefix={pathPrefix}
572
+ setPostId={() => {}}
573
+ setChannelId={() => {}}
574
+ onMessageClick={onMessageClick}
575
+ />
576
+ )
449
577
  ) : (
450
- <ThreadMessagesInbox
578
+ <MessagesComponent
451
579
  channelId={channelId}
452
- postId={postId}
453
- role={channelRole}
454
- goBack={false}
455
- pathPrefix={pathPrefix}
456
- setPostId={() => {}}
457
- setChannelId={() => {}}
580
+ MessagesLoaderQuery={MessagesLoaderQuery}
581
+ channelsDetail={channelsDetail}
582
+ channelLoading={channelLoading}
458
583
  onMessageClick={onMessageClick}
584
+ isSmallScreen={isSmallScreen}
585
+ isDesktopView={isDesktopView}
586
+ windowHeight={windowHeight}
587
+ windowWidth={windowWidth}
459
588
  />
460
- )
461
- ) : (
462
- <MessagesComponent
463
- channelId={channelId}
464
- MessagesLoaderQuery={MessagesLoaderQuery}
465
- channelsDetail={channelsDetail}
466
- channelLoading={channelLoading}
467
- onMessageClick={onMessageClick}
468
- />
469
- )}
470
- </>
471
- )}
589
+ )}
590
+ </>
591
+ )}
592
+ </div>
472
593
  </div>
473
594
 
474
- {/* Mobile Drawer */}
475
- {isMobileView && (
595
+ {/* Mobile/Small Screen Drawer */}
596
+ {(isMobileView || isSmallTabletView) && (
476
597
  <Drawer
477
598
  isOpen={isBottomDrawerOpen}
478
599
  onClose={() => setBottomDrawer(false)}
@@ -500,19 +621,29 @@ const RightSidebarWrapper = React.memo(({ MessagesLoaderQuery, selectedPost, det
500
621
  if (!sortedMessages.length) return null;
501
622
 
502
623
  return (
503
- // <div className="w-80 xl:w-96 border-l border-gray-200 bg-white flex-shrink-0">
504
- <RightSidebar
505
- channelMessages={sortedMessages}
506
- visibility="visible"
507
- selectedPost={selectedPost}
508
- {...detailSidebarOptions}
509
- />
510
- // </div>
624
+ <div className="h-full flex flex-col overflow-hidden">
625
+ <RightSidebar
626
+ channelMessages={sortedMessages}
627
+ visibility="visible"
628
+ selectedPost={selectedPost}
629
+ {...detailSidebarOptions}
630
+ />
631
+ </div>
511
632
  );
512
633
  });
513
634
 
514
635
  const MessagesComponent = React.memo((props: any) => {
515
- const { channelId, MessagesLoaderQuery, channelsDetail, channelLoading, onMessageClick } = props;
636
+ const {
637
+ channelId,
638
+ MessagesLoaderQuery,
639
+ channelsDetail,
640
+ channelLoading,
641
+ onMessageClick,
642
+ isSmallScreen,
643
+ isDesktopView,
644
+ windowHeight = 768,
645
+ windowWidth = 1024,
646
+ } = props;
516
647
 
517
648
  const messageRootListRef = useRef(null);
518
649
  const messageListRef = useRef(null);
@@ -869,66 +1000,85 @@ const MessagesComponent = React.memo((props: any) => {
869
1000
  <>
870
1001
  <div
871
1002
  ref={messageRootListRef}
872
- className="flex flex-col flex-grow flex-shrink overflow-y-auto p-4 px-4 md:px-8 lg:px-12 bg-gray-50"
1003
+ className={`overflow-y-scroll bg-gray-50 ${
1004
+ isSmallScreen ? 'p-2 px-3' : isDesktopView ? 'p-6 px-8' : 'p-4 px-6'
1005
+ }`}
873
1006
  onScroll={onMessagesScroll}
1007
+ style={{
1008
+ height: `${windowHeight - 140}px`, // Subtract header + input height
1009
+ maxHeight: '100vh',
1010
+ scrollbarWidth: 'thin',
1011
+ scrollbarColor: '#cbd5e0 #f7fafc',
1012
+ overflowY: 'scroll',
1013
+ WebkitOverflowScrolling: 'touch',
1014
+ }}
874
1015
  >
875
- {messages.length > 0 ? (
876
- <>
877
- {/* Loading indicator for older messages at the top */}
878
- {isLoadingOlder && (
879
- <div className="flex justify-center py-4">
880
- <div className="flex items-center space-x-2 text-gray-500">
881
- <Spinner className="w-4 h-4" />
882
- <span className="text-sm">Loading older messages...</span>
1016
+ <div className="min-h-full">
1017
+ {messages.length > 0 ? (
1018
+ <>
1019
+ {/* Loading indicator for older messages at the top */}
1020
+ {isLoadingOlder && (
1021
+ <div className="flex justify-center py-4">
1022
+ <div className="flex items-center space-x-2 text-gray-500">
1023
+ <Spinner className="w-4 h-4" />
1024
+ <span className="text-sm">Loading older messages...</span>
1025
+ </div>
883
1026
  </div>
1027
+ )}
1028
+ <Messages
1029
+ innerRef={messageListRef}
1030
+ channelId={channelId}
1031
+ currentUser={auth}
1032
+ channelMessages={messages}
1033
+ totalCount={totalCount}
1034
+ onMessageClick={onMessageClick}
1035
+ isDesktopView={isDesktopView || false}
1036
+ isSmallScreen={isSmallScreen || false}
1037
+ />
1038
+ <SubscriptionHandler
1039
+ subscribeToMore={subscribeToMore}
1040
+ document={CHAT_MESSAGE_ADDED}
1041
+ variables={{ channelId: channelId.toString() }}
1042
+ enabled={!!channelId && !!subscribeToMore}
1043
+ updateQuery={(prev: any, { subscriptionData }: any) => {
1044
+ console.log('Subscription updateQuery called:', { prev, subscriptionData });
1045
+ if (!subscriptionData.data) {
1046
+ console.log('No subscription data, returning prev');
1047
+ return prev;
1048
+ }
1049
+ const newMessage = subscriptionData.data.chatMessageAdded;
1050
+ console.log('New message received via subscription:', newMessage);
1051
+
1052
+ return {
1053
+ ...prev,
1054
+ messages: {
1055
+ ...prev?.messages,
1056
+ data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
1057
+ totalCount: (prev?.messages?.totalCount || 0) + 1,
1058
+ },
1059
+ };
1060
+ }}
1061
+ onError={(error) => {
1062
+ console.error('Subscription error:', error);
1063
+ }}
1064
+ />
1065
+ </>
1066
+ ) : (
1067
+ <div className="flex items-center justify-center text-gray-500 min-h-96">
1068
+ <div className="text-center max-w-sm mx-auto px-4">
1069
+ <div className="text-6xl mb-4 opacity-50">💬</div>
1070
+ <h3 className="text-lg font-semibold text-gray-600 mb-2">No messages yet</h3>
1071
+ <p className="text-sm text-gray-500">
1072
+ Start the conversation by sending a message below!
1073
+ </p>
884
1074
  </div>
885
- )}
886
- <Messages
887
- innerRef={messageListRef}
888
- channelId={channelId}
889
- currentUser={auth}
890
- channelMessages={messages}
891
- totalCount={totalCount}
892
- onMessageClick={onMessageClick}
893
- />
894
- <SubscriptionHandler
895
- subscribeToMore={subscribeToMore}
896
- document={CHAT_MESSAGE_ADDED}
897
- variables={{ channelId: channelId.toString() }}
898
- enabled={!!channelId && !!subscribeToMore}
899
- updateQuery={(prev: any, { subscriptionData }: any) => {
900
- console.log('Subscription updateQuery called:', { prev, subscriptionData });
901
- if (!subscriptionData.data) {
902
- console.log('No subscription data, returning prev');
903
- return prev;
904
- }
905
- const newMessage = subscriptionData.data.chatMessageAdded;
906
- console.log('New message received via subscription:', newMessage);
907
-
908
- return {
909
- ...prev,
910
- messages: {
911
- ...prev?.messages,
912
- data: uniqBy([...(prev?.messages?.data || []), newMessage], 'id'),
913
- totalCount: (prev?.messages?.totalCount || 0) + 1,
914
- },
915
- };
916
- }}
917
- onError={(error) => {
918
- console.error('Subscription error:', error);
919
- }}
920
- />
921
- </>
922
- ) : (
923
- <div className="flex-1 flex items-center justify-center text-gray-500">
924
- <div className="text-center">
925
- <div className="text-4xl mb-4">💬</div>
926
- <p>No messages yet. Start the conversation!</p>
927
1075
  </div>
928
- </div>
929
- )}
1076
+ )}
1077
+ </div>
1078
+ </div>
1079
+ <div className="flex-shrink-0 border-t border-gray-200 bg-white">
1080
+ <MessageInput channelId={channelId} handleSend={handleSend} placeholder="Message" />
930
1081
  </div>
931
- <MessageInput channelId={channelId} handleSend={handleSend} placeholder="Message" />
932
1082
  </>
933
1083
  );
934
1084
  });
@@ -0,0 +1,68 @@
1
+ import React, { useMemo, useCallback } from 'react';
2
+ import { useParams, useLocation } from '@remix-run/react';
3
+ import {
4
+ useGetChannelsByUserQuery,
5
+ useGetChannelsByUserWithLastMessageQuery,
6
+ useMessagesQuery,
7
+ useViewChannelDetailQuery,
8
+ } from 'common/graphql';
9
+ import { RoomType } from 'common';
10
+ import { config } from '../config';
11
+ import Inbox from '../templates/InboxWithAi';
12
+ import { InputComponent } from '../components/InboxMessage';
13
+ import { AIAgent } from '../components/AIAgent';
14
+ import { useSelector, shallowEqual } from 'react-redux';
15
+ import { Store, userSelector } from '@adminide-stack/user-auth0-client';
16
+ import { IUserState } from '@adminide-stack/core';
17
+
18
+ const { MESSAGES_PER_PAGE } = config;
19
+
20
+ // Enhanced query parameters generator with better typing and flexibility
21
+ export const queryParamsGenerator = (params: {
22
+ role?: string;
23
+ criteria?: Record<string, any>;
24
+ supportServices?: boolean;
25
+ orgName?: string;
26
+ }) => ({
27
+ variable1: {
28
+ role: params.role,
29
+ criteria: {
30
+ ...params.criteria,
31
+ ...(params.orgName && { orgName: params.orgName }),
32
+ },
33
+ supportServices: params.supportServices ? true : false,
34
+ supportServiceCriteria: params.supportServices
35
+ ? {
36
+ type: RoomType.Service,
37
+ }
38
+ : undefined,
39
+ orderBy: {
40
+ lastPostAt: 'desc',
41
+ },
42
+ },
43
+ });
44
+
45
+ interface InboxWithAiLoaderOutletProps {
46
+ channelFilters?: Record<string, any>;
47
+ channelRole?: string;
48
+ supportServices?: boolean;
49
+ pathPrefix?: string;
50
+ orgName?: string;
51
+ [key: string]: any; // Allow other props to be passed through to Inbox
52
+ }
53
+
54
+ const InboxWithAiLoaderOutlet = (props: InboxWithAiLoaderOutletProps) => {
55
+ const { channelFilters: channelFilterProp, channelRole: channelRoleProp, supportServices, pathPrefix } = props;
56
+ const { orgName, channelRole: channelRoleParam } = useParams();
57
+ const location = useLocation();
58
+ const urlParams = location?.search ? new URLSearchParams(location.search) : null;
59
+ const channelId = urlParams?.get('id');
60
+ const user: any = useSelector<Store.Auth, IUserState>(userSelector, shallowEqual);
61
+
62
+ return <AIAgent channelId={channelId} placeholder="Ask me anything..." className="h-full" currentUser={user} />;
63
+ };
64
+
65
+ // Display name for debugging
66
+ InboxWithAiLoaderOutlet.displayName = 'InboxWithAiLoaderOutlet';
67
+
68
+ export default React.memo(InboxWithAiLoaderOutlet);