@aslaluroba/help-center-react 1.0.1
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 +176 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/shared/Button/button.d.ts +11 -0
- package/dist/components/shared/Button/index.d.ts +1 -0
- package/dist/components/shared/Card/card.d.ts +11 -0
- package/dist/components/shared/Card/index.d.ts +1 -0
- package/dist/components/shared/index.d.ts +2 -0
- package/dist/components/ui/agent-response/agent-response.d.ts +9 -0
- package/dist/components/ui/header.d.ts +6 -0
- package/dist/core/ApiService.d.ts +16 -0
- package/dist/core/SignalRService.d.ts +11 -0
- package/dist/core/api.d.ts +4 -0
- package/dist/core/token-service.d.ts +10 -0
- package/dist/i18n.d.ts +2 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.esm.js +26076 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +26110 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/custom-hooks/useTypewriter.d.ts +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/types.d.ts +111 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/ui/chatbot-popup/chat-window-screen/footer.d.ts +9 -0
- package/dist/ui/chatbot-popup/chat-window-screen/header.d.ts +11 -0
- package/dist/ui/chatbot-popup/chat-window-screen/index.d.ts +10 -0
- package/dist/ui/chatbot-popup/error-screen/index.d.ts +7 -0
- package/dist/ui/chatbot-popup/home-screen/card.d.ts +7 -0
- package/dist/ui/chatbot-popup/home-screen/chat-now-card.d.ts +6 -0
- package/dist/ui/chatbot-popup/home-screen/index.d.ts +7 -0
- package/dist/ui/chatbot-popup/loading-screen/index.d.ts +7 -0
- package/dist/ui/chatbot-popup/options-list-screen/expanded-option.d.ts +8 -0
- package/dist/ui/chatbot-popup/options-list-screen/header.d.ts +7 -0
- package/dist/ui/chatbot-popup/options-list-screen/index.d.ts +12 -0
- package/dist/ui/chatbot-popup/options-list-screen/option-card.d.ts +6 -0
- package/dist/ui/floating-message.d.ts +7 -0
- package/dist/ui/help-button.d.ts +6 -0
- package/dist/ui/help-center.d.ts +17 -0
- package/dist/ui/help-popup.d.ts +24 -0
- package/dist/useLocalTranslation.d.ts +5 -0
- package/package.json +86 -0
- package/src/assets/animatedLogo.gif +0 -0
- package/src/assets/icons/arrowRight.svg +3 -0
- package/src/assets/icons/chat.svg +4 -0
- package/src/assets/icons/close.svg +1 -0
- package/src/assets/icons/closeCircle.svg +3 -0
- package/src/assets/icons/closeCirclePrimary.svg +3 -0
- package/src/assets/icons/envelope.svg +3 -0
- package/src/assets/icons/seperator.svg +5 -0
- package/src/assets/icons/threeDots.svg +3 -0
- package/src/assets/icons/user.svg +3 -0
- package/src/assets/logo.svg +5 -0
- package/src/assets/logoColors.svg +5 -0
- package/src/assets/logo_ai.svg +14 -0
- package/src/assets/thinking-logo.svg +3 -0
- package/src/components/index.ts +1 -0
- package/src/components/shared/Button/button.tsx +46 -0
- package/src/components/shared/Button/index.ts +1 -0
- package/src/components/shared/Card/card.tsx +44 -0
- package/src/components/shared/Card/index.ts +1 -0
- package/src/components/shared/index.ts +2 -0
- package/src/components/ui/agent-response/agent-response.tsx +47 -0
- package/src/components/ui/agent-response/doc.md +88 -0
- package/src/components/ui/header.tsx +17 -0
- package/src/components/ui/index.ts +0 -0
- package/src/core/ApiService.ts +118 -0
- package/src/core/SignalRService.ts +83 -0
- package/src/core/api.ts +71 -0
- package/src/core/token-service.ts +35 -0
- package/src/globals.css +484 -0
- package/src/i18n.ts +17 -0
- package/src/index.ts +21 -0
- package/src/lib/config.ts +59 -0
- package/src/lib/custom-hooks/useTypewriter.ts +24 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/types.ts +120 -0
- package/src/lib/utils.ts +6 -0
- package/src/locales/ar.json +13 -0
- package/src/locales/en.json +15 -0
- package/src/styles/tailwind.css +4 -0
- package/src/types/svg.d.ts +5 -0
- package/src/types.d.ts +9 -0
- package/src/ui/chatbot-popup/chat-window-screen/footer.tsx +42 -0
- package/src/ui/chatbot-popup/chat-window-screen/header.tsx +64 -0
- package/src/ui/chatbot-popup/chat-window-screen/index.tsx +103 -0
- package/src/ui/chatbot-popup/error-screen/index.tsx +22 -0
- package/src/ui/chatbot-popup/home-screen/card.tsx +34 -0
- package/src/ui/chatbot-popup/home-screen/chat-now-card.tsx +36 -0
- package/src/ui/chatbot-popup/home-screen/index.tsx +44 -0
- package/src/ui/chatbot-popup/loading-screen/index.tsx +33 -0
- package/src/ui/chatbot-popup/options-list-screen/expanded-option.tsx +38 -0
- package/src/ui/chatbot-popup/options-list-screen/header.tsx +38 -0
- package/src/ui/chatbot-popup/options-list-screen/index.tsx +59 -0
- package/src/ui/chatbot-popup/options-list-screen/option-card.tsx +20 -0
- package/src/ui/floating-message.tsx +25 -0
- package/src/ui/help-button.tsx +22 -0
- package/src/ui/help-center.tsx +303 -0
- package/src/ui/help-popup.tsx +264 -0
- package/src/useLocalTranslation.ts +14 -0
|
@@ -0,0 +1,303 @@
|
|
|
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'
|
|
11
|
+
|
|
12
|
+
interface HelpCenterProps {
|
|
13
|
+
helpScreenId: string
|
|
14
|
+
language: string
|
|
15
|
+
user?: {
|
|
16
|
+
id?: string
|
|
17
|
+
name?: string
|
|
18
|
+
email?: string
|
|
19
|
+
avatar?: string
|
|
20
|
+
}
|
|
21
|
+
showArrow?: boolean
|
|
22
|
+
messageLabel?: string | null
|
|
23
|
+
showHelpScreen?: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function HelpCenter({
|
|
27
|
+
helpScreenId,
|
|
28
|
+
user,
|
|
29
|
+
showArrow = true,
|
|
30
|
+
language = 'en',
|
|
31
|
+
messageLabel = null,
|
|
32
|
+
showHelpScreen = false
|
|
33
|
+
}: 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')
|
|
48
|
+
|
|
49
|
+
const handleTogglePopup = () => {
|
|
50
|
+
setIsOpen(!isOpen)
|
|
51
|
+
setShowArrowAnimation(isOpen)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleCloseArrowAnimation = () => {
|
|
55
|
+
setShowArrowAnimation(false)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const handleReceiveMessage = (message: string, senderType: number, needsAgent: boolean) => {
|
|
59
|
+
// Update agent status if needed
|
|
60
|
+
if (needsAgent) {
|
|
61
|
+
setNeedsAgent(true)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add the received message to the chat
|
|
65
|
+
setMessages((prevMessages) => [
|
|
66
|
+
...prevMessages,
|
|
67
|
+
{
|
|
68
|
+
id: Date.now(),
|
|
69
|
+
senderType: senderType,
|
|
70
|
+
messageContent: message,
|
|
71
|
+
sentAt: new Date(),
|
|
72
|
+
isSeen: true
|
|
73
|
+
}
|
|
74
|
+
])
|
|
75
|
+
|
|
76
|
+
// Reset assistant status after receiving message
|
|
77
|
+
setAssistantStatus('idle')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const handleEndChat = async () => {
|
|
81
|
+
if (!sessionId || !selectedOption) return
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
// Disconnect SignalR
|
|
85
|
+
await ClientSignalRService.stopConnection()
|
|
86
|
+
setIsSignalRConnected(false)
|
|
87
|
+
|
|
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')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
setSessionId(null)
|
|
95
|
+
setIsChatClosed(true)
|
|
96
|
+
|
|
97
|
+
// Clear messages after a delay
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
setMessages([])
|
|
100
|
+
setSelectedOption(null)
|
|
101
|
+
}, 3000)
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('Error ending chat:', error)
|
|
104
|
+
setError('Failed to end chat session')
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const handleStartChat = async (option: Option) => {
|
|
109
|
+
await startNewChatSession(option)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const startNewChatSession = async (option: Option) => {
|
|
113
|
+
try {
|
|
114
|
+
setStatus('loading')
|
|
115
|
+
setError('')
|
|
116
|
+
setMessages([])
|
|
117
|
+
|
|
118
|
+
const tokenResponse = await configService.getToken()
|
|
119
|
+
const chatSessionCreateDto = {
|
|
120
|
+
helpScreenId: helpScreenId,
|
|
121
|
+
optionId: option.id,
|
|
122
|
+
...(user && {
|
|
123
|
+
user: {
|
|
124
|
+
id: user.id,
|
|
125
|
+
name: user.name,
|
|
126
|
+
email: user.email
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto)
|
|
132
|
+
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
throw new Error('Failed to create chat session')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const createdSession = await response.json()
|
|
138
|
+
|
|
139
|
+
setSessionId(createdSession.id)
|
|
140
|
+
|
|
141
|
+
// Add greeting message if available
|
|
142
|
+
if (option.assistant?.greeting) {
|
|
143
|
+
setMessages([
|
|
144
|
+
{
|
|
145
|
+
id: Date.now(),
|
|
146
|
+
senderType: 3, // AI
|
|
147
|
+
messageContent: option.assistant.greeting,
|
|
148
|
+
sentAt: new Date(),
|
|
149
|
+
isSeen: true
|
|
150
|
+
}
|
|
151
|
+
])
|
|
152
|
+
} else {
|
|
153
|
+
// Default greeting if none provided
|
|
154
|
+
setMessages([
|
|
155
|
+
{
|
|
156
|
+
id: Date.now(),
|
|
157
|
+
senderType: 3,
|
|
158
|
+
messageContent: 'Hello! How can I assist you today?\nمرحباً! كيف يمكنني مساعدتك اليوم؟',
|
|
159
|
+
sentAt: new Date(),
|
|
160
|
+
isSeen: true
|
|
161
|
+
}
|
|
162
|
+
])
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Connect to SignalR
|
|
166
|
+
await ClientSignalRService.startConnection(createdSession.id, tokenResponse, handleReceiveMessage)
|
|
167
|
+
|
|
168
|
+
setIsSignalRConnected(true)
|
|
169
|
+
setIsChatClosed(false)
|
|
170
|
+
setStatus('succeeded')
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('Chat start error:', error)
|
|
173
|
+
setError(error instanceof Error ? error.message : 'Failed to start chat session')
|
|
174
|
+
setStatus('failed')
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const handleSendMessage = async (message: string) => {
|
|
179
|
+
let currentSessionId = sessionId
|
|
180
|
+
|
|
181
|
+
if (message.trim() !== '') {
|
|
182
|
+
try {
|
|
183
|
+
// Set loading state
|
|
184
|
+
setAssistantStatus('typing')
|
|
185
|
+
|
|
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
|
+
])
|
|
197
|
+
|
|
198
|
+
// Create a new chat session if not started yet
|
|
199
|
+
if (!currentSessionId) {
|
|
200
|
+
const chatSessionCreateDto = {
|
|
201
|
+
helpScreenId: helpScreenId,
|
|
202
|
+
optionId: selectedOption?.id,
|
|
203
|
+
user: {
|
|
204
|
+
id: user?.id,
|
|
205
|
+
name: user?.name,
|
|
206
|
+
email: user?.email
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const response = await apiRequest('Client/ClientChatSession/create-session', 'POST', chatSessionCreateDto)
|
|
211
|
+
|
|
212
|
+
if (!response.ok) {
|
|
213
|
+
throw new Error('Failed to create chat session')
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const createdSession = await response.json()
|
|
217
|
+
setSessionId(createdSession.id)
|
|
218
|
+
currentSessionId = createdSession.id
|
|
219
|
+
|
|
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)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Send the message
|
|
227
|
+
const messageDto = { messageContent: message }
|
|
228
|
+
const response = await apiRequest(`Client/ClientChatSession/${currentSessionId}/send-message`, 'POST', messageDto)
|
|
229
|
+
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
throw new Error('Failed to send message')
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Update the sent message as seen
|
|
235
|
+
setMessages((prevMessages) => prevMessages.map((msg) => (msg.senderType === 1 && !msg.isSeen ? { ...msg, isSeen: true } : msg)))
|
|
236
|
+
} 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
|
+
])
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
if (isOpen && helpScreenId) {
|
|
255
|
+
setStatus('loading')
|
|
256
|
+
|
|
257
|
+
apiRequest(`client/clientHelpScreen/${helpScreenId}`)
|
|
258
|
+
.then((res) => res.json())
|
|
259
|
+
.then((data) => {
|
|
260
|
+
setHelpScreenData(data)
|
|
261
|
+
setStatus('succeeded')
|
|
262
|
+
setError('')
|
|
263
|
+
})
|
|
264
|
+
.catch((err) => {
|
|
265
|
+
setError(err.message)
|
|
266
|
+
setStatus('failed')
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
}, [isOpen, helpScreenId])
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<div className="babylai-help-center-container mb-4">
|
|
273
|
+
{showArrowAnimation && !isOpen && (
|
|
274
|
+
<FloatingMessage onClose={handleCloseArrowAnimation} message={messageLabel || t('homeSdk.needAssistance')} />
|
|
275
|
+
)}
|
|
276
|
+
|
|
277
|
+
<HelpButton onClick={handleTogglePopup} />
|
|
278
|
+
|
|
279
|
+
{isOpen && (
|
|
280
|
+
<HelpPopup
|
|
281
|
+
isOpen={isOpen}
|
|
282
|
+
onClose={() => setIsOpen(false)}
|
|
283
|
+
helpScreen={helpScreenData}
|
|
284
|
+
status={status}
|
|
285
|
+
error={error}
|
|
286
|
+
user={user}
|
|
287
|
+
onStartChat={handleStartChat}
|
|
288
|
+
onSendMessage={handleSendMessage}
|
|
289
|
+
onEndChat={handleEndChat}
|
|
290
|
+
messages={messages}
|
|
291
|
+
needsAgent={needsAgent}
|
|
292
|
+
assistantStatus={assistantStatus}
|
|
293
|
+
sessionId={sessionId}
|
|
294
|
+
isChatClosed={isChatClosed}
|
|
295
|
+
isSignalRConnected={isSignalRConnected}
|
|
296
|
+
selectedOption={selectedOption}
|
|
297
|
+
setSelectedOption={setSelectedOption}
|
|
298
|
+
showHelpScreen={showHelpScreen}
|
|
299
|
+
/>
|
|
300
|
+
)}
|
|
301
|
+
</div>
|
|
302
|
+
)
|
|
303
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { cn } from '@/lib'
|
|
2
|
+
import { ChatWindow } from '@/ui/chatbot-popup/chat-window-screen'
|
|
3
|
+
import ChatWindowHeader from '@/ui/chatbot-popup/chat-window-screen/header'
|
|
4
|
+
import ChatBotErrorScreen from '@/ui/chatbot-popup/error-screen'
|
|
5
|
+
import HomeScreen from '@/ui/chatbot-popup/home-screen'
|
|
6
|
+
import ChatBotLoadingScreen from '@/ui/chatbot-popup/loading-screen'
|
|
7
|
+
import OptionsListScreen from '@/ui/chatbot-popup/options-list-screen'
|
|
8
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
9
|
+
import ChatIcon from '../assets/icons/chat.svg'
|
|
10
|
+
import { Button } from '../components'
|
|
11
|
+
import { HelpScreenData, Message, Option } from '../lib/types'
|
|
12
|
+
|
|
13
|
+
type HelpPopupProps = {
|
|
14
|
+
isOpen: boolean
|
|
15
|
+
onClose: () => void
|
|
16
|
+
helpScreen: HelpScreenData | null
|
|
17
|
+
status: string
|
|
18
|
+
error: string | null
|
|
19
|
+
user: any
|
|
20
|
+
onStartChat: (option: Option) => void
|
|
21
|
+
onSendMessage: (message: string) => void
|
|
22
|
+
onEndChat: () => void
|
|
23
|
+
messages: Message[]
|
|
24
|
+
needsAgent: boolean
|
|
25
|
+
assistantStatus: string
|
|
26
|
+
sessionId: string | null
|
|
27
|
+
isChatClosed: boolean
|
|
28
|
+
isSignalRConnected: boolean
|
|
29
|
+
selectedOption: Option | null
|
|
30
|
+
setSelectedOption: (option: Option | null) => void
|
|
31
|
+
showHelpScreen: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Confirmation Modal Component
|
|
35
|
+
const ConfirmationModal = ({
|
|
36
|
+
title,
|
|
37
|
+
message,
|
|
38
|
+
onCancel,
|
|
39
|
+
onConfirm
|
|
40
|
+
}: {
|
|
41
|
+
title: string
|
|
42
|
+
message: string
|
|
43
|
+
onCancel: () => void
|
|
44
|
+
onConfirm: () => void
|
|
45
|
+
}) => {
|
|
46
|
+
return (
|
|
47
|
+
<div className="babylai-absolute babylai-inset-0 babylai-z-50 babylai-flex babylai-items-center babylai-justify-center babylai-rounded-3xl babylai-overflow-hidden">
|
|
48
|
+
<div className="babylai-absolute babylai-inset-0 babylai-bg-black/60" onClick={onCancel}></div>
|
|
49
|
+
<div className="babylai-bg-black-white-100 babylai-rounded-3xl babylai-p-4 babylai-w-[220px] babylai-z-50 babylai-shadow-lg">
|
|
50
|
+
<h3 className="babylai-text-black-white-900 babylai-font-bold babylai-mb-2 babylai-text-center">{title}</h3>
|
|
51
|
+
<p className="babylai-text-black-white-700 babylai-text-xs babylai-mb-4">{message}</p>
|
|
52
|
+
<div className="babylai-flex babylai-justify-end babylai-gap-2 babylai-w-full">
|
|
53
|
+
<Button variant="default" size="sm" onClick={onConfirm} className="babylai-text-sm babylai-w-full !babylai-font-bold">
|
|
54
|
+
Confirm
|
|
55
|
+
</Button>
|
|
56
|
+
<Button
|
|
57
|
+
variant="outline"
|
|
58
|
+
size="sm"
|
|
59
|
+
onClick={onCancel}
|
|
60
|
+
className="babylai-text-sm babylai-w-full babylai-text-primary-500 !babylai-font-bold"
|
|
61
|
+
>
|
|
62
|
+
Cancel
|
|
63
|
+
</Button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function HelpPopup({
|
|
71
|
+
onClose,
|
|
72
|
+
helpScreen,
|
|
73
|
+
status,
|
|
74
|
+
error,
|
|
75
|
+
onStartChat,
|
|
76
|
+
onSendMessage,
|
|
77
|
+
onEndChat,
|
|
78
|
+
messages,
|
|
79
|
+
assistantStatus,
|
|
80
|
+
needsAgent,
|
|
81
|
+
sessionId,
|
|
82
|
+
isChatClosed,
|
|
83
|
+
isSignalRConnected,
|
|
84
|
+
selectedOption,
|
|
85
|
+
setSelectedOption,
|
|
86
|
+
showHelpScreen
|
|
87
|
+
}: HelpPopupProps) {
|
|
88
|
+
const [showChat, setShowChat] = useState(false)
|
|
89
|
+
const [currentMessages, setCurrentMessages] = useState<Message[]>([])
|
|
90
|
+
const [isShowList, setIsShowList] = useState<boolean>(!showHelpScreen || false)
|
|
91
|
+
const [expandedOption, setExpandedOption] = useState<Option | null>(null)
|
|
92
|
+
const [endChatConfirmation, setEndChatConfirmation] = useState<boolean>(false)
|
|
93
|
+
|
|
94
|
+
const chatBoxRef = useRef<HTMLDivElement>(null)
|
|
95
|
+
|
|
96
|
+
// Scroll to bottom when new messages arrive
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (chatBoxRef.current) {
|
|
99
|
+
chatBoxRef.current.scrollTop = chatBoxRef.current.scrollHeight
|
|
100
|
+
}
|
|
101
|
+
setCurrentMessages(messages)
|
|
102
|
+
}, [messages])
|
|
103
|
+
|
|
104
|
+
const handleBack = () => {
|
|
105
|
+
if (showChat) {
|
|
106
|
+
setShowChat(false)
|
|
107
|
+
// onEndChat()
|
|
108
|
+
} else if (selectedOption) {
|
|
109
|
+
setSelectedOption(null)
|
|
110
|
+
} else {
|
|
111
|
+
setIsShowList(false)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const handleStartChat = (option: Option) => {
|
|
116
|
+
if (option) {
|
|
117
|
+
setCurrentMessages([
|
|
118
|
+
{
|
|
119
|
+
id: 1,
|
|
120
|
+
senderType: 3,
|
|
121
|
+
messageContent: selectedOption?.assistant?.greeting || '',
|
|
122
|
+
sentAt: new Date(),
|
|
123
|
+
isSeen: true
|
|
124
|
+
}
|
|
125
|
+
])
|
|
126
|
+
setShowChat(true)
|
|
127
|
+
onStartChat(option)
|
|
128
|
+
setSelectedOption(option)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const handleSendMessage = (message: string) => {
|
|
133
|
+
if (message.trim() && isSignalRConnected && !isChatClosed) {
|
|
134
|
+
onSendMessage(message.trim())
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const hideEndChatConfirmation = () => {
|
|
139
|
+
setEndChatConfirmation(false)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const handleEndChat = () => {
|
|
143
|
+
setEndChatConfirmation(false)
|
|
144
|
+
setCurrentMessages((prev) => [
|
|
145
|
+
...prev,
|
|
146
|
+
{
|
|
147
|
+
id: prev.length + 1,
|
|
148
|
+
senderType: 3,
|
|
149
|
+
messageContent: selectedOption?.assistant?.closing || '',
|
|
150
|
+
sentAt: new Date(),
|
|
151
|
+
isSeen: true
|
|
152
|
+
}
|
|
153
|
+
])
|
|
154
|
+
// setTimeout to close the chat after 3 seconds
|
|
155
|
+
setTimeout(() => {
|
|
156
|
+
onEndChat()
|
|
157
|
+
setShowChat(false)
|
|
158
|
+
setSelectedOption(null)
|
|
159
|
+
}, 3000)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const handleShowActiveChat = () => {
|
|
163
|
+
setShowChat(true)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (status === 'loading' && !helpScreen) {
|
|
167
|
+
return (
|
|
168
|
+
<div
|
|
169
|
+
className="babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-min-w-sm md:babylai-h-[calc(100vh-240px)]
|
|
170
|
+
babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
|
|
171
|
+
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"
|
|
172
|
+
>
|
|
173
|
+
<ChatBotLoadingScreen isShowList={isShowList} onClose={onClose} />
|
|
174
|
+
</div>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (error) {
|
|
179
|
+
return (
|
|
180
|
+
<div
|
|
181
|
+
className="babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-min-w-sm md:babylai-h-[calc(100vh-240px)]
|
|
182
|
+
babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
|
|
183
|
+
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"
|
|
184
|
+
>
|
|
185
|
+
<ChatBotErrorScreen onClose={onClose} error={error} />
|
|
186
|
+
</div>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const renderContent = () => {
|
|
191
|
+
if (showChat && selectedOption) {
|
|
192
|
+
return (
|
|
193
|
+
<>
|
|
194
|
+
<ChatWindowHeader
|
|
195
|
+
handleBack={handleBack}
|
|
196
|
+
handleEndChat={handleEndChat}
|
|
197
|
+
onClose={onClose}
|
|
198
|
+
isShowList={isShowList}
|
|
199
|
+
showChat={showChat}
|
|
200
|
+
setIsShowList={setIsShowList}
|
|
201
|
+
/>
|
|
202
|
+
<ChatWindow
|
|
203
|
+
onSendMessage={handleSendMessage}
|
|
204
|
+
messages={currentMessages}
|
|
205
|
+
assistantStatus={assistantStatus}
|
|
206
|
+
needsAgent={needsAgent}
|
|
207
|
+
/>
|
|
208
|
+
</>
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (isShowList) {
|
|
213
|
+
return (
|
|
214
|
+
<OptionsListScreen
|
|
215
|
+
helpScreen={helpScreen}
|
|
216
|
+
expandedOption={expandedOption}
|
|
217
|
+
setExpandedOption={setExpandedOption}
|
|
218
|
+
handleStartChat={handleStartChat}
|
|
219
|
+
handleBack={showHelpScreen ? handleBack : onClose}
|
|
220
|
+
showHelpScreen={showHelpScreen}
|
|
221
|
+
/>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
return <HomeScreen setIsShowList={setIsShowList} onClose={onClose} />
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div
|
|
229
|
+
className="babylai-fixed babylai-inset-0 md:babylai-inset-auto md:babylai-max-w-sm md:babylai-min-w-sm md:babylai-h-[calc(100vh-240px)]
|
|
230
|
+
babylai-overflow-auto babylai-w-full babylai-bg-black-white-50 md:babylai-mb-4
|
|
231
|
+
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"
|
|
232
|
+
>
|
|
233
|
+
<div
|
|
234
|
+
className={cn('babylai-h-full babylai-rounded-none md:babylai-rounded-3xl babylai-flex babylai-flex-col babylai-relative', {
|
|
235
|
+
'babylai-bg-gradient-to-b babylai-from-primary-500 babylai-to-primary-500/60': !isShowList,
|
|
236
|
+
'babylai-bg-black-white-100': isShowList
|
|
237
|
+
})}
|
|
238
|
+
>
|
|
239
|
+
{sessionId && !showChat && (
|
|
240
|
+
<Button
|
|
241
|
+
variant="rounded-icon"
|
|
242
|
+
size="icon"
|
|
243
|
+
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"
|
|
244
|
+
onClick={handleShowActiveChat}
|
|
245
|
+
>
|
|
246
|
+
<ChatIcon className="babylai-w-5 babylai-h-5 babylai-text-black-white-50" />
|
|
247
|
+
</Button>
|
|
248
|
+
)}
|
|
249
|
+
{/* Content */}
|
|
250
|
+
{renderContent()}
|
|
251
|
+
|
|
252
|
+
{/* End Chat Confirmation Modal */}
|
|
253
|
+
{endChatConfirmation && (
|
|
254
|
+
<ConfirmationModal
|
|
255
|
+
title="Leaving so soon? 👋"
|
|
256
|
+
message="Don't worry, you can come back anytime. We're always here if you need help or have questions."
|
|
257
|
+
onCancel={hideEndChatConfirmation}
|
|
258
|
+
onConfirm={handleEndChat}
|
|
259
|
+
/>
|
|
260
|
+
)}
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
)
|
|
264
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { createHelpCenterI18n } from './i18n';
|
|
4
|
+
|
|
5
|
+
export const useLocalTranslation = (languageFromProps?: string) => {
|
|
6
|
+
const language = languageFromProps || localStorage.getItem('app-language') || 'en';
|
|
7
|
+
|
|
8
|
+
const i18n = useMemo(() => createHelpCenterI18n(language), [language]);
|
|
9
|
+
|
|
10
|
+
const t = (key: string) => i18n.t(key);
|
|
11
|
+
const dir = i18n.dir();
|
|
12
|
+
|
|
13
|
+
return { t, dir , i18n };
|
|
14
|
+
};
|