(function() { 'use strict'; const WIDGET_CONFIG = { tenant: 'itlive', subagent: '', project: '', page: '', apiBase: 'https://portal.itlive.nl/admin_portal/api', locale: 'nl', strings: {"header":"AI Assistent","powered":"Powered by IT Live","placeholder":"Typ je bericht...","send":"Verstuur","welcome":"\ud83d\udc4b Hallo! Ik ben de AI-assistent van IT Live. Hoe kan ik je helpen? Stel gerust je vraag over websites, hosting, SEO of neem contact op.","error":"\u274c Er ging iets mis. Probeer het opnieuw.","connectionError":"\u274c Verbindingsfout. Controleer je internet.","footer":"Powered by IT Live","whatsappUrl":"https:\/\/wa.me\/31850604017","phoneTel":"+31850604017","micLabel":"Spraak","micRecording":"Opnemen...","quickLinks":[{"label":"Offerte aanvragen","url":"https:\/\/itlive.nl\/offerte"},{"label":"Gratis kennismaking","url":"https:\/\/itlive.nl\/gratis-kennismaking"},{"label":"Contact","url":"https:\/\/itlive.nl\/contact"},{"label":"Vertel je idee","url":"https:\/\/itlive.nl\/idee"},{"label":"Klantportaal","url":"https:\/\/portal.itlive.nl\/customer_portal\/"},{"label":"Gratis website scan","url":"https:\/\/itlive.nl\/gratis-website-scan"},{"label":"Meta scan","url":"https:\/\/itlive.nl\/meta-campagne\/"},{"label":"Diensten","url":"https:\/\/itlive.nl\/diensten"},{"label":"Sitechat","url":"https:\/\/portal.itlive.nl\/sitechat\/"}]}, theme: {"primary":"#667eea","secondary":"#764ba2","background":"#0f172a","messagesBg":"#1e293b","text":"#f1f5f9","inputBg":"#1e293b","inputBorder":"#334155","botMessageBg":"#334155","botMessageText":"#f1f5f9"} }; // Create widget container const widgetHTML = `
`; // Inject widget HTML if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initWidget); } else { initWidget(); } let attachedUrls = []; function initWidget() { const container = document.createElement('div'); container.innerHTML = widgetHTML; document.body.appendChild(container); // Show widget after a delay setTimeout(() => { document.getElementById('itlive-ai-widget').style.display = 'block'; }, 1000); // Event listeners const bubble = document.getElementById('itlive-ai-chat-bubble'); const window = document.getElementById('itlive-ai-chat-window'); const closeBtn = document.getElementById('itlive-ai-close'); const sendBtn = document.getElementById('itlive-ai-send'); const input = document.getElementById('itlive-ai-input'); bubble.addEventListener('click', () => { window.style.display = 'flex'; bubble.style.transform = 'scale(0)'; document.body.classList.add('itlive-ai-widget-open'); input.focus(); }); closeBtn.addEventListener('click', () => { window.style.display = 'none'; bubble.style.transform = 'scale(1)'; document.body.classList.remove('itlive-ai-widget-open'); }); // Snelle links: standaard ingeklapt, toggle bij klik const qlWrap = document.getElementById('itlive-ai-quicklinks-wrap'); const qlToggle = document.getElementById('itlive-ai-quicklinks-toggle'); const qlList = document.getElementById('itlive-ai-quicklinks-list'); const qlChevron = document.getElementById('itlive-ai-quicklinks-chevron'); const qlinks = (WIDGET_CONFIG.strings.quickLinks || []); if (qlWrap && qlList && qlinks.length > 0) { qlWrap.style.display = 'flex'; qlWrap.style.flexDirection = 'column'; qlinks.forEach(function(link) { const a = document.createElement('a'); a.href = link.url || '#'; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.className = 'itlive-quick-link'; a.textContent = link.label || 'Link'; a.style.cssText = (['prepfoodz', 'prepfoodz-klant'].includes(WIDGET_CONFIG.tenant)) ? 'display: inline-block; padding: 8px 14px; font-size: 13px; background: rgba(214,194,163,0.25); color: #D6C2A3; text-decoration: none; border-radius: 10px; border: 1px solid rgba(214,194,163,0.4); transition: background 0.2s, border-color 0.2s;' : 'display: inline-block; padding: 8px 14px; font-size: 13px; background: rgba(102,126,234,0.2); color: #818cf8; text-decoration: none; border-radius: 10px; border: 1px solid rgba(102,126,234,0.35); transition: background 0.2s, border-color 0.2s;'; qlList.appendChild(a); }); if (qlToggle && qlChevron) { qlToggle.addEventListener('click', function() { const isExpanded = qlList.style.display !== 'none'; qlList.style.display = isExpanded ? 'none' : 'flex'; qlToggle.setAttribute('aria-expanded', isExpanded ? 'false' : 'true'); qlChevron.textContent = isExpanded ? '▶' : '▼'; }); } } sendBtn.addEventListener('click', sendMessage); input.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendMessage(); }); // Expose programmatic send for pages (e.g. mijn-bedrijf Start AI-rapport) window.itliveAISendMessage = function(text) { const i = document.getElementById('itlive-ai-input'); const s = document.getElementById('itlive-ai-send'); if (i && s && text != null && String(text).trim() !== '') { i.value = String(text).trim(); s.click(); } }; // Microfoon / spraakherkenning (Web Speech API) const micBtn = document.getElementById('itlive-ai-mic'); if (micBtn) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; const micLabel = WIDGET_CONFIG.strings.micLabel || (WIDGET_CONFIG.locale === 'nl' ? 'Spraak' : 'Voice'); const micRecording = WIDGET_CONFIG.strings.micRecording || (WIDGET_CONFIG.locale === 'nl' ? 'Opnemen...' : 'Recording...'); if (!SpeechRecognition) { micBtn.style.display = 'none'; } else { let recognition = null; let isRecording = false; micBtn.addEventListener('click', function() { const inp = document.getElementById('itlive-ai-input'); if (!inp) return; if (isRecording && recognition) { recognition.stop(); return; } recognition = recognition || new SpeechRecognition(); recognition.continuous = true; recognition.interimResults = true; recognition.lang = WIDGET_CONFIG.locale === 'nl' ? 'nl-NL' : 'en-GB'; recognition.onstart = function() { isRecording = true; micBtn.style.background = '#ef4444'; micBtn.style.color = '#fff'; micBtn.title = micRecording; micBtn.setAttribute('aria-label', micRecording); micBtn.textContent = '⏹'; }; recognition.onend = function() { isRecording = false; micBtn.style.background = ''; micBtn.style.color = ''; micBtn.title = micLabel; micBtn.setAttribute('aria-label', micLabel + (WIDGET_CONFIG.locale === 'nl' ? ' opnemen' : ' input')); micBtn.textContent = '🎤'; }; recognition.onresult = function(event) { let transcript = ''; for (let i = event.resultIndex; i < event.results.length; i++) { transcript += event.results[i][0].transcript; } if (transcript) inp.value = (inp.value ? inp.value + ' ' : '') + transcript; }; recognition.onerror = function(e) { if (e.error !== 'aborted') { isRecording = false; micBtn.style.background = ''; micBtn.style.color = ''; micBtn.textContent = '🎤'; } }; recognition.start(); }); } } // Prepfoodz: file attach if (WIDGET_CONFIG.tenant === 'prepfoodz') { const attachBtn = document.getElementById('itlive-ai-attach-btn'); const fileInput = document.getElementById('itlive-ai-file-input'); const attachmentsDiv = document.getElementById('itlive-ai-attachments'); if (attachBtn && fileInput && attachmentsDiv) { attachBtn.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', async function() { const file = this.files[0]; if (!file) return; const fd = new FormData(); fd.append('file', file); try { const r = await fetch(WIDGET_CONFIG.apiBase.replace('/api', '') + '/api/prepfoodz-feedback-upload.php', { method: 'POST', body: fd }); const d = await r.json(); if (d.success && d.urls && d.urls.length) { attachedUrls = attachedUrls.concat(d.urls); attachmentsDiv.style.display = 'block'; attachmentsDiv.textContent = (attachedUrls.length === 1 ? '1 foto toegevoegd' : attachedUrls.length + ' foto\'s toegevoegd'); } } catch (e) { console.warn('Upload mislukt', e); } this.value = ''; }); } } // Welcome message setTimeout(() => { addMessage('bot', WIDGET_CONFIG.strings.welcome); }, 1500); } function sendMessage() { const input = document.getElementById('itlive-ai-input'); let message = input.value.trim(); const attachmentsDiv = document.getElementById('itlive-ai-attachments'); if (attachedUrls && attachedUrls.length) { message += (message ? '\n\n' : '') + '[Bijgevoegde foto(s): ' + attachedUrls.join(', ') + ']'; attachedUrls = []; if (attachmentsDiv) { attachmentsDiv.style.display = 'none'; attachmentsDiv.textContent = ''; } } if (!message) return; addMessage('user', message); input.value = ''; // Show typing indicator const typingId = addMessage('bot', '...', true); // Send to API fetch(WIDGET_CONFIG.apiBase + '/universal-ai-chat.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: message, tenant: WIDGET_CONFIG.tenant, subagent: WIDGET_CONFIG.subagent || undefined, project: WIDGET_CONFIG.project || undefined, page: WIDGET_CONFIG.page || undefined, conversation_id: getConversationId() }) }) .then(r => r.json()) .then(data => { // Remove typing indicator const typing = document.getElementById(typingId); if (typing) typing.remove(); if (data.success) { addMessage('bot', data.response, false, data.metadata); } else { addMessage('bot', WIDGET_CONFIG.strings.error); } }) .catch(err => { const typing = document.getElementById(typingId); if (typing) typing.remove(); addMessage('bot', WIDGET_CONFIG.strings.connectionError); }); } function linkify(text) { if (typeof text !== 'string') return text; const escaped = text.replace(/&/g,'&').replace(//g,'>').replace(/\n/g, '