{"version":3,"file":"chatbot-198d720b.js","sources":["../../../../app/frontend/components/chatbot/chatbotElementUtils.js","../../../../app/frontend/components/chatbot/chatbotConversationPersitenceUtils.js","../../../../app/frontend/components/chatbot/chatbotMinMaxButtonsController.js","../../../../app/frontend/components/chatbot/chatbotLoadingDotsController.js","../../../../app/frontend/components/chatbot/chatbotMessagingController.js","../../../../app/frontend/components/chatbot/chatbotButtonsAndFormsController.js","../../../../app/frontend/components/chatbot/chatbotWidgetContentController.js","../../../../app/frontend/entrypoints/chatbot.js"],"sourcesContent":["function getWidgetContainer() {\n return document.querySelector('[data-solv-chatbot-container]');\n}\n\nfunction getRequestId() {\n return getWidgetContainer().dataset.requestId;\n}\n\nfunction getGroupId() {\n return getWidgetContainer().dataset.groupId;\n}\n\nfunction setRequestIdOnDom(id) {\n getWidgetContainer().dataset.requestId = id;\n}\n\nfunction getWidgetContent() {\n return document.querySelector('[data-solv-chatbot-content-slot]');\n}\n\nfunction widgetIsClosed() {\n return getWidgetContent().classList.contains('solv-chatbot-widget--hidden');\n}\n\nfunction getMinimizeBtn() {\n return document.querySelector('[data-solv-chatbot-widget-minimize-btn]');\n}\n\nfunction getCloseBtn() {\n return document.querySelector('[data-solv-chatbot-widget-close-btn]');\n}\n\nfunction getMaximizeBtn() {\n return document.querySelector('[data-solv-chatbot-widget-maximize-btn]');\n}\n\nfunction getMessagesElement() {\n return document.querySelector('[data-solv-chatbot-messages]');\n}\n\nfunction getGreetingElement() {\n return document.querySelector('[data-solv-chatbot-greeting]');\n}\n\nfunction getMessageFeed() {\n return document.querySelector('[data-solv-chatbot-message-feed]');\n}\n\nfunction getUserMsgInputField() {\n return document.querySelector('[data-solv-chatbot-message-input]');\n}\n\nfunction getMsgInputForm() {\n return document.querySelector('[data-solv-chatbot-message-form]');\n}\n\nfunction getMsgSendBtn() {\n return document.querySelector('[data-solv-chatbot-user-send]');\n}\n\nfunction getGreetingsButtons() {\n return document.querySelectorAll('[data-solv-chatbot-greetings-button]');\n}\n\nfunction getnewUserForm() {\n return document.querySelector('[data-solv-chatbot-phone-form]');\n}\n\nfunction getFirstNameInput() {\n return document.querySelector('[data-solv-chatbot-first-name-input]');\n}\n\nfunction getLastNameInput() {\n return document.querySelector('[data-solv-chatbot-last-name-input]');\n}\n\nfunction getPhoneNumberInput() {\n return document.querySelector('[data-solv-chatbot-phone-number-input]');\n}\n\nfunction getFirstNameErrorMessage() {\n return document.querySelector('[data-solv-chatbot-user-name-error]');\n}\n\nfunction getLastNameErrorMessage() {\n return document.querySelector('[data-solv-chatbot-user-last-name-error]');\n}\n\nfunction getPhoneNumberErrorMessage() {\n return document.querySelector('[data-solv-chatbot-user-phone-error]');\n}\n\nfunction getButtons() {\n return document.querySelectorAll('[data-solv-chatbot-button]');\n}\n\nfunction getButtonContainers() {\n return document.querySelectorAll('[data-solv-chatbot-buttons]');\n}\n\nfunction getMinMaxButtonContainer() {\n return document.querySelector('[data-solv-chatbot-min-max-btn-container]');\n}\n\nfunction getForms() {\n return document.querySelectorAll('[data-solv-chatbot-form]');\n}\n\nfunction getLoadingDots() {\n return document.querySelector('[data-solv-chatbot-loading-dots]');\n}\n\nfunction getHiddenMessages() {\n return document.querySelectorAll('.solv-chatbot-widget__message-wrapper--hidden');\n}\n\nfunction getTestInformation() {\n let testElment = document.querySelector('[data-chat-bot-test]');\n if (testElment) {\n return true;\n } else {\n return false;\n }\n}\n\nfunction getTimeStampElement() {\n return document.querySelector('[data-solv-chatbot-timestamp]');\n}\n\nfunction getTimeStampElementByIntervalID(id) {\n return document.querySelector(`[data-solv-chatbot-timestamp-id=\"${id}\"]`);\n}\n\nfunction getTimeStampInfoElement(id) {\n const timeStampElement = getTimeStampElementByIntervalID(id);\n if (timeStampElement === null || timeStampElement === undefined) {\n return null;\n }\n return timeStampElement.querySelector('[data-solv-chatbot-timestamp-info]');\n}\n\nfunction setTimeStamp(value, id) {\n const timeStamp = getTimeStampInfoElement(id);\n if (timeStamp) {\n timeStamp.innerHTML = value;\n timeStamp.ariaLabel = value;\n }\n}\n\nfunction setTimeStampIntervalID(newID) {\n const timeStamp = getTimeStampElement();\n if (timeStamp === null || timeStamp === undefined) {\n return;\n }\n timeStamp.dataset.solvChatbotTimestampId = newID;\n}\n\nfunction deleteTimestamp() {\n const timeStamp = getTimeStampElement();\n if (timeStamp) {\n timeStamp.remove();\n }\n}\n\nexport {\n getMaximizeBtn,\n getMinimizeBtn,\n getWidgetContainer,\n widgetIsClosed,\n getWidgetContent,\n getMessageFeed,\n getUserMsgInputField,\n getMsgInputForm,\n getMsgSendBtn,\n getMessagesElement,\n getGreetingsButtons,\n getButtonContainers,\n getnewUserForm,\n getPhoneNumberInput,\n getFirstNameInput,\n getButtons,\n getLoadingDots,\n getGreetingElement,\n getRequestId,\n getGroupId,\n setRequestIdOnDom,\n getHiddenMessages,\n getForms,\n getPhoneNumberErrorMessage,\n getFirstNameErrorMessage,\n getLastNameInput,\n getLastNameErrorMessage,\n getTestInformation,\n getTimeStampElement,\n getTimeStampInfoElement,\n setTimeStamp,\n deleteTimestamp,\n setTimeStampIntervalID,\n getCloseBtn,\n getMinMaxButtonContainer,\n};\n","import {\n getGroupId\n} from '@/components/chatbot/chatbotElementUtils';\n\nfunction saveRequestIdToLocalStorage(id) {\n const groupId = getGroupId();\n const expirationTime = new Date().getTime() + 60 * 60000; // one hour from now\n const chatIdInfo = { storedID: id, expiry: expirationTime };\n const key = \"solvChatId\" + groupId;\n window.localStorage.setItem(key, JSON.stringify(chatIdInfo));\n}\n\nfunction setGreetingView() {\n const expirationTime = new Date().getTime(); // one hour from now\n const groupId = getGroupId();\n const key = \"solvGreetingSeen\" + groupId;\n window.localStorage.setItem(key, expirationTime);\n}\n\nfunction getGreetingView() {\n const groupId = getGroupId();\n const key = \"solvGreetingSeen\" + groupId;\n return window.localStorage.getItem(key);\n}\n\nfunction setMinimization() {\n const expirationTime = new Date().getTime(); // one hour from now\n const groupId = getGroupId();\n const key = \"solvMinimize\" + groupId;\n window.localStorage.setItem(key, expirationTime);\n}\n\nfunction getMinimization() {\n const groupId = getGroupId();\n const key = \"solvMinimize\" + groupId;\n return window.localStorage.getItem(key);\n}\n\nfunction setMaximization() {\n const groupId = getGroupId();\n const key = \"solvMinimize\" + groupId;\n window.localStorage.removeItem(key);\n}\n\nfunction getStoredRequestId() {\n const groupId = getGroupId();\n const key = \"solvChatId\" + groupId;\n\n let idHashInfo = window.localStorage.getItem(key);\n idHashInfo = JSON.parse(idHashInfo);\n\n if (idHashInfo == null || idHashInfo == undefined) {\n return \"\";\n }\n\n const idHashExpired = idHashInfo.expiry < new Date().getTime()\n\n if (!idHashExpired) {\n return idHashInfo.storedID;\n }\n\n return '';\n}\n\n\nfunction isIdHashExpired() {\n let idHashInfo = window.localStorage.getItem(\"solvChatId\");\n idHashInfo = JSON.parse(idHashInfo);\n\n if (idHashInfo == null || idHashInfo == undefined) {\n return false;\n }\n\n const idHashValues = Object.values(idHashInfo);\n const idHashExpired = idHashValues[1] < new Date().getTime()\n\n return idHashExpired;\n}\n\nfunction storeUserInformation(userInformation) {\n if (userInformation) {\n window.localStorage.setItem(\"solvChatUserInformation\", userInformation);\n }\n}\n\n\nfunction getUserInformation() {\n let userInformation = window.localStorage.getItem(\"solvChatUserInformation\");\n\n if (userInformation == null || userInformation == undefined) {\n return null;\n }\n return userInformation;\n}\n\nexport { saveRequestIdToLocalStorage, getStoredRequestId, storeUserInformation, getUserInformation, isIdHashExpired, setGreetingView, getGreetingView, setMinimization, setMaximization, getMinimization };\n","import {\n getMaximizeBtn,\n getMinimizeBtn,\n getWidgetContent,\n getGreetingElement,\n getMessagesElement,\n getUserMsgInputField,\n getRequestId,\n getFirstNameInput,\n getMinMaxButtonContainer,\n getCloseBtn\n} from '@/components/chatbot/chatbotElementUtils';\nimport { autoScrollToBottom } from '@/components/chatbot/chatbotButtonsAndFormsController';\nimport { setMinimization, setMaximization, setGreetingView } from '@/components/chatbot/chatbotConversationPersitenceUtils';\n\n\nfunction minimizeContainer() {\n\n const minimizeBtn = getMinimizeBtn();\n const maximizeBtn = getMaximizeBtn();\n const widgetContent = getWidgetContent();\n const minMaxButtonContainer = getMinMaxButtonContainer();\n\n minMaxButtonContainer.classList.add('solv-chatbot-widget--minimized');\n minMaxButtonContainer.classList.remove('solv-chatbot-widget--maximized');\n\n minimizeBtn.classList.add('solv-chatbot-widget--hidden');\n minimizeBtn.ariaHidden = true;\n\n maximizeBtn.classList.remove('solv-chatbot-widget--hidden');\n maximizeBtn.ariaHidden = false;\n\n widgetContent.classList.add('solv-chatbot-widget--hidden');\n\n widgetContent.ariaHidden = true;\n\n setMinimization();\n trackConversationMinimization()\n}\n\nfunction maximizeContainer() {\n const minimizeBtn = getMinimizeBtn();\n const maximizeBtn = getMaximizeBtn();\n const widgetContent = getWidgetContent();\n const minMaxButtonContainer = getMinMaxButtonContainer();\n\n setMaximization();\n\n minMaxButtonContainer.classList.remove('solv-chatbot-widget--minimized');\n minMaxButtonContainer.classList.add('solv-chatbot-widget--maximized');\n\n minimizeBtn.classList.remove('solv-chatbot-widget--hidden');\n minimizeBtn.ariaHidden = false;\n\n maximizeBtn.classList.add('solv-chatbot-widget--hidden');\n maximizeBtn.ariaHidden = true;\n\n widgetContent.classList.remove('solv-chatbot-widget--hidden');\n widgetContent.ariaHidden = false;\n}\n\nfunction setUpMinimizeButton() {\n const minimizeBtn = getMinimizeBtn();\n minimizeBtn.addEventListener('click', (e) => {\n minimizeContainer();\n });\n const closeBtn = getCloseBtn();\n closeBtn.addEventListener('click', (e) => {\n minimizeContainer();\n });\n}\n\nfunction setUpMaximizeButton() {\n const maximizeBtn = getMaximizeBtn();\n maximizeBtn.addEventListener('click', (e) => {\n const greeting = getGreetingElement();\n if (greeting) {\n removeGreetingElement();\n }\n maximizeContainer();\n const userInputField = getUserMsgInputField();\n const firstNameInput = getFirstNameInput();\n // CHECK FOR MOBILE WIDTH\n const mobileWidth = window.matchMedia('(max-width: 767px)');\n if (mobileWidth.matches) {\n // do nothing\n } else if (firstNameInput) {\n firstNameInput.focus();\n } else if (userInputField) {\n userInputField.focus();\n autoScrollToBottom();\n }\n });\n}\n\nfunction showMessagesTemplate() {\n const messages = getMessagesElement();\n messages.classList.remove('solv-chatbot-widget__messages--hidden');\n messages.ariaHidden = false;\n}\n\nfunction removeGreetingElement() {\n const greeting = getGreetingElement();\n greeting.remove();\n\n const widgetContent = getWidgetContent();\n widgetContent.classList.remove('uninitialized');\n\n // unhide the messages element which is hidden behind the greeting element\n showMessagesTemplate();\n\n // send message to the backend that the user has started the chat for analytics purposes\n trackConversationInitiation()\n}\n\nasync function trackConversationInitiation() {\n // send message to the backend that the user has started the chat for analytics purposes\n const requestId = getRequestId();\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let messageURL = 'https://www.solvhealth.com/dir/chatbot-conversation-started';\n if (testURLElement) {\n messageURL = '/dir/chatbot-conversation-started';\n }\n const data = {\n request_id: requestId,\n };\n await fetch(messageURL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n}\n\nasync function trackConversationMinimization() {\n // send message to the backend that the user has started the chat for analytics purposes\n const requestId = getRequestId();\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let messageURL = 'https://www.solvhealth.com/dir/chatbot-conversation-closed';\n if (testURLElement) {\n messageURL = '/dir/chatbot-conversation-closed';\n }\n const data = {\n request_id: requestId,\n };\n await fetch(messageURL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n}\n\n// change the visibility of the buttons without affecting the container\nfunction switchMinMaxButtonVisibility() {\n const minimizeBtn = getMinimizeBtn();\n const maximizeBtn = getMaximizeBtn();\n\n minimizeBtn.classList.toggle('solv-chatbot-widget--hidden');\n minimizeBtn.ariaHidden = minimizeBtn.classList.contains('solv-chatbot-widget--hidden');\n\n maximizeBtn.classList.toggle('solv-chatbot-widget--hidden');\n maximizeBtn.ariaHidden = maximizeBtn.classList.contains('solv-chatbot-widget--hidden');\n}\n\nexport { setUpMinimizeButton, setUpMaximizeButton, switchMinMaxButtonVisibility, removeGreetingElement, showMessagesTemplate, maximizeContainer };\n","import { getLoadingDots, getMessageFeed } from '@/components/chatbot/chatbotElementUtils';\nimport { autoScrollToBottom } from '@/components/chatbot/chatbotButtonsAndFormsController';\n\nfunction moveLoadingDotsToBottomOfFeed() {\n const dots = getLoadingDots();\n const feed = getMessageFeed();\n\n feed.appendChild(dots);\n}\n\nfunction showLoadingDots() {\n const dots = getLoadingDots();\n dots.ariaHidden = false;\n moveLoadingDotsToBottomOfFeed();\n\n dots.classList.remove('solv-chatbot-widget--hidden');\n autoScrollToBottom(); // loading get cut off when this isn't called here\n}\n\nfunction hideLoadingDots() {\n const dots = getLoadingDots();\n dots.ariaHidden = true;\n dots.classList.add('solv-chatbot-widget--hidden');\n}\n\nexport { showLoadingDots, hideLoadingDots }\n","import {\n getMessageFeed,\n getMsgInputForm,\n getMsgSendBtn,\n getUserMsgInputField,\n getHiddenMessages,\n getRequestId,\n getMessagesElement,\n getTestInformation,\n widgetIsClosed, setTimeStamp, getTimeStampElement, deleteTimestamp, setTimeStampIntervalID\n} from '@/components/chatbot/chatbotElementUtils';\nimport { hideLoadingDots, showLoadingDots } from '@/components/chatbot/chatbotLoadingDotsController';\nimport {\n removeButtons,\n setUpButtons,\n setUpNewUserForm,\n removeForms,\n autoScrollToBottom,\n} from '@/components/chatbot/chatbotButtonsAndFormsController';\nimport { saveRequestIdToLocalStorage } from '@/components/chatbot/chatbotConversationPersitenceUtils';\nimport { maximizeContainer } from '@/components/chatbot/chatbotMinMaxButtonsController';\nimport { checkForSessionTimeout } from '@/components/chatbot/chatbotWidgetContentController';\n\n\nconst PLACEHOLDER_VALUES = {\n 'introInput': 'Ask a question...',\n 'replyInput': 'Type your reply...',\n 'phoneInput': 'Enter your name and phone above',\n 'timeInput': 'Select a time or ask a question...',\n 'infoInput': 'Enter your information above',\n \"\": \"\"\n};\n\nlet interstitialCount = 0;\n\n/**\n * Sets the placeholder value for the user message input\n * Takes in a key from the PLACEHOLDER_VALUES constant and sets the placeholder to its respective value\n * @param placeholderKey {string}\n */\nfunction setPlaceHolderContent(placeholderKey) {\n const inputField = getUserMsgInputField();\n inputField.placeholder = PLACEHOLDER_VALUES[placeholderKey];\n}\n\nasync function handleUserMessage(message, userInformation = null) {\n\n renderUserMessageOnFeed(message);\n\n const domRequestId = getRequestId();\n\n saveRequestIdToLocalStorage(domRequestId);\n\n initiateSessionTimeoutCheck();\n\n await submitMessage(message, userInformation);\n}\n\nfunction initiateSessionTimeoutCheck() {\n if (!window.solvCheckForSessionTimeout) {\n window.solvCheckForSessionTimeout = setInterval(checkForSessionTimeout, 5000);\n }\n}\n\nasync function submitMessage(message, userInformation = null) {\n interstitialCount = 0;\n showLoadingDots();\n const resData = await sendMessage(message, userInformation);\n\n const request_new_message = resData.request_new_message;\n\n hideLoadingDots();\n\n renderAssistantMessageOnFeed(resData.content, true);\n\n if (resData.user_message_content) {\n setTimeout(() => {\n renderAssistantMessageOnFeed(resData.user_message_content, false);\n }, 500);\n }\n\n if (request_new_message) {\n submitMessage(null);\n }\n\n if (resData.is_conclusion_of_conversation) {\n setPlaceHolderContent(\"\")\n disableMessageInput();\n } else {\n const userInputField = getUserMsgInputField();\n userInputField.focus();\n }\n}\n\nasync function sendMessage(message, userInformation = null) {\n const requestId = getRequestId();\n const data = {\n message,\n request_id: requestId,\n is_test: getTestInformation(),\n user_information: userInformation,\n };\n\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let messageURL = 'https://www.solvhealth.com/dir/chatbot-widget-message';\n if (testURLElement) {\n messageURL = '/dir/chatbot-widget-message';\n }\n\n try {\n const res = await fetch(messageURL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n });\n\n if (res.status == 200) {\n const resData = await res.json();\n if (resData.message == 'assistant') {\n return resData;\n } else if (resData.message == 'function_call') {\n if (resData.content !== null && resData.content !== undefined && resData.content !== \"\" && interstitialCount < 2) {\n interstitialCount++;\n hideLoadingDots();\n renderAssistantMessageOnFeed(resData.content, true);\n showLoadingDots();\n }\n return sendMessage(null);\n }\n } else {\n return sendErrorMessage();\n }\n }\n catch (err) {\n return sendErrorMessage();\n }\n}\n\nasync function sendErrorMessage(retries = 0) {\n const requestId = getRequestId();\n const data = {\n request_id: requestId,\n retries,\n };\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let errorURL = 'https://www.solvhealth.com/dir/chatbot-widget-message-error';\n if (testURLElement) {\n errorURL = '/dir/chatbot-widget-message-error';\n }\n const res = await fetch(errorURL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(data),\n })\n if (res.status == 200) {\n const resData = await res.json();\n\n if (resData.message == 'waiting') {\n if (resData.content !== null && resData.content !== undefined && resData.content !== \"\" && interstitialCount < 2) {\n interstitialCount++;\n hideLoadingDots();\n renderAssistantMessageOnFeed(resData.content, true);\n showLoadingDots();\n }\n return sendErrorMessage(retries + 1);\n } else if (resData.message == 'assistant') {\n return resData;\n } else if (resData.message == 'function_call') {\n return sendMessage(null);\n }\n }\n}\n\nfunction renderUserMessageOnFeed(message) {\n removeButtons();\n unhideMessages();\n removeForms();\n updateBanner();\n\n const messageFeed = getMessageFeed();\n const newMsgWrapper = document.createElement('div');\n const newMsgContent = document.createElement('div');\n\n newMsgWrapper.classList.add('solv-chatbot-widget__message-wrapper', 'solv-chatbot-widget__user-message-wrapper');\n newMsgWrapper.ariaLabel = 'User message';\n newMsgContent.classList.add('solv-chatbot-widget__message-content', 'solv-chatbot-widget__user-message-content');\n newMsgContent.innerHTML = message;\n newMsgWrapper.appendChild(newMsgContent);\n\n messageFeed.appendChild(newMsgWrapper);\n autoScrollToBottom();\n deleteTimestamp();\n}\n\nfunction updateBanner() {\n const messageElement = getMessagesElement();\n messageElement.dataset.solvChatbotMessagesInit = 'true';\n}\n\nfunction unhideMessages() {\n const hiddenMessages = getHiddenMessages();\n hiddenMessages.forEach(message => {\n message.classList.remove('solv-chatbot-widget__message-wrapper--hidden');\n });\n}\n\nfunction renderAssistantMessageOnFeed(message, showStamp = false) {\n\n // this is for the situation of the chatbot returning consecutive messages, we only want the most recent message to have a timestamp\n if (showStamp) {\n deleteTimestamp();\n }\n\n const messageFeed = getMessageFeed();\n\n const content = document.createRange().createContextualFragment(message);\n messageFeed.appendChild(content);\n autoScrollToBottom();\n if (showStamp) {\n showTimeStamp();\n }\n\n setUpButtons();\n setUpNewUserForm();\n\n if (widgetIsClosed()) {\n maximizeContainer();\n }\n}\n\nfunction autosizeInputField() {\n const inputField = getUserMsgInputField();\n\n setTimeout(() => {\n inputField.style.cssText = 'height:auto;';\n inputField.style.cssText = `height:${inputField.scrollHeight}px`;\n })\n}\n\nfunction setupMessageForm() {\n const userForm = getMsgInputForm();\n const sendBtn = getMsgSendBtn();\n const inputField = getUserMsgInputField();\n\n setPlaceHolderContent('introInput');\n\n userForm.addEventListener('submit', async (e) => {\n e.preventDefault();\n const messageInput = getUserMsgInputField();\n const message = messageInput.value;\n messageInput.value = '';\n\n await handleUserMessage(message);\n });\n\n inputField.addEventListener('keydown', (e) => {\n // for normal inputs, resize the container to allow for mulitiple lines\n autosizeInputField();\n\n // submit the form when the user presses 'enter', but not for 'shift + enter'\n if (e.which === 13 && !e.shiftKey) {\n e.preventDefault();\n userForm.requestSubmit();\n }\n });\n\n sendBtn.addEventListener('click', (e) => {\n userForm.requestSubmit();\n });\n}\n\nfunction hideSendButtonDisplay() {\n const sendBtn = getMsgSendBtn();\n sendBtn.classList.add('solv-chatbot-widget--hidden');\n}\n\nfunction showSendButtonDisplay() {\n const sendBtn = getMsgSendBtn();\n sendBtn.classList.remove('solv-chatbot-widget--hidden');\n}\n\nfunction enableMessageInput() {\n const inputField = getUserMsgInputField();\n inputField.disabled = false;\n inputField.ariaDisabled = false;\n showSendButtonDisplay();\n}\n\nfunction disableMessageInput() {\n const inputField = getUserMsgInputField();\n inputField.disabled = true;\n inputField.ariaDisabled = true;\n hideSendButtonDisplay();\n}\n\nfunction showTimeStamp() {\n const timeStamp = getTimeStampElement();\n timeStamp.classList.remove('solv-chatbot-widget--hidden');\n\n const initialTime = new Date().getMinutes();\n\n const intervalID = setInterval(() => {\n updateTimeStampValue(initialTime, intervalID);\n }, 60000);\n // NOTE: very important that this goes after interval is set\n setTimeStampIntervalID(intervalID);\n}\n\nfunction updateTimeStampValue(initialTime, intervalID) {\n const currentTime = new Date().getMinutes();\n const difference = currentTime - initialTime;\n\n if (difference > 0) {\n if (difference === 1) {\n setTimeStamp(`${difference} minute ago`, intervalID)\n } else {\n setTimeStamp(`${difference} minutes ago`, intervalID)\n }\n }\n}\n\nexport { setupMessageForm, enableMessageInput, disableMessageInput, handleUserMessage, setPlaceHolderContent, initiateSessionTimeoutCheck };\n","import {\n getButtonContainers,\n getButtons,\n getForms,\n getGreetingsButtons,\n getMessageFeed,\n getnewUserForm,\n getFirstNameErrorMessage,\n getFirstNameInput,\n getPhoneNumberErrorMessage,\n getPhoneNumberInput,\n getLastNameInput,\n getMinMaxButtonContainer,\n getLastNameErrorMessage,\n} from '@/components/chatbot/chatbotElementUtils';\nimport {\n removeGreetingElement,\n setUpMaximizeButton,\n setUpMinimizeButton,\n switchMinMaxButtonVisibility,\n} from '@/components/chatbot/chatbotMinMaxButtonsController';\nimport {\n disableMessageInput,\n enableMessageInput,\n handleUserMessage,\n setPlaceHolderContent\n} from './chatbotMessagingController';\nimport {setGreetingView} from '@/components/chatbot/chatbotConversationPersitenceUtils';\n\nfunction setUpMinMaxButtons() {\n setUpMinimizeButton();\n setUpMaximizeButton();\n}\n\nfunction setUpGreetingButtons() {\n const greetingsBtns = getGreetingsButtons();\n greetingsBtns.forEach(btn => {\n btn.addEventListener('click', async (e) => {\n const minMaxButtonContainer = getMinMaxButtonContainer();\n setGreetingView();\n if (btn.dataset.book) {\n window.bookAVisitClicked = true;\n }\n minMaxButtonContainer.classList.remove('solv-chatbot-widget--minimized');\n minMaxButtonContainer.classList.add('solv-chatbot-widget--maximized');\n removeGreetingElement();\n switchMinMaxButtonVisibility();\n const firstNameInput = getFirstNameInput();\n firstNameInput.focus();\n\n });\n });\n}\n\nfunction autoScrollToBottom() {\n const messageFeed = getMessageFeed();\n\n setTimeout(() => {\n messageFeed.scrollIntoView(false);\n }, 500);\n}\n\nfunction setUpButtons() {\n const buttons = getButtons();\n buttons.forEach(button => {\n button.addEventListener('click', async (e) => {\n if (button.dataset.viewMoreLocations) {\n handleViewMoreLocationsButtonClick();\n button.remove();\n } else {\n const message = button.dataset.buttonContent;\n if (message) {\n await handleUserMessage(message);\n }\n }\n });\n });\n}\n\nfunction handleViewMoreLocationsButtonClick() {\n const hiddenLocations = document.querySelectorAll('[data-hidden-location]');\n hiddenLocations.forEach(location => {\n location.classList.remove('hidden');\n });\n}\n\nasync function submitUserInfo() {\n const firstName = getFirstNameInput().value\n const lastName = getLastNameInput().value\n const phone = getPhoneNumberInput().value\n\n const userInformation = {\n first_name: firstName,\n last_name: lastName,\n phone_number: phone\n }\n\n let message = `First Name: ${firstName},
Last Name: ${lastName},
Phone: ${phone},`\n\n if (window.bookAVisitClicked) {\n message = `${message}
I would like to book a visit`\n }\n\n setPlaceHolderContent('replyInput');\n enableMessageInput();\n\n await handleUserMessage(message, userInformation);\n\n\n}\n\nfunction removeForms() {\n const forms = getForms();\n forms.forEach(form => {\n form.remove();\n });\n}\n\nfunction isValidPhoneNumber() {\n const phoneNumberInput = getPhoneNumberInput();\n const phoneRegExp = /^[\\+]?[(]?[0-9]{3}[)]?[+\\s\\.]?[0-9]{3}[-\\s\\.]?[0-9]{4,6}$/im;\n return phoneRegExp.test(phoneNumberInput.value);\n}\n\nfunction isValidName(inputElement) {\n const nameRegExp = /^\\s*$/;\n return !nameRegExp.test(inputElement.value);\n}\n\nfunction showErrorMessage(inputElement, messageElement) {\n inputElement.classList.add('invalid');\n inputElement.ariaInvalid = true;\n messageElement.classList.remove('solv-chatbot-widget--hidden');\n messageElement.ariaHidden = false;\n}\n\nfunction hideErrorMessage(inputElement, messageElement) {\n inputElement.classList.remove('invalid');\n inputElement.ariaInvalid = false;\n messageElement.classList.add('solv-chatbot-widget--hidden');\n messageElement.ariaHidden = true;\n}\n\nconst isNumericInput = (event) => {\n const key = event.keyCode;\n return ((key >= 48 && key <= 57) || // Allow number line\n (key >= 96 && key <= 105) // Allow number pad\n );\n};\n\nconst isModifierKey = (event) => {\n const key = event.keyCode;\n return (event.shiftKey === true || key === 35 || key === 36) || // Allow Shift, Home, End\n (key === 8 || key === 9 || key === 13 || key === 46) || // Allow Backspace, Tab, Enter, Delete\n (key > 36 && key < 41) || // Allow left, up, right, down\n (\n // Allow Ctrl/Command + A,C,V,X,Z\n (event.ctrlKey === true || event.metaKey === true) &&\n (key === 65 || key === 67 || key === 86 || key === 88 || key === 90)\n )\n};\n\nconst enforceFormat = (event) => {\n // Input must be of a valid number format or a modifier key, and not longer than ten digits\n if (!isNumericInput(event) && !isModifierKey(event)) {\n event.preventDefault();\n }\n};\n\nconst formatToPhone = (event) => {\n if (isModifierKey(event)) {\n return;\n }\n\n const input = event.target.value.replace(/\\D/g, '').substring(0, 10); // First ten digits of input only\n const areaCode = input.substring(0, 3);\n const middle = input.substring(3, 6);\n const last = input.substring(6, 10);\n\n if (input.length > 6) {\n event.target.value = `(${areaCode}) ${middle}-${last}`;\n } else if (input.length > 3) {\n event.target.value = `(${areaCode}) ${middle}`;\n } else if (input.length > 0) {\n event.target.value = `(${areaCode}`;\n }\n}\n\nfunction setUpNewUserForm() {\n const newUserForm = getnewUserForm();\n const phoneNumberInput = getPhoneNumberInput();\n const firstNameInput = getFirstNameInput();\n const lastNameInput = getLastNameInput();\n\n if (!newUserForm) return;\n\n setPlaceHolderContent('phoneInput');\n\n disableMessageInput();\n\n phoneNumberInput.addEventListener('input', (e) => {\n enforceFormat(e);\n formatToPhone(e);\n\n // This is to help avoid confusing the user if they've inputted an incorrect value. We don't want to show the error anymore if they input a valid value.\n if (isValidPhoneNumber()) {\n hideErrorMessage(phoneNumberInput, getPhoneNumberErrorMessage());\n } else {\n showErrorMessage(phoneNumberInput, getPhoneNumberErrorMessage());\n }\n });\n\n firstNameInput.addEventListener('input', (e) => {\n // This is to help avoid confusing the user if they've inputted an incorrect value. We don't want to show the error anymore if they input a valid value.\n if (isValidName(firstNameInput)) {\n hideErrorMessage(firstNameInput, getFirstNameErrorMessage());\n } else {\n showErrorMessage(firstNameInput, getFirstNameErrorMessage());\n }\n });\n\n lastNameInput.addEventListener('input', (e) => {\n // This is to help avoid confusing the user if they've inputted an incorrect value. We don't want to show the error anymore if they input a valid value.\n if (isValidName(lastNameInput)) {\n hideErrorMessage(lastNameInput, getLastNameErrorMessage());\n } else {\n showErrorMessage(lastNameInput, getLastNameErrorMessage());\n }\n })\n\n newUserForm.addEventListener('submit', async (e) => {\n e.preventDefault();\n\n const phoneValid = isValidPhoneNumber();\n const firstNameValid = isValidName(getFirstNameInput());\n const lastNameValid = isValidName(getLastNameInput());\n\n if (phoneValid && firstNameValid && lastNameValid) {\n await submitUserInfo();\n } else {\n\n if (!phoneValid) {\n showErrorMessage(phoneNumberInput, getPhoneNumberErrorMessage());\n }\n\n if (!firstNameValid) {\n showErrorMessage(firstNameInput, getFirstNameErrorMessage());\n }\n\n if (!lastNameValid) {\n showErrorMessage(lastNameInput, getFirstNameErrorMessage());\n }\n }\n });\n}\n\nfunction removeButtons() {\n const buttonContainers = getButtonContainers();\n buttonContainers.forEach(container => {\n container.remove();\n });\n}\n\n\nexport {\n setUpButtons,\n setUpGreetingButtons,\n setUpMinMaxButtons,\n setUpNewUserForm,\n removeButtons,\n removeForms,\n autoScrollToBottom\n}\n","import {\n getWidgetContainer,\n getRequestId,\n getGreetingElement,\n setRequestIdOnDom\n} from '@/components/chatbot/chatbotElementUtils';\nimport {\n setUpGreetingButtons,\n setUpButtons,\n setUpMinMaxButtons,\n setUpNewUserForm,\n autoScrollToBottom\n} from '@/components/chatbot/chatbotButtonsAndFormsController';\nimport { showMessagesTemplate } from '@/components/chatbot/chatbotMinMaxButtonsController';\nimport { setupMessageForm, initiateSessionTimeoutCheck } from '@/components/chatbot/chatbotMessagingController';\nimport { getStoredRequestId, storeUserInformation, getUserInformation, isIdHashExpired, getGreetingView, getMinimization } from '@/components/chatbot/chatbotConversationPersitenceUtils';\n\nfunction checkForSessionTimeout() {\n const idHashExpired = isIdHashExpired()\n\n if (idHashExpired) {\n clearInterval(window.solvCheckForSessionTimeout);\n window.solvCheckForSessionTimeout = null;\n window.localStorage.removeItem(\"solvChatId\");\n reinitializeWidget();\n }\n}\n\nasync function reinitializeWidget() {\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let resetUrl = 'https://www.solvhealth.com/dir/chatbot-new-session';\n if (testURLElement) {\n resetUrl = '/dir/chatbot-new-session';\n }\n\n const userInformation = getUserInformation();\n const oldRequestId = getRequestId();\n\n const res = await fetch(`${resetUrl}?user_information=${userInformation}&request_id=${oldRequestId}`);\n const data = await res.json();\n const requestId = data.request_id;\n\n const widgetContainer = document.querySelector('solv-chatbot-widget');\n widgetContainer.dataset.requestId = requestId;\n\n await loadWidgetInitialContent()\n}\n\nasync function loadWidgetInitialContent() {\n let requestId = getStoredRequestId();\n let newRequestId = null;\n\n // if there is a stored request id, we add that to the dom. This indicates that this is an ongoing conversation. We pass the newRequestId back to server to delete the erroneous request id\n if (requestId !== '') {\n newRequestId = getRequestId();\n setRequestIdOnDom(requestId);\n } else {\n // if there is no stored requestid, this is a new conversation. the request id is set in the data attribute on the initial rendering of the template\n requestId = getRequestId();\n }\n\n const testURLElement = document.getElementById('testing-chatbot-locally');\n let templateURL = 'https://www.solvhealth.com/dir/chatbot-widget-template';\n if (testURLElement) {\n templateURL = '/dir/chatbot-widget-template';\n }\n\n const userInformation = getUserInformation();\n const greetingView = getGreetingView();\n const minimizationTime = getMinimization();\n\n let url = `${templateURL}?request_id=${requestId}&user_information=${userInformation}`\n if (newRequestId) {\n url += `&new_request_id=${newRequestId}`;\n }\n if (greetingView) {\n url += `&greeting_view=${greetingView}`;\n }\n\n // If the user has previously minimized the widget, we check if the minimization time is within the last hour. If it is, we may keep the widget minimized\n if (minimizationTime) {\n url += `&minimized=${minimizationTime}`;\n }\n\n const res = await fetch(url);\n const data = await res.json();\n const template = data.content;\n const newUserInformation = data.user_information;\n if (newUserInformation != userInformation) {\n storeUserInformation(newUserInformation);\n }\n\n const container = getWidgetContainer();\n container.innerHTML = template;\n\n const greetingTemplate = getGreetingElement();\n if (greetingTemplate) {\n setUpGreetingButtons();\n } else {\n initiateSessionTimeoutCheck();\n showMessagesTemplate();\n }\n setUpButtons();\n setUpMinMaxButtons();\n setupMessageForm();\n autoScrollToBottom();\n setUpNewUserForm();\n}\n\nexport { loadWidgetInitialContent, checkForSessionTimeout };\n","import { loadWidgetInitialContent } from '@/components/chatbot/chatbotWidgetContentController';\n\n// the below logic interacts with the JS on the UBS. It is for a better user experience.\nfunction geolocationSucceeded() {\n // we don't want to do anything if geolocate succeeds because the page will be reloaded\n // I'm adding this console.log here to generate a new version of this file in the cdn\n console.log(\"Browser geolocation succeeded\");\n}\n\nfunction geolocationRejected() {\n loadWidgetInitialContent();\n}\n\nif (window.UbsGeolocationPending === true) {\n let options = {\n enableHighAccuracy: false,\n timeout: 10000,\n maximumAge: 0,\n };\n navigator.geolocation.watchPosition(geolocationSucceeded, geolocationRejected, options);\n\n} else {\n loadWidgetInitialContent();\n}\n"],"names":["getWidgetContainer","getRequestId","getGroupId","setRequestIdOnDom","id","getWidgetContent","widgetIsClosed","getMinimizeBtn","getCloseBtn","getMaximizeBtn","getMessagesElement","getGreetingElement","getMessageFeed","getUserMsgInputField","getMsgInputForm","getMsgSendBtn","getGreetingsButtons","getnewUserForm","getFirstNameInput","getLastNameInput","getPhoneNumberInput","getFirstNameErrorMessage","getLastNameErrorMessage","getPhoneNumberErrorMessage","getButtons","getButtonContainers","getMinMaxButtonContainer","getForms","getLoadingDots","getHiddenMessages","getTestInformation","getTimeStampElement","getTimeStampElementByIntervalID","getTimeStampInfoElement","timeStampElement","setTimeStamp","value","timeStamp","setTimeStampIntervalID","newID","deleteTimestamp","saveRequestIdToLocalStorage","groupId","expirationTime","chatIdInfo","key","setGreetingView","getGreetingView","setMinimization","getMinimization","setMaximization","getStoredRequestId","idHashInfo","isIdHashExpired","storeUserInformation","userInformation","getUserInformation","minimizeContainer","minimizeBtn","maximizeBtn","widgetContent","minMaxButtonContainer","trackConversationMinimization","maximizeContainer","setUpMinimizeButton","e","setUpMaximizeButton","removeGreetingElement","userInputField","firstNameInput","autoScrollToBottom","showMessagesTemplate","messages","trackConversationInitiation","requestId","testURLElement","messageURL","switchMinMaxButtonVisibility","moveLoadingDotsToBottomOfFeed","dots","showLoadingDots","hideLoadingDots","PLACEHOLDER_VALUES","interstitialCount","setPlaceHolderContent","placeholderKey","inputField","handleUserMessage","message","renderUserMessageOnFeed","domRequestId","initiateSessionTimeoutCheck","submitMessage","checkForSessionTimeout","resData","sendMessage","request_new_message","renderAssistantMessageOnFeed","disableMessageInput","data","res","sendErrorMessage","retries","errorURL","removeButtons","unhideMessages","removeForms","updateBanner","messageFeed","newMsgWrapper","newMsgContent","messageElement","showStamp","content","showTimeStamp","setUpButtons","setUpNewUserForm","autosizeInputField","setupMessageForm","userForm","sendBtn","messageInput","hideSendButtonDisplay","showSendButtonDisplay","enableMessageInput","initialTime","intervalID","updateTimeStampValue","difference","setUpMinMaxButtons","setUpGreetingButtons","btn","button","handleViewMoreLocationsButtonClick","location","submitUserInfo","firstName","lastName","phone","form","isValidPhoneNumber","phoneNumberInput","isValidName","inputElement","showErrorMessage","hideErrorMessage","isNumericInput","event","isModifierKey","enforceFormat","formatToPhone","input","areaCode","middle","last","newUserForm","lastNameInput","phoneValid","firstNameValid","lastNameValid","container","reinitializeWidget","resetUrl","oldRequestId","widgetContainer","loadWidgetInitialContent","newRequestId","templateURL","greetingView","minimizationTime","url","template","newUserInformation","geolocationSucceeded","geolocationRejected","options"],"mappings":"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"}