@aslaluroba/help-center-react 3.2.4 → 3.2.6
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/README.md +0 -3
- package/dist/components/shared/Button/button.d.ts +3 -3
- package/dist/components/ui/index.d.ts +0 -1
- package/dist/core/AblyService.d.ts +4 -1
- package/dist/core/api.d.ts +4 -4
- package/dist/index.css +1 -1
- package/dist/index.esm.js +16040 -15655
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +16043 -15664
- package/dist/index.js.map +1 -1
- package/dist/lib/custom-hooks/useActionHandler.d.ts +8 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/theme-utils.d.ts +0 -9
- package/dist/lib/types.d.ts +6 -3
- package/dist/services.esm.js +9588 -9443
- package/dist/services.esm.js.map +1 -1
- package/dist/services.js +9582 -9439
- package/dist/services.js.map +1 -1
- package/dist/ui/chatbot-popup/active-chat-actions.d.ts +7 -0
- package/dist/ui/chatbot-popup/chat-window-screen/action-button.d.ts +10 -0
- package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -0
- package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +2 -5
- package/dist/ui/chatbot-popup/chat-window-screen/in-chat-review.d.ts +9 -0
- package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +7 -3
- package/dist/ui/chatbot-popup/chat-window-screen/typing-indicator.d.ts +6 -0
- package/dist/ui/chatbot-popup/error-screen/index.d.ts +0 -1
- package/dist/ui/chatbot-popup/loading-screen/index.d.ts +0 -2
- package/dist/ui/chatbot-popup/options-list-screen/company-card.d.ts +9 -0
- package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +1 -2
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-intro.d.ts +6 -0
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-list.d.ts +10 -0
- package/dist/ui/chatbot-popup/options-list-screen/helpscreen-option.d.ts +9 -0
- package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +1 -4
- package/dist/ui/help-center.d.ts +2 -5
- package/dist/ui/help-popup.d.ts +16 -7
- package/dist/ui/review-dialog/index.d.ts +2 -1
- package/package.json +35 -29
- package/src/components/shared/Button/button.tsx +11 -18
- package/src/components/shared/Card/card.tsx +8 -8
- package/src/components/ui/agent-response/agent-response.tsx +4 -4
- package/src/components/ui/image-attachment.tsx +8 -8
- package/src/components/ui/image-preview-dialog.tsx +41 -41
- package/src/components/ui/index.ts +0 -1
- package/src/core/AblyService.ts +60 -23
- package/src/core/api.ts +9 -7
- package/src/globals.css +216 -50
- package/src/lib/custom-hooks/useActionHandler.ts +102 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/theme-utils.ts +1 -33
- package/src/lib/types.ts +7 -4
- package/src/locales/ar.json +16 -6
- package/src/locales/en.json +16 -6
- package/src/types/icons.d.ts +6 -0
- package/src/ui/chatbot-popup/active-chat-actions.tsx +39 -0
- package/src/ui/chatbot-popup/chat-window-screen/action-button.tsx +37 -0
- package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +42 -43
- package/src/ui/chatbot-popup/chat-window-screen/header.tsx +34 -67
- package/src/ui/chatbot-popup/chat-window-screen/in-chat-review.tsx +83 -0
- package/src/ui/chatbot-popup/chat-window-screen/index.tsx +49 -42
- package/src/ui/chatbot-popup/chat-window-screen/typing-indicator.tsx +27 -0
- package/src/ui/chatbot-popup/error-screen/index.tsx +7 -7
- package/src/ui/chatbot-popup/loading-screen/index.tsx +6 -17
- package/src/ui/chatbot-popup/options-list-screen/company-card.tsx +37 -0
- package/src/ui/chatbot-popup/options-list-screen/header.tsx +12 -31
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-intro.tsx +32 -0
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-list.tsx +48 -0
- package/src/ui/chatbot-popup/options-list-screen/helpscreen-option.tsx +38 -0
- package/src/ui/chatbot-popup/options-list-screen/index.tsx +44 -38
- package/src/ui/confirmation-modal/index.tsx +27 -12
- package/src/ui/floating-message.tsx +8 -7
- package/src/ui/help-button.tsx +5 -5
- package/src/ui/help-center.tsx +95 -58
- package/src/ui/help-popup.tsx +114 -91
- package/src/ui/powered-by.tsx +49 -7
- package/src/ui/review-dialog/index.tsx +48 -65
- package/src/ui/review-dialog/rating.tsx +7 -7
- package/dist/components/ui/header.d.ts +0 -6
- package/dist/ui/chatbot-popup/home-screen/card.d.ts +0 -6
- package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +0 -5
- package/dist/ui/chatbot-popup/home-screen/index.d.ts +0 -7
- package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +0 -7
- package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +0 -5
- package/src/.DS_Store +0 -0
- package/src/assets/icons/arrowRight.svg +0 -3
- package/src/assets/icons/chat.svg +0 -4
- package/src/assets/icons/close.svg +0 -1
- package/src/assets/icons/closeCircle.svg +0 -3
- package/src/assets/icons/closeCirclePrimary.svg +0 -4
- package/src/assets/icons/envelope.svg +0 -3
- package/src/assets/icons/paperclip.svg +0 -3
- package/src/assets/icons/threeDots.svg +0 -3
- package/src/assets/icons/user.svg +0 -3
- package/src/assets/icons/x.svg +0 -4
- package/src/assets/logoColors.svg +0 -5
- package/src/assets/logo_ai.svg +0 -14
- package/src/assets/thinking-logo.svg +0 -3
- package/src/components/ui/header.tsx +0 -22
- package/src/ui/chatbot-popup/home-screen/card.tsx +0 -33
- package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +0 -36
- package/src/ui/chatbot-popup/home-screen/index.tsx +0 -44
- package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +0 -37
- package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +0 -31
- /package/src/assets/{icons/seperator.svg → seperator.svg} +0 -0
package/src/ui/help-center.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
2
|
import { apiRequest } from '../core/api';
|
|
4
3
|
import { ClientAblyService } from '../core/AblyService';
|
|
5
4
|
import { useLocalTranslation } from '../useLocalTranslation';
|
|
@@ -10,11 +9,12 @@ import HelpButton from './help-button';
|
|
|
10
9
|
import HelpPopup from './help-popup';
|
|
11
10
|
import { defaultLanguage } from '@/i18n';
|
|
12
11
|
import { LanguageProvider } from '@/lib/LanguageContext';
|
|
13
|
-
import {
|
|
12
|
+
import { getPrimaryColorStyles } from '@/lib/theme-utils';
|
|
13
|
+
import { useActionHandler } from '@/lib/custom-hooks/useActionHandler';
|
|
14
14
|
|
|
15
15
|
interface HelpCenterProps {
|
|
16
16
|
helpScreenId: string;
|
|
17
|
-
language
|
|
17
|
+
language?: 'ar' | 'en';
|
|
18
18
|
user?: {
|
|
19
19
|
id?: string;
|
|
20
20
|
name?: string;
|
|
@@ -23,10 +23,7 @@ interface HelpCenterProps {
|
|
|
23
23
|
};
|
|
24
24
|
showArrow?: boolean;
|
|
25
25
|
messageLabel?: string | null;
|
|
26
|
-
showHelpScreen?: boolean;
|
|
27
26
|
primaryColor?: string;
|
|
28
|
-
secondaryColor?: string;
|
|
29
|
-
logoUrl?: string;
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
const HelpCenterContent = ({
|
|
@@ -34,11 +31,8 @@ const HelpCenterContent = ({
|
|
|
34
31
|
user,
|
|
35
32
|
showArrow = true,
|
|
36
33
|
messageLabel = null,
|
|
37
|
-
showHelpScreen = false,
|
|
38
34
|
primaryColor,
|
|
39
|
-
|
|
40
|
-
logoUrl,
|
|
41
|
-
language,
|
|
35
|
+
language = defaultLanguage,
|
|
42
36
|
}: HelpCenterProps) => {
|
|
43
37
|
const { t } = useLocalTranslation();
|
|
44
38
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -50,12 +44,17 @@ const HelpCenterContent = ({
|
|
|
50
44
|
|
|
51
45
|
const [sessionId, setSessionId] = useState<string | null>(null);
|
|
52
46
|
const [reviewSessionId, setReviewSessionId] = useState<string | null>(null);
|
|
47
|
+
const [inChatReviewSessionId, setInChatReviewSessionId] = useState<string | null>(null);
|
|
53
48
|
const [isAblyConnected, setIsAblyConnected] = useState(false);
|
|
54
49
|
const [isChatClosed, setIsChatClosed] = useState(false);
|
|
55
50
|
const [messages, setMessages] = useState<Message[]>([]);
|
|
56
51
|
const [needsAgent, setNeedsAgent] = useState(false);
|
|
57
52
|
const [assistantStatus, setAssistantStatus] = useState('idle');
|
|
58
53
|
const [isReviewDialogOpen, setIsReviewDialogOpen] = useState(false);
|
|
54
|
+
const [isSubmittingReview, setIsSubmittingReview] = useState(false);
|
|
55
|
+
const [navigateToOptionsListAfterReview, setNavigateToOptionsListAfterReview] = useState(false);
|
|
56
|
+
|
|
57
|
+
const actionHandler = useActionHandler();
|
|
59
58
|
|
|
60
59
|
const handleTogglePopup = () => {
|
|
61
60
|
setIsOpen(!isOpen);
|
|
@@ -70,7 +69,8 @@ const HelpCenterContent = ({
|
|
|
70
69
|
message: string,
|
|
71
70
|
senderType: number,
|
|
72
71
|
needsAgent: boolean,
|
|
73
|
-
|
|
72
|
+
attachmentUrls: string[] = [],
|
|
73
|
+
attachmentIds: string[] = []
|
|
74
74
|
) => {
|
|
75
75
|
if (needsAgent) {
|
|
76
76
|
setNeedsAgent(true);
|
|
@@ -83,8 +83,8 @@ const HelpCenterContent = ({
|
|
|
83
83
|
messageContent: message,
|
|
84
84
|
sentAt: new Date(),
|
|
85
85
|
isSeen: true,
|
|
86
|
-
|
|
87
|
-
...(
|
|
86
|
+
...(attachmentUrls.length > 0 && { attachmentUrls }),
|
|
87
|
+
...(attachmentIds.length > 0 && { attachmentIds }),
|
|
88
88
|
};
|
|
89
89
|
|
|
90
90
|
return [...prevMessages, newMessage];
|
|
@@ -93,43 +93,54 @@ const HelpCenterContent = ({
|
|
|
93
93
|
setAssistantStatus('idle');
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
-
const handleEndChat =
|
|
97
|
-
|
|
96
|
+
const handleEndChat = useCallback(
|
|
97
|
+
async (options?: { fromChatScreen?: boolean }) => {
|
|
98
|
+
if (!sessionId || !selectedOption) return;
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
await ClientAblyService.stopConnection();
|
|
101
|
-
setIsAblyConnected(false);
|
|
102
|
-
setAssistantStatus('idle');
|
|
100
|
+
const fromChatScreen = options?.fromChatScreen === true;
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Store sessionId for review before clearing the main sessionId
|
|
110
|
-
setReviewSessionId(sessionId);
|
|
111
|
-
|
|
112
|
-
// Clear the sessionId after successfully closing the session
|
|
113
|
-
setSessionId(null);
|
|
114
|
-
setSelectedOption(null);
|
|
115
|
-
setMessages([]);
|
|
102
|
+
try {
|
|
103
|
+
await ClientAblyService.stopConnection();
|
|
104
|
+
setIsAblyConnected(false);
|
|
105
|
+
setAssistantStatus('idle');
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
107
|
+
const response = await apiRequest(`Client/ClientChatSession/${sessionId}/close`, 'POST', null, {
|
|
108
|
+
language: language,
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) throw new Error('Failed to close chat session');
|
|
111
|
+
|
|
112
|
+
setReviewSessionId(sessionId);
|
|
113
|
+
setSessionId(null);
|
|
114
|
+
|
|
115
|
+
if (fromChatScreen) {
|
|
116
|
+
setInChatReviewSessionId(sessionId);
|
|
117
|
+
setIsChatClosed(true);
|
|
118
|
+
// Keep selectedOption and messages; do not open popup
|
|
119
|
+
} else {
|
|
120
|
+
setSelectedOption(null);
|
|
121
|
+
setMessages([]);
|
|
122
|
+
setIsReviewDialogOpen(true);
|
|
123
|
+
}
|
|
124
|
+
} catch (err) {
|
|
125
|
+
setError('Failed to end chat session');
|
|
126
|
+
setAssistantStatus('idle');
|
|
127
|
+
setReviewSessionId(sessionId);
|
|
128
|
+
setSessionId(null);
|
|
129
|
+
if (!fromChatScreen) {
|
|
130
|
+
setSelectedOption(null);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
[language, selectedOption, sessionId]
|
|
135
|
+
);
|
|
127
136
|
|
|
128
137
|
const handleSendChatReview = async ({ comment, rating }: ReviewProps) => {
|
|
129
138
|
if (!reviewSessionId) return;
|
|
130
139
|
|
|
131
140
|
const payload = { rating, comment };
|
|
141
|
+
const wasInChatReview = !!inChatReviewSessionId;
|
|
132
142
|
|
|
143
|
+
setIsSubmittingReview(true);
|
|
133
144
|
try {
|
|
134
145
|
const response = await apiRequest(`Client/ClientChatSession/${reviewSessionId}/review`, 'POST', payload, {
|
|
135
146
|
language,
|
|
@@ -137,17 +148,24 @@ const HelpCenterContent = ({
|
|
|
137
148
|
if (!response.ok) throw new Error('Failed to send chat review');
|
|
138
149
|
|
|
139
150
|
handleCloseChatReview();
|
|
140
|
-
|
|
151
|
+
if (wasInChatReview) {
|
|
152
|
+
setNavigateToOptionsListAfterReview(true);
|
|
153
|
+
}
|
|
154
|
+
} catch (err) {
|
|
141
155
|
setError('Failed to send chat review');
|
|
156
|
+
} finally {
|
|
157
|
+
setIsSubmittingReview(false);
|
|
142
158
|
}
|
|
143
159
|
};
|
|
144
160
|
|
|
145
161
|
const handleCloseChatReview = () => {
|
|
146
162
|
setIsReviewDialogOpen(false);
|
|
147
163
|
setReviewSessionId(null);
|
|
164
|
+
setInChatReviewSessionId(null);
|
|
148
165
|
};
|
|
149
166
|
|
|
150
167
|
const handleStartChat = async (option: Option) => {
|
|
168
|
+
setInChatReviewSessionId(null);
|
|
151
169
|
setMessages([
|
|
152
170
|
{
|
|
153
171
|
id: Date.now(),
|
|
@@ -195,7 +213,10 @@ const HelpCenterContent = ({
|
|
|
195
213
|
newSessionId,
|
|
196
214
|
responseData.ablyToken,
|
|
197
215
|
handleReceiveMessage,
|
|
198
|
-
responseData.chatSession.tenantId
|
|
216
|
+
responseData.chatSession.tenantId,
|
|
217
|
+
(actionType, messageData) => {
|
|
218
|
+
void actionHandler.handleAction(actionType, messageData);
|
|
219
|
+
}
|
|
199
220
|
);
|
|
200
221
|
|
|
201
222
|
// Verify the connection is actually active
|
|
@@ -297,6 +318,24 @@ const HelpCenterContent = ({
|
|
|
297
318
|
}
|
|
298
319
|
};
|
|
299
320
|
|
|
321
|
+
// Register known action handlers for realtime messages
|
|
322
|
+
useEffect(() => {
|
|
323
|
+
// "needs_agent" → trigger handoff / needs agent UI flow
|
|
324
|
+
actionHandler.registerHandler('needs_agent', () => {
|
|
325
|
+
setNeedsAgent(true);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// "end_session" → close session and show in-chat review (user stays in chat)
|
|
329
|
+
actionHandler.registerHandler('end_session', () => {
|
|
330
|
+
void handleEndChat({ fromChatScreen: true });
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
return () => {
|
|
334
|
+
actionHandler.unregisterHandler('needs_agent');
|
|
335
|
+
actionHandler.unregisterHandler('end_session');
|
|
336
|
+
};
|
|
337
|
+
}, [actionHandler, handleEndChat]);
|
|
338
|
+
|
|
300
339
|
useEffect(() => {
|
|
301
340
|
if (isOpen && helpScreenId) {
|
|
302
341
|
setStatus('loading');
|
|
@@ -317,10 +356,10 @@ const HelpCenterContent = ({
|
|
|
317
356
|
}
|
|
318
357
|
}, [isOpen, helpScreenId]);
|
|
319
358
|
|
|
320
|
-
const themeStyles =
|
|
359
|
+
const themeStyles = getPrimaryColorStyles(primaryColor);
|
|
321
360
|
|
|
322
361
|
return (
|
|
323
|
-
<div className='babylai-
|
|
362
|
+
<div className='babylai-theme-root babylai:mb-4' style={themeStyles}>
|
|
324
363
|
{showArrowAnimation && !isOpen && (
|
|
325
364
|
<FloatingMessage onClose={handleCloseArrowAnimation} message={messageLabel || t('homeSdk.needAssistance')} />
|
|
326
365
|
)}
|
|
@@ -344,16 +383,20 @@ const HelpCenterContent = ({
|
|
|
344
383
|
assistantStatus={assistantStatus}
|
|
345
384
|
sessionId={sessionId}
|
|
346
385
|
isChatClosed={isChatClosed}
|
|
347
|
-
isAblyConnected={isAblyConnected}
|
|
348
386
|
selectedOption={selectedOption}
|
|
349
387
|
setSelectedOption={setSelectedOption}
|
|
350
|
-
|
|
351
|
-
|
|
388
|
+
inChatReviewSessionId={inChatReviewSessionId}
|
|
389
|
+
onInChatReviewSubmit={handleSendChatReview}
|
|
390
|
+
onInChatReviewDone={handleCloseChatReview}
|
|
391
|
+
navigateToOptionsListAfterReview={navigateToOptionsListAfterReview}
|
|
392
|
+
onNavigatedToOptionsList={() => setNavigateToOptionsListAfterReview(false)}
|
|
393
|
+
isReviewDialogOpen={isReviewDialogOpen}
|
|
394
|
+
reviewSessionId={reviewSessionId}
|
|
395
|
+
isSubmittingReview={isSubmittingReview}
|
|
396
|
+
onReviewDialogSubmit={handleSendChatReview}
|
|
397
|
+
onReviewDialogClose={handleCloseChatReview}
|
|
352
398
|
/>
|
|
353
399
|
)}
|
|
354
|
-
{isOpen && !!isReviewDialogOpen && reviewSessionId && (
|
|
355
|
-
<ReviewDialog handleSubmit={handleSendChatReview} onClose={handleCloseChatReview} />
|
|
356
|
-
)}
|
|
357
400
|
</div>
|
|
358
401
|
);
|
|
359
402
|
};
|
|
@@ -365,10 +408,7 @@ const HelpCenter = ({
|
|
|
365
408
|
showArrow = true,
|
|
366
409
|
language = defaultLanguage,
|
|
367
410
|
messageLabel = null,
|
|
368
|
-
showHelpScreen = false,
|
|
369
411
|
primaryColor,
|
|
370
|
-
secondaryColor,
|
|
371
|
-
logoUrl,
|
|
372
412
|
}: HelpCenterProps) => {
|
|
373
413
|
return (
|
|
374
414
|
<LanguageProvider language={language}>
|
|
@@ -378,10 +418,7 @@ const HelpCenter = ({
|
|
|
378
418
|
user={user}
|
|
379
419
|
showArrow={showArrow}
|
|
380
420
|
messageLabel={messageLabel}
|
|
381
|
-
showHelpScreen={showHelpScreen}
|
|
382
421
|
primaryColor={primaryColor}
|
|
383
|
-
secondaryColor={secondaryColor}
|
|
384
|
-
logoUrl={logoUrl}
|
|
385
422
|
/>
|
|
386
423
|
</LanguageProvider>
|
|
387
424
|
);
|
package/src/ui/help-popup.tsx
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { cn } from '@/lib';
|
|
2
1
|
import { ChatWindow } from '@/ui/chatbot-popup/chat-window-screen';
|
|
3
2
|
import ChatWindowHeader from '@/ui/chatbot-popup/chat-window-screen/header';
|
|
4
3
|
import ChatBotErrorScreen from '@/ui/chatbot-popup/error-screen';
|
|
5
|
-
import HomeScreen from '@/ui/chatbot-popup/home-screen';
|
|
6
4
|
import ChatBotLoadingScreen from '@/ui/chatbot-popup/loading-screen';
|
|
7
5
|
import OptionsListScreen from '@/ui/chatbot-popup/options-list-screen';
|
|
6
|
+
import { ActiveChatActions } from '@/ui/chatbot-popup/active-chat-actions';
|
|
8
7
|
import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
|
|
9
|
-
import
|
|
10
|
-
import { Button } from '@/components';
|
|
11
|
-
import { HelpScreenData, Message, Option } from '@/lib/types';
|
|
8
|
+
import { HelpScreenData, Message, Option, ReviewProps } from '@/lib/types';
|
|
12
9
|
import { useLocalTranslation } from '../useLocalTranslation';
|
|
13
10
|
import ConfirmationModal from './confirmation-modal';
|
|
14
|
-
import
|
|
11
|
+
import ReviewDialog from './review-dialog';
|
|
15
12
|
|
|
16
13
|
type HelpPopupProps = {
|
|
17
14
|
isOpen: boolean;
|
|
@@ -19,24 +16,32 @@ type HelpPopupProps = {
|
|
|
19
16
|
helpScreen: HelpScreenData | null;
|
|
20
17
|
status: string;
|
|
21
18
|
error: string | null;
|
|
22
|
-
user:
|
|
19
|
+
user: unknown;
|
|
23
20
|
onStartChat: (option: Option) => void;
|
|
24
21
|
onSendMessage: (message: string, attachmentIds: string[]) => void;
|
|
25
22
|
onEnsureSession: () => Promise<string>;
|
|
26
|
-
onEndChat: (
|
|
23
|
+
onEndChat: (options?: { fromChatScreen?: boolean }) => void | Promise<void>;
|
|
27
24
|
messages: Message[];
|
|
28
25
|
needsAgent: boolean;
|
|
29
26
|
assistantStatus: string;
|
|
30
27
|
sessionId: string | null;
|
|
31
28
|
isChatClosed: boolean;
|
|
32
|
-
isAblyConnected: boolean;
|
|
33
29
|
selectedOption: Option | null;
|
|
34
30
|
setSelectedOption: (option: Option | null) => void;
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
inChatReviewSessionId?: string | null;
|
|
32
|
+
onInChatReviewSubmit?: (payload: ReviewProps) => void | Promise<void>;
|
|
33
|
+
onInChatReviewDone?: () => void;
|
|
34
|
+
navigateToOptionsListAfterReview?: boolean;
|
|
35
|
+
onNavigatedToOptionsList?: () => void;
|
|
36
|
+
isReviewDialogOpen?: boolean;
|
|
37
|
+
reviewSessionId?: string | null;
|
|
38
|
+
isSubmittingReview?: boolean;
|
|
39
|
+
onReviewDialogSubmit?: (payload: ReviewProps) => void | Promise<void>;
|
|
40
|
+
onReviewDialogClose?: () => void;
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
const HelpPopup = ({
|
|
44
|
+
isOpen,
|
|
40
45
|
onClose,
|
|
41
46
|
helpScreen,
|
|
42
47
|
status,
|
|
@@ -49,21 +54,28 @@ const HelpPopup = ({
|
|
|
49
54
|
assistantStatus,
|
|
50
55
|
needsAgent,
|
|
51
56
|
sessionId,
|
|
57
|
+
isChatClosed,
|
|
52
58
|
selectedOption,
|
|
53
59
|
setSelectedOption,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
inChatReviewSessionId = null,
|
|
61
|
+
onInChatReviewSubmit,
|
|
62
|
+
onInChatReviewDone,
|
|
63
|
+
navigateToOptionsListAfterReview = false,
|
|
64
|
+
onNavigatedToOptionsList,
|
|
65
|
+
isReviewDialogOpen = false,
|
|
66
|
+
reviewSessionId = null,
|
|
67
|
+
isSubmittingReview = false,
|
|
68
|
+
onReviewDialogSubmit,
|
|
69
|
+
onReviewDialogClose,
|
|
57
70
|
}: HelpPopupProps) => {
|
|
58
71
|
// ALL HOOKS MUST BE CALLED FIRST - BEFORE ANY EARLY RETURNS
|
|
59
72
|
const [showChat, setShowChat] = useState(false);
|
|
60
|
-
const [isShowList, setIsShowList] = useState<boolean>(!showHelpScreen || false);
|
|
61
|
-
const [expandedOption, setExpandedOption] = useState<Option | null>(null);
|
|
62
73
|
const [endChatConfirmation, setEndChatConfirmation] = useState<boolean>(false);
|
|
63
74
|
const [startNewChatConfirmation, setStartNewChatConfirmation] = useState<boolean>(false);
|
|
64
75
|
const [tempSelectedOption, setTempSelectedOption] = useState<Option | null>(null);
|
|
65
76
|
|
|
66
77
|
const chatBoxRef = useRef<HTMLDivElement>(null);
|
|
78
|
+
const prevIsOpenRef = useRef(false);
|
|
67
79
|
const { t } = useLocalTranslation();
|
|
68
80
|
const messagesRef = useRef<Message[]>([]);
|
|
69
81
|
|
|
@@ -92,8 +104,6 @@ const HelpPopup = ({
|
|
|
92
104
|
// onEndChat()
|
|
93
105
|
} else if (selectedOption) {
|
|
94
106
|
setSelectedOption(null);
|
|
95
|
-
} else {
|
|
96
|
-
setIsShowList(false);
|
|
97
107
|
}
|
|
98
108
|
}, [showChat, selectedOption, setSelectedOption]);
|
|
99
109
|
|
|
@@ -131,29 +141,34 @@ const HelpPopup = ({
|
|
|
131
141
|
if (tempSelectedOption) {
|
|
132
142
|
setStartNewChatConfirmation(false);
|
|
133
143
|
|
|
134
|
-
await
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
})
|
|
140
|
-
.finally(() => {
|
|
141
|
-
setTempSelectedOption(null);
|
|
142
|
-
});
|
|
144
|
+
await onEndChat();
|
|
145
|
+
setShowChat(true);
|
|
146
|
+
onStartChat(tempSelectedOption);
|
|
147
|
+
setSelectedOption(tempSelectedOption);
|
|
148
|
+
setTempSelectedOption(null);
|
|
143
149
|
}
|
|
144
150
|
};
|
|
145
151
|
|
|
146
|
-
const
|
|
152
|
+
const handleEndChatFromChatScreen = useCallback(async () => {
|
|
147
153
|
setEndChatConfirmation(false);
|
|
148
|
-
await onEndChat();
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
await onEndChat({ fromChatScreen: true });
|
|
155
|
+
// Keep showChat and selectedOption so chat screen stays open with in-chat review
|
|
156
|
+
}, [onEndChat]);
|
|
157
|
+
|
|
158
|
+
const handleMinimize = useCallback(() => {
|
|
159
|
+
onClose();
|
|
160
|
+
}, [onClose]);
|
|
152
161
|
|
|
153
162
|
const handleShowActiveChat = useCallback(() => {
|
|
154
163
|
setShowChat(true);
|
|
155
164
|
}, []);
|
|
156
165
|
|
|
166
|
+
const handleEndChatFromActiveActions = useCallback(async () => {
|
|
167
|
+
await onEndChat();
|
|
168
|
+
setShowChat(false);
|
|
169
|
+
setSelectedOption(null);
|
|
170
|
+
}, [onEndChat, setSelectedOption]);
|
|
171
|
+
|
|
157
172
|
// Memoize render content function
|
|
158
173
|
const renderContent = useCallback(() => {
|
|
159
174
|
if (showChat && selectedOption) {
|
|
@@ -162,11 +177,8 @@ const HelpPopup = ({
|
|
|
162
177
|
<ChatWindowHeader
|
|
163
178
|
handleBack={handleBack}
|
|
164
179
|
handleEndChat={showEndChatConfirmation}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
showChat={showChat}
|
|
168
|
-
setIsShowList={setIsShowList}
|
|
169
|
-
logoUrl={logoUrl}
|
|
180
|
+
handleMinimize={handleMinimize}
|
|
181
|
+
optionTitle={selectedOption?.title}
|
|
170
182
|
/>
|
|
171
183
|
<ChatWindow
|
|
172
184
|
onSendMessage={handleSendMessage}
|
|
@@ -174,49 +186,46 @@ const HelpPopup = ({
|
|
|
174
186
|
messages={memoizedMessages}
|
|
175
187
|
assistantStatus={assistantStatus}
|
|
176
188
|
needsAgent={needsAgent}
|
|
177
|
-
isAblyConnected={isAblyConnected}
|
|
178
189
|
sessionId={sessionId}
|
|
190
|
+
isChatClosed={isChatClosed}
|
|
191
|
+
inChatReviewSessionId={inChatReviewSessionId ?? undefined}
|
|
192
|
+
isSubmittingReview={isSubmittingReview}
|
|
193
|
+
onInChatReviewSubmit={onInChatReviewSubmit}
|
|
194
|
+
onInChatReviewDone={onInChatReviewDone}
|
|
179
195
|
/>
|
|
180
196
|
</>
|
|
181
197
|
);
|
|
182
198
|
}
|
|
183
199
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
handleBack={showHelpScreen ? handleBack : onClose}
|
|
192
|
-
showHelpScreen={showHelpScreen}
|
|
193
|
-
/>
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
return <HomeScreen setIsShowList={setIsShowList} onClose={onClose} logoUrl={logoUrl} />;
|
|
200
|
+
return (
|
|
201
|
+
<OptionsListScreen
|
|
202
|
+
helpScreen={helpScreen}
|
|
203
|
+
handleStartChat={handleStartChat}
|
|
204
|
+
handleMinimize={handleMinimize}
|
|
205
|
+
/>
|
|
206
|
+
);
|
|
197
207
|
}, [
|
|
198
208
|
showChat,
|
|
199
209
|
selectedOption,
|
|
200
210
|
handleBack,
|
|
201
211
|
showEndChatConfirmation,
|
|
202
|
-
onClose,
|
|
203
|
-
isShowList,
|
|
204
|
-
setIsShowList,
|
|
205
212
|
handleSendMessage,
|
|
206
213
|
onEnsureSession,
|
|
207
214
|
memoizedMessages,
|
|
208
215
|
assistantStatus,
|
|
209
216
|
needsAgent,
|
|
210
217
|
helpScreen,
|
|
211
|
-
expandedOption,
|
|
212
|
-
setExpandedOption,
|
|
213
218
|
handleStartChat,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
handleMinimize,
|
|
220
|
+
sessionId,
|
|
221
|
+
isChatClosed,
|
|
222
|
+
inChatReviewSessionId,
|
|
223
|
+
isSubmittingReview,
|
|
224
|
+
onInChatReviewSubmit,
|
|
225
|
+
onInChatReviewDone,
|
|
217
226
|
]);
|
|
218
227
|
|
|
219
|
-
// Memoize confirmation modal
|
|
228
|
+
// Memoize confirmation modal (End Chat from chat screen → keep chat open, show in-chat review)
|
|
220
229
|
const confirmationModal = useMemo(() => {
|
|
221
230
|
if (!endChatConfirmation) return null;
|
|
222
231
|
|
|
@@ -225,26 +234,40 @@ const HelpPopup = ({
|
|
|
225
234
|
title={t('homeSdk.ConfirmationModal.title')}
|
|
226
235
|
message={t('homeSdk.ConfirmationModal.message')}
|
|
227
236
|
onCancel={hideEndChatConfirmation}
|
|
228
|
-
onConfirm={
|
|
237
|
+
onConfirm={handleEndChatFromChatScreen}
|
|
229
238
|
/>
|
|
230
239
|
);
|
|
231
|
-
}, [endChatConfirmation, t, hideEndChatConfirmation,
|
|
240
|
+
}, [endChatConfirmation, t, hideEndChatConfirmation, handleEndChatFromChatScreen]);
|
|
232
241
|
|
|
233
242
|
// Memoize active chat button
|
|
234
243
|
const activeChatButton = useMemo(() => {
|
|
235
244
|
if (!sessionId || showChat) return null;
|
|
236
245
|
|
|
237
246
|
return (
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
onClick={handleShowActiveChat}
|
|
243
|
-
>
|
|
244
|
-
<ChatIcon className='babylai-w-5 babylai-h-5 babylai-text-black-white-50' />
|
|
245
|
-
</Button>
|
|
247
|
+
<ActiveChatActions
|
|
248
|
+
onConfirm={handleEndChatFromActiveActions}
|
|
249
|
+
onCancel={handleShowActiveChat}
|
|
250
|
+
/>
|
|
246
251
|
);
|
|
247
|
-
}, [sessionId, showChat, handleShowActiveChat]);
|
|
252
|
+
}, [sessionId, showChat, handleShowActiveChat, handleEndChatFromActiveActions]);
|
|
253
|
+
|
|
254
|
+
// Restore chat view only when popup reopens (not when user clicks back)
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
const justOpened = isOpen && !prevIsOpenRef.current;
|
|
257
|
+
prevIsOpenRef.current = isOpen;
|
|
258
|
+
if (justOpened && sessionId && selectedOption && !showChat) {
|
|
259
|
+
setShowChat(true);
|
|
260
|
+
}
|
|
261
|
+
}, [isOpen, sessionId, selectedOption, showChat]);
|
|
262
|
+
|
|
263
|
+
// After submitting in-chat review, navigate to options list
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
if (navigateToOptionsListAfterReview) {
|
|
266
|
+
setShowChat(false);
|
|
267
|
+
setSelectedOption(null);
|
|
268
|
+
onNavigatedToOptionsList?.();
|
|
269
|
+
}
|
|
270
|
+
}, [navigateToOptionsListAfterReview, onNavigatedToOptionsList, setSelectedOption]);
|
|
248
271
|
|
|
249
272
|
// Scroll to bottom when new messages arrive - optimize with ref comparison
|
|
250
273
|
useEffect(() => {
|
|
@@ -259,11 +282,11 @@ const HelpPopup = ({
|
|
|
259
282
|
if (status === 'loading' && !helpScreen) {
|
|
260
283
|
return (
|
|
261
284
|
<div
|
|
262
|
-
className='babylai
|
|
263
|
-
babylai
|
|
264
|
-
md:
|
|
285
|
+
className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
|
|
286
|
+
babylai:overflow-auto babylai:w-full babylai:bg-black-white-50 babylai:md:mb-4
|
|
287
|
+
babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
|
|
265
288
|
>
|
|
266
|
-
<ChatBotLoadingScreen
|
|
289
|
+
<ChatBotLoadingScreen onClose={onClose} />
|
|
267
290
|
</div>
|
|
268
291
|
);
|
|
269
292
|
}
|
|
@@ -271,35 +294,27 @@ md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-roun
|
|
|
271
294
|
if (error) {
|
|
272
295
|
return (
|
|
273
296
|
<div
|
|
274
|
-
className='babylai
|
|
275
|
-
babylai
|
|
276
|
-
md:
|
|
297
|
+
className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
|
|
298
|
+
babylai:overflow-auto babylai:w-full babylai:bg-black-white-50 babylai:md:mb-4
|
|
299
|
+
babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
|
|
277
300
|
>
|
|
278
|
-
<ChatBotErrorScreen onClose={onClose} error={error || ''}
|
|
301
|
+
<ChatBotErrorScreen onClose={onClose} error={error || ''} />
|
|
279
302
|
</div>
|
|
280
303
|
);
|
|
281
304
|
}
|
|
282
305
|
|
|
283
306
|
return (
|
|
284
307
|
<div
|
|
285
|
-
className='babylai
|
|
286
|
-
babylai
|
|
287
|
-
md:
|
|
308
|
+
className='babylai:fixed babylai:inset-0 babylai:md:inset-auto babylai:md:max-w-sm babylai:md:h-[calc(100vh-220px)] babylai:max-h-[800px]
|
|
309
|
+
babylai:overflow-auto babylai:w-full babylai:bg-secondary babylai:md:mb-4
|
|
310
|
+
babylai:md:bottom-24 babylai:md:right-4 babylai:rounded-none babylai:md:rounded-3xl babylai:shadow-lg babylai:z-50 babylai:flex babylai:flex-col'
|
|
288
311
|
>
|
|
289
|
-
<div
|
|
290
|
-
className={cn(
|
|
291
|
-
'babylai-h-full babylai-rounded-none md:babylai-rounded-3xl babylai-flex babylai-flex-col babylai-relative',
|
|
292
|
-
{
|
|
293
|
-
'babylai-bg-linear-to-b': !isShowList,
|
|
294
|
-
'babylai-bg-black-white-100 dark:babylai-bg-storm-dust-950': isShowList,
|
|
295
|
-
}
|
|
296
|
-
)}
|
|
312
|
+
<div className='babylai:h-full babylai:rounded-none babylai:md:rounded-3xl babylai:flex babylai:flex-col babylai:relative'
|
|
297
313
|
>
|
|
298
314
|
{activeChatButton}
|
|
299
315
|
|
|
300
316
|
{/* Content */}
|
|
301
317
|
{renderContent()}
|
|
302
|
-
<PoweredBy />
|
|
303
318
|
|
|
304
319
|
{/* End Chat Confirmation Modal */}
|
|
305
320
|
{confirmationModal}
|
|
@@ -312,6 +327,14 @@ md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-roun
|
|
|
312
327
|
onConfirm={handleEndAndStartNewChat}
|
|
313
328
|
/>
|
|
314
329
|
)}
|
|
330
|
+
|
|
331
|
+
{!!isReviewDialogOpen && !!reviewSessionId && onReviewDialogSubmit && onReviewDialogClose && (
|
|
332
|
+
<ReviewDialog
|
|
333
|
+
handleSubmit={onReviewDialogSubmit}
|
|
334
|
+
onClose={onReviewDialogClose}
|
|
335
|
+
isSubmitting={isSubmittingReview}
|
|
336
|
+
/>
|
|
337
|
+
)}
|
|
315
338
|
</div>
|
|
316
339
|
</div>
|
|
317
340
|
);
|