srs-heritage-chatbot 1.0.0

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 (187) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +194 -0
  3. package/lib/commonjs/assets/chat-icon-mobile.svg +1 -0
  4. package/lib/commonjs/assets/heritage.png +0 -0
  5. package/lib/commonjs/assets/posiden.svg +51 -0
  6. package/lib/commonjs/components/LoadingTips.js +104 -0
  7. package/lib/commonjs/components/LoadingTips.js.map +1 -0
  8. package/lib/commonjs/components/email.js +461 -0
  9. package/lib/commonjs/components/email.js.map +1 -0
  10. package/lib/commonjs/components/feedback.js +114 -0
  11. package/lib/commonjs/components/feedback.js.map +1 -0
  12. package/lib/commonjs/components/header.js +126 -0
  13. package/lib/commonjs/components/header.js.map +1 -0
  14. package/lib/commonjs/components/input.js +144 -0
  15. package/lib/commonjs/components/input.js.map +1 -0
  16. package/lib/commonjs/components/productCard.js +688 -0
  17. package/lib/commonjs/components/productCard.js.map +1 -0
  18. package/lib/commonjs/components/progressCircle.js +99 -0
  19. package/lib/commonjs/components/progressCircle.js.map +1 -0
  20. package/lib/commonjs/components/testing.js +74 -0
  21. package/lib/commonjs/components/testing.js.map +1 -0
  22. package/lib/commonjs/components/voice.js +184 -0
  23. package/lib/commonjs/components/voice.js.map +1 -0
  24. package/lib/commonjs/components/welcomeButton.js +149 -0
  25. package/lib/commonjs/components/welcomeButton.js.map +1 -0
  26. package/lib/commonjs/components/welcomeInput.js +137 -0
  27. package/lib/commonjs/components/welcomeInput.js.map +1 -0
  28. package/lib/commonjs/contexts/AppContext.js +552 -0
  29. package/lib/commonjs/contexts/AppContext.js.map +1 -0
  30. package/lib/commonjs/hooks/Stream.js +599 -0
  31. package/lib/commonjs/hooks/Stream.js.map +1 -0
  32. package/lib/commonjs/hooks/useAsyncStorage.js +36 -0
  33. package/lib/commonjs/hooks/useAsyncStorage.js.map +1 -0
  34. package/lib/commonjs/index.js +44 -0
  35. package/lib/commonjs/index.js.map +1 -0
  36. package/lib/commonjs/layout/disclaimer.js +208 -0
  37. package/lib/commonjs/layout/disclaimer.js.map +1 -0
  38. package/lib/commonjs/layout/ex.js +254 -0
  39. package/lib/commonjs/layout/ex.js.map +1 -0
  40. package/lib/commonjs/layout/icon.js +118 -0
  41. package/lib/commonjs/layout/icon.js.map +1 -0
  42. package/lib/commonjs/layout/layout.js +168 -0
  43. package/lib/commonjs/layout/layout.js.map +1 -0
  44. package/lib/commonjs/layout/welcome.js +160 -0
  45. package/lib/commonjs/layout/welcome.js.map +1 -0
  46. package/lib/commonjs/layout/window.js +396 -0
  47. package/lib/commonjs/layout/window.js.map +1 -0
  48. package/lib/commonjs/utils/audioRecorder.js +412 -0
  49. package/lib/commonjs/utils/audioRecorder.js.map +1 -0
  50. package/lib/commonjs/utils/cloudinary.js +69 -0
  51. package/lib/commonjs/utils/cloudinary.js.map +1 -0
  52. package/lib/commonjs/utils/storage.js +76 -0
  53. package/lib/commonjs/utils/storage.js.map +1 -0
  54. package/lib/commonjs/utils/textToSpeech.js +53 -0
  55. package/lib/commonjs/utils/textToSpeech.js.map +1 -0
  56. package/lib/module/assets/chat-icon-mobile.svg +1 -0
  57. package/lib/module/assets/heritage.png +0 -0
  58. package/lib/module/assets/posiden.svg +51 -0
  59. package/lib/module/components/LoadingTips.js +95 -0
  60. package/lib/module/components/LoadingTips.js.map +1 -0
  61. package/lib/module/components/email.js +452 -0
  62. package/lib/module/components/email.js.map +1 -0
  63. package/lib/module/components/feedback.js +105 -0
  64. package/lib/module/components/feedback.js.map +1 -0
  65. package/lib/module/components/header.js +117 -0
  66. package/lib/module/components/header.js.map +1 -0
  67. package/lib/module/components/input.js +135 -0
  68. package/lib/module/components/input.js.map +1 -0
  69. package/lib/module/components/productCard.js +679 -0
  70. package/lib/module/components/productCard.js.map +1 -0
  71. package/lib/module/components/progressCircle.js +91 -0
  72. package/lib/module/components/progressCircle.js.map +1 -0
  73. package/lib/module/components/testing.js +66 -0
  74. package/lib/module/components/testing.js.map +1 -0
  75. package/lib/module/components/voice.js +175 -0
  76. package/lib/module/components/voice.js.map +1 -0
  77. package/lib/module/components/welcomeButton.js +140 -0
  78. package/lib/module/components/welcomeButton.js.map +1 -0
  79. package/lib/module/components/welcomeInput.js +128 -0
  80. package/lib/module/components/welcomeInput.js.map +1 -0
  81. package/lib/module/contexts/AppContext.js +542 -0
  82. package/lib/module/contexts/AppContext.js.map +1 -0
  83. package/lib/module/hooks/Stream.js +592 -0
  84. package/lib/module/hooks/Stream.js.map +1 -0
  85. package/lib/module/hooks/useAsyncStorage.js +29 -0
  86. package/lib/module/hooks/useAsyncStorage.js.map +1 -0
  87. package/lib/module/index.js +36 -0
  88. package/lib/module/index.js.map +1 -0
  89. package/lib/module/layout/disclaimer.js +199 -0
  90. package/lib/module/layout/disclaimer.js.map +1 -0
  91. package/lib/module/layout/ex.js +253 -0
  92. package/lib/module/layout/ex.js.map +1 -0
  93. package/lib/module/layout/icon.js +108 -0
  94. package/lib/module/layout/icon.js.map +1 -0
  95. package/lib/module/layout/layout.js +160 -0
  96. package/lib/module/layout/layout.js.map +1 -0
  97. package/lib/module/layout/welcome.js +150 -0
  98. package/lib/module/layout/welcome.js.map +1 -0
  99. package/lib/module/layout/window.js +387 -0
  100. package/lib/module/layout/window.js.map +1 -0
  101. package/lib/module/utils/audioRecorder.js +398 -0
  102. package/lib/module/utils/audioRecorder.js.map +1 -0
  103. package/lib/module/utils/cloudinary.js +61 -0
  104. package/lib/module/utils/cloudinary.js.map +1 -0
  105. package/lib/module/utils/storage.js +67 -0
  106. package/lib/module/utils/storage.js.map +1 -0
  107. package/lib/module/utils/textToSpeech.js +43 -0
  108. package/lib/module/utils/textToSpeech.js.map +1 -0
  109. package/lib/typescript/components/LoadingTips.d.ts +3 -0
  110. package/lib/typescript/components/LoadingTips.d.ts.map +1 -0
  111. package/lib/typescript/components/email.d.ts +6 -0
  112. package/lib/typescript/components/email.d.ts.map +1 -0
  113. package/lib/typescript/components/feedback.d.ts +6 -0
  114. package/lib/typescript/components/feedback.d.ts.map +1 -0
  115. package/lib/typescript/components/header.d.ts +3 -0
  116. package/lib/typescript/components/header.d.ts.map +1 -0
  117. package/lib/typescript/components/input.d.ts +6 -0
  118. package/lib/typescript/components/input.d.ts.map +1 -0
  119. package/lib/typescript/components/productCard.d.ts +7 -0
  120. package/lib/typescript/components/productCard.d.ts.map +1 -0
  121. package/lib/typescript/components/progressCircle.d.ts +3 -0
  122. package/lib/typescript/components/progressCircle.d.ts.map +1 -0
  123. package/lib/typescript/components/testing.d.ts +6 -0
  124. package/lib/typescript/components/testing.d.ts.map +1 -0
  125. package/lib/typescript/components/voice.d.ts +5 -0
  126. package/lib/typescript/components/voice.d.ts.map +1 -0
  127. package/lib/typescript/components/welcomeButton.d.ts +4 -0
  128. package/lib/typescript/components/welcomeButton.d.ts.map +1 -0
  129. package/lib/typescript/components/welcomeInput.d.ts +6 -0
  130. package/lib/typescript/components/welcomeInput.d.ts.map +1 -0
  131. package/lib/typescript/contexts/AppContext.d.ts +10 -0
  132. package/lib/typescript/contexts/AppContext.d.ts.map +1 -0
  133. package/lib/typescript/hooks/Stream.d.ts +2 -0
  134. package/lib/typescript/hooks/Stream.d.ts.map +1 -0
  135. package/lib/typescript/hooks/useAsyncStorage.d.ts +2 -0
  136. package/lib/typescript/hooks/useAsyncStorage.d.ts.map +1 -0
  137. package/lib/typescript/index.d.ts +8 -0
  138. package/lib/typescript/index.d.ts.map +1 -0
  139. package/lib/typescript/layout/disclaimer.d.ts +5 -0
  140. package/lib/typescript/layout/disclaimer.d.ts.map +1 -0
  141. package/lib/typescript/layout/ex.d.ts +1 -0
  142. package/lib/typescript/layout/ex.d.ts.map +1 -0
  143. package/lib/typescript/layout/icon.d.ts +3 -0
  144. package/lib/typescript/layout/icon.d.ts.map +1 -0
  145. package/lib/typescript/layout/layout.d.ts +3 -0
  146. package/lib/typescript/layout/layout.d.ts.map +1 -0
  147. package/lib/typescript/layout/welcome.d.ts +6 -0
  148. package/lib/typescript/layout/welcome.d.ts.map +1 -0
  149. package/lib/typescript/layout/window.d.ts +5 -0
  150. package/lib/typescript/layout/window.d.ts.map +1 -0
  151. package/lib/typescript/utils/audioRecorder.d.ts +9 -0
  152. package/lib/typescript/utils/audioRecorder.d.ts.map +1 -0
  153. package/lib/typescript/utils/cloudinary.d.ts +17 -0
  154. package/lib/typescript/utils/cloudinary.d.ts.map +1 -0
  155. package/lib/typescript/utils/storage.d.ts +29 -0
  156. package/lib/typescript/utils/storage.d.ts.map +1 -0
  157. package/lib/typescript/utils/textToSpeech.d.ts +2 -0
  158. package/lib/typescript/utils/textToSpeech.d.ts.map +1 -0
  159. package/package.json +109 -0
  160. package/src/assets/chat-icon-mobile.svg +1 -0
  161. package/src/assets/heritage.png +0 -0
  162. package/src/assets/posiden.svg +51 -0
  163. package/src/components/LoadingTips.js +99 -0
  164. package/src/components/email.js +467 -0
  165. package/src/components/feedback.js +114 -0
  166. package/src/components/header.js +119 -0
  167. package/src/components/input.js +133 -0
  168. package/src/components/productCard.js +815 -0
  169. package/src/components/progressCircle.js +88 -0
  170. package/src/components/testing.js +60 -0
  171. package/src/components/voice.js +228 -0
  172. package/src/components/welcomeButton.js +161 -0
  173. package/src/components/welcomeInput.js +133 -0
  174. package/src/contexts/AppContext.js +678 -0
  175. package/src/hooks/Stream.js +655 -0
  176. package/src/hooks/useAsyncStorage.js +33 -0
  177. package/src/index.js +30 -0
  178. package/src/layout/disclaimer.js +231 -0
  179. package/src/layout/ex.js +252 -0
  180. package/src/layout/icon.js +105 -0
  181. package/src/layout/layout.js +160 -0
  182. package/src/layout/welcome.js +172 -0
  183. package/src/layout/window.js +476 -0
  184. package/src/utils/audioRecorder.js +445 -0
  185. package/src/utils/cloudinary.js +61 -0
  186. package/src/utils/storage.ts +89 -0
  187. package/src/utils/textToSpeech.js +49 -0
@@ -0,0 +1,655 @@
1
+ import React, { useState, useEffect, useRef, useContext } from 'react';
2
+ import { AppContext } from '../contexts/AppContext';
3
+
4
+ export function useWebSocketMessage() {
5
+ const {
6
+ setIsComplete,
7
+ startStreaming,
8
+ setMessages,
9
+ messages,
10
+ setGhostMessage,
11
+ data,
12
+ setTypingIndicator,
13
+ setStartStreaming,
14
+ lastUserMessage,
15
+ stopActivated,
16
+ sessionId,
17
+ setGhostCard,
18
+ BASE_URL,
19
+ setStopActivated,
20
+ setLastMessageId,
21
+ conversationStartTime,
22
+ } = useContext(AppContext);
23
+
24
+ const wsProtocol = 'wss://';
25
+ //const wsProtocol = 'ws://';
26
+ const wsUrl = BASE_URL.replace(/^http(s)?:\/\//, '');
27
+ const ENDPOINT = '/send/event';
28
+
29
+ const payload = {
30
+ customer_code: data.customer_code,
31
+ branch_code: data.branch_code, // "NBPISLA"
32
+ branch_full_name: data.branch_full_name,
33
+ customer_token: data.customer_token,
34
+ active_ship_to_information: {
35
+ shipToId: data.active_ship_to,
36
+ /* "customerId": 0,
37
+ "customerCode": "HPTA",
38
+ "shipToSequenceId": 1,
39
+ "customerShipToName": "HERITAGE PLUS TEST ACCOUNT",
40
+ "addressLine1": "7440 STATE HIGHWAY 121",
41
+ "addressLine2": "",
42
+ "addressLine3": "",
43
+ "city": "MCKINNEY",
44
+ "state": "TX",
45
+ "zipCode": "750702196",
46
+ "phone": "2144914149",
47
+ "fax": " ",
48
+ "orderAckEmail": "",
49
+ "customerPORequiredInd": "N",
50
+ "termsCode": "NET30",
51
+ "shipVia": "",
52
+ "salesPerson": "AS201585",
53
+ "salesPersonName": "",
54
+ "salesPersonCellPhone": "405-226-5844",
55
+ "salesPersonEmail": "Aaron.Spitz@heritagepsg.com",
56
+ "insideSalesPerson": "",
57
+ "secondarySalesPersonName": "",
58
+ "secondarySalesPersonEmail": null */
59
+ },
60
+ branch_details: data.branch_details,
61
+ /* branch_details: {
62
+ "active_branch_business_hours": "8:00 AM - 4:30 PM",
63
+ "active_branch_email": "OrdersHarrisburg@bel-aqua.com",
64
+ "active_branch_location": "Elizabethtown,PA",
65
+ "active_branch_name": "BEL-AQUA HARRISBURG",
66
+ "active_branch_phone": "(717)-689-3314",
67
+ "active_brand_name": "BEL-AQUA"
68
+ }, */
69
+ user_query: lastUserMessage,
70
+ session_id: data.session_id || data.session || sessionId,
71
+ conversation_start_time: conversationStartTime,
72
+ // /* customer_name: "Cristin Connerney",
73
+ user_UUID: data.user_id || 'mobile_user_unspecified',
74
+ device: 'mobile',
75
+ window_location: 'mobile',
76
+ };
77
+
78
+ const wsRef = useRef(null);
79
+
80
+ useEffect(() => {
81
+ if (startStreaming) {
82
+ console.log(payload, BASE_URL);
83
+ const socketUrl = `${wsProtocol}${wsUrl}${ENDPOINT}`;
84
+ console.log(socketUrl);
85
+
86
+ const ws = new WebSocket(socketUrl);
87
+ wsRef.current = ws;
88
+
89
+ ws.onopen = () => {
90
+ console.log('WebSocket connection established.');
91
+ ws.send(JSON.stringify(payload));
92
+ };
93
+
94
+ ws.onmessage = event => {
95
+ const response = JSON.parse(event.data);
96
+
97
+ if (response.type !== 'chunk') {
98
+ console.log(JSON.stringify(response, null, 2));
99
+ }
100
+ switch (response.type) {
101
+ case 'middle_message':
102
+ const middleMessage = {
103
+ type: 'middle',
104
+ text: response.message,
105
+ products: [],
106
+ product_cards: 'False',
107
+ };
108
+ setMessages([...messages, middleMessage]);
109
+ break;
110
+ case 'message':
111
+ if (
112
+ response.product_cards == 'False' ||
113
+ response.product_cards == false
114
+ ) {
115
+ setGhostMessage(false);
116
+ setTypingIndicator(false);
117
+ } else {
118
+ setGhostMessage(false);
119
+ setGhostCard(true);
120
+ }
121
+ const newMessage = {
122
+ type: 'ai',
123
+ message_id: response.message_id || '',
124
+ text: response.message,
125
+ feedback: 'True',
126
+ products: [],
127
+ product_cards: response.product_cards || 'False',
128
+ resource: response?.resource_details?.[0]?.link ?? '',
129
+ resource_type: response?.resource_details?.[0]?.type ?? '',
130
+ };
131
+ setMessages(prevMessages => [...prevMessages, newMessage]);
132
+ setLastMessageId(response.message_id);
133
+ break;
134
+ case 'chunk':
135
+ const newContent = response.chunk;
136
+ const newMessageId = response.message_id;
137
+
138
+ setMessages(prevMessages => {
139
+ if (
140
+ prevMessages.length > 0 &&
141
+ prevMessages[prevMessages.length - 1].type === 'ai'
142
+ ) {
143
+ return prevMessages.map((message, index) =>
144
+ index === prevMessages.length - 1
145
+ ? {
146
+ ...message,
147
+ text: message.text + newContent,
148
+ message_id: newMessageId || message.message_id,
149
+ feedback: 'True',
150
+ }
151
+ : message,
152
+ );
153
+ } else {
154
+ return [
155
+ ...prevMessages,
156
+ {
157
+ type: 'ai',
158
+ text: newContent,
159
+ message_id: newMessageId,
160
+ feedback: 'True',
161
+ },
162
+ ];
163
+ }
164
+ });
165
+ setGhostMessage(false);
166
+ if (newMessageId) {
167
+ setLastMessageId(newMessageId);
168
+ }
169
+ break;
170
+ case 'product_cards':
171
+ console.log(
172
+ '\n\n\n\nthis is for my own sanity: ',
173
+ response.products[0],
174
+ '\n\n\n\n',
175
+ );
176
+ setMessages(prevMessages => {
177
+ const lastMessageIndex = prevMessages.length - 1;
178
+
179
+ if (
180
+ prevMessages[lastMessageIndex] &&
181
+ prevMessages[lastMessageIndex].type === 'ai'
182
+ ) {
183
+ const expandedProducts = response.products.map(prod => ({
184
+ part_number: prod.part_number || '',
185
+ inventory_info: prod.inventory_info
186
+ ? {
187
+ default_uom: prod.inventory_info.default_uom || '',
188
+ is_valid: prod.inventory_info.is_valid || false,
189
+ info_by_uom: prod.inventory_info.info_by_uom
190
+ ? Object.keys(prod.inventory_info.info_by_uom).reduce(
191
+ (acc, key) => {
192
+ const value =
193
+ prod.inventory_info.info_by_uom[key] || {};
194
+ acc[key] = {
195
+ gross_price: value.gross_price ?? 0,
196
+ net_price: value.net_price ?? 0,
197
+ is_on_sale: value.is_on_sale ?? false,
198
+ quantity_available:
199
+ value.quantity_available ?? 0,
200
+ discounts: value.discounts ?? null,
201
+ min_pack_qty: value.min_pack_qty ?? 0,
202
+ };
203
+ return acc;
204
+ },
205
+ {},
206
+ )
207
+ : {},
208
+ }
209
+ : {},
210
+ product_details: prod.product_details
211
+ ? {
212
+ brand: prod.product_details.brand || '',
213
+ flow: prod.product_details.flow || '',
214
+ heritage_link: prod.product_details.heritage_link || '',
215
+ image_url: prod.product_details.image_url || '',
216
+ is_pump: prod.product_details.is_pump || '',
217
+ manufacturer_id:
218
+ prod.product_details.manufacturer_id || '',
219
+ mfg_number: prod.product_details.mfg_number || '',
220
+ part_number: prod.product_details.part_number || '',
221
+ product_description:
222
+ prod.product_details.product_description || '',
223
+ product_name: prod.product_details.product_name || '',
224
+ type: prod.product_details.type || '',
225
+ vertical: prod.product_details.vertical || '',
226
+ sku: prod.product_details.sku || '',
227
+ }
228
+ : {},
229
+ }));
230
+
231
+ const updatedLastMessage = {
232
+ ...prevMessages[lastMessageIndex],
233
+ products: expandedProducts,
234
+ product_cards: 'True',
235
+ };
236
+
237
+ return [
238
+ ...prevMessages.slice(0, lastMessageIndex),
239
+ updatedLastMessage,
240
+ ];
241
+ }
242
+
243
+ return prevMessages;
244
+ });
245
+
246
+ setGhostMessage(false);
247
+ setTypingIndicator(false);
248
+ setGhostCard(false);
249
+ break;
250
+ case 'product_document':
251
+ setMessages(prevMessages => {
252
+ const lastMessageIndex = prevMessages.length - 1;
253
+ if (
254
+ prevMessages[lastMessageIndex] &&
255
+ prevMessages[lastMessageIndex].type === 'ai'
256
+ ) {
257
+ const updatedLastMessage = {
258
+ ...prevMessages[lastMessageIndex],
259
+ resource: response?.resource_details?.[0]?.link ?? '',
260
+ resource_type: response?.resource_details?.[0]?.type ?? '',
261
+ };
262
+ return [
263
+ ...prevMessages.slice(0, lastMessageIndex),
264
+ updatedLastMessage,
265
+ ];
266
+ }
267
+ });
268
+ setGhostMessage(false);
269
+ setTypingIndicator(false);
270
+ setGhostCard(false);
271
+ break;
272
+ case 'suggested_questions':
273
+ setMessages(prevMessages => {
274
+ const lastMessageIndex = prevMessages.length - 1;
275
+ if (
276
+ prevMessages[lastMessageIndex] &&
277
+ prevMessages[lastMessageIndex].type === 'ai'
278
+ ) {
279
+ const updatedLastMessage = {
280
+ ...prevMessages[lastMessageIndex],
281
+ suggested_questions: true,
282
+ questions: response.suggested_questions,
283
+ };
284
+ return [
285
+ ...prevMessages.slice(0, lastMessageIndex),
286
+ updatedLastMessage,
287
+ ];
288
+ }
289
+ });
290
+ break;
291
+ case 'setComplete':
292
+ setTypingIndicator(false);
293
+ setStartStreaming(false);
294
+ setGhostCard(false);
295
+ break;
296
+ }
297
+ };
298
+
299
+ ws.onerror = error => {
300
+ setStartStreaming(false);
301
+ setGhostMessage(false);
302
+ setTypingIndicator(false);
303
+ setGhostCard(false);
304
+ };
305
+
306
+ ws.onclose = event => {
307
+ console.log('WebSocket connection closed:', event.reason);
308
+ setStartStreaming(false);
309
+ setGhostMessage(false);
310
+ setTypingIndicator(false);
311
+ setGhostCard(false);
312
+ };
313
+
314
+ return () => {
315
+ ws.close();
316
+ };
317
+ }
318
+ }, [startStreaming]);
319
+
320
+ useEffect(() => {
321
+ if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
322
+ wsRef.current.close();
323
+ setStartStreaming(false);
324
+ setGhostMessage(false);
325
+ setGhostCard(false);
326
+ setTypingIndicator(false);
327
+ setStopActivated(false);
328
+ }
329
+ }, [stopActivated, setStartStreaming]);
330
+ }
331
+
332
+ // import React, { useState, useEffect, useRef, useContext } from 'react';
333
+ // import { AppContext } from '../contexts/AppContext';
334
+ //
335
+ // export function useWebSocketMessage() {
336
+ // const {
337
+ // setIsComplete,
338
+ // startStreaming,
339
+ // setMessages,
340
+ // messages,
341
+ // setGhostMessage,
342
+ // data,
343
+ // setTypingIndicator,
344
+ // setStartStreaming,
345
+ // lastUserMessage,
346
+ // stopActivated,
347
+ // sessionId,
348
+ // setGhostCard,
349
+ // BASE_URL,
350
+ // setStopActivated,
351
+ // setLastMessageId,
352
+ // conversationStartTime,
353
+ // } = useContext(AppContext);
354
+ //
355
+ // const wsProtocol = 'wss://';
356
+ // const wsUrl = BASE_URL.replace(/^http(s)?:\/\//, '');
357
+ // const ENDPOINT = '/send/event';
358
+ //
359
+ // const payload = {
360
+ // customer_code: data.customer_code,
361
+ // branch_code: data.branch_code,
362
+ // branch_full_name: data.branch_full_name,
363
+ // customer_token: data.customer_token,
364
+ // active_ship_to_information: {
365
+ // shipToId: data.active_ship_to,
366
+ // },
367
+ // branch_details: data.branch_details,
368
+ // user_query: lastUserMessage,
369
+ // session_id: data.session_id || data.session || sessionId,
370
+ // conversation_start_time: conversationStartTime,
371
+ // user_UUID: data.user_id || 'mobile_user_unspecified',
372
+ // device: 'mobile',
373
+ // window_location: 'mobile',
374
+ // };
375
+ //
376
+ // const wsRef = useRef(null);
377
+ //
378
+ // useEffect(() => {
379
+ // if (startStreaming) {
380
+ // console.log(payload, BASE_URL);
381
+ // const socketUrl = `${wsProtocol}${wsUrl}${ENDPOINT}`;
382
+ // console.log(socketUrl);
383
+ //
384
+ // const ws = new WebSocket(socketUrl);
385
+ // wsRef.current = ws;
386
+ //
387
+ // ws.onopen = () => {
388
+ // console.log('WebSocket connection established.');
389
+ // ws.send(JSON.stringify(payload));
390
+ // };
391
+ //
392
+ // ws.onmessage = event => {
393
+ // const response = JSON.parse(event.data);
394
+ //
395
+ // if (response.type !== 'chunk') {
396
+ // console.log(JSON.stringify(response, null, 2));
397
+ // }
398
+ // switch (response.type) {
399
+ // case 'middle_message':
400
+ // const middleMessage = {
401
+ // type: 'middle',
402
+ // text: response.message,
403
+ // products: [],
404
+ // product_cards: 'False',
405
+ // };
406
+ // setMessages(prevMessages => [...prevMessages, middleMessage]);
407
+ // break;
408
+ // case 'message':
409
+ // if (
410
+ // response.product_cards == 'False' ||
411
+ // response.product_cards == false
412
+ // ) {
413
+ // setGhostMessage(false);
414
+ // setTypingIndicator(false);
415
+ // } else {
416
+ // setGhostMessage(false);
417
+ // setGhostCard(true);
418
+ // }
419
+ // const newMessage = {
420
+ // type: 'ai',
421
+ // message_id: response.message_id || '',
422
+ // text: response.message,
423
+ // feedback: 'True',
424
+ // products: [],
425
+ // product_cards: response.product_cards || 'False',
426
+ // resource: response?.resource_details?.[0]?.link ?? '',
427
+ // resource_type: response?.resource_details?.[0]?.type ?? '',
428
+ // };
429
+ // setMessages(prevMessages => [...prevMessages, newMessage]);
430
+ // setLastMessageId(response.message_id);
431
+ // break;
432
+ // case 'chunk':
433
+ // const newContent = response.chunk;
434
+ // const newMessageId = response.message_id;
435
+ //
436
+ // setMessages(prevMessages => {
437
+ // if (
438
+ // prevMessages.length > 0 &&
439
+ // prevMessages[prevMessages.length - 1].type === 'ai'
440
+ // ) {
441
+ // return prevMessages.map((message, index) =>
442
+ // index === prevMessages.length - 1
443
+ // ? {
444
+ // ...message,
445
+ // text: message.text + newContent,
446
+ // message_id: newMessageId || message.message_id,
447
+ // feedback: 'True',
448
+ // }
449
+ // : message,
450
+ // );
451
+ // } else {
452
+ // return [
453
+ // ...prevMessages,
454
+ // {
455
+ // type: 'ai',
456
+ // text: newContent,
457
+ // message_id: newMessageId,
458
+ // feedback: 'True',
459
+ // },
460
+ // ];
461
+ // }
462
+ // });
463
+ // setGhostMessage(false);
464
+ // if (newMessageId) {
465
+ // setLastMessageId(newMessageId);
466
+ // }
467
+ // break;
468
+ // case 'product_cards':
469
+ // console.log('🛒 PRODUCT_CARDS RECEIVED:', response);
470
+ // setMessages(prevMessages => {
471
+ // console.log(
472
+ // '📦 Current messages array length:',
473
+ // prevMessages.length,
474
+ // );
475
+ // const lastMessageIndex = prevMessages.length - 1;
476
+ //
477
+ // if (lastMessageIndex < 0) {
478
+ // console.warn('⚠️ No messages exist yet!');
479
+ // return prevMessages;
480
+ // }
481
+ //
482
+ // const lastMessage = prevMessages[lastMessageIndex];
483
+ // console.log('📝 Last message:', {
484
+ // type: lastMessage?.type,
485
+ // message_id: lastMessage?.message_id,
486
+ // has_products: !!lastMessage?.products,
487
+ // text_preview: lastMessage?.text?.substring(0, 50),
488
+ // });
489
+ //
490
+ // if (lastMessage && lastMessage.type === 'ai') {
491
+ // const expandedProducts = response.products.map(prod => ({
492
+ // part_number: prod.part_number || '',
493
+ // inventory_info: prod.inventory_info
494
+ // ? {
495
+ // default_uom: prod.inventory_info.default_uom || '',
496
+ // is_valid: prod.inventory_info.is_valid || false,
497
+ // info_by_uom: prod.inventory_info.info_by_uom
498
+ // ? Object.keys(prod.inventory_info.info_by_uom).reduce(
499
+ // (acc, key) => {
500
+ // const value =
501
+ // prod.inventory_info.info_by_uom[key] || {};
502
+ // acc[key] = {
503
+ // gross_price: value.gross_price ?? 0,
504
+ // net_price: value.net_price ?? 0,
505
+ // is_on_sale: value.is_on_sale ?? false,
506
+ // quantity_available:
507
+ // value.quantity_available ?? 0,
508
+ // discounts: value.discounts ?? null,
509
+ // min_pack_qty: value.min_pack_qty ?? 0,
510
+ // };
511
+ // return acc;
512
+ // },
513
+ // {},
514
+ // )
515
+ // : {},
516
+ // }
517
+ // : {},
518
+ // product_details: prod.product_details
519
+ // ? {
520
+ // brand: prod.product_details.brand || '',
521
+ // flow: prod.product_details.flow || '',
522
+ // heritage_link: prod.product_details.heritage_link || '',
523
+ // image_url: prod.product_details.image_url || '',
524
+ // is_pump: prod.product_details.is_pump || '',
525
+ // manufacturer_id:
526
+ // prod.product_details.manufacturer_id || '',
527
+ // mfg_number: prod.product_details.mfg_number || '',
528
+ // part_number: prod.product_details.part_number || '',
529
+ // product_description:
530
+ // prod.product_details.product_description || '',
531
+ // product_name: prod.product_details.product_name || '',
532
+ // type: prod.product_details.type || '',
533
+ // vertical: prod.product_details.vertical || '',
534
+ // sku: prod.product_details.sku || '',
535
+ // }
536
+ // : {},
537
+ // }));
538
+ //
539
+ // console.log(
540
+ // '✅ Merging',
541
+ // expandedProducts.length,
542
+ // 'products into last message',
543
+ // );
544
+ //
545
+ // const updatedLastMessage = {
546
+ // ...lastMessage,
547
+ // products: expandedProducts,
548
+ // product_cards: 'True',
549
+ // };
550
+ //
551
+ // const newMessages = [
552
+ // ...prevMessages.slice(0, lastMessageIndex),
553
+ // updatedLastMessage,
554
+ // ];
555
+ //
556
+ // console.log(
557
+ // '🎯 Updated message now has products:',
558
+ // updatedLastMessage.products.length,
559
+ // );
560
+ // return newMessages;
561
+ // }
562
+ //
563
+ // console.warn("⚠️ Last message is not AI type or doesn't exist");
564
+ // return prevMessages;
565
+ // });
566
+ //
567
+ // setGhostMessage(false);
568
+ // setTypingIndicator(false);
569
+ // setGhostCard(false);
570
+ // break;
571
+ // case 'product_document':
572
+ // setMessages(prevMessages => {
573
+ // const lastMessageIndex = prevMessages.length - 1;
574
+ // if (
575
+ // prevMessages[lastMessageIndex] &&
576
+ // prevMessages[lastMessageIndex].type === 'ai'
577
+ // ) {
578
+ // const updatedLastMessage = {
579
+ // ...prevMessages[lastMessageIndex],
580
+ // resource: response?.resource_details?.[0]?.link ?? '',
581
+ // resource_type: response?.resource_details?.[0]?.type ?? '',
582
+ // };
583
+ // return [
584
+ // ...prevMessages.slice(0, lastMessageIndex),
585
+ // updatedLastMessage,
586
+ // ];
587
+ // }
588
+ // // FIX: Always return prevMessages if condition not met
589
+ // return prevMessages;
590
+ // });
591
+ // setGhostMessage(false);
592
+ // setTypingIndicator(false);
593
+ // setGhostCard(false);
594
+ // break;
595
+ // case 'suggested_questions':
596
+ // setMessages(prevMessages => {
597
+ // const lastMessageIndex = prevMessages.length - 1;
598
+ // if (
599
+ // prevMessages[lastMessageIndex] &&
600
+ // prevMessages[lastMessageIndex].type === 'ai'
601
+ // ) {
602
+ // const updatedLastMessage = {
603
+ // ...prevMessages[lastMessageIndex],
604
+ // suggested_questions: true,
605
+ // questions: response.suggested_questions,
606
+ // };
607
+ // return [
608
+ // ...prevMessages.slice(0, lastMessageIndex),
609
+ // updatedLastMessage,
610
+ // ];
611
+ // }
612
+ // // FIX: Always return prevMessages if condition not met
613
+ // return prevMessages;
614
+ // });
615
+ // break;
616
+ // case 'setComplete':
617
+ // setTypingIndicator(false);
618
+ // setStartStreaming(false);
619
+ // setGhostCard(false);
620
+ // break;
621
+ // }
622
+ // };
623
+ //
624
+ // ws.onerror = error => {
625
+ // setStartStreaming(false);
626
+ // setGhostMessage(false);
627
+ // setTypingIndicator(false);
628
+ // setGhostCard(false);
629
+ // };
630
+ //
631
+ // ws.onclose = event => {
632
+ // console.log('WebSocket connection closed:', event.reason);
633
+ // setStartStreaming(false);
634
+ // setGhostMessage(false);
635
+ // setTypingIndicator(false);
636
+ // setGhostCard(false);
637
+ // };
638
+ //
639
+ // return () => {
640
+ // ws.close();
641
+ // };
642
+ // }
643
+ // }, [startStreaming]);
644
+ //
645
+ // useEffect(() => {
646
+ // if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
647
+ // wsRef.current.close();
648
+ // setStartStreaming(false);
649
+ // setGhostMessage(false);
650
+ // setGhostCard(false);
651
+ // setTypingIndicator(false);
652
+ // setStopActivated(false);
653
+ // }
654
+ // }, [stopActivated, setStartStreaming]);
655
+ // }
@@ -0,0 +1,33 @@
1
+ import { useState, useEffect } from 'react';
2
+ import AsyncStorage from '@react-native-async-storage/async-storage';
3
+
4
+ export default function useAsyncStorage(key, defaultValue) {
5
+ const [value, setValue] = useState(defaultValue);
6
+
7
+ useEffect(() => {
8
+ const loadValue = async () => {
9
+ try {
10
+ const storedValue = await AsyncStorage.getItem(key);
11
+ if (storedValue !== null) {
12
+ setValue(JSON.parse(storedValue));
13
+ }
14
+ } catch (error) {
15
+ console.error(`Error loading data for key "${key}":`, error);
16
+ }
17
+ };
18
+
19
+ loadValue();
20
+ }, [key]);
21
+
22
+ const setValueInAsyncStorage = async (newValue) => {
23
+ try {
24
+ const result = typeof newValue === 'function' ? newValue(value) : newValue;
25
+ setValue(result);
26
+ await AsyncStorage.setItem(key, JSON.stringify(result));
27
+ } catch (error) {
28
+ console.error(`Error saving data for key "${key}":`, error);
29
+ }
30
+ };
31
+
32
+ return [value, setValueInAsyncStorage];
33
+ }