shopify-chatbot-widget 0.5.2 β 0.5.5
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/dist/jaweb-chatbot.iife.js +76 -76
- package/package.json +1 -1
- package/xx.html +256 -0
package/package.json
CHANGED
package/xx.html
CHANGED
|
@@ -54,3 +54,259 @@
|
|
|
54
54
|
|
|
55
55
|
</body>
|
|
56
56
|
</html>
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
import React, { useState,useEffect } from 'react';
|
|
61
|
+
import { Button } from 'antd';
|
|
62
|
+
|
|
63
|
+
import { useChatbotData } from '../hooks/useChatbotData';
|
|
64
|
+
import ChatSessions from './components/Sessions/RenderList';
|
|
65
|
+
import CreateSession from './components/Sessions/CreateSession';
|
|
66
|
+
import Messenger from './components/Messenger/Messenger';
|
|
67
|
+
import './Chatbot.css'
|
|
68
|
+
import config from '../hooks/config';
|
|
69
|
+
import FingerprintJS from '@fingerprintjs/fingerprintjs';
|
|
70
|
+
|
|
71
|
+
const Chatbot: React.FC = () => {
|
|
72
|
+
const [open, setOpen] = useState(false);
|
|
73
|
+
const [viewMode, setViewMode] = useState<'sessions' | 'create' | 'messenger'>('sessions');
|
|
74
|
+
const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
|
|
75
|
+
const [HasInfo,setHasInfo]=useState(false)
|
|
76
|
+
const [activeAgentName,setActiveAgentName]=useState('')
|
|
77
|
+
const [activeAgentImage,setActiveAgentImage]=useState('')
|
|
78
|
+
const [newSession,setNewSession]=useState(false)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
const windowWidth = window.innerWidth;
|
|
82
|
+
|
|
83
|
+
const {
|
|
84
|
+
chatbotLogo,
|
|
85
|
+
colorCode,
|
|
86
|
+
subscription,
|
|
87
|
+
messagesSuggestions,
|
|
88
|
+
isFetchingDetails,
|
|
89
|
+
disableForm,
|
|
90
|
+
merchantPhone,
|
|
91
|
+
userType
|
|
92
|
+
} = useChatbotData();
|
|
93
|
+
|
|
94
|
+
const [visitorData, setVisitorData] = useState<{ visitorId: string; country: string } | null>(null);
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
const handleNewSessionClick = () => {
|
|
98
|
+
// If the form is *not* disabled, always go to create
|
|
99
|
+
if (!disableForm && !HasInfo) {
|
|
100
|
+
setViewMode('create');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
else {
|
|
105
|
+
const newSessionId = crypto.randomUUID();
|
|
106
|
+
setActiveSessionId(newSessionId);
|
|
107
|
+
setActiveAgentImage(chatbotLogo);
|
|
108
|
+
setActiveAgentName('Ai Agent');
|
|
109
|
+
console.log(newSessionId);
|
|
110
|
+
setNewSession(true);
|
|
111
|
+
setViewMode('messenger');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Otherwise (disableForm true && !HasInfo) we simply bail.
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
const fetchVisitorInfo = async () => {
|
|
119
|
+
try {
|
|
120
|
+
let visitorId = localStorage.getItem('visitor_id');
|
|
121
|
+
let ip = localStorage.getItem('ip_address');
|
|
122
|
+
let country = localStorage.getItem('country');
|
|
123
|
+
|
|
124
|
+
// β
If all cached, safely set and exit
|
|
125
|
+
// if (visitorId && ip && country) {
|
|
126
|
+
// setVisitorData({ visitorId, country });
|
|
127
|
+
|
|
128
|
+
// return;
|
|
129
|
+
// }
|
|
130
|
+
|
|
131
|
+
// π Generate fingerprint if needed
|
|
132
|
+
if (!visitorId) {
|
|
133
|
+
const fp = await FingerprintJS.load();
|
|
134
|
+
const result = await fp.get();
|
|
135
|
+
visitorId = result.visitorId;
|
|
136
|
+
localStorage.setItem('visitor_id', visitorId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// π Fetch IP info if missing
|
|
140
|
+
if (!ip || !country) {
|
|
141
|
+
const res = await fetch('https://ipapi.co/json');
|
|
142
|
+
const data = await res.json();
|
|
143
|
+
ip = data.ip;
|
|
144
|
+
country = data.country_name;
|
|
145
|
+
|
|
146
|
+
if (ip) localStorage.setItem('ip_address', ip);
|
|
147
|
+
if (country) localStorage.setItem('country', country);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// β
Ensure values are non-null before use
|
|
151
|
+
if (visitorId && ip && country) {
|
|
152
|
+
console.log("HHH")
|
|
153
|
+
setVisitorData({ visitorId, country });
|
|
154
|
+
|
|
155
|
+
// π‘ Send to backend
|
|
156
|
+
const backendRes = await fetch(`${config.apiUrl}register-ip/`, {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: {
|
|
159
|
+
'Content-Type': 'application/json',
|
|
160
|
+
},
|
|
161
|
+
body: JSON.stringify({
|
|
162
|
+
ip_address: ip,
|
|
163
|
+
country,
|
|
164
|
+
visitor_id: visitorId,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const result = await backendRes.json();
|
|
169
|
+
setHasInfo(result.has_user_info || false);
|
|
170
|
+
} else {
|
|
171
|
+
console.warn('Missing IP or country info after fetch');
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
console.error('Failed to fetch or send visitor info', err);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
fetchVisitorInfo();
|
|
179
|
+
}, []);
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
const handleSessionSelect = (sessionId: string,agentName:string,agentImage:string) => {
|
|
186
|
+
setActiveSessionId(sessionId);
|
|
187
|
+
setActiveAgentName(agentName)
|
|
188
|
+
setActiveAgentImage(agentImage)
|
|
189
|
+
setNewSession(false)
|
|
190
|
+
setViewMode('messenger');
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
const onMessage = (e: MessageEvent) => {
|
|
196
|
+
const msg = (e.data || {}) as any;
|
|
197
|
+
if (msg.type !== 'JAWEB_CHAT') return;
|
|
198
|
+
|
|
199
|
+
if (msg.action === 'open-ready') {
|
|
200
|
+
// Parent has expanded iframe β now we can render full UI
|
|
201
|
+
setOpen(true);
|
|
202
|
+
} else if (msg.action === 'closed') {
|
|
203
|
+
// Parent collapsed iframe β hide full UI
|
|
204
|
+
setOpen(false);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
window.addEventListener('message', onMessage);
|
|
208
|
+
return () => window.removeEventListener('message', onMessage);
|
|
209
|
+
}, []);
|
|
210
|
+
|
|
211
|
+
const requestOpen = () => {
|
|
212
|
+
// Ask parent to expand iframe
|
|
213
|
+
window.parent?.postMessage({ type: 'JAWEB_CHAT', action: 'open' }, '*');
|
|
214
|
+
};
|
|
215
|
+
const requestClose = () => {
|
|
216
|
+
// Ask parent to collapse iframe
|
|
217
|
+
window.parent?.postMessage({ type: 'JAWEB_CHAT', action: 'close' }, '*');
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<div>
|
|
225
|
+
{!isFetchingDetails && subscription ? (
|
|
226
|
+
<div
|
|
227
|
+
style={{
|
|
228
|
+
bottom: windowWidth < 768 ? '20%' : 0,
|
|
229
|
+
top: windowWidth < 768 ? '0' : '5%',
|
|
230
|
+
height: windowWidth < 768 ? '100%' : '85%',
|
|
231
|
+
borderRadius: 10,
|
|
232
|
+
width: '100%',
|
|
233
|
+
zIndex: 9999,
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
{open && (
|
|
237
|
+
<div className="chatbot-box">
|
|
238
|
+
{viewMode === 'sessions' && (
|
|
239
|
+
<ChatSessions
|
|
240
|
+
chatbotLogo={chatbotLogo}
|
|
241
|
+
Phone={merchantPhone || ''}
|
|
242
|
+
colorCode={colorCode}
|
|
243
|
+
visitorId={visitorData?.visitorId || ''}
|
|
244
|
+
Opened={open}
|
|
245
|
+
// when a child wants to close, talk to parent
|
|
246
|
+
setOpen={(v: boolean) => (v ? requestOpen() : requestClose())}
|
|
247
|
+
onNewSession={handleNewSessionClick}
|
|
248
|
+
onSessionSelect={handleSessionSelect}
|
|
249
|
+
/>
|
|
250
|
+
)}
|
|
251
|
+
|
|
252
|
+
{viewMode === 'create' && (
|
|
253
|
+
<CreateSession
|
|
254
|
+
colorCode={colorCode}
|
|
255
|
+
visitorId={visitorData?.visitorId || ''}
|
|
256
|
+
country={visitorData?.country || ''}
|
|
257
|
+
onBack={() => setViewMode('sessions')}
|
|
258
|
+
onCreate={(userData) => {
|
|
259
|
+
setActiveSessionId(userData.session_id);
|
|
260
|
+
setHasInfo(userData.hasInfo);
|
|
261
|
+
setViewMode('messenger');
|
|
262
|
+
}}
|
|
263
|
+
/>
|
|
264
|
+
)}
|
|
265
|
+
|
|
266
|
+
{viewMode === 'messenger' && activeSessionId && (
|
|
267
|
+
<Messenger
|
|
268
|
+
sessionId={activeSessionId}
|
|
269
|
+
chatbotLogo={activeAgentImage || chatbotLogo}
|
|
270
|
+
agentName={activeAgentName || 'Ai Assistant'}
|
|
271
|
+
colorCode={colorCode}
|
|
272
|
+
messagesSuggestions={messagesSuggestions}
|
|
273
|
+
newSession={newSession}
|
|
274
|
+
disableForm={disableForm}
|
|
275
|
+
// children call this to close/open β routed to parent
|
|
276
|
+
setOpen={(v: boolean) => (v ? requestOpen() : requestClose())}
|
|
277
|
+
setNewSession={setNewSession}
|
|
278
|
+
Opened={open}
|
|
279
|
+
setView={() => setViewMode('sessions')}
|
|
280
|
+
userType={userType}
|
|
281
|
+
/>
|
|
282
|
+
)}
|
|
283
|
+
</div>
|
|
284
|
+
)}
|
|
285
|
+
</div>
|
|
286
|
+
) : null}
|
|
287
|
+
|
|
288
|
+
<div className="jaweb-chatbot-container">
|
|
289
|
+
{!isFetchingDetails && subscription ? (
|
|
290
|
+
<Button
|
|
291
|
+
type="primary"
|
|
292
|
+
shape="circle"
|
|
293
|
+
icon={
|
|
294
|
+
<img
|
|
295
|
+
src="https://jaweb.me/wp-content/uploads/2025/03/download__2_-removebg-preview.png"
|
|
296
|
+
alt="Chat Icon"
|
|
297
|
+
style={{ width: 30, height: 30 }}
|
|
298
|
+
/>
|
|
299
|
+
}
|
|
300
|
+
size="large"
|
|
301
|
+
style={{ backgroundColor: colorCode, width: 60, height: 60 }}
|
|
302
|
+
className={`chat-launcher ${open ? 'chatbot-open' : ''}`}
|
|
303
|
+
// π Donβt setOpen directly; request parent resize
|
|
304
|
+
onClick={() => (open ? requestClose() : requestOpen())}
|
|
305
|
+
/>
|
|
306
|
+
) : null}
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
);
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
export default Chatbot;
|