shopify-chatbot-widget 1.0.9 → 1.0.10
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/.env.development +2 -0
- package/dist/jaweb-chatbot.css +1 -1
- package/dist/jaweb-chatbot.iife.js +192 -599
- package/package.json +1 -1
- package/src/App.tsx +9 -0
- package/src/Chatbot/Chatbot.css +193 -113
- package/src/Chatbot/Chatbot.tsx +26 -19
- package/src/Chatbot/components/Cart/Index.tsx +10 -8
- package/src/Chatbot/components/ChatInput.tsx +11 -11
- package/src/Chatbot/components/Home/Home.css +456 -0
- package/src/Chatbot/components/Home/Home.tsx +293 -0
- package/src/Chatbot/components/Messages/Addcart.tsx +1 -1
- package/src/Chatbot/components/Messages/AssistantMesage.tsx +78 -37
- package/src/Chatbot/components/Messages/CardSwiper.tsx +1 -1
- package/src/Chatbot/components/Messages/Carousel/CardSwiper.tsx +87 -92
- package/src/Chatbot/components/Messages/Carousel/ProductSwiper.css +361 -0
- package/src/Chatbot/components/Messages/Carousel/TryOn.tsx +2 -2
- package/src/Chatbot/components/Messages/ChatMessages.css +32 -1
- package/src/Chatbot/components/Messages/ChatMessages.tsx +21 -38
- package/src/Chatbot/components/Messages/OrderCard.css +177 -0
- package/src/Chatbot/components/Messages/OrderCard.tsx +120 -0
- package/src/Chatbot/components/Messages/ProductCard.css +1 -1
- package/src/Chatbot/components/Messages/Support.tsx +311 -118
- package/src/Chatbot/components/Messages/Typing.css +31 -35
- package/src/Chatbot/components/Messages/Typing.tsx +19 -18
- package/src/Chatbot/components/Messenger/Messenger.tsx +67 -14
- package/src/Chatbot/components/Powered.css +26 -28
- package/src/Chatbot/components/Powered.tsx +1 -1
- package/src/Chatbot/components/Sessions/CreateSession.tsx +12 -10
- package/src/Chatbot/components/TryOn/View.tsx +2 -2
- package/src/Chatbot/components/VoiceMode.css +247 -0
- package/src/Chatbot/components/VoiceMode.tsx +613 -0
- package/src/hooks/config.tsx +9 -10
- package/src/hooks/useChatbotAPI.tsx +146 -61
- package/src/hooks/useChatbotData.tsx +8 -5
- package/src/hooks/useSessionMessages.tsx +0 -1
- package/src/hooks/useWebsocke.tsx +40 -18
- package/src/i18n.tsx +384 -10
- package/src/Chatbot/components/Messages/Carousel/CardSwiperSalla.tsx +0 -187
- package/src/Chatbot/components/Messages/Carousel/CardSwiperZid.tsx +0 -208
- package/src/Chatbot/components/Messages/Carousel/SallaSwiper.css +0 -245
- package/src/Chatbot/components/Messages/SallaAssistantMessage.tsx +0 -202
- package/src/Chatbot/components/Messages/ZidAssistantMesage.tsx +0 -203
- package/src/Chatbot/components/Sessions/RenderList.tsx +0 -519
|
@@ -44,4 +44,35 @@
|
|
|
44
44
|
|
|
45
45
|
.first-message {
|
|
46
46
|
animation: fadeSlideIn 0.5s ease-out;
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
|
+
/* Support handoff — mini equalizer bars (matches voice mode) */
|
|
49
|
+
.jwbS-bars {
|
|
50
|
+
--jwbS-accent: #111827;
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: 3px;
|
|
54
|
+
height: 22px;
|
|
55
|
+
flex-shrink: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.jwbS-bars span {
|
|
59
|
+
width: 4px;
|
|
60
|
+
height: 16px;
|
|
61
|
+
border-radius: 3px;
|
|
62
|
+
background: var(--jwbS-accent);
|
|
63
|
+
animation: jwbS-wave 1.1s ease-in-out infinite;
|
|
64
|
+
transform-origin: center;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.jwbS-bars span:nth-child(2) {
|
|
68
|
+
animation-delay: 0.18s;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.jwbS-bars span:nth-child(3) {
|
|
72
|
+
animation-delay: 0.36s;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@keyframes jwbS-wave {
|
|
76
|
+
0%, 100% { transform: scaleY(0.4); opacity: 0.6; }
|
|
77
|
+
50% { transform: scaleY(1); opacity: 1; }
|
|
78
|
+
}
|
|
@@ -11,8 +11,6 @@ import AgentStatusBanner from './AgentStatus';
|
|
|
11
11
|
import AddToCartConfirmation from './Addcart';
|
|
12
12
|
import SupportConnect from './Support';
|
|
13
13
|
import ChatImageTextAssist from './ChatImageTextAssis';
|
|
14
|
-
import ZidAssistantChatMessage from './ZidAssistantMesage';
|
|
15
|
-
import SallaAsssiatnt from './SallaAssistantMessage';
|
|
16
14
|
import CalendlyEmbeds from './CalendlyEmbeds';
|
|
17
15
|
|
|
18
16
|
|
|
@@ -50,7 +48,6 @@ interface ChatMessagesProps {
|
|
|
50
48
|
status?: string;
|
|
51
49
|
user?: string;
|
|
52
50
|
};
|
|
53
|
-
userType: string;
|
|
54
51
|
calendly: string;
|
|
55
52
|
disableCheckout: boolean;
|
|
56
53
|
isfetchingMessage: boolean;
|
|
@@ -117,7 +114,6 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({
|
|
|
117
114
|
isLoading,
|
|
118
115
|
agentStatus,
|
|
119
116
|
sessionId,
|
|
120
|
-
userType,
|
|
121
117
|
calendly,
|
|
122
118
|
disableCheckout,
|
|
123
119
|
isfetchingMessage,
|
|
@@ -188,7 +184,18 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({
|
|
|
188
184
|
}
|
|
189
185
|
|
|
190
186
|
if (msg.isConnect) {
|
|
191
|
-
|
|
187
|
+
// Escalations carry their ticket in the message content
|
|
188
|
+
let ticket = null;
|
|
189
|
+
const rawContent = typeof msg.content === 'string' ? msg.content : '';
|
|
190
|
+
const tm = rawContent.match(/\[\[SUPPORT_TICKET\]\]([\s\S]*?)\[\[\/SUPPORT_TICKET\]\]/);
|
|
191
|
+
if (tm) {
|
|
192
|
+
try {
|
|
193
|
+
ticket = JSON.parse(tm[1]);
|
|
194
|
+
} catch { /* no ticket card, stage card still shows */ }
|
|
195
|
+
}
|
|
196
|
+
return (
|
|
197
|
+
<SupportConnect key={i} sessionId={sessionId} colorCode={colorCode} ticket={ticket} />
|
|
198
|
+
);
|
|
192
199
|
}
|
|
193
200
|
|
|
194
201
|
if (msg.isBookings) {
|
|
@@ -254,39 +261,15 @@ const ChatMessages: React.FC<ChatMessagesProps> = ({
|
|
|
254
261
|
/>
|
|
255
262
|
)}
|
|
256
263
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
/>
|
|
267
|
-
) : userType === "salla" ? (
|
|
268
|
-
<SallaAsssiatnt
|
|
269
|
-
message={msg.content || msg.text || ""}
|
|
270
|
-
colorCode={colorCode}
|
|
271
|
-
handleAddToCart={handleAddToCart}
|
|
272
|
-
handleRemoveFromCart={handleRemoveFromCart}
|
|
273
|
-
onTryOnSelect={onTryOnSelect}
|
|
274
|
-
enableTry={enableTry}
|
|
275
|
-
// enableTry={enableTry}
|
|
276
|
-
|
|
277
|
-
/>
|
|
278
|
-
) : (
|
|
279
|
-
<ZidAssistantChatMessage
|
|
280
|
-
message={msg.content || msg.text || ""}
|
|
281
|
-
colorCode={colorCode}
|
|
282
|
-
handleAddToCart={handleAddToCart}
|
|
283
|
-
handleRemoveFromCart={handleRemoveFromCart}
|
|
284
|
-
onTryOnSelect={onTryOnSelect}
|
|
285
|
-
enableTry={enableTry}
|
|
286
|
-
// enableTry={enableTry}
|
|
287
|
-
|
|
288
|
-
/>
|
|
289
|
-
)}
|
|
264
|
+
<AssistantMessage
|
|
265
|
+
message={msg.content || msg.text || ""}
|
|
266
|
+
colorCode={colorCode}
|
|
267
|
+
disableCheckout={disableCheckout}
|
|
268
|
+
handleAddToCart={handleAddToCart}
|
|
269
|
+
handleRemoveFromCart={handleRemoveFromCart}
|
|
270
|
+
onTryOnSelect={onTryOnSelect}
|
|
271
|
+
enableTry={enableTry}
|
|
272
|
+
/>
|
|
290
273
|
</div>
|
|
291
274
|
|
|
292
275
|
{/* ADD suggestions here - MOVED OUTSIDE the chat-msg div */}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/* Order tracking card — matches the product card design language */
|
|
2
|
+
.jwbO-card {
|
|
3
|
+
--jwbO-accent: #111111;
|
|
4
|
+
background: #ffffff;
|
|
5
|
+
border: 1px solid #ececec;
|
|
6
|
+
border-radius: 16px;
|
|
7
|
+
padding: 14px;
|
|
8
|
+
box-shadow: 0 1px 2px rgba(17, 24, 39, 0.05);
|
|
9
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
10
|
+
color: #111827;
|
|
11
|
+
max-width: 340px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.jwbO-head {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: space-between;
|
|
18
|
+
gap: 10px;
|
|
19
|
+
margin-bottom: 14px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.jwbO-label {
|
|
23
|
+
display: block;
|
|
24
|
+
font-size: 10px;
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
letter-spacing: 0.1em;
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
color: #9ca3af;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.jwbO-number {
|
|
32
|
+
font-size: 16px;
|
|
33
|
+
font-weight: 700;
|
|
34
|
+
letter-spacing: -0.01em;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.jwbO-pill {
|
|
38
|
+
font-size: 11px;
|
|
39
|
+
font-weight: 700;
|
|
40
|
+
padding: 5px 10px;
|
|
41
|
+
border-radius: 999px;
|
|
42
|
+
background: var(--jwbO-accent);
|
|
43
|
+
color: #ffffff;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.jwbO-pill--done {
|
|
48
|
+
background: #16a34a;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* ===== Timeline ===== */
|
|
52
|
+
.jwbO-timeline {
|
|
53
|
+
display: flex;
|
|
54
|
+
margin-bottom: 12px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.jwbO-step {
|
|
58
|
+
flex: 1;
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
gap: 5px;
|
|
62
|
+
min-width: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.jwbO-step:last-child {
|
|
66
|
+
flex: 0 0 auto;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.jwbO-track {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.jwbO-dot {
|
|
75
|
+
width: 18px;
|
|
76
|
+
height: 18px;
|
|
77
|
+
border-radius: 50%;
|
|
78
|
+
border: 2px solid #e5e7eb;
|
|
79
|
+
background: #ffffff;
|
|
80
|
+
color: #ffffff;
|
|
81
|
+
font-size: 10px;
|
|
82
|
+
font-weight: 700;
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
flex-shrink: 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.jwbO-dot--done {
|
|
90
|
+
background: var(--jwbO-accent);
|
|
91
|
+
border-color: var(--jwbO-accent);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.jwbO-line {
|
|
95
|
+
flex: 1;
|
|
96
|
+
height: 2px;
|
|
97
|
+
background: #e5e7eb;
|
|
98
|
+
margin: 0 3px;
|
|
99
|
+
min-width: 14px;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.jwbO-line--done {
|
|
103
|
+
background: var(--jwbO-accent);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.jwbO-stepLabel {
|
|
107
|
+
font-size: 10px;
|
|
108
|
+
font-weight: 600;
|
|
109
|
+
color: #9ca3af;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.jwbO-stepLabel--done {
|
|
113
|
+
color: #111827;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* ===== Meta ===== */
|
|
117
|
+
.jwbO-meta {
|
|
118
|
+
font-size: 12px;
|
|
119
|
+
color: #6b7280;
|
|
120
|
+
margin: 0 0 4px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.jwbO-items {
|
|
124
|
+
font-size: 12px;
|
|
125
|
+
color: #6b7280;
|
|
126
|
+
margin: 0;
|
|
127
|
+
white-space: nowrap;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
text-overflow: ellipsis;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ===== Tracking footer ===== */
|
|
133
|
+
.jwbO-tracking {
|
|
134
|
+
display: flex;
|
|
135
|
+
align-items: center;
|
|
136
|
+
justify-content: space-between;
|
|
137
|
+
gap: 10px;
|
|
138
|
+
margin-top: 12px;
|
|
139
|
+
padding-top: 12px;
|
|
140
|
+
border-top: 1px solid #f3f4f6;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.jwbO-trackingInfo {
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-direction: column;
|
|
146
|
+
gap: 1px;
|
|
147
|
+
min-width: 0;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.jwbO-carrier {
|
|
151
|
+
font-size: 12px;
|
|
152
|
+
font-weight: 700;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.jwbO-trackingNo {
|
|
156
|
+
font-size: 11px;
|
|
157
|
+
color: #6b7280;
|
|
158
|
+
font-variant-numeric: tabular-nums;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
text-overflow: ellipsis;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.jwbO-trackBtn {
|
|
164
|
+
flex-shrink: 0;
|
|
165
|
+
background: var(--jwbO-accent);
|
|
166
|
+
color: #ffffff;
|
|
167
|
+
font-size: 12px;
|
|
168
|
+
font-weight: 700;
|
|
169
|
+
padding: 9px 14px;
|
|
170
|
+
border-radius: 10px;
|
|
171
|
+
text-decoration: none;
|
|
172
|
+
transition: opacity 0.15s ease;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.jwbO-trackBtn:hover {
|
|
176
|
+
opacity: 0.85;
|
|
177
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import './OrderCard.css';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
export interface OrderStatusData {
|
|
6
|
+
order: string;
|
|
7
|
+
placed?: string;
|
|
8
|
+
payment?: string;
|
|
9
|
+
fulfillment?: string;
|
|
10
|
+
shipment_status?: string;
|
|
11
|
+
items?: string[];
|
|
12
|
+
tracking_company?: string | null;
|
|
13
|
+
tracking_number?: string | null;
|
|
14
|
+
tracking_url?: string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
data: OrderStatusData;
|
|
19
|
+
colorCode?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const STEP_KEYS = ['order.stepPlaced', 'order.stepPaid', 'order.stepShipped', 'order.stepDelivered'] as const;
|
|
23
|
+
|
|
24
|
+
const OrderCard: FC<Props> = ({ data, colorCode = '#111111' }) => {
|
|
25
|
+
const { t } = useTranslation();
|
|
26
|
+
const payment = (data.payment || '').toUpperCase();
|
|
27
|
+
const fulfillment = (data.fulfillment || '').toUpperCase();
|
|
28
|
+
const shipment = (data.shipment_status || '').toUpperCase();
|
|
29
|
+
|
|
30
|
+
const paid = payment.includes('PAID') || payment.includes('REFUND');
|
|
31
|
+
const shipped =
|
|
32
|
+
shipment !== '' ||
|
|
33
|
+
fulfillment === 'FULFILLED' ||
|
|
34
|
+
fulfillment === 'PARTIALLY_FULFILLED';
|
|
35
|
+
const delivered = shipment === 'DELIVERED';
|
|
36
|
+
|
|
37
|
+
const doneCount = delivered ? 4 : shipped ? 3 : paid ? 2 : 1;
|
|
38
|
+
|
|
39
|
+
const stageLabel = delivered
|
|
40
|
+
? t('order.delivered')
|
|
41
|
+
: shipped
|
|
42
|
+
? t('order.onItsWay')
|
|
43
|
+
: paid
|
|
44
|
+
? t('order.preparing')
|
|
45
|
+
: t('order.awaitingPayment');
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div
|
|
49
|
+
className="jwbO-card"
|
|
50
|
+
style={{ '--jwbO-accent': colorCode } as React.CSSProperties}
|
|
51
|
+
>
|
|
52
|
+
<div className="jwbO-head">
|
|
53
|
+
<div>
|
|
54
|
+
<span className="jwbO-label">{t('order.order')}</span>
|
|
55
|
+
<span className="jwbO-number">{data.order}</span>
|
|
56
|
+
</div>
|
|
57
|
+
<span className={`jwbO-pill ${delivered ? 'jwbO-pill--done' : ''}`}>
|
|
58
|
+
{stageLabel}
|
|
59
|
+
</span>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div className="jwbO-timeline" role="list" aria-label={t('order.progress')}>
|
|
63
|
+
{STEP_KEYS.map((step, i) => {
|
|
64
|
+
const done = i < doneCount;
|
|
65
|
+
const isLast = i === STEP_KEYS.length - 1;
|
|
66
|
+
return (
|
|
67
|
+
<div key={step} className="jwbO-step" role="listitem">
|
|
68
|
+
<div className="jwbO-track">
|
|
69
|
+
<span className={`jwbO-dot ${done ? 'jwbO-dot--done' : ''}`}>
|
|
70
|
+
{done ? '✓' : ''}
|
|
71
|
+
</span>
|
|
72
|
+
{!isLast && (
|
|
73
|
+
<span
|
|
74
|
+
className={`jwbO-line ${i < doneCount - 1 ? 'jwbO-line--done' : ''}`}
|
|
75
|
+
/>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
<span className={`jwbO-stepLabel ${done ? 'jwbO-stepLabel--done' : ''}`}>
|
|
79
|
+
{t(step)}
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
{data.placed && <p className="jwbO-meta">{t('order.placedOn', { date: data.placed })}</p>}
|
|
87
|
+
|
|
88
|
+
{data.items && data.items.length > 0 && (
|
|
89
|
+
<p className="jwbO-items" title={data.items.join(', ')}>
|
|
90
|
+
{data.items.join(', ')}
|
|
91
|
+
</p>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
{(data.tracking_company || data.tracking_number || data.tracking_url) && (
|
|
95
|
+
<div className="jwbO-tracking">
|
|
96
|
+
<div className="jwbO-trackingInfo">
|
|
97
|
+
{data.tracking_company && (
|
|
98
|
+
<span className="jwbO-carrier">{data.tracking_company}</span>
|
|
99
|
+
)}
|
|
100
|
+
{data.tracking_number && (
|
|
101
|
+
<span className="jwbO-trackingNo">{data.tracking_number}</span>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
{data.tracking_url && (
|
|
105
|
+
<a
|
|
106
|
+
href={data.tracking_url}
|
|
107
|
+
target="_blank"
|
|
108
|
+
rel="noopener noreferrer"
|
|
109
|
+
className="jwbO-trackBtn"
|
|
110
|
+
>
|
|
111
|
+
{t('order.trackPackage')}
|
|
112
|
+
</a>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default OrderCard;
|