@aslaluroba/help-center-react 2.0.4 → 2.0.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 (38) hide show
  1. package/dist/core/api.d.ts +4 -1
  2. package/dist/index.d.ts +3 -2
  3. package/dist/index.esm.js +994 -25294
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +995 -25295
  6. package/dist/index.js.map +1 -1
  7. package/dist/lib/config.d.ts +1 -1
  8. package/dist/lib/types.d.ts +4 -0
  9. package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +1 -0
  10. package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +1 -1
  11. package/dist/ui/help-center.d.ts +1 -1
  12. package/dist/ui/help-popup.d.ts +9 -3
  13. package/dist/ui/review-dialog/index.d.ts +8 -0
  14. package/dist/ui/review-dialog/rating.d.ts +12 -0
  15. package/package.json +26 -5
  16. package/src/assets/icons/arrowRight.svg +1 -1
  17. package/src/assets/icons/closeCircle.svg +1 -1
  18. package/src/components/ui/agent-response/agent-response.tsx +36 -34
  19. package/src/components/ui/header.tsx +2 -3
  20. package/src/core/SignalRService.ts +25 -25
  21. package/src/core/api.ts +180 -44
  22. package/src/globals.css +0 -9
  23. package/src/index.ts +3 -2
  24. package/src/lib/config.ts +25 -25
  25. package/src/lib/types.ts +5 -0
  26. package/src/locales/ar.json +18 -1
  27. package/src/locales/en.json +26 -8
  28. package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +31 -33
  29. package/src/ui/chatbot-popup/chat-window-screen/header.tsx +47 -53
  30. package/src/ui/chatbot-popup/chat-window-screen/index.tsx +182 -88
  31. package/src/ui/chatbot-popup/options-list-screen/header.tsx +24 -20
  32. package/src/ui/chatbot-popup/options-list-screen/index.tsx +24 -24
  33. package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +9 -4
  34. package/src/ui/help-center.tsx +189 -159
  35. package/src/ui/help-popup.tsx +241 -165
  36. package/src/ui/review-dialog/index.tsx +106 -0
  37. package/src/ui/review-dialog/rating.tsx +78 -0
  38. package/tsconfig.json +48 -0
@@ -1,26 +1,27 @@
1
- import React, { useState, useEffect } from 'react'
2
- import { HelpButton } from './help-button'
3
- import { FloatingMessage } from './floating-message'
4
- import { HelpPopup } from './help-popup'
5
- import { apiRequest } from '../core/api'
6
- import { ClientSignalRService } from '../core/SignalRService'
7
- import { Message, HelpScreenData, Option } from '../lib/types'
8
- import { configService } from '../lib/config'
9
- import { useLocalTranslation } from '../useLocalTranslation'
10
- import '../globals.css'
1
+ import ReviewDialog from '@/ui/review-dialog';
2
+ import React, { useEffect, useState } from 'react';
3
+ import { apiRequest } from '../core/api';
4
+ import { ClientSignalRService } from '../core/SignalRService';
5
+ import { configService } from '../lib/config';
6
+ import { useLocalTranslation } from '../useLocalTranslation';
7
+ import '../globals.css';
8
+ import { HelpScreenData, Message, Option, ReviewProps } from '../lib/types';
9
+ import { FloatingMessage } from './floating-message';
10
+ import { HelpButton } from './help-button';
11
+ import { HelpPopup } from './help-popup';
11
12
 
12
13
  interface HelpCenterProps {
13
- helpScreenId: string
14
- language: string
14
+ helpScreenId: string;
15
+ language: string;
15
16
  user?: {
16
- id?: string
17
- name?: string
18
- email?: string
19
- avatar?: string
20
- }
21
- showArrow?: boolean
22
- messageLabel?: string | null
23
- showHelpScreen?: boolean
17
+ id?: string;
18
+ name?: string;
19
+ email?: string;
20
+ avatar?: string;
21
+ };
22
+ showArrow?: boolean;
23
+ messageLabel?: string | null;
24
+ showHelpScreen?: boolean;
24
25
  }
25
26
 
26
27
  export function HelpCenter({
@@ -29,93 +30,113 @@ export function HelpCenter({
29
30
  showArrow = true,
30
31
  language = 'en',
31
32
  messageLabel = null,
32
- showHelpScreen = false
33
+ showHelpScreen = false,
33
34
  }: HelpCenterProps) {
34
- const { t } = useLocalTranslation(language)
35
- const [isOpen, setIsOpen] = useState(false)
36
- const [showArrowAnimation, setShowArrowAnimation] = useState(showArrow)
37
- const [helpScreenData, setHelpScreenData] = useState<HelpScreenData | null>(null)
38
- const [status, setStatus] = useState('idle')
39
- const [error, setError] = useState('')
40
- const [selectedOption, setSelectedOption] = useState<Option | null>(null)
41
-
42
- const [sessionId, setSessionId] = useState<string | null>(null)
43
- const [isSignalRConnected, setIsSignalRConnected] = useState(false)
44
- const [isChatClosed, setIsChatClosed] = useState(false)
45
- const [messages, setMessages] = useState<Message[]>([])
46
- const [needsAgent, setNeedsAgent] = useState(false)
47
- const [assistantStatus, setAssistantStatus] = useState('idle')
35
+ const { t } = useLocalTranslation(language);
36
+ const [isOpen, setIsOpen] = useState(false);
37
+ const [showArrowAnimation, setShowArrowAnimation] = useState(showArrow);
38
+ const [helpScreenData, setHelpScreenData] = useState<HelpScreenData | null>(null);
39
+ const [status, setStatus] = useState('idle');
40
+ const [error, setError] = useState('');
41
+ const [selectedOption, setSelectedOption] = useState<Option | null>(null);
42
+
43
+ const [sessionId, setSessionId] = useState<string | null>(null);
44
+ const [isSignalRConnected, setIsSignalRConnected] = useState(false);
45
+ const [isChatClosed, setIsChatClosed] = useState(false);
46
+ const [messages, setMessages] = useState<Message[]>([]);
47
+ const [needsAgent, setNeedsAgent] = useState(false);
48
+ const [assistantStatus, setAssistantStatus] = useState('idle');
49
+
50
+ const [isReviewDialogOpen, setIsReviewDialogOpen] = useState(false);
48
51
 
49
52
  const handleTogglePopup = () => {
50
- setIsOpen(!isOpen)
51
- setShowArrowAnimation(isOpen)
52
- }
53
+ setIsOpen(!isOpen);
54
+ setShowArrowAnimation(isOpen);
55
+ };
53
56
 
54
57
  const handleCloseArrowAnimation = () => {
55
- setShowArrowAnimation(false)
56
- }
58
+ setShowArrowAnimation(false);
59
+ };
57
60
 
58
61
  const handleReceiveMessage = (message: string, senderType: number, needsAgent: boolean) => {
59
- // Update agent status if needed
60
62
  if (needsAgent) {
61
- setNeedsAgent(true)
63
+ setNeedsAgent(true);
62
64
  }
63
65
 
64
- // Add the received message to the chat
65
- setMessages((prevMessages) => [
66
- ...prevMessages,
67
- {
66
+ setMessages((prevMessages) => {
67
+ const newMessage = {
68
68
  id: Date.now(),
69
69
  senderType: senderType,
70
70
  messageContent: message,
71
71
  sentAt: new Date(),
72
- isSeen: true
73
- }
74
- ])
72
+ isSeen: true,
73
+ };
74
+
75
+ const updatedMessages = [...prevMessages, newMessage];
76
+
77
+ return updatedMessages;
78
+ });
75
79
 
76
- // Reset assistant status after receiving message
77
- setAssistantStatus('idle')
78
- }
80
+ setAssistantStatus('idle');
81
+ };
79
82
 
80
- const handleEndChat = async () => {
81
- if (!sessionId || !selectedOption) return
83
+ const handleEndChat = async (option?: Option) => {
84
+ if (!sessionId || !selectedOption) return;
82
85
 
83
86
  try {
84
- // Disconnect SignalR
85
- await ClientSignalRService.stopConnection()
86
- setIsSignalRConnected(false)
87
+ await ClientSignalRService.stopConnection();
88
+ setIsSignalRConnected(false);
89
+ setAssistantStatus('idle');
87
90
 
88
- // Close chat session
89
- const response = await apiRequest(`Client/ClientChatSession/${sessionId}/close`, 'POST')
90
- if (!response.ok) {
91
- throw new Error('Failed to close chat session')
91
+ const response = await apiRequest(`Client/ClientChatSession/${sessionId}/close`, 'POST');
92
+ if (!response.ok) throw new Error('Failed to close chat session');
93
+
94
+ setIsReviewDialogOpen(true);
95
+ if (option) {
96
+ handleStartChat(option);
92
97
  }
98
+ } catch (error) {
99
+ console.error('Error ending chat:', error);
100
+ setError('Failed to end chat session');
101
+ setAssistantStatus('idle');
102
+ }
103
+ };
104
+
105
+ const handleSendChatReview = async ({ comment, rating }: ReviewProps) => {
106
+ if (!sessionId) return;
107
+
108
+ const payload = { rating, comment };
93
109
 
94
- setSessionId(null)
95
- setIsChatClosed(true)
110
+ try {
111
+ const response = await apiRequest(`Client/ClientChatSession/${sessionId}/review`, 'POST', payload);
112
+ if (!response.ok) throw new Error('Failed to send chat review');
96
113
 
97
- // Clear messages after a delay
98
- setTimeout(() => {
99
- setMessages([])
100
- setSelectedOption(null)
101
- }, 3000)
114
+ setIsReviewDialogOpen(false);
102
115
  } catch (error) {
103
- console.error('Error ending chat:', error)
104
- setError('Failed to end chat session')
116
+ console.error('Error sending chat review:', error);
117
+ setError('Failed to send chat review');
105
118
  }
106
- }
119
+ };
120
+
121
+ const handleCloseChatReview = () => {
122
+ setIsReviewDialogOpen(false);
123
+ };
107
124
 
108
125
  const handleStartChat = async (option: Option) => {
109
- await startNewChatSession(option)
110
- }
126
+ await startNewChatSession(option);
127
+ };
111
128
 
112
129
  const startNewChatSession = async (option: Option) => {
130
+ if (isSignalRConnected || sessionId) {
131
+ handleEndChat();
132
+ }
113
133
  try {
114
- setStatus('loading')
115
- setError('')
116
- setMessages([])
134
+ setStatus('loading');
135
+ setError('');
136
+ setMessages([]);
137
+
138
+ const tokenResponse = await configService.getToken();
117
139
 
118
- const tokenResponse = await configService.getToken()
119
140
  const chatSessionCreateDto = {
120
141
  helpScreenId: helpScreenId,
121
142
  optionId: option.id,
@@ -123,79 +144,82 @@ export function HelpCenter({
123
144
  user: {
124
145
  id: user.id,
125
146
  name: user.name,
126
- email: user.email
127
- }
128
- })
129
- }
147
+ email: user.email,
148
+ },
149
+ }),
150
+ };
130
151
 
131
- const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto)
152
+ const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto);
132
153
 
133
154
  if (!response.ok) {
134
- throw new Error('Failed to create chat session')
155
+ throw new Error('Failed to create chat session');
135
156
  }
136
157
 
137
- const createdSession = await response.json()
158
+ const createdSession = await response.json();
138
159
 
139
- setSessionId(createdSession.id)
160
+ setSessionId(createdSession.id);
140
161
 
141
- // Add greeting message if available
142
162
  if (option.assistant?.greeting) {
143
163
  setMessages([
144
164
  {
145
165
  id: Date.now(),
146
- senderType: 3, // AI
166
+ senderType: 3,
147
167
  messageContent: option.assistant.greeting,
148
168
  sentAt: new Date(),
149
- isSeen: true
150
- }
151
- ])
169
+ isSeen: true,
170
+ },
171
+ ]);
152
172
  } else {
153
- // Default greeting if none provided
154
173
  setMessages([
155
174
  {
156
175
  id: Date.now(),
157
176
  senderType: 3,
158
177
  messageContent: 'Hello! How can I assist you today?\nمرحباً! كيف يمكنني مساعدتك اليوم؟',
159
178
  sentAt: new Date(),
160
- isSeen: true
161
- }
162
- ])
179
+ isSeen: true,
180
+ },
181
+ ]);
163
182
  }
164
183
 
165
- // Connect to SignalR
166
- await ClientSignalRService.startConnection(createdSession.id, tokenResponse, handleReceiveMessage)
184
+ await ClientSignalRService.startConnection(createdSession.id, tokenResponse, handleReceiveMessage);
185
+
186
+ // Verify the connection is actually active
187
+ if (!ClientSignalRService.isConnectionActive()) {
188
+ throw new Error('SignalR connection failed to establish properly');
189
+ }
167
190
 
168
- setIsSignalRConnected(true)
169
- setIsChatClosed(false)
170
- setStatus('succeeded')
191
+ setIsSignalRConnected(true);
192
+ setIsChatClosed(false);
193
+ setStatus('succeeded');
171
194
  } catch (error) {
172
- console.error('Chat start error:', error)
173
- setError(error instanceof Error ? error.message : 'Failed to start chat session')
174
- setStatus('failed')
195
+ setError(error instanceof Error ? error.message : 'Failed to start chat session');
196
+ setStatus('failed');
175
197
  }
176
- }
198
+ };
177
199
 
178
200
  const handleSendMessage = async (message: string) => {
179
- let currentSessionId = sessionId
201
+ // Only send message if SignalR is connected
202
+ if (!isSignalRConnected) {
203
+ setError('Connection lost. Please try again.');
204
+ return;
205
+ }
206
+
207
+ let currentSessionId = sessionId;
180
208
 
181
209
  if (message.trim() !== '') {
182
210
  try {
183
- // Set loading state
184
- setAssistantStatus('typing')
211
+ setAssistantStatus('typing');
185
212
 
186
- // Add user message to the chat immediately
187
- setMessages((prevMessages) => [
188
- ...prevMessages,
189
- {
190
- id: Date.now(),
191
- senderType: 1, // Customer
192
- messageContent: message,
193
- sentAt: new Date(),
194
- isSeen: false
195
- }
196
- ])
213
+ const userMessage = {
214
+ id: Date.now(),
215
+ senderType: 1,
216
+ messageContent: message,
217
+ sentAt: new Date(),
218
+ isSeen: false,
219
+ };
220
+
221
+ setMessages((prevMessages) => [...prevMessages, userMessage]);
197
222
 
198
- // Create a new chat session if not started yet
199
223
  if (!currentSessionId) {
200
224
  const chatSessionCreateDto = {
201
225
  helpScreenId: helpScreenId,
@@ -203,73 +227,76 @@ export function HelpCenter({
203
227
  user: {
204
228
  id: user?.id,
205
229
  name: user?.name,
206
- email: user?.email
207
- }
208
- }
230
+ email: user?.email,
231
+ },
232
+ };
209
233
 
210
- const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto)
234
+ const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto);
211
235
 
212
236
  if (!response.ok) {
213
- throw new Error('Failed to create chat session')
237
+ throw new Error('Failed to create chat session');
214
238
  }
215
239
 
216
- const createdSession = await response.json()
217
- setSessionId(createdSession.id)
218
- currentSessionId = createdSession.id
240
+ const createdSession = await response.json();
241
+ setSessionId(createdSession.id);
242
+ currentSessionId = createdSession.id;
219
243
 
220
- // Connect to SignalR with the new session
221
- const tokenResponse = await configService.getToken()
222
- await ClientSignalRService.startConnection(createdSession.id, tokenResponse, handleReceiveMessage)
223
- setIsSignalRConnected(true)
244
+ const tokenResponse = await configService.getToken();
245
+ await ClientSignalRService.startConnection(createdSession.id, tokenResponse, handleReceiveMessage);
246
+ setIsSignalRConnected(true);
224
247
  }
225
248
 
226
- // Send the message
227
- const messageDto = { messageContent: message }
228
- const response = await apiRequest(`Client/ClientChatSession/${currentSessionId}/send-message`, 'POST', messageDto)
249
+ const messageDto = { messageContent: message };
250
+
251
+ const response = await apiRequest(
252
+ `Client/ClientChatSession/${currentSessionId}/send-message`,
253
+ 'POST',
254
+ messageDto
255
+ );
229
256
 
230
257
  if (!response.ok) {
231
- throw new Error('Failed to send message')
258
+ throw new Error('Failed to send message');
232
259
  }
233
260
 
234
- // Update the sent message as seen
235
- setMessages((prevMessages) => prevMessages.map((msg) => (msg.senderType === 1 && !msg.isSeen ? { ...msg, isSeen: true } : msg)))
261
+ setMessages((prevMessages) =>
262
+ prevMessages.map((msg) => (msg.senderType === 1 && !msg.isSeen ? { ...msg, isSeen: true } : msg))
263
+ );
236
264
  } catch (error) {
237
- console.error('Error in message handling:', error)
238
- setAssistantStatus('idle')
239
- setMessages((prevMessages) => [
240
- ...prevMessages,
241
- {
242
- id: Date.now(),
243
- senderType: 3, // System
244
- messageContent: 'Failed to send the message. Please try again.\n لم يتم إرسال الرسالة. يرجى المحاولة مرة أخرى.',
245
- sentAt: new Date(),
246
- isSeen: true
247
- }
248
- ])
265
+ setAssistantStatus('idle');
266
+ const errorMessage = {
267
+ id: Date.now(),
268
+ senderType: 3,
269
+ messageContent:
270
+ 'Failed to send the message. Please try again.\n لم يتم إرسال الرسالة. يرجى المحاولة مرة أخرى.',
271
+ sentAt: new Date(),
272
+ isSeen: true,
273
+ };
274
+
275
+ setMessages((prevMessages) => [...prevMessages, errorMessage]);
249
276
  }
250
277
  }
251
- }
278
+ };
252
279
 
253
280
  useEffect(() => {
254
281
  if (isOpen && helpScreenId) {
255
- setStatus('loading')
282
+ setStatus('loading');
256
283
 
257
284
  apiRequest(`client/clientHelpScreen/${helpScreenId}`)
258
285
  .then((res) => res.json())
259
286
  .then((data) => {
260
- setHelpScreenData(data)
261
- setStatus('succeeded')
262
- setError('')
287
+ setHelpScreenData(data);
288
+ setStatus('succeeded');
289
+ setError('');
263
290
  })
264
291
  .catch((err) => {
265
- setError(err.message)
266
- setStatus('failed')
267
- })
292
+ setError(err.message);
293
+ setStatus('failed');
294
+ });
268
295
  }
269
- }, [isOpen, helpScreenId])
296
+ }, [isOpen, helpScreenId]);
270
297
 
271
298
  return (
272
- <div className="babylai-help-center-container mb-4">
299
+ <div className='babylai-help-center-container mb-4'>
273
300
  {showArrowAnimation && !isOpen && (
274
301
  <FloatingMessage onClose={handleCloseArrowAnimation} message={messageLabel || t('homeSdk.needAssistance')} />
275
302
  )}
@@ -298,6 +325,9 @@ export function HelpCenter({
298
325
  showHelpScreen={showHelpScreen}
299
326
  />
300
327
  )}
328
+ {isOpen && !!isReviewDialogOpen && (
329
+ <ReviewDialog handleSubmit={handleSendChatReview} onClose={handleCloseChatReview} />
330
+ )}
301
331
  </div>
302
- )
332
+ );
303
333
  }