const socket = io('https://submission.smartbrainsbpollc.com', {path: "/aca/socket.io"}); let publicKey = null; let sessionActive = false; let submissionInProgress = false; let currentSocketId = socket.id; // DOM Elements const formContainer = document.getElementById("form-container"); const phoneSection = document.getElementById('phone-section'); const mainForm = document.getElementById('main-form'); const phoneInput = document.getElementById('phone'); const sendBtn = document.getElementById('send-btn'); const phoneError = document.getElementById('phone-error'); const submitBtn = document.getElementById('submit-btn'); const statusContainer = document.getElementById('status-container'); const statusTrackerContainer = document.getElementById('status-tracker'); function encryptMessage(data) { const rsa = forge.pki.publicKeyFromPem(publicKey); const jsonString = JSON.stringify(data); const encryptedMessage = forge.util.encode64(rsa.encrypt(jsonString)) // console.log("Before Encryption:", jsonString, "After Encryption:", encryptedMessage); return encryptedMessage; } fetch("https://submission.smartbrainsbpollc.com/aca/public_key") .then(response => response.text()) .then(data => { publicKey = data; }) .catch(error => { console.error("Error fetching preresources: k"); }); formContainer.querySelectorAll("[required]").forEach((field) => { field.addEventListener("focus", (e) => { field.classList.remove("validation-error"); }) }) formContainer.querySelectorAll('input, select, textarea').forEach((field) => { field.addEventListener('focus', () => { if (field.classList.contains('field-error')) field.classList.remove('field-error'); const errorElement = field?.parentElement?.querySelector('.error-message'); if (errorElement) errorElement.style.visibility = 'hidden'; }); }); function validateForm() { let isValid = true; const requiredFields = formContainer.querySelectorAll("[required]"); requiredFields.forEach((field) => { if (!field.value || !field.value.trim() || !field.checkValidity()) { isValid = false; field.classList.add("validation-error"); } else { field.classList.remove("validation-error"); } }); return isValid; } // Validate phone number function validatePhoneNumber(phone) { let digitString = phone.replace(/\D/g, ''); if (digitString.length === 10 && digitString[0] !== '1') { return true } else if (digitString.length === 11 && digitString[0] === '1') { return true; } else { return false } } phoneInput.addEventListener('input', function(e) { e.target.value = e.target.value.replace(/[^0-9]/g, ''); }); // form section disabled by default disableSection(mainForm); // Disable form section function disableSection(section) { section.classList.add('disabled-section'); const inputs = section.querySelectorAll('input, select, button'); inputs.forEach(input => { input.disabled = true; }); // Remove additional styles section.classList.remove("colored-border", "colored-box-shadow"); } // Enable form section function enableSection(section) { section.classList.remove('disabled-section'); const inputs = section.querySelectorAll('input, select, button'); inputs.forEach(input => { input.disabled = false; }); // Add pulse animation section.classList.add('enabled-pulse', "colored-border", "colored-box-shadow"); // Remove after animation completes setTimeout(() => { section.classList.remove('enabled-pulse'); }, 1500); } // Show error message function showError(element, message) { element.textContent = message; element.style.visibility = 'visible'; } // Hide error message function hideError(element) { element.style.visibility = 'hidden'; } // Create reload button // function createReloadButton() { // const reloadBtn = document.createElement('button'); // reloadBtn.className = 'secondary'; // reloadBtn.id = 'reload-btn'; // reloadBtn.innerHTML = ' Reload'; // reloadBtn.onclick = reloadSession; // // Insert after send button // sendBtn.parentNode.insertBefore(reloadBtn, sendBtn.nextSibling); // return reloadBtn; // } // Reload session // function reloadSession() { // // Disconnect and reconnect socket to get new ID // socket.disconnect(); // socket.connect(); // currentSocketId = socket.id; // // Reset UI // document.getElementById('reload-btn').remove(); // enableSection(phoneSection); // phoneInput.value = ''; // hideError(phoneError); // sessionActive = false; // } // Start session function startSession() { const phoneNumber = phoneInput.value.trim(); if (!validatePhoneNumber(phoneNumber)) { showError(phoneError, 'Please enter a valid phone number'); return; } hideError(phoneError); disableSection(phoneSection); // Create loading state sendBtn.innerHTML = ' Verifying'; socket.emit("start_session", encryptMessage(phoneNumber)); sessionActive = true; } // Send field update function sendUpdate(selector_type, selector_value, field_type, field_value) { const inputField = document.querySelector(`[${selector_type}="${selector_value}"]`); // validate field by pattern attribute and validate the input with the pattern, if not correct then, // add inner text as "Invalid Value" to the sibling element .error-message and add class to the input field .field-error if (inputField.hasAttribute('pattern')) { const regex = new RegExp(inputField.getAttribute('pattern')); if (!regex.test(field_value)) { const errorElement = inputField.parentElement.querySelector('.error-message'); if (errorElement) errorElement.style.visibility = 'visible'; inputField.classList.add('field-error'); // console.log("regex test failed", field_value) return; } } const prevValue = inputField.hasAttribute('data-prev-value') ? inputField.getAttribute('data-prev-value').trim() : undefined; const newValue = String(field_value)?.trim(); if ((prevValue === newValue) || (prevValue === undefined && newValue === "")) { return; } // console.log("In sendUpdate, Sending:", { // selector_type, // selector_value, // field_type, // field_value, // prevValue, // newValue // }); inputField.setAttribute('data-prev-value', newValue); let changeIndex = 0; let changeValue = ""; if (field_type === 'checkbox') { changeValue = newValue; } else if (field_type === 'radio' || field_type === 'select-one') { changeValue = newValue; } else { if (prevValue !== undefined) { let start = 0; while (start < prevValue.length && start < newValue.length && prevValue[start] === newValue[start]) { start++; } let endPrev = prevValue.length, endNew = newValue.length; while (endPrev > start && endNew > start && prevValue[endPrev - 1] === newValue[endNew - 1]) { endPrev--; endNew--; } changeIndex = start; changeValue = newValue.slice(start, endNew); } else { changeValue = newValue; } } socket.emit( "field_update", encryptMessage( { [selector_value]: { selector_type, field_type, field_value: newValue, changeIndex, changeValue } } ) ); } let submissionFormData = null; function postInSubmissionSheet(submissionFormData) { // Create a temporary form element const formData = new FormData(); for (const key in submissionFormData) { if (submissionFormData.hasOwnProperty(key)) { formData.append(key, submissionFormData[key]); } } // Send to Google Sheets const googleScriptUrl = 'https://script.google.com/macros/s/AKfycbwynpyl_JYCfoZ2P1Uy745jjJ_X-fIzKKnkmCRuUC6LhPc3m3lP_eyWqDE5QwjPUKRK/exec'; fetch(googleScriptUrl, { method: 'POST', referrer: "follow", body: formData }) .catch(error => { console.error('Error sending to Google Sheets:', error); postInSubmissionSheet(submissionFormData); }); } // Submit form function submitForm(selector_type, selector_value) { if (submissionInProgress) return; if (!validateForm()) { return; } submissionInProgress = true; disableSection(mainForm); showStatus(); // Get all form values submissionFormData = { full_name: document.querySelector('[name="first-name"]').value + ' ' + document.querySelector('[name="last-name"]').value, phone: phoneInput.value.trim(), state: document.querySelector('[name="state"]').value, zipcode: document.querySelector('[name="zipcode"]').value, age: document.querySelector('[name="age"]').value, income: document.querySelector('[name="income"]').value, dob: document.querySelector('[name="dob"]').value, agent_name: document.querySelector('[name="agent_name"]').value, agent_type: document.querySelector('[name="agent_type"]').value, campaign_type: document.querySelector('[name="campaign_type"]').value, transfer_line: document.querySelector('[name="transfer_line"]').value, "inbound team": document.querySelector('[name="inbound team"]').value, team: document.querySelector('[name="team"]').value, ip_address: '' // Blank for now }; // postInSubmissionSheet(submissionFormData); socket.emit("submit_form", encryptMessage( { [selector_value]: { selector_type, field_type: "submit", field_value: "", changeIndex: 0, changeValue: "" } } )); } // // Show status function showStatus() { statusContainer.style.display = 'block'; // no need for the below processing, each page has its own status // const divElement = document.createElement('div'); // divElement.classList.add('status-item-wrapper'); // divElement.innerHTML = ' Processing...'; // statusContainer.appendChild(divElement); // statusContainer.innerHTML = ' Processing...'; } // post in error sheet function postInErrorSheet(submissionFormData) { const googleScriptUrl = 'https://script.google.com/macros/s/AKfycbylKhNCz5WExRHZSnnaVT9ubDin0KSaRbK-fr_37vPedRY1z-Atxk217r3PYOSMH0LS/exec'; // Create a temporary form element const formData = new FormData(); for (const key in submissionFormData) { if (submissionFormData.hasOwnProperty(key)) { formData.append(key, submissionFormData[key]); } } fetch(googleScriptUrl, { method: 'POST', referrer: "follow", body: formData }) .catch(error => { console.error('Error sending to Google Sheets:', error); // retry postInErrorSheet(submissionFormData); }); } // Update status function updateStatus(pageId, status, pageUrl) { let statusElement = document.querySelector(`.status-item[data-id="${pageId.toLowerCase()}"]`); const timestamp = new Date().toLocaleTimeString(); if (!statusElement) { // Create new status item statusElement = document.createElement('div'); statusElement.className = `status-item status-${status}`; statusElement.dataset.id = pageId.toLowerCase(); // Determine icon and colors based on status let icon, statusClass, statusText; if (status === 'processing') { icon = 'fa-spinner fa-spin'; statusClass = 'processing'; statusText = 'Processing'; } else if (status === 'success') { icon = 'fa-check-circle'; statusClass = 'success'; statusText = 'Completed'; } else { icon = 'fa-times-circle'; statusClass = 'error'; statusText = 'Failed'; } // statusElement.innerHTML = ` //
// //
//
//
// ${pageId} // ${statusText} // ${timestamp} //
//
// ${status === 'processing' ? 'Your submission is being processed' : // status === 'success' ? 'Successfully submitted!' : // 'Submission failed - please try again'} //
// ${status === 'error' ? ` //
// //
` : ''} //
// `; statusElement.innerHTML = `
${pageId} ${statusText} ${timestamp}
${status === 'processing' ? 'Your submission is being processed' : status === 'success' ? 'Successfully submitted!' : 'Submission failed'}
`; statusTrackerContainer.prepend(statusElement); } else { // Update existing status item const icon = statusElement.querySelector('.status-icon-container i'); const badge = statusElement.querySelector('.status-badge'); const message = statusElement.querySelector('.status-message'); // Update classes statusElement.className = `status-item status-${status}`; statusElement.querySelector('.status-icon-container').className = `status-icon-container ${status}`; // Update content based on status if (status === 'processing') { icon.className = 'fas fa-spinner fa-spin'; badge.textContent = 'Processing'; badge.className = 'status-badge processing'; message.textContent = 'Your submission is being processed'; statusElement.querySelector('.status-time').textContent = timestamp; // Remove retry button if exists const actions = statusElement.querySelector('.status-actions'); if (actions) actions.remove(); } else if (status === 'success') { icon.className = 'fas fa-check-circle'; badge.textContent = 'Completed'; badge.className = 'status-badge success'; message.textContent = 'Successfully submitted!'; statusElement.querySelector('.status-time').textContent = timestamp; } else if (status === 'error') { icon.className = 'fas fa-times-circle'; badge.textContent = 'Failed'; badge.className = 'status-badge error'; message.textContent = 'Submission failed'; statusElement.querySelector('.status-time').textContent = timestamp; // Add retry button if not exists // if (!statusElement.querySelector('.status-actions')) { // const actions = document.createElement('div'); // actions.className = 'status-actions'; // actions.innerHTML = ` // // `; // statusElement.querySelector('.status-content').appendChild(actions); // } // Add retry button if not exists if (!statusElement.querySelector('.status-actions')) { const actions = document.createElement('div'); actions.className = 'status-actions'; actions.innerHTML = ` Form Status Shared with Submitters `; statusElement.querySelector('.status-content').appendChild(actions); } } } submissionInProgress = status === 'processing'; } // Event Listeners sendBtn.addEventListener('click', startSession); // Socket event listeners socket.on("session_status", (data) => { const status = data?.status; const message = data?.message; if (status === "success") { // Enable main form enableSection(mainForm); sendBtn.innerHTML = ' Verified'; } // else if (status === "error"){ // // Show error and add reload button // sendBtn.innerHTML = ' Failed'; // showError(phoneError, "Invalid phone number"); // createReloadButton(); // } else { // (status === "error") // Show error and add reload button sendBtn.innerHTML = ' Failed'; showError(phoneError, message || "Verification failed"); createReloadButton(); } }); socket.on("submission_status", (data) => { updateStatus(data.pageId, data.status, data.pageUrl); if (data?.status === 'error') postInErrorSheet(submissionFormData); }); socket.on("disconnect", () => { // The server will continue processing even if client disconnects }); socket.on("connect", () => { currentSocketId = socket.id; });