shopify-chatbot-widget 1.0.8 → 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.
Files changed (46) hide show
  1. package/.env.development +2 -0
  2. package/dist/jaweb-chatbot.css +1 -1
  3. package/dist/jaweb-chatbot.iife.js +192 -599
  4. package/home.html +1 -1
  5. package/jawebDirect.js +1 -1
  6. package/package.json +1 -1
  7. package/src/App.tsx +9 -0
  8. package/src/Chatbot/Chatbot.css +193 -113
  9. package/src/Chatbot/Chatbot.tsx +26 -19
  10. package/src/Chatbot/components/Cart/Index.tsx +10 -8
  11. package/src/Chatbot/components/ChatInput.tsx +11 -11
  12. package/src/Chatbot/components/Home/Home.css +456 -0
  13. package/src/Chatbot/components/Home/Home.tsx +293 -0
  14. package/src/Chatbot/components/Messages/Addcart.tsx +1 -1
  15. package/src/Chatbot/components/Messages/AssistantMesage.tsx +78 -37
  16. package/src/Chatbot/components/Messages/CardSwiper.tsx +1 -1
  17. package/src/Chatbot/components/Messages/Carousel/CardSwiper.tsx +87 -92
  18. package/src/Chatbot/components/Messages/Carousel/ProductSwiper.css +361 -0
  19. package/src/Chatbot/components/Messages/Carousel/TryOn.tsx +2 -2
  20. package/src/Chatbot/components/Messages/ChatMessages.css +32 -1
  21. package/src/Chatbot/components/Messages/ChatMessages.tsx +21 -38
  22. package/src/Chatbot/components/Messages/OrderCard.css +177 -0
  23. package/src/Chatbot/components/Messages/OrderCard.tsx +120 -0
  24. package/src/Chatbot/components/Messages/ProductCard.css +1 -1
  25. package/src/Chatbot/components/Messages/Support.tsx +311 -118
  26. package/src/Chatbot/components/Messages/Typing.css +31 -35
  27. package/src/Chatbot/components/Messages/Typing.tsx +19 -18
  28. package/src/Chatbot/components/Messenger/Messenger.tsx +67 -14
  29. package/src/Chatbot/components/Powered.css +26 -28
  30. package/src/Chatbot/components/Powered.tsx +1 -1
  31. package/src/Chatbot/components/Sessions/CreateSession.tsx +12 -10
  32. package/src/Chatbot/components/TryOn/View.tsx +2 -2
  33. package/src/Chatbot/components/VoiceMode.css +247 -0
  34. package/src/Chatbot/components/VoiceMode.tsx +613 -0
  35. package/src/hooks/config.tsx +9 -10
  36. package/src/hooks/useChatbotAPI.tsx +146 -61
  37. package/src/hooks/useChatbotData.tsx +8 -5
  38. package/src/hooks/useSessionMessages.tsx +0 -1
  39. package/src/hooks/useWebsocke.tsx +40 -18
  40. package/src/i18n.tsx +384 -10
  41. package/src/Chatbot/components/Messages/Carousel/CardSwiperSalla.tsx +0 -187
  42. package/src/Chatbot/components/Messages/Carousel/CardSwiperZid.tsx +0 -208
  43. package/src/Chatbot/components/Messages/Carousel/SallaSwiper.css +0 -245
  44. package/src/Chatbot/components/Messages/SallaAssistantMessage.tsx +0 -202
  45. package/src/Chatbot/components/Messages/ZidAssistantMesage.tsx +0 -203
  46. package/src/Chatbot/components/Sessions/RenderList.tsx +0 -519
@@ -1,203 +0,0 @@
1
- import React, { useState, useMemo, type FC } from 'react';
2
- import './ProductCard.css';
3
- import ZidProductCarousel from './Carousel/CardSwiperZid';
4
- import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons';
5
- import { Button } from 'antd';
6
- import { useKeenSlider } from 'keen-slider/react';
7
- import 'keen-slider/keen-slider.min.css';
8
-
9
- interface ProductVariant {
10
- name: string;
11
- price: string;
12
- link: string;
13
- image: string;
14
- variant_id: string;
15
- variant_tag_name: string;
16
- option?: string;
17
- }
18
-
19
- interface AssistantMessageProps {
20
- message: string;
21
- colorCode: string;
22
- isBusiness?: boolean;
23
- handleAddToCart: (variantId: string, name: string,variantImage:string,price:string, qty?: number) => Promise<void>;
24
- handleRemoveFromCart: (variantId: string, qty?: number) => Promise<void>;
25
- onTryOnSelect: (product: any) => void; // Add this
26
- enableTry:boolean;
27
- }
28
-
29
- const SallaAsssiatnt: FC<AssistantMessageProps> = ({
30
- message,
31
- colorCode,
32
- handleAddToCart,
33
- handleRemoveFromCart,
34
- onTryOnSelect,
35
- enableTry
36
-
37
- }) => {
38
- const [counts, setCounts] = useState<Record<string, number>>({});
39
- const [selectedVariants, setSelectedVariants] = useState<Record<string, string>>({});
40
-
41
- const formatTextWithLinks = (text: string): React.ReactNode[] => {
42
- const urlRegex = /(https?:\/\/[^\s]+)/g;
43
- return text.split(urlRegex).map((part, i) =>
44
- urlRegex.test(part) ? (
45
- <a
46
- key={i}
47
- href={part.trim()}
48
- style={{ color: '#00b3bc' }}
49
- target="_blank"
50
- rel="noopener noreferrer"
51
- className="underline break-words"
52
- >
53
- {part}
54
- </a>
55
- ) : (
56
- <span key={i}>{part}</span>
57
- )
58
- );
59
- };
60
-
61
- const extractProductDetails = (text: string): ProductVariant | null => {
62
- const normalized = text.trim();
63
- if (!normalized.includes('Name:') || !normalized.includes('VariantId')) return null;
64
- const nameMatch = normalized.match(/Name\s*[:\-]\s*(.+)/i);
65
- const priceMatch = normalized.match(/Price\s*[:\-]\s*(.+)/i);
66
- const linkMatch = normalized.match(/Link\s*[:\-]\s*(https?:\/\/[^\s]+)/i);
67
- const variantMatch = normalized.match(/VariantId\s*[:\-]\s*(.+)/i);
68
- const tagNameMatch = normalized.match(/variant_tag_name\s*[:\-]\s*(.+)/i);
69
- const OptionMatch = normalized.match(/options\s*[:\-]\s*([^|\r\n]+)/i);
70
- if (!nameMatch || !priceMatch || !linkMatch || !variantMatch || !tagNameMatch) return null;
71
- return {
72
- name: nameMatch[1].trim(),
73
- price: priceMatch[1].trim(),
74
- link: linkMatch[1].trim(),
75
- image: '',
76
- variant_id: variantMatch[1].trim(),
77
- variant_tag_name: tagNameMatch[1].trim(),
78
- option: OptionMatch?.[1]?.trim(),
79
- };
80
- };
81
-
82
- const parsedSegments = useMemo(() => {
83
- const parts = message.split('|||').map(p => p.trim()).filter(Boolean);
84
- const segments: { type: 'text' | 'product'; data: any }[] = [];
85
- let lastProduct: ProductVariant | null = null;
86
-
87
- parts.forEach(part => {
88
- if (part.startsWith('img - ')) {
89
- const url = part.replace(/^img\s*[-:]\s*/, '').trim();
90
- if (lastProduct) lastProduct.image = url;
91
- else {
92
- const lastSeg = [...segments].reverse().find(s => s.type === 'product');
93
- if (lastSeg) (lastSeg.data as ProductVariant).image = url;
94
- }
95
- } else if (part.includes('Name:') && part.includes('VariantId')) {
96
- const product = extractProductDetails(part);
97
- if (product) {
98
- segments.push({ type: 'product', data: product });
99
- lastProduct = product;
100
- }
101
- } else {
102
- segments.push({ type: 'text', data: part });
103
- lastProduct = null;
104
- }
105
- });
106
-
107
- return segments;
108
- }, [message]);
109
-
110
- const groupedProducts = useMemo(() => {
111
- const groups: Record<string, ProductVariant[]> = {};
112
- parsedSegments.forEach(seg => {
113
- if (seg.type === 'product') {
114
- const p = seg.data as ProductVariant;
115
- groups[p.variant_tag_name] = groups[p.variant_tag_name] || [];
116
- groups[p.variant_tag_name].push(p);
117
- }
118
- });
119
- return groups;
120
- }, [parsedSegments]);
121
-
122
- const shortenName = (name: string, maxLength = 22) =>
123
- name.length > maxLength ? name.slice(0, maxLength) + '...' : name;
124
-
125
-
126
-
127
- const [currentSlide, setCurrentSlide] = useState(0);
128
- const totalSlides =Object.keys(groupedProducts).length ;
129
- const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
130
- loop: false,
131
- mode: 'free',
132
- slides: { perView: 1, spacing: 16 },
133
- slideChanged(s) {
134
- setCurrentSlide(s.track.details.rel);
135
- },
136
- });
137
-
138
-
139
- return (
140
- <div className="space-y-6 mt-4 h-fit">
141
- {parsedSegments
142
- .filter(seg => seg.type === 'text')
143
- .map((seg, i) => (
144
- <p key={i} className="whitespace-pre-wrap break-words">
145
- {formatTextWithLinks(seg.data)}
146
- </p>
147
- ))}
148
-
149
-
150
-
151
- {Object.keys(groupedProducts).length > 0 && (
152
- <>
153
- {Object.keys(groupedProducts).length > 1 && (
154
- <div
155
- style={{
156
- display: 'flex',
157
- margin: 0,
158
- marginBottom: '6px',
159
- justifyContent: 'space-between',
160
- paddingInline: '4px',
161
- }}
162
- >
163
- <Button
164
- shape="circle"
165
- icon={<ArrowLeftOutlined />}
166
- onClick={() => slider.current?.prev()}
167
- disabled={currentSlide === 0}
168
- />
169
- <Button
170
- shape="circle"
171
- icon={<ArrowRightOutlined />}
172
- onClick={() => slider.current?.next()}
173
- disabled={currentSlide === totalSlides - 1}
174
- />
175
- </div>
176
- )}
177
- <div ref={sliderRef} className="keen-slider">
178
- <ZidProductCarousel
179
- groupedProducts={groupedProducts}
180
- selectedVariants={selectedVariants}
181
- setSelectedVariants={setSelectedVariants}
182
- counts={counts}
183
- setCounts={setCounts}
184
- handleAddToCart={handleAddToCart}
185
- handleRemoveFromCart={handleRemoveFromCart}
186
- colorCode={colorCode}
187
- shortenName={shortenName}
188
- sliderInstance={slider} // pass it down if needed
189
- currentSlide={currentSlide}
190
- totalSlides={totalSlides}
191
- sliderRef={sliderRef}
192
- onTryOnSelect={onTryOnSelect}
193
- enableTry={enableTry}
194
-
195
- />
196
- </div>
197
- </>
198
- )}
199
- </div>
200
- );
201
- };
202
-
203
- export default SallaAsssiatnt;