@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.
Files changed (103) hide show
  1. package/README.md +0 -3
  2. package/dist/components/shared/Button/button.d.ts +3 -3
  3. package/dist/components/ui/index.d.ts +0 -1
  4. package/dist/core/AblyService.d.ts +4 -1
  5. package/dist/core/api.d.ts +4 -4
  6. package/dist/index.css +1 -1
  7. package/dist/index.esm.js +16040 -15655
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +16043 -15664
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/custom-hooks/useActionHandler.d.ts +8 -0
  12. package/dist/lib/index.d.ts +1 -0
  13. package/dist/lib/theme-utils.d.ts +0 -9
  14. package/dist/lib/types.d.ts +6 -3
  15. package/dist/services.esm.js +9588 -9443
  16. package/dist/services.esm.js.map +1 -1
  17. package/dist/services.js +9582 -9439
  18. package/dist/services.js.map +1 -1
  19. package/dist/ui/chatbot-popup/active-chat-actions.d.ts +7 -0
  20. package/dist/ui/chatbot-popup/chat-window-screen/action-button.d.ts +10 -0
  21. package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -0
  22. package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +2 -5
  23. package/dist/ui/chatbot-popup/chat-window-screen/in-chat-review.d.ts +9 -0
  24. package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +7 -3
  25. package/dist/ui/chatbot-popup/chat-window-screen/typing-indicator.d.ts +6 -0
  26. package/dist/ui/chatbot-popup/error-screen/index.d.ts +0 -1
  27. package/dist/ui/chatbot-popup/loading-screen/index.d.ts +0 -2
  28. package/dist/ui/chatbot-popup/options-list-screen/company-card.d.ts +9 -0
  29. package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +1 -2
  30. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-intro.d.ts +6 -0
  31. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-list.d.ts +10 -0
  32. package/dist/ui/chatbot-popup/options-list-screen/helpscreen-option.d.ts +9 -0
  33. package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +1 -4
  34. package/dist/ui/help-center.d.ts +2 -5
  35. package/dist/ui/help-popup.d.ts +16 -7
  36. package/dist/ui/review-dialog/index.d.ts +2 -1
  37. package/package.json +35 -29
  38. package/src/components/shared/Button/button.tsx +11 -18
  39. package/src/components/shared/Card/card.tsx +8 -8
  40. package/src/components/ui/agent-response/agent-response.tsx +4 -4
  41. package/src/components/ui/image-attachment.tsx +8 -8
  42. package/src/components/ui/image-preview-dialog.tsx +41 -41
  43. package/src/components/ui/index.ts +0 -1
  44. package/src/core/AblyService.ts +60 -23
  45. package/src/core/api.ts +9 -7
  46. package/src/globals.css +216 -50
  47. package/src/lib/custom-hooks/useActionHandler.ts +102 -0
  48. package/src/lib/index.ts +1 -0
  49. package/src/lib/theme-utils.ts +1 -33
  50. package/src/lib/types.ts +7 -4
  51. package/src/locales/ar.json +16 -6
  52. package/src/locales/en.json +16 -6
  53. package/src/types/icons.d.ts +6 -0
  54. package/src/ui/chatbot-popup/active-chat-actions.tsx +39 -0
  55. package/src/ui/chatbot-popup/chat-window-screen/action-button.tsx +37 -0
  56. package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +42 -43
  57. package/src/ui/chatbot-popup/chat-window-screen/header.tsx +34 -67
  58. package/src/ui/chatbot-popup/chat-window-screen/in-chat-review.tsx +83 -0
  59. package/src/ui/chatbot-popup/chat-window-screen/index.tsx +49 -42
  60. package/src/ui/chatbot-popup/chat-window-screen/typing-indicator.tsx +27 -0
  61. package/src/ui/chatbot-popup/error-screen/index.tsx +7 -7
  62. package/src/ui/chatbot-popup/loading-screen/index.tsx +6 -17
  63. package/src/ui/chatbot-popup/options-list-screen/company-card.tsx +37 -0
  64. package/src/ui/chatbot-popup/options-list-screen/header.tsx +12 -31
  65. package/src/ui/chatbot-popup/options-list-screen/helpscreen-intro.tsx +32 -0
  66. package/src/ui/chatbot-popup/options-list-screen/helpscreen-list.tsx +48 -0
  67. package/src/ui/chatbot-popup/options-list-screen/helpscreen-option.tsx +38 -0
  68. package/src/ui/chatbot-popup/options-list-screen/index.tsx +44 -38
  69. package/src/ui/confirmation-modal/index.tsx +27 -12
  70. package/src/ui/floating-message.tsx +8 -7
  71. package/src/ui/help-button.tsx +5 -5
  72. package/src/ui/help-center.tsx +95 -58
  73. package/src/ui/help-popup.tsx +114 -91
  74. package/src/ui/powered-by.tsx +49 -7
  75. package/src/ui/review-dialog/index.tsx +48 -65
  76. package/src/ui/review-dialog/rating.tsx +7 -7
  77. package/dist/components/ui/header.d.ts +0 -6
  78. package/dist/ui/chatbot-popup/home-screen/card.d.ts +0 -6
  79. package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +0 -5
  80. package/dist/ui/chatbot-popup/home-screen/index.d.ts +0 -7
  81. package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +0 -7
  82. package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +0 -5
  83. package/src/.DS_Store +0 -0
  84. package/src/assets/icons/arrowRight.svg +0 -3
  85. package/src/assets/icons/chat.svg +0 -4
  86. package/src/assets/icons/close.svg +0 -1
  87. package/src/assets/icons/closeCircle.svg +0 -3
  88. package/src/assets/icons/closeCirclePrimary.svg +0 -4
  89. package/src/assets/icons/envelope.svg +0 -3
  90. package/src/assets/icons/paperclip.svg +0 -3
  91. package/src/assets/icons/threeDots.svg +0 -3
  92. package/src/assets/icons/user.svg +0 -3
  93. package/src/assets/icons/x.svg +0 -4
  94. package/src/assets/logoColors.svg +0 -5
  95. package/src/assets/logo_ai.svg +0 -14
  96. package/src/assets/thinking-logo.svg +0 -3
  97. package/src/components/ui/header.tsx +0 -22
  98. package/src/ui/chatbot-popup/home-screen/card.tsx +0 -33
  99. package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +0 -36
  100. package/src/ui/chatbot-popup/home-screen/index.tsx +0 -44
  101. package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +0 -37
  102. package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +0 -31
  103. /package/src/assets/{icons/seperator.svg → seperator.svg} +0 -0
@@ -1,5 +1,4 @@
1
- import ReviewDialog from '@/ui/review-dialog';
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 { getThemeStyles } from '@/lib/theme-utils';
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: string;
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
- secondaryColor,
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
- attachments: string[] = []
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
- // Ably now returns downloadUrls directly, not file IDs
87
- ...(attachments.length > 0 && { attachmentUrls: attachments }),
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 = async () => {
97
- if (!sessionId || !selectedOption) return;
96
+ const handleEndChat = useCallback(
97
+ async (options?: { fromChatScreen?: boolean }) => {
98
+ if (!sessionId || !selectedOption) return;
98
99
 
99
- try {
100
- await ClientAblyService.stopConnection();
101
- setIsAblyConnected(false);
102
- setAssistantStatus('idle');
100
+ const fromChatScreen = options?.fromChatScreen === true;
103
101
 
104
- const response = await apiRequest(`Client/ClientChatSession/${sessionId}/close`, 'POST', null, {
105
- language: language,
106
- });
107
- if (!response.ok) throw new Error('Failed to close chat session');
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
- setIsReviewDialogOpen(true);
118
- } catch (error) {
119
- setError('Failed to end chat session');
120
- setAssistantStatus('idle');
121
- // Even if there's an error, clear the session state to prevent stuck state
122
- setReviewSessionId(sessionId);
123
- setSessionId(null);
124
- setSelectedOption(null);
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
- } catch (error) {
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 = getThemeStyles({ primaryColor, secondaryColor });
359
+ const themeStyles = getPrimaryColorStyles(primaryColor);
321
360
 
322
361
  return (
323
- <div className='babylai-help-center-container mb-4' style={themeStyles}>
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
- showHelpScreen={showHelpScreen}
351
- logoUrl={logoUrl}
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
  );
@@ -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 ChatIcon from '../assets/icons/chat.svg';
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 PoweredBy from './powered-by';
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: any;
19
+ user: unknown;
23
20
  onStartChat: (option: Option) => void;
24
21
  onSendMessage: (message: string, attachmentIds: string[]) => void;
25
22
  onEnsureSession: () => Promise<string>;
26
- onEndChat: (option?: Option) => void;
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
- showHelpScreen: boolean;
36
- logoUrl?: string;
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
- showHelpScreen,
55
- isAblyConnected,
56
- logoUrl,
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 handleEndChat()
135
- .then(() => {
136
- setShowChat(true);
137
- onStartChat(tempSelectedOption);
138
- setSelectedOption(tempSelectedOption);
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 handleEndChat = async () => {
152
+ const handleEndChatFromChatScreen = useCallback(async () => {
147
153
  setEndChatConfirmation(false);
148
- await onEndChat();
149
- setShowChat(false);
150
- setSelectedOption(null);
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
- onClose={onClose}
166
- isShowList={isShowList}
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
- if (isShowList) {
185
- return (
186
- <OptionsListScreen
187
- helpScreen={helpScreen}
188
- expandedOption={expandedOption}
189
- setExpandedOption={setExpandedOption}
190
- handleStartChat={handleStartChat}
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
- showHelpScreen,
215
- isAblyConnected,
216
- logoUrl,
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={handleEndChat}
237
+ onConfirm={handleEndChatFromChatScreen}
229
238
  />
230
239
  );
231
- }, [endChatConfirmation, t, hideEndChatConfirmation, handleEndChat]);
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
- <Button
239
- variant='rounded-icon'
240
- size='icon'
241
- className='!babylai-bg-primary-500 babylai-absolute babylai-bottom-4 babylai-right-3 babylai-z-20 !babylai-w-10 !babylai-h-10 babylai-p-2'
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-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
263
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
264
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
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 isShowList={isShowList} onClose={onClose} logoUrl={logoUrl} />
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-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
275
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
276
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
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 || ''} logoUrl={logoUrl} />
301
+ <ChatBotErrorScreen onClose={onClose} error={error || ''} />
279
302
  </div>
280
303
  );
281
304
  }
282
305
 
283
306
  return (
284
307
  <div
285
- className='babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-h-[calc(100vh-220px)] babylai-max-h-[800px]
286
- babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
287
- md:babylai-bottom-[6rem] md:babylai-right-4 babylai-rounded-none md:babylai-rounded-3xl babylai-shadow-lg babylai-z-50 babylai-flex babylai-flex-col'
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
  );