Dental CAD Knowledge Base

Expert Insights for Digital Dentistry

Practical guides, workflow breakdowns, and clinical perspectives from our CAD design team — written for dentists, labs, and specialists worldwide.

(function() { 'use strict'; if (window.__CHAT_WIDGET_INITIALIZED__) return; window.__CHAT_WIDGET_INITIALIZED__ = true; const widget = $('#chatWidget'); if (!widget) return; const toggle = $('#chatToggle'), panel = $('#chatPanel'), initForm = $('#chatInitForm'), chatMain = $('#chatMain'), chatName = $('#chatName'), chatEmail = $('#chatEmail'), chatInitMsg = $('#chatInitMsg'), chatMessages = $('#chatMessages'), chatForm = $('#chatForm'), chatInput = $('#chatInput'), chatUserLabel = $('#chatUserLabel'), chatReset = $('#chatReset'), closeBtn = $('.chat-close'), minBtn = $('.chat-min'), liveDot = $('.chat-live-dot'); let chatSession = null, isInitialized = false, pollInterval = null; function showInitForm() { panel.classList.remove('is-chatting'); initForm.hidden = false; chatMain.hidden = true; chatInitMsg.textContent = ''; chatName.focus(); } function showChatMain() { panel.classList.add('is-chatting'); initForm.hidden = true; chatMain.hidden = false; liveDot.hidden = false; chatInput.focus(); } function showInitError(message) { chatInitMsg.textContent = message; chatInitMsg.style.color = '#b33'; } function addMessage(text, sender, senderName) { const msg = document.createElement('div'); msg.className = `chat-msg ${sender}`; if (senderName) { const senderEl = document.createElement('div'); senderEl.className = 'msg-sender'; senderEl.textContent = senderName; msg.appendChild(senderEl); } const body = document.createElement('div'); body.className = 'msg-body'; const content = document.createElement('div'); content.className = 'msg-content'; content.textContent = text; body.appendChild(content); const time = document.createElement('div'); time.className = 'msg-time'; time.textContent = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); body.appendChild(time); msg.appendChild(body); chatMessages.appendChild(msg); chatMessages.scrollTop = chatMessages.scrollHeight; } function startPolling() { if (pollInterval) clearInterval(pollInterval); pollInterval = setInterval(async () => { if (!chatSession) return; try { const response = await fetch((window.APP_BASE_URL || '/') + 'actions/chat_poll.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: chatSession, _csrf: window.CSRF_TOKEN }) }); const result = await response.json(); if (result.success && result.messages) { result.messages.forEach(msg => { addMessage(msg.message, 'support', 'iDentCAD Support'); }); } } catch (error) { console.error('Poll error:', error); } }, 3000); } function endSession() { if (chatSession) { navigator.sendBeacon((window.APP_BASE_URL || '/') + 'actions/chat_end.php', JSON.stringify({ session_id: chatSession, _csrf: window.CSRF_TOKEN })); } if (pollInterval) clearInterval(pollInterval); pollInterval = null; chatSession = null; isInitialized = false; chatMessages.innerHTML = ''; liveDot.hidden = true; showInitForm(); } function saveCustomerInfo(name, email) { try { localStorage.setItem('identcad_chat_customer', JSON.stringify({ name, email })); } catch (e) { console.warn('Could not save customer info.', e); } } function loadCustomerInfo() { try { const storedInfo = localStorage.getItem('identcad_chat_customer'); if (storedInfo) { const customer = JSON.parse(storedInfo); chatName.value = customer.name || ''; chatEmail.value = customer.email || ''; } } catch (e) { console.warn('Could not load customer info.', e); } } on(toggle, 'click', (e) => { e.stopPropagation(); const isOpening = panel.hidden; panel.hidden = !isOpening; toggle.setAttribute('aria-expanded', String(isOpening)); if (isOpening) { const waPanel = $('#whatsappPanel'); if (waPanel) waPanel.hidden = true; loadCustomerInfo(); if (!isInitialized) showInitForm(); } }); on(closeBtn, 'click', () => { panel.hidden = true; toggle.setAttribute('aria-expanded', 'false'); }); on(minBtn, 'click', () => { panel.hidden = true; toggle.setAttribute('aria-expanded', 'false'); }); on(initForm, 'submit', async (e) => { e.preventDefault(); const name = chatName.value.trim(), email = chatEmail.value.trim(); if (!name) { showInitError('Please enter your name'); return; } if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { showInitError('Please enter a valid email'); return; } const submitBtn = initForm.querySelector('button'); submitBtn.disabled = true; submitBtn.textContent = 'Starting...'; chatInitMsg.textContent = 'Connecting...'; chatInitMsg.style.color = '#555'; try { saveCustomerInfo(name, email); const response = await fetch((window.APP_BASE_URL || '/') + 'actions/chat_start.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, email, _csrf: window.CSRF_TOKEN }) }); const result = await response.json(); if (result.success) { chatSession = result.session_id; isInitialized = true; chatUserLabel.textContent = `${name}`; showChatMain(); addMessage('Welcome! How can we help you today?', 'support', 'iDentCAD Support'); startPolling(); } else { throw new Error(result.error || 'Failed to start chat'); } } catch (error) { console.error('Chat init error:', error); showInitError(error.message || 'Connection failed.'); } finally { submitBtn.disabled = false; submitBtn.textContent = 'Start Chat'; } }); on(chatForm, 'submit', async (e) => { e.preventDefault(); const message = chatInput.value.trim(); if (!message || !chatSession) return; addMessage(message, 'user', chatName.value); chatInput.value = ''; try { await fetch((window.APP_BASE_URL || '/') + 'actions/chat_send.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: chatSession, message, _csrf: window.CSRF_TOKEN }) }); } catch (error) { console.error('Send message error:', error); addMessage('Failed to send message.', 'system-error'); } }); on(chatReset, 'click', () => { if (confirm('Are you sure you want to end this chat session?')) endSession(); }); })();