react-native-srschat 0.1.13 → 0.1.15

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 (140) hide show
  1. package/lib/commonjs/components/email.js +243 -0
  2. package/lib/commonjs/components/email.js.map +1 -0
  3. package/lib/commonjs/components/feedback.js +115 -0
  4. package/lib/commonjs/components/feedback.js.map +1 -0
  5. package/lib/commonjs/components/header.js +35 -17
  6. package/lib/commonjs/components/header.js.map +1 -1
  7. package/lib/commonjs/components/input.js +106 -0
  8. package/lib/commonjs/components/input.js.map +1 -0
  9. package/lib/commonjs/components/productCard.js +234 -0
  10. package/lib/commonjs/components/productCard.js.map +1 -0
  11. package/lib/commonjs/components/testing.js +19 -6
  12. package/lib/commonjs/components/testing.js.map +1 -1
  13. package/lib/commonjs/{layout/chatIcon.js → components/welcomeButton.js} +40 -37
  14. package/lib/commonjs/components/welcomeButton.js.map +1 -0
  15. package/lib/commonjs/components/welcomeInput.js +87 -0
  16. package/lib/commonjs/components/welcomeInput.js.map +1 -0
  17. package/lib/commonjs/contexts/AppContext.js +272 -56
  18. package/lib/commonjs/contexts/AppContext.js.map +1 -1
  19. package/lib/commonjs/hooks/{Stream.js → stream.js} +107 -39
  20. package/lib/commonjs/hooks/stream.js.map +1 -0
  21. package/lib/commonjs/hooks/useAsyncStorage.js +36 -0
  22. package/lib/commonjs/hooks/useAsyncStorage.js.map +1 -0
  23. package/lib/commonjs/index.js +13 -6
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/layout/disclaimer.js +200 -0
  26. package/lib/commonjs/layout/disclaimer.js.map +1 -0
  27. package/lib/commonjs/layout/ex.js +272 -0
  28. package/lib/commonjs/layout/ex.js.map +1 -0
  29. package/lib/commonjs/layout/icon.js +114 -0
  30. package/lib/commonjs/layout/icon.js.map +1 -0
  31. package/lib/commonjs/layout/layout.js +148 -14
  32. package/lib/commonjs/layout/layout.js.map +1 -1
  33. package/lib/commonjs/layout/welcome.js +135 -0
  34. package/lib/commonjs/layout/welcome.js.map +1 -0
  35. package/lib/commonjs/layout/window.js +205 -0
  36. package/lib/commonjs/layout/window.js.map +1 -0
  37. package/lib/module/components/email.js +233 -0
  38. package/lib/module/components/email.js.map +1 -0
  39. package/lib/module/components/feedback.js +105 -0
  40. package/lib/module/components/feedback.js.map +1 -0
  41. package/lib/module/components/header.js +35 -17
  42. package/lib/module/components/header.js.map +1 -1
  43. package/lib/module/components/input.js +96 -0
  44. package/lib/module/components/input.js.map +1 -0
  45. package/lib/module/components/productCard.js +225 -0
  46. package/lib/module/components/productCard.js.map +1 -0
  47. package/lib/module/components/testing.js +20 -7
  48. package/lib/module/components/testing.js.map +1 -1
  49. package/lib/module/components/welcomeButton.js +48 -0
  50. package/lib/module/components/welcomeButton.js.map +1 -0
  51. package/lib/module/components/welcomeInput.js +77 -0
  52. package/lib/module/components/welcomeInput.js.map +1 -0
  53. package/lib/module/contexts/AppContext.js +272 -57
  54. package/lib/module/contexts/AppContext.js.map +1 -1
  55. package/lib/module/hooks/{Stream.js → stream.js} +107 -39
  56. package/lib/module/hooks/stream.js.map +1 -0
  57. package/lib/module/hooks/useAsyncStorage.js +29 -0
  58. package/lib/module/hooks/useAsyncStorage.js.map +1 -0
  59. package/lib/module/index.js +13 -6
  60. package/lib/module/index.js.map +1 -1
  61. package/lib/module/layout/disclaimer.js +190 -0
  62. package/lib/module/layout/disclaimer.js.map +1 -0
  63. package/lib/module/layout/ex.js +262 -0
  64. package/lib/module/layout/ex.js.map +1 -0
  65. package/lib/module/layout/icon.js +104 -0
  66. package/lib/module/layout/icon.js.map +1 -0
  67. package/lib/module/layout/layout.js +150 -16
  68. package/lib/module/layout/layout.js.map +1 -1
  69. package/lib/module/layout/welcome.js +126 -0
  70. package/lib/module/layout/welcome.js.map +1 -0
  71. package/lib/module/layout/window.js +195 -0
  72. package/lib/module/layout/window.js.map +1 -0
  73. package/lib/typescript/components/email.d.ts +5 -0
  74. package/lib/typescript/components/email.d.ts.map +1 -0
  75. package/lib/typescript/components/feedback.d.ts +6 -0
  76. package/lib/typescript/components/feedback.d.ts.map +1 -0
  77. package/lib/typescript/components/header.d.ts.map +1 -1
  78. package/lib/typescript/components/input.d.ts +6 -0
  79. package/lib/typescript/components/input.d.ts.map +1 -0
  80. package/lib/typescript/components/productCard.d.ts +5 -0
  81. package/lib/typescript/components/productCard.d.ts.map +1 -0
  82. package/lib/typescript/components/testing.d.ts.map +1 -1
  83. package/lib/typescript/components/welcomeButton.d.ts +4 -0
  84. package/lib/typescript/components/welcomeButton.d.ts.map +1 -0
  85. package/lib/typescript/components/welcomeInput.d.ts +6 -0
  86. package/lib/typescript/components/welcomeInput.d.ts.map +1 -0
  87. package/lib/typescript/contexts/AppContext.d.ts +5 -1
  88. package/lib/typescript/contexts/AppContext.d.ts.map +1 -1
  89. package/lib/typescript/hooks/{Stream.d.ts → stream.d.ts} +1 -1
  90. package/lib/typescript/hooks/stream.d.ts.map +1 -0
  91. package/lib/typescript/hooks/useAsyncStorage.d.ts +2 -0
  92. package/lib/typescript/hooks/useAsyncStorage.d.ts.map +1 -0
  93. package/lib/typescript/index.d.ts +2 -1
  94. package/lib/typescript/index.d.ts.map +1 -1
  95. package/lib/typescript/layout/disclaimer.d.ts +5 -0
  96. package/lib/typescript/layout/disclaimer.d.ts.map +1 -0
  97. package/lib/typescript/layout/ex.d.ts +3 -0
  98. package/lib/typescript/layout/ex.d.ts.map +1 -0
  99. package/lib/typescript/layout/{chatIcon.d.ts → icon.d.ts} +1 -1
  100. package/lib/typescript/layout/icon.d.ts.map +1 -0
  101. package/lib/typescript/layout/layout.d.ts +1 -4
  102. package/lib/typescript/layout/layout.d.ts.map +1 -1
  103. package/lib/typescript/layout/welcome.d.ts +5 -0
  104. package/lib/typescript/layout/welcome.d.ts.map +1 -0
  105. package/lib/typescript/layout/window.d.ts +5 -0
  106. package/lib/typescript/layout/window.d.ts.map +1 -0
  107. package/package.json +7 -1
  108. package/src/components/email.js +210 -0
  109. package/src/components/feedback.js +114 -0
  110. package/src/components/header.js +32 -17
  111. package/src/components/input.js +95 -0
  112. package/src/components/productCard.js +240 -0
  113. package/src/components/testing.js +17 -4
  114. package/src/components/welcomeButton.js +51 -0
  115. package/src/components/welcomeInput.js +81 -0
  116. package/src/contexts/AppContext.js +237 -52
  117. package/src/hooks/{Stream.js → stream.js} +123 -41
  118. package/src/hooks/useAsyncStorage.js +33 -0
  119. package/src/index.js +7 -3
  120. package/src/layout/disclaimer.js +187 -0
  121. package/src/layout/ex.js +251 -0
  122. package/src/layout/icon.js +96 -0
  123. package/src/layout/layout.js +137 -10
  124. package/src/layout/welcome.js +124 -0
  125. package/src/layout/window.js +194 -0
  126. package/lib/commonjs/hooks/Stream.js.map +0 -1
  127. package/lib/commonjs/layout/chatIcon.js.map +0 -1
  128. package/lib/commonjs/layout/chatWindow.js +0 -214
  129. package/lib/commonjs/layout/chatWindow.js.map +0 -1
  130. package/lib/module/hooks/Stream.js.map +0 -1
  131. package/lib/module/layout/chatIcon.js +0 -44
  132. package/lib/module/layout/chatIcon.js.map +0 -1
  133. package/lib/module/layout/chatWindow.js +0 -204
  134. package/lib/module/layout/chatWindow.js.map +0 -1
  135. package/lib/typescript/hooks/Stream.d.ts.map +0 -1
  136. package/lib/typescript/layout/chatIcon.d.ts.map +0 -1
  137. package/lib/typescript/layout/chatWindow.d.ts +0 -6
  138. package/lib/typescript/layout/chatWindow.d.ts.map +0 -1
  139. package/src/layout/chatIcon.js +0 -38
  140. package/src/layout/chatWindow.js +0 -207
@@ -1,80 +1,265 @@
1
- import React, {createContext, useContext, useState, useEffect } from "react";
1
+ import React, {createContext, useContext, useState, useEffect, useMemo } from "react";
2
+ import uuid from 'react-native-uuid';
3
+ import axios from "axios";
4
+ import useAsyncStorage from '../hooks/useAsyncStorage';
2
5
 
3
6
  export const AppContext = createContext();
4
7
 
5
- export const AppProvider = ({ children }) => {
8
+ export const AppProvider = ({ data, onProductCardClick, onAddToCartClick, uiConfig = {}, children }) => {
6
9
 
7
- const [showModal, setShowModal] = useState("Icon");
10
+ const theme = {
11
+ userMessage: '#003764',
12
+ botMessage: '#003764',
13
+ backgroundColor: '#f6f6f6',
14
+ textColor: '#161616',
15
+ textColorSecondary: '#FFFFFF',
16
+ inlineButtonColor: '#dbd4c8'
17
+ };
18
+
19
+ // Backend URLs
20
+ const BASE_URL = "srs-external-agent-backend-586731320826.us-central1.run.app";
21
+ const LOGGING_URL = "srs-external-agent-logging-ve7hwyltsq-uc.a.run.app";
22
+ const API_PREFIX = "https://";
23
+
24
+ // Default Messages
25
+ const defaultMessage = [
26
+ {type: "ai", text: "Hi there 👋 I’m Poseidon, your Heritage Pool+ AI Agent. I can help you during your online visit with Product and Account information. How can I help you today?"}
27
+ ]
8
28
 
29
+ const maintenanceMessage = [
30
+ { type: "ai", text: "Hi there 👋 I’m Poseidon, your Heritage Pool+ AI Agent. I'm currently undergoing maintenance to improve my services. Thank you for your patience and understanding!",},
31
+ ];
32
+
33
+ // Base Variables
34
+ const [showModal, setShowModal] = useState("Icon");
9
35
  const [input, setInput] = useState('');
10
- const [messages, setMessages] = useState([
11
- {type: "ai", text: "Hi there 👋 I’m Poseidon, your Heritage Pool+ AI Agent. I can help you during your online visit with Product and Account information. How can I help you today?"},
12
- {type: "user", text: "Do you carry Hayward super pumps?"},
13
- {type: "ai", text: "Could you provide more details on the specific model or horsepower you are interested in for the Hayward Super Pump? We have various models with different features, such as variable speed settings and different horsepower ratings. Alternatively, I can offer you some recommendations right away to help you decide."},
14
- ]);
36
+ const [messages, setMessages] = useState(defaultMessage);
37
+ const [conversationStartTime, setConversationStartTime] = useState(null);
38
+ const [lastUserMessage, setLastUserMessage] = useState("");
39
+ const [lastMessageId, setLastMessageId] = useState("");
40
+ const [sessionId, setSessionId] = useState(null);
15
41
 
16
- const handleSend = async () => {
17
- if (!input.trim()) return;
42
+ useEffect(() => {
43
+ const newSessionId = uuid.v4(); // Generate UUID v4
44
+ setSessionId(newSessionId);
45
+ }, []);
18
46
 
19
- const userMessage = input;
20
- setInput('');
47
+ useEffect(() => {
48
+ if (showModal == "Off") {
49
+ setShowModal("Icon")
50
+ }
51
+ }, [uiConfig.showIcon]);
21
52
 
22
- // Add user message to the list
23
- setMessages((prev) => [...prev, { type: "user", text: userMessage }]);
53
+ // Message UI
54
+ const [typingIndicator, setTypingIndicator] = useState(false);
55
+ const [ghostMessage, setGhostMessage] = useState(false);
56
+ const [ghostCard, setGhostCard] = useState(false);
57
+ const [stopActivated, setStopActivated] = useState(false);
58
+ const [disclaimer, setDisclaimer] = useState(false);
59
+ const [startStreaming, setStartStreaming] = useState(false);
24
60
 
25
- try {
26
- // Add placeholder for AI message
27
- setMessages((prev) => [...prev, { type: "ai", text: '' }]);
28
-
29
- // Simulate response with streaming
30
- const response = await onSendMessage(userMessage, (chunk) => {
31
- setMessages((prev) => {
32
- const newMessages = [...prev];
33
- const lastMessage = newMessages[newMessages.length - 1];
34
- if (lastMessage && lastMessage.type === "ai") {
35
- lastMessage.text += chunk;
36
- }
37
- return newMessages;
38
- });
39
- });
61
+ const stopGenerating = () => {
62
+ setTypingIndicator(false);
63
+ setStopActivated(true);
64
+ };
65
+
66
+ function handleSend(input) {
67
+ if (maintenance) {
68
+ setMessages([ ...messages, { type: "user", text: input },
69
+ { type: "ai", text: "The chat is currently unavailable, please come back later!",},]);
70
+ return;
71
+ }
72
+ if (input.trim() !== "") {
73
+ if (messages.length <= 1) {
74
+ const startTime = new Date().toISOString();
75
+ setConversationStartTime(startTime);
76
+ }
77
+
78
+ // Initiate streaming
79
+ setShowModal("ChatWindow");
80
+ setLastUserMessage(input);
81
+ setMessages([...messages, { type: "user", text: input }]);
82
+ setTypingIndicator(true);
83
+ setGhostMessage(true);
84
+ setStartStreaming(true);
85
+ setInput("")
86
+ }
87
+ }
40
88
 
41
- // Finalize AI response
42
- setMessages((prev) => {
43
- const newMessages = [...prev];
44
- const lastMessage = newMessages[newMessages.length - 1];
45
- if (lastMessage && lastMessage.type === "ai" && lastMessage.text !== response) {
46
- lastMessage.text = response;
89
+ // After form submission
90
+ function setNextMessage(name) {
91
+ setMessages((prevMessages) => {
92
+ const updatedMessages = prevMessages.map((message, index) => {
93
+ if (index === prevMessages.length - 1 && message.form) {
94
+ return { ...message, form: false };
47
95
  }
48
- return newMessages;
96
+ return message;
49
97
  });
98
+
99
+ const nextMessage = {
100
+ type: "ai",
101
+ text: [`Nice to meet you ${name}. How can I help you today?`],
102
+ };
103
+ return [...updatedMessages, nextMessage];
104
+ });
105
+ }
106
+
107
+ // Confirm Disclaimer
108
+ async function confirmDisclaimer() {
109
+ setDisclaimer(true);
110
+ if (!maintenance) {
111
+ setShowModal("Welcome");
112
+ setMessages(defaultMessage);
113
+ } else {
114
+ setShowModal("ChatWindow");
115
+ setMessages(maintenanceMessage);
116
+ }
117
+ try {
118
+ const response = await axios.post(
119
+ API_PREFIX + LOGGING_URL + "/log-disclaimer",
120
+ { email: "cristin@instalily.ai" },
121
+ );
50
122
  } catch (error) {
51
- console.error('Error sending message:', error);
123
+ console.error("Error in Log disclaimer:", error);
124
+ }
125
+ }
126
+
127
+ function handleButtonClick(buttonText) {
128
+ handleSend(buttonText);
129
+ }
130
+
131
+ const [maintenance, setMaintenance] = useState(false);
132
+
133
+ const handleClearState = async () => {
134
+ if (!maintenance) {
135
+ setShowModal("Welcome");
136
+ }
137
+ if (messages.length > 1) {
138
+ if (maintenance) {
139
+ setMessages(maintenanceMessage);
140
+ } else {
141
+ setMessages(defaultMessage);
142
+ }
143
+ const newSessionId = uuid.v4();
144
+ setSessionId(newSessionId);
145
+ setTypingIndicator(false);
146
+ setGhostMessage(false);
147
+ /* try {
148
+ const response = await axios.post(API_PREFIX + BASE_URL + "/clear", {
149
+ customer_code: data.customer_code,
150
+ session_id: data.session_id,
151
+ message_id: lastMessageId,
152
+ user_UUID: data.user_UUID,
153
+ });
154
+ console.log(response);
155
+ } catch (error) {
156
+ console.error("Error in Clear:", error);
157
+ } */
52
158
  }
53
159
  };
54
160
 
55
- const onSendMessage = async (message, onStream) => {
56
- try {
57
- if (onStream) {
58
- const words = `You said: ${message}`.split(' ');
59
- for (const word of words) {
60
- await new Promise((resolve) => setTimeout(resolve, 100));
61
- onStream(word + ' ');
62
- }
63
- return `You said: ${message}`;
161
+ const [feedback, setFeedback] = useState({});
162
+
163
+ async function handleFeedback(feedbackValue, messageId) {
164
+ switchFeedbackOpen(true, messageId, true);
165
+ setFeedback((prevFeedback) => {
166
+ const updatedFeedback = { ...prevFeedback };
167
+
168
+ if (!updatedFeedback[messageId]) {
169
+ updatedFeedback[messageId] = 0;
64
170
  }
65
171
 
66
- await new Promise((resolve) => setTimeout(resolve, 1000));
67
- return `You said: ${message}`;
172
+ updatedFeedback[messageId] = feedbackValue;
173
+
174
+ return updatedFeedback;
175
+ });
176
+ try {
177
+ const response = await axios.post(
178
+ API_PREFIX + LOGGING_URL + "/feedback",
179
+ {
180
+ message_id: messageId,
181
+ feedback: feedbackValue,
182
+ },
183
+ );
184
+ //console.log(response)
68
185
  } catch (error) {
69
- console.error('Error handling message:', error);
70
- return 'Error processing message';
186
+ console.error("Error in feedback post:", error);
71
187
  }
72
- };
188
+ }
73
189
 
190
+ const [feedbackOpen, setFeedbackOpen] = useState({});
191
+ const [writeFeedback, setWriteFeedback] = useState("");
192
+ const [writeAnswer, setWriteAnswer] = useState("");
193
+
194
+ // Written Feedback ----------------------------
195
+
196
+ function switchFeedbackOpen(newVal, messageId, resetvalue) {
197
+ console.log(newVal,feedbackOpen[messageId], messageId, resetvalue)
198
+ console.log(feedbackOpen)
199
+ if (newVal != feedbackOpen[messageId]) {
200
+ setWriteFeedback("");
201
+ setWriteAnswer("");
202
+ }
203
+ if (resetvalue) {
204
+ setWriteFeedback("");
205
+ setWriteAnswer("");
206
+ }
207
+ if (feedbackOpen[messageId] == "done") {
208
+ return;
209
+ }
210
+ setFeedbackOpen((prevFeedback) => {
211
+ const updatedFeedback = { ...prevFeedback };
212
+ updatedFeedback[messageId] = newVal;
213
+ return updatedFeedback;
214
+ });
215
+ console.log(feedbackOpen)
216
+ }
217
+
218
+ async function handleWrittenFeedback(messageId) {
219
+ if (writeFeedback.trim() !== "" || writeAnswer.trim() !== "") {
220
+ //console.log(messageId, writeFeedback)
221
+ switchFeedbackOpen(-1, messageId, true);
222
+ try {
223
+ const response = await axios.post(
224
+ API_PREFIX + LOGGING_URL + "/feedback-message",
225
+ {
226
+ message_id: messageId,
227
+ feedback_message: writeFeedback,
228
+ correct_answer: writeAnswer,
229
+ },
230
+ );
231
+ //console.log(response)
232
+ } catch (error) {
233
+ console.error("Error in feedback_message:", error);
234
+ }
235
+ }
236
+ }
237
+
238
+ const formatChatHistory = () => {
239
+ // Skip the first message (index 0) which is the welcome message
240
+ return messages.slice(1).map((message) => {
241
+ if (Array.isArray(message.text)) {
242
+ return {
243
+ type: message.type,
244
+ content: message.text.join("\n"),
245
+ };
246
+ }
247
+ return {
248
+ type: message.type,
249
+ content: message.text,
250
+ };
251
+ });
252
+ };
74
253
 
75
254
  return (
76
255
  <AppContext.Provider
77
- value={{ showModal, setShowModal, messages, setMessages, handleSend, onSendMessage, input, setInput
256
+ value={{ showModal, setShowModal, messages, setMessages, handleSend, input, setInput, defaultMessage, typingIndicator, setTypingIndicator,
257
+ handleClearState, theme, handleButtonClick, conversationStartTime, setConversationStartTime, lastUserMessage, setLastUserMessage,
258
+ ghostMessage, setGhostMessage, ghostCard, setGhostCard, stopActivated, setStopActivated, disclaimer, setDisclaimer,
259
+ startStreaming, setStartStreaming, maintenance, setMaintenance, feedback, setFeedback, handleFeedback, feedbackOpen, setFeedbackOpen,
260
+ writeFeedback, setWriteFeedback, writeAnswer, setWriteAnswer, BASE_URL, lastMessageId, setLastMessageId,
261
+ onProductCardClick, onAddToCartClick, data, sessionId, setSessionId, handleWrittenFeedback, switchFeedbackOpen, confirmDisclaimer,
262
+ formatChatHistory, uiConfig
78
263
  }}
79
264
  >
80
265
  {children}
@@ -2,26 +2,70 @@ import React, { useState, useEffect, useRef, useContext } from 'react';
2
2
  import { AppContext } from "../contexts/AppContext";
3
3
 
4
4
  export function useWebSocketMessage() {
5
- const { setIsComplete, startStreaming, setMessages, messages, setGhostMessage, isMobile,
6
- setTypingIndicator, setStartStreaming, lastUserMessage, stopActivated, custEmail, custName, data,
7
- setGhostCard, BASE_URL, setStopActivated, setLastMessageId } = useContext(AppContext);
5
+ const { setIsComplete, startStreaming, setMessages, messages, setGhostMessage,data,
6
+ setTypingIndicator, setStartStreaming, lastUserMessage, stopActivated,sessionId,
7
+ setGhostCard, BASE_URL, setStopActivated, setLastMessageId, conversationStartTime } = useContext(AppContext);
8
8
 
9
- const wsProtocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
9
+ const wsProtocol = 'wss://'
10
10
  const wsUrl = BASE_URL.replace(/^http(s)?:\/\//, '');
11
11
  const ENDPOINT = '/send/event';
12
12
 
13
13
  const payload = {
14
- ...data,
14
+ "customer_code": data.customer_code,
15
+ "branch_code": "NBPISLA" /* data.branch_code */,
16
+ "branch_full_name": data.branch_full_name,
17
+ "customer_token": data.customer_token,
18
+ active_ship_to_information: {
19
+ shipToId: data.active_ship_to,
20
+ "customerId": 0,
21
+ "customerCode": "HPTA",
22
+ "shipToSequenceId": 1,
23
+ "customerShipToName": "HERITAGE PLUS TEST ACCOUNT",
24
+ "addressLine1": "7440 STATE HIGHWAY 121",
25
+ "addressLine2": "",
26
+ "addressLine3": "",
27
+ "city": "MCKINNEY",
28
+ "state": "TX",
29
+ "zipCode": "750702196",
30
+ "phone": "2144914149",
31
+ "fax": " ",
32
+ "orderAckEmail": "",
33
+ "customerPORequiredInd": "N",
34
+ "termsCode": "NET30",
35
+ "shipVia": "",
36
+ "salesPerson": "AS201585",
37
+ "salesPersonName": "",
38
+ "salesPersonCellPhone": "405-226-5844",
39
+ "salesPersonEmail": "Aaron.Spitz@heritagepsg.com",
40
+ "insideSalesPerson": "",
41
+ "secondarySalesPersonName": "",
42
+ "secondarySalesPersonEmail": null
43
+ },
44
+ branch_details: {
45
+ "active_branch_business_hours": "8:00 AM - 4:30 PM",
46
+ "active_branch_email": "OrdersHarrisburg@bel-aqua.com",
47
+ "active_branch_location": "Elizabethtown,PA",
48
+ "active_branch_name": "BEL-AQUA HARRISBURG",
49
+ "active_branch_phone": "(717)-689-3314",
50
+ "active_brand_name": "BEL-AQUA"
51
+ },
15
52
  user_query: lastUserMessage,
16
- customer_name: data.customer_name
53
+ session_id: String(sessionId),
54
+ conversation_start_time: conversationStartTime,
55
+ customer_name: "Cristin Connerney",
56
+ device: "mobile",
57
+ user_UUID: "cristin.connerney@srsdistribution.com",
58
+ window_location: "mobile"
17
59
  };
18
60
 
19
61
  const wsRef = useRef(null);
20
62
 
21
63
  useEffect(() => {
22
64
  if (startStreaming) {
23
- console.log(payload)
65
+ console.log(payload, BASE_URL)
24
66
  const socketUrl = `${wsProtocol}${wsUrl}${ENDPOINT}`;
67
+ console.log(socketUrl)
68
+
25
69
  const ws = new WebSocket(socketUrl);
26
70
  wsRef.current = ws;
27
71
 
@@ -32,9 +76,11 @@ export function useWebSocketMessage() {
32
76
 
33
77
  ws.onmessage = (event) => {
34
78
  const response = JSON.parse(event.data);
35
- console.log(response)
79
+ if (response.type != "chunk") {
80
+ console.log(response)
81
+ }
36
82
  switch (response.type) {
37
- case 'middle_message':
83
+ /* case 'middle_message':
38
84
  const middleMessage = {
39
85
  type: "middle",
40
86
  text: response.message,
@@ -42,7 +88,7 @@ export function useWebSocketMessage() {
42
88
  product_cards: "False",
43
89
  }
44
90
  setMessages([...messages, middleMessage])
45
- break;
91
+ break; */
46
92
  case 'message':
47
93
  if (response.product_cards == "False" || response.product_cards == false ) {
48
94
  setGhostMessage(false);
@@ -54,7 +100,7 @@ export function useWebSocketMessage() {
54
100
  const newMessage = {
55
101
  type: "ai",
56
102
  message_id: response.message_id || '',
57
- text: [response.message],
103
+ text: response.message,
58
104
  feedback: "True",
59
105
  products: [],
60
106
  product_cards: response.product_cards || "False",
@@ -67,51 +113,94 @@ export function useWebSocketMessage() {
67
113
  case 'chunk':
68
114
  const newContent = response.chunk;
69
115
  const newMessageId = response.message_id;
116
+
70
117
  setMessages(prevMessages => {
71
- const lastMessageIndex = prevMessages.length - 1;
72
- if (prevMessages[lastMessageIndex] && prevMessages[lastMessageIndex].type === "ai") {
73
- const updatedLastMessage = {
74
- ...prevMessages[lastMessageIndex],
75
- text: [prevMessages[lastMessageIndex].text[0] + newContent],
76
- message_id: newMessageId || prevMessages[lastMessageIndex].message_id,
77
- feedback: "True"
78
- };
118
+ if (prevMessages.length > 0 && prevMessages[prevMessages.length - 1].type === "ai") {
119
+ return prevMessages.map((message, index) =>
120
+ index === prevMessages.length - 1
121
+ ? {
122
+ ...message,
123
+ text: message.text + newContent,
124
+ message_id: newMessageId || message.message_id,
125
+ feedback: "True"
126
+ }
127
+ : message
128
+ );
129
+ } else {
79
130
  return [
80
- ...prevMessages.slice(0, lastMessageIndex),
81
- updatedLastMessage
131
+ ...prevMessages,
132
+ {
133
+ type: "ai",
134
+ text: newContent,
135
+ message_id: newMessageId,
136
+ feedback: "True"
137
+ }
82
138
  ];
83
- } else {
84
- setGhostMessage(false);
85
- return [...prevMessages, {
86
- type: "ai",
87
- text: [newContent],
88
- message_id: newMessageId,
89
- feedback: "True"
90
- }];
91
139
  }
92
140
  });
141
+ setGhostMessage(false);
93
142
  if (newMessageId) {
94
143
  setLastMessageId(newMessageId);
95
144
  }
96
- break;
145
+ break;
97
146
  case 'product_cards':
98
147
  setMessages(prevMessages => {
99
148
  const lastMessageIndex = prevMessages.length - 1;
149
+
100
150
  if (prevMessages[lastMessageIndex] && prevMessages[lastMessageIndex].type === "ai") {
151
+ const expandedProducts = response.products.map(prod => ({
152
+ part_number: prod.part_number || "",
153
+ inventory_info: prod.inventory_info ? {
154
+ default_uom: prod.inventory_info.default_uom || "",
155
+ is_valid: prod.inventory_info.is_valid || false,
156
+ info_by_uom: prod.inventory_info.info_by_uom
157
+ ? Object.keys(prod.inventory_info.info_by_uom).reduce((acc, key) => {
158
+ const value = prod.inventory_info.info_by_uom[key] || {};
159
+ acc[key] = {
160
+ gross_price: value.gross_price ?? 0,
161
+ net_price: value.net_price ?? 0,
162
+ is_on_sale: value.is_on_sale ?? false,
163
+ quantity_available: value.quantity_available ?? 0,
164
+ discounts: value.discounts ?? null,
165
+ };
166
+ return acc;
167
+ }, {})
168
+ : {}
169
+ } : {},
170
+ product_details: prod.product_details ? {
171
+ brand: prod.product_details.brand || "",
172
+ flow: prod.product_details.flow || "",
173
+ heritage_link: prod.product_details.heritage_link || "",
174
+ image_url: prod.product_details.image_url || "",
175
+ is_pump: prod.product_details.is_pump || "",
176
+ manufacturer_id: prod.product_details.manufacturer_id || "",
177
+ mfg_number: prod.product_details.mfg_number || "",
178
+ part_number: prod.product_details.part_number || "",
179
+ product_description: prod.product_details.product_description || "",
180
+ product_name: prod.product_details.product_name || "",
181
+ type: prod.product_details.type || "",
182
+ vertical: prod.product_details.vertical || ""
183
+ } : {}
184
+ }));
185
+
101
186
  const updatedLastMessage = {
102
187
  ...prevMessages[lastMessageIndex],
103
- products: response.products || [],
188
+ products: expandedProducts,
104
189
  product_cards: "True"
105
190
  };
191
+
106
192
  return [
107
193
  ...prevMessages.slice(0, lastMessageIndex),
108
194
  updatedLastMessage
109
195
  ];
110
- }
196
+ }
197
+
198
+ return prevMessages;
111
199
  });
200
+
112
201
  setGhostMessage(false);
113
- setTypingIndicator(false)
114
- setGhostCard(false)
202
+ setTypingIndicator(false);
203
+ setGhostCard(false);
115
204
  break;
116
205
  case 'product_document':
117
206
  setMessages(prevMessages => {
@@ -133,11 +222,6 @@ export function useWebSocketMessage() {
133
222
  setGhostCard(false)
134
223
  break;
135
224
  case 'suggested_questions':
136
- /* const questions = {
137
- type: "questions",
138
- message_id: response.message_id || '',
139
- suggested_questions: response.suggested_questions || [],
140
- }; */
141
225
  setMessages(prevMessages => {
142
226
  const lastMessageIndex = prevMessages.length - 1;
143
227
  if (prevMessages[lastMessageIndex] && prevMessages[lastMessageIndex].type === "ai") {
@@ -152,10 +236,8 @@ export function useWebSocketMessage() {
152
236
  ];
153
237
  }
154
238
  });
155
- //setMessages((prevMessages) => [...prevMessages, questions]);
156
239
  break;
157
240
  case 'setComplete':
158
- setIsComplete(true);
159
241
  setTypingIndicator(false);
160
242
  setStartStreaming(false)
161
243
  setGhostCard(false)
@@ -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
+ }
package/src/index.js CHANGED
@@ -3,11 +3,11 @@ import { View, StyleSheet } from 'react-native';
3
3
  import { AppProvider } from './contexts/AppContext';
4
4
  import { Layout } from './layout/layout';
5
5
 
6
- export const Chat = ({ data, onProductCardClick, onAddToCartClick }) => {
6
+ export const Chat = ({ data, onProductCardClick, onAddToCartClick, uiConfig }) => {
7
7
  return (
8
- <AppProvider>
8
+ <AppProvider data={data} onProductCardClick={onProductCardClick} onAddToCartClick={onAddToCartClick} uiConfig={uiConfig}>
9
9
  <View style={styles.container} pointerEvents='box-none'>
10
- <Layout onProductCardClick={onProductCardClick} onAddToCartClick={onAddToCartClick} />
10
+ <Layout/>
11
11
  </View>
12
12
  </AppProvider>
13
13
  );
@@ -23,4 +23,8 @@ const styles = StyleSheet.create({
23
23
  bottom: 0,
24
24
  zIndex: 1000,
25
25
  },
26
+ text: {
27
+ fontFamily: "Helvetica Neue" || "sans-serif",
28
+ fontSize: 16,
29
+ },
26
30
  });