nhance/app/Views/chatbot.php
2025-08-16 17:35:18 +05:30

672 lines
26 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Insurance ChatBot</title>
</head>
<style>
html, body {
height: 100%;
margin: 0;
}
/* body {
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
}
h1 {
font-size: 3rem;
font-weight: bold;
animation: colorShift 2s infinite linear;
}
@keyframes colorShift {
0% { color: red; }
25% { color: orange; }
50% { color: green; }
75% { color: blue; }
100% { color: violet; }
}*/
</style>
<style>
/* Full-screen overlay */
#page-loader {
position: fixed;
inset: 0; /* top:0; right:0; bottom:0; left:0 */
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,0.85);
z-index: 9999;
transition: opacity 300ms ease, visibility 300ms ease;
visibility: visible;
opacity: 1;
}
/* Hidden state */
#page-loader.hidden {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
/* Optional card around GIF */
#page-loader .loader-box {
text-align: center;
padding: 18px;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0,0,0,0.12);
background: rgba(255,255,255,0.95);
backdrop-filter: blur(4px);
}
/* Restrict gif size for large screens */
#page-loader img {
display: block;
max-width: 120px;
width: 20vw;
height: auto;
}
/* Example page content styling */
body.noscroll {
overflow: hidden; /* prevent scrolling while loader is visible */
}
main { padding: 2rem; font-family: Arial, Helvetica, sans-serif; }
</style>
<body>
<!-- <h1>Loading...from page</h1> -->
<!-- Page loader overlay (visible by default) -->
<div id="page-loader" aria-hidden="false">
<div class="loader-box">
<!-- Replace the src with your GIF file path -->
<img src="https://venbait.in/nhance/dev/assets/images/nhance-loader.gif" alt="Loading..." />
<!-- <div style="margin-top:8px;font-size:14px;color:#555;">Loading, please wait...</div> -->
</div>
</div>
<script>
// alert('start of main');
var uid = Math.floor(100000 + Math.random() * 900000);
console.log('CURRENT_USER' + uid);
const queryParams = getQueryParams();
console.log(queryParams);
const isMobile = window.innerWidth <= 600;
const calcHeight = Math.floor(window.innerHeight * 0.6);
const calcWidth = isMobile
? (window.innerWidth)
: Math.min(400, window.innerWidth - 50);
const name = queryParams['name'];
var botmanWidget = {
// chatServer: 'https://venbait.in/nhance/chatbot/chat',
// frameEndpoint: 'https://venbait.in/nhance/chatbot/widget',
chatServer: `<?=base_url('chat')?>`,
frameEndpoint: `<?=base_url('widget')?>`,
title: "Ask ILA",
placeholderText: "Type your message here...",
aboutText: "Insurance Assistant ILA",
enableAttachments: false,
introMessage: ('Welcome '+ name + '...! Say Hi...'),
bubbleAvatarUrl:"https://botman.io/img/logo.png",
parameters: {
employee_id: queryParams['employee_id'],
session_id: "XYZ789",
origin: queryParams['origin'],
emp_code: queryParams['emp_code'],
client_id:queryParams['client_id'],
client_branch_id: queryParams['client_branch_id']
}
};
// Also add scrolling when new messages arrive by observing the chat area
function setupMessageObserver() {
if (!currentIframe) {
console.log('No iframe available for message observer');
return;
}
try {
const doc = currentIframe.contentDocument || currentIframe.contentWindow.document;
if (!doc) {
console.log('Cannot access iframe document for message observer');
return;
}
const waitForChatArea = () => {
const chatArea = doc.querySelector("#messageArea .chat") ||
doc.querySelector("#messageArea ol.chat") ||
doc.querySelector("ol.chat");
if (chatArea) {
console.log('Chat area found, setting up mutation observer');
// Create observer instance
const observer = new MutationObserver((mutations) => {
// Check if any mutations added nodes
const hasNewMessages = mutations.some(mutation =>
mutation.addedNodes && mutation.addedNodes.length > 0
);
if (hasNewMessages) {
// Scroll to bottom when new messages arrive
setTimeout(() => {
scrollToBottom();
}, 100);
}
});
// Start observing the chat area for child list changes
observer.observe(chatArea, {
childList: true,
subtree: true
});
// Also scroll to bottom initially
setTimeout(() => {
scrollToBottom();
}, 500);
} else {
console.log('Chat area not found yet, retrying...');
setTimeout(waitForChatArea, 200);
}
};
waitForChatArea();
} catch (error) {
console.error('Error setting up message observer:', error);
}
}
// Improved CSS injection function with better timing and specificity
function injectCSS(frame) {
console.log('injectCSS called');
// Store the iframe reference for later use
currentIframe = frame;
try {
const doc = frame.contentDocument || frame.contentWindow.document;
if (!doc) {
console.error("Cannot access iframe document");
return;
}
// ✅ Change iframe body background here
doc.body.style.background = "url('https://venbait.in/nhance/app/dev/assets/chat-bg.jpg') no-repeat center center fixed";
// doc.body.style.background = "covercover";
doc.body.style.backgroundSize = "cover";
doc.body.style.margin = "0"; // optional
// Wait for the document to be ready
const waitForElement = () => {
const messageArea = doc.querySelector("#messageArea");
const chatElement = doc.querySelector("#messageArea .chat");
if (messageArea && chatElement) {
console.log('Elements found, injecting CSS');
// Set initial height based on device
const initialHeight = isMobile ? 700 : 800; // Default to keyboard closed state
// // Method 1: Create style element with high specificity
// const style = doc.createElement("style");
// style.id = 'dynamic-chat-height';
// style.textContent = `
// /* High specificity selectors */
// #messageArea ol.chat,
// #messageArea .chat,
// ol.chat {
// height: ${initialHeight}px !important;
// max-height: ${initialHeight}px !important;
// min-height: ${initialHeight}px !important;
// transition: height 0.3s ease;
// }
// /* Additional styling to ensure proper display */
// #messageArea {
// height: auto !important;
// }
// `;
// doc.head.appendChild(style);
// Method 2: Direct style application as backup
setTimeout(() => {
const chatElements = doc.querySelectorAll("#messageArea .chat, #messageArea ol.chat, ol.chat");
chatElements.forEach(element => {
if (element) {
element.style.setProperty("height", 85 + "vh", "important");
element.style.setProperty("max-height", 85 + "vh", "important");
element.style.setProperty("min-height", 85 + "vh", "important");
element.style.setProperty("transition", "height 0.3s ease", "important");
console.log('Direct style applied to:', element);
}
});
// Update current height
currentChatHeight = initialHeight;
// Setup input focus listeners after CSS is applied
setTimeout(() => {
setupInputFocusListeners();
}, 500);
// setTimeout(() => {
// setupMessageObserver();
// }, 500);
}, 500);
} else {
console.log('Elements not found yet, retrying...');
setTimeout(waitForElement, 200);
}
};
// Start checking for elements
if (doc.readyState === 'complete') {
waitForElement();
} else {
doc.addEventListener('DOMContentLoaded', waitForElement);
// Fallback timeout
setTimeout(waitForElement, 1000);
}
} catch (error) {
console.error('Error injecting CSS:', error);
}
}
// Improved iframe detection with better timing
function waitForBotmanIframe(callback) {
console.log('waitForBotmanIframe');
const checkForIframe = () => {
const iframe = document.querySelector("#chatBotManFrame") ||
document.querySelector("iframe[src*='widget']") ||
document.querySelector("#botmanChatRoot iframe");
if (iframe) {
console.log('Iframe found:', iframe);
callback(iframe);
return true;
}
return false;
};
// Check immediately
if (checkForIframe()) return;
// Use MutationObserver as fallback
const container = document.querySelector("#botmanChatRoot") || document.body;
const observer = new MutationObserver((mutations, obs) => {
if (checkForIframe()) {
obs.disconnect();
}
});
observer.observe(container, {
childList: true,
subtree: true,
attributes: true
});
// Timeout fallback
setTimeout(() => {
observer.disconnect();
checkForIframe();
}, 5000);
}
// Enhanced CSS application for the main document
function applyBotManChatCSS() {
console.log('applyBotManChatCSS called');
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
/* Hide unwanted elements */
div[style*="background: rgb(64, 133, 145)"][style*="line-height: 30px"] {
display: none !important;
}
div[class*="desktop-closed-message-avatar"] {
display: none !important;
}
/* Iframe styling */
iframe#chatBotManFrame {
height: 100% !important;
width: 100% !important;
display: block;
}
/* Additional iframe selectors */
iframe[src*="widget"] {
height: 100% !important;
width: 100% !important;
}
iframe#body {
background: none !important;
}
`;
document.getElementsByTagName('head')[0].appendChild(style);
}
// Input focus-based height adjustment
let currentChatHeight = 800; // Default height
let isInputFocused = false;
let currentIframe = null;
function adjustChatHeight(height) {
console.log('Adjusting chat height to:', height);
currentChatHeight = height;
if (currentIframe) {
try {
const doc = currentIframe.contentDocument || currentIframe.contentWindow.document;
if (doc) {
// Update existing style
// let styleElement = doc.querySelector('#dynamic-chat-height');
// if (!styleElement) {
// styleElement = doc.createElement('style');
// styleElement.id = 'dynamic-chat-height';
// doc.head.appendChild(styleElement);
// }
// styleElement.textContent = `
// #messageArea ol.chat,
// #messageArea .chat,
// ol.chat {
// height: ${height}px !important;
// max-height: ${height}px !important;
// min-height: ${height}px !important;
// transition: height 0.3s ease;
// }
// `;
// Direct style application as backup
const chatElements = doc.querySelectorAll("#messageArea .chat, #messageArea ol.chat, ol.chat");
chatElements.forEach(element => {
if (element) {
element.style.setProperty("height", 85 + "vh", "important");
element.style.setProperty("max-height", 85 + "vh", "important");
element.style.setProperty("min-height", 85 + "vh", "important");
}
});
console.log('Chat height adjusted successfully to:', height);
}
} catch (error) {
console.error('Error adjusting chat height:', error);
}
}
}
// Setup input focus/blur listeners for height adjustment
function setupInputFocusListeners() {
if (!currentIframe) {
console.log('No iframe available for input listeners');
return;
}
try {
const doc = currentIframe.contentDocument || currentIframe.contentWindow.document;
if (!doc) {
console.log('Cannot access iframe document for input listeners');
return;
}
// Function to find and attach listeners to the userText input
const attachInputListeners = () => {
const userTextInput = doc.querySelector('#userText');
if (userTextInput) {
console.log('Found userText input, attaching listeners');
// Remove existing listeners to prevent duplicates
userTextInput.removeEventListener('focus', handleInputFocus);
userTextInput.removeEventListener('blur', handleInputBlur);
// Add new listeners
userTextInput.addEventListener('focus', handleInputFocus);
userTextInput.addEventListener('blur', handleInputBlur);
console.log('Input focus/blur listeners attached successfully');
return true;
} else {
console.log('userText input not found, retrying...');
return false;
}
};
// Try to attach listeners immediately
if (!attachInputListeners()) {
// If input not found, set up a mutation observer to wait for it
const observer = new MutationObserver((mutations, obs) => {
if (attachInputListeners()) {
obs.disconnect();
}
});
observer.observe(doc.body, {
childList: true,
subtree: true
});
// Stop observing after 10 seconds
setTimeout(() => {
observer.disconnect();
console.log('Stopped observing for userText input');
}, 10000);
}
} catch (error) {
console.error('Error setting up input focus listeners:', error);
}
}
// Handle input focus event
function handleInputFocus(event) {
console.log('Input focused - userText field');
if (!isInputFocused && isMobile) {
// alert('focused');
isInputFocused = true;
// Adjust height when input is focused (keyboard likely open)
adjustChatHeight(400); // Smaller height when keyboard is open
scrollToBottom();
// Add scroll to bottom when input is focused
setTimeout(() => {
scrollToBottom();
}, 300); // Small delay to allow height adjustment to complete
}
}
// Handle input blur event
function handleInputBlur(event) {
console.log('Input blurred - userText field');
// alert('blurred');
if (isInputFocused && isMobile) {
isInputFocused = false;
// Small delay to ensure keyboard is fully closed
setTimeout(() => {
// Adjust height when input is blurred (keyboard likely closed)
adjustChatHeight(700); // Larger height when keyboard is closed
}, 300);
}
}
function scrollToBottom() {
if (!currentIframe) return;
try {
console.info('CALLED START: scrollToBottom');
const doc = currentIframe.contentDocument || currentIframe.contentWindow.document;
if (!doc) return;
const messageArea = doc.querySelector("#messageArea .chat") ||
doc.querySelector("#messageArea ol.chat") ||
doc.querySelector("ol.chat");
if (messageArea) {
// Scroll to bottom with smooth behavior
console.info('CALLED WORKING: scrollToBottom');
messageArea.scrollTo({
top: messageArea.scrollHeight,
behavior: 'smooth'
});
}
console.info('CALLED ENDs: scrollToBottom');
} catch (error) {
console.error('Error scrolling to bottom:', error);
}
}
function getQueryParams() {
const params = {};
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
for (const [key, value] of urlParams.entries()) {
params[key] = value;
}
return params;
}
// Main initialization
window.addEventListener("load", function () {
console.log('Page loaded, initializing bot');
setTimeout(function () {
if (window.botmanWidget) {
botmanChatWidget.open();
setTimeout(function(){
botmanChatWidget.sayAsBot('Hi ' + (typeof name !== "undefined" && name !== null && name !== "" ? name : "Guest User") + ', This is ILA your Insurance Assistant, plz choose the following options');
botmanChatWidget.whisper('Hi');
}, 1000);
applyBotManChatCSS();
// Multiple attempts to inject CSS with different timings
waitForBotmanIframe((chatFrame) => {
console.log('Iframe detected, attempting CSS injection');
// Immediate attempt
injectCSS(chatFrame);
// Delayed attempts for better reliability
setTimeout(() => injectCSS(chatFrame), 1000);
setTimeout(() => injectCSS(chatFrame), 2000);
setTimeout(() => injectCSS(chatFrame), 3000);
// Listen for iframe load events
chatFrame.addEventListener("load", () => {
console.log('Iframe loaded event triggered');
setTimeout(() => injectCSS(chatFrame), 100);
});
});
}
}, 1000);
});
// Additional fallback - try to inject CSS periodically and setup input listeners
setInterval(() => {
const iframe = document.querySelector("#chatBotManFrame") ||
document.querySelector("iframe[src*='widget']") ||
document.querySelector("#botmanChatRoot iframe");
if (iframe && !currentIframe) {
currentIframe = iframe;
console.log('Iframe reference updated via periodic check');
// Setup input listeners when iframe is found
setTimeout(() => setupInputFocusListeners(), 1000);
}
if (iframe && currentIframe) {
try {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const chatElement = doc?.querySelector("#messageArea .chat");
if (chatElement) {
const expectedHeight = isMobile ? (isInputFocused ? 400 : 700) : 800;
const actualHeight = parseInt(chatElement.style.height);
if (actualHeight !== expectedHeight) {
console.log('Periodic CSS injection attempt - height mismatch');
adjustChatHeight(expectedHeight);
}
// Check if input listeners need to be setup
const userTextInput = doc.querySelector('#userText');
if (userTextInput && !userTextInput.hasAttribute('data-listeners-attached')) {
console.log('Input found without listeners, setting up...');
setupInputFocusListeners();
}
}
} catch (e) {
// Silently handle cross-origin errors
}
}
}, 3000);
// Debug function to manually test height changes
window.debugChatHeight = function(height) {
console.log('Manual height adjustment:', height);
adjustChatHeight(height);
};
// Debug function to check current state
window.debugInputState = function() {
console.log('Current state:', {
isMobile: isMobile,
isInputFocused: isInputFocused,
currentChatHeight: currentChatHeight,
currentIframe: !!currentIframe
});
if (currentIframe) {
try {
const doc = currentIframe.contentDocument || currentIframe.contentWindow.document;
const userTextInput = doc?.querySelector('#userText');
console.log('userText input found:', !!userTextInput);
if (userTextInput) {
console.log('Input is focused:', document.activeElement === userTextInput);
}
} catch (e) {
console.log('Cannot access iframe document');
}
}
};
// Debug function to manually setup input listeners
window.debugSetupInputListeners = function() {
console.log('Manually setting up input listeners');
setupInputFocusListeners();
};
</script>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src='https://cdn.jsdelivr.net/npm/botman-web-widget@0/build/js/widget.js'></script>
</body>
</html>