@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.
- package/CHANGELOG.md +8 -0
- package/lib/components/AIAgent/AIAgent.d.ts +14 -0
- package/lib/components/AIAgent/AIAgent.d.ts.map +1 -0
- package/lib/components/AIAgent/AIAgent.js +1148 -0
- package/lib/components/AIAgent/AIAgent.js.map +1 -0
- package/lib/components/AIAgent/index.d.ts +2 -0
- package/lib/components/AIAgent/index.d.ts.map +1 -0
- package/lib/components/InboxMessage/InputComponent.d.ts +9 -0
- package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -0
- package/lib/components/InboxMessage/InputComponent.js +210 -0
- package/lib/components/InboxMessage/InputComponent.js.map +1 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts +2 -0
- package/lib/components/InboxMessage/LeftSidebar.d.ts.map +1 -1
- package/lib/components/InboxMessage/LeftSidebar.js +16 -5
- package/lib/components/InboxMessage/LeftSidebar.js.map +1 -1
- package/lib/components/InboxMessage/MessageInput.d.ts.map +1 -1
- package/lib/components/InboxMessage/MessageInput.js +14 -10
- package/lib/components/InboxMessage/MessageInput.js.map +1 -1
- package/lib/components/InboxMessage/MessageInputComponent.d.ts +9 -0
- package/lib/components/InboxMessage/MessageInputComponent.d.ts.map +1 -0
- package/lib/components/InboxMessage/MessageInputComponent.js +173 -0
- package/lib/components/InboxMessage/MessageInputComponent.js.map +1 -0
- package/lib/components/InboxMessage/Messages.d.ts +3 -1
- package/lib/components/InboxMessage/Messages.d.ts.map +1 -1
- package/lib/components/InboxMessage/Messages.js +16 -60
- package/lib/components/InboxMessage/Messages.js.map +1 -1
- package/lib/components/InboxMessage/MessagesBuilderUi.d.ts +17 -0
- package/lib/components/InboxMessage/MessagesBuilderUi.d.ts.map +1 -0
- package/lib/components/InboxMessage/MessagesBuilderUi.js +162 -0
- package/lib/components/InboxMessage/MessagesBuilderUi.js.map +1 -0
- package/lib/components/InboxMessage/UploadImageButton.d.ts +1 -0
- package/lib/components/InboxMessage/UploadImageButton.d.ts.map +1 -1
- package/lib/components/InboxMessage/UploadImageButton.js +3 -3
- package/lib/components/InboxMessage/UploadImageButton.js.map +1 -1
- package/lib/components/InboxMessage/index.d.ts +3 -0
- package/lib/components/InboxMessage/index.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/CommonMessage.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/CommonMessage.js +11 -6
- package/lib/components/InboxMessage/message-widgets/CommonMessage.js.map +1 -1
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +14 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +1525 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -0
- package/lib/components/InboxMessage/message-widgets/PlainMessage.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/PlainMessage.js +6 -3
- package/lib/components/InboxMessage/message-widgets/PlainMessage.js.map +1 -1
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts +2 -0
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js +225 -26
- package/lib/components/InboxMessage/message-widgets/SlackLikeMessageGroup.js.map +1 -1
- package/lib/components/InboxMessage/message-widgets/index.d.ts +1 -0
- package/lib/components/InboxMessage/message-widgets/index.d.ts.map +1 -1
- package/lib/components/index.d.ts +2 -1
- package/lib/components/index.d.ts.map +1 -1
- package/lib/compute.d.ts.map +1 -1
- package/lib/compute.js +79 -3
- package/lib/compute.js.map +1 -1
- package/lib/config/env-config.d.ts +6 -0
- package/lib/config/env-config.d.ts.map +1 -1
- package/lib/config/env-config.js +19 -1
- package/lib/config/env-config.js.map +1 -1
- package/lib/container/AiInbox.d.ts +15 -0
- package/lib/container/AiInbox.d.ts.map +1 -0
- package/lib/container/AiInbox.js +1520 -0
- package/lib/container/AiInbox.js.map +1 -0
- package/lib/container/AiInboxWithLoader.d.ts +36 -0
- package/lib/container/AiInboxWithLoader.d.ts.map +1 -0
- package/lib/container/AiInboxWithLoader.js +300 -0
- package/lib/container/AiInboxWithLoader.js.map +1 -0
- package/lib/container/AiLandingInput.d.ts +4 -0
- package/lib/container/AiLandingInput.d.ts.map +1 -0
- package/lib/container/AiLandingInput.js +164 -0
- package/lib/container/AiLandingInput.js.map +1 -0
- package/lib/container/Inbox.d.ts.map +1 -1
- package/lib/container/Inbox.js +177 -58
- package/lib/container/Inbox.js.map +1 -1
- package/lib/container/InboxAiMessagesLoader.d.ts +36 -0
- package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -0
- package/lib/container/InboxAiMessagesLoader.js +47 -0
- package/lib/container/InboxAiMessagesLoader.js.map +1 -0
- package/lib/container/InboxContainer.d.ts +12 -0
- package/lib/container/InboxContainer.d.ts.map +1 -0
- package/lib/container/InboxContainer.js +31 -0
- package/lib/container/InboxContainer.js.map +1 -0
- package/lib/container/InboxTemplate1.d.ts +15 -0
- package/lib/container/InboxTemplate1.d.ts.map +1 -0
- package/lib/container/InboxTemplate1.js +1375 -0
- package/lib/container/InboxTemplate1.js.map +1 -0
- package/lib/container/InboxTemplate1WithLoader.d.ts +36 -0
- package/lib/container/InboxTemplate1WithLoader.d.ts.map +1 -0
- package/lib/container/InboxTemplate2.d.ts +15 -0
- package/lib/container/InboxTemplate2.d.ts.map +1 -0
- package/lib/container/InboxTemplate2.js +1426 -0
- package/lib/container/InboxTemplate2.js.map +1 -0
- package/lib/container/InboxWithAiLoader.d.ts +15 -0
- package/lib/container/InboxWithAiLoader.d.ts.map +1 -0
- package/lib/container/InboxWithAiLoader.js +56 -0
- package/lib/container/InboxWithAiLoader.js.map +1 -0
- package/lib/container/ServiceInbox.js +1 -1
- package/lib/container/ServiceInbox.js.map +1 -1
- package/lib/container/ThreadMessages.js +1 -1
- package/lib/container/ThreadMessages.js.map +1 -1
- package/lib/container/ThreadMessagesInbox.js +1 -1
- package/lib/container/ThreadMessagesInbox.js.map +1 -1
- package/lib/container/Threads.js +1 -1
- package/lib/container/Threads.js.map +1 -1
- package/lib/container/index.d.ts +4 -1
- package/lib/container/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/machines/aiAgentMachine.d.ts +3 -0
- package/lib/machines/aiAgentMachine.d.ts.map +1 -0
- package/lib/machines/aiAgentMachine.js +1040 -0
- package/lib/machines/aiAgentMachine.js.map +1 -0
- package/lib/machines/types.d.ts +77 -0
- package/lib/machines/types.d.ts.map +1 -0
- package/lib/routes.json +40 -0
- package/lib/templates/InboxWithAi.d.ts +15 -0
- package/lib/templates/InboxWithAi.d.ts.map +1 -0
- package/lib/templates/InboxWithAi.js +405 -0
- package/lib/templates/InboxWithAi.js.map +1 -0
- package/lib/templates/InboxWithAi.tsx +502 -0
- package/package.json +7 -5
- package/src/components/AIAgent/AIAgent.tsx +1351 -0
- package/src/components/AIAgent/README.md +82 -0
- package/src/components/AIAgent/index.ts +1 -0
- package/src/components/InboxMessage/InputComponent.tsx +263 -0
- package/src/components/InboxMessage/LeftSidebar.tsx +14 -4
- package/src/components/InboxMessage/MessageInput.tsx +73 -66
- package/src/components/InboxMessage/MessageInputComponent.tsx +245 -0
- package/src/components/InboxMessage/Messages.tsx +24 -68
- package/src/components/InboxMessage/MessagesBuilderUi.tsx +205 -0
- package/src/components/InboxMessage/UploadImageButton.tsx +3 -2
- package/src/components/InboxMessage/index.ts +3 -0
- package/src/components/InboxMessage/message-widgets/CommonMessage.tsx +39 -21
- package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +1968 -0
- package/src/components/InboxMessage/message-widgets/PlainMessage.tsx +6 -2
- package/src/components/InboxMessage/message-widgets/SlackLikeMessageGroup.tsx +337 -53
- package/src/components/InboxMessage/message-widgets/index.ts +1 -0
- package/src/components/index.ts +4 -0
- package/src/compute.ts +83 -2
- package/src/config/env-config.ts +6 -0
- package/src/container/AiInbox.tsx +1796 -0
- package/src/container/AiInboxWithLoader.tsx +356 -0
- package/src/container/AiLandingInput.tsx +168 -0
- package/src/container/Inbox.tsx +280 -130
- package/src/container/InboxAiMessagesLoader.tsx +68 -0
- package/src/container/InboxContainer.tsx +35 -0
- package/src/container/InboxTemplate1.tsx +1542 -0
- package/src/container/InboxTemplate1WithLoader.tsx +338 -0
- package/src/container/InboxTemplate2.tsx +1606 -0
- package/src/container/InboxWithAiLoader.tsx +76 -0
- package/src/container/index.ts +15 -1
- package/src/machines/aiAgentMachine.ts +1248 -0
- package/src/machines/types.ts +59 -0
- package/src/templates/InboxWithAi.tsx +502 -0
package/src/container/Inbox.tsx
CHANGED
|
@@ -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
|
|
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"
|
|
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
|
|
138
|
-
const
|
|
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
|
|
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' : '
|
|
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' : '
|
|
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] &&
|
|
332
|
-
// <div
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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=
|
|
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-
|
|
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
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
postId
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
<
|
|
578
|
+
<MessagesComponent
|
|
451
579
|
channelId={channelId}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
|
|
463
|
-
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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 {
|
|
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=
|
|
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
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
<div className="flex
|
|
881
|
-
<
|
|
882
|
-
|
|
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
|
-
|
|
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);
|