(function () { var cfg = window.EB_CONCIERGE || {}; var botId = cfg.botId; var apiBase = (cfg.apiBase || '').replace(/\/$/, ''); if (!botId || !apiBase) { // eslint-disable-next-line no-console console.error('[EventBuzz Concierge] Missing window.EB_CONCIERGE.botId or apiBase'); return; } var storageKey = 'ebc_session_' + botId; var sessionId = null; try { sessionId = localStorage.getItem(storageKey); } catch {} function el(tag, attrs, children) { var n = document.createElement(tag); if (attrs) for (var k in attrs) n.setAttribute(k, attrs[k]); if (children) children.forEach(function (c) { n.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); }); return n; } function addCssOnce() { if (document.getElementById('ebc-css')) return; var link = el('link', { id: 'ebc-css', rel: 'stylesheet', href: apiBase.replace(/\/api$/, '') + '/embed/concierge-widget.css' }); document.head.appendChild(link); } addCssOnce(); var launcher = el('button', { class: 'ebc-launcher', type: 'button', 'aria-label': 'Chat with event concierge' }, ['Chat']); var panel = el('div', { class: 'ebc-panel', role: 'dialog', 'aria-label': 'Event concierge chat' }); var header = el('div', { class: 'ebc-header' }); var title = el('div', { class: 'ebc-title' }, ['Event Concierge']); var closeBtn = el('button', { class: 'ebc-close', type: 'button', 'aria-label': 'Close' }, ['×']); header.appendChild(title); header.appendChild(closeBtn); var messages = el('div', { class: 'ebc-messages' }); var error = el('div', { class: 'ebc-error' }, ['']); var inputBar = el('div', { class: 'ebc-inputbar' }); var input = el('input', { class: 'ebc-input', placeholder: 'Ask a question…', maxlength: '800' }); var sendBtn = el('button', { class: 'ebc-send', type: 'button' }, ['Send']); inputBar.appendChild(input); inputBar.appendChild(sendBtn); panel.appendChild(header); panel.appendChild(messages); panel.appendChild(error); panel.appendChild(inputBar); document.body.appendChild(launcher); document.body.appendChild(panel); function setError(msg) { if (!msg) { error.style.display = 'none'; error.textContent = ''; return; } error.style.display = 'block'; error.textContent = msg; } function addMessage(role, text) { var bubble = el('div', { class: 'ebc-msg' + (role === 'user' ? ' ebc-user' : '') }); bubble.textContent = text; messages.appendChild(bubble); messages.scrollTop = messages.scrollHeight; } function openPanel() { panel.classList.add('ebc-open'); input.focus(); } function closePanel() { panel.classList.remove('ebc-open'); } launcher.addEventListener('click', function () { if (panel.classList.contains('ebc-open')) closePanel(); else openPanel(); }); closeBtn.addEventListener('click', closePanel); function http(path, body) { return fetch(apiBase + path, { method: body ? 'POST' : 'GET', headers: { 'Content-Type': 'application/json' }, body: body ? JSON.stringify(body) : undefined, credentials: 'omit' }).then(function (r) { return r.json().then(function (j) { return { status: r.status, json: j }; }); }); } // Load config http('/public/concierge/' + encodeURIComponent(botId) + '/config').then(function (res) { if (res.json && res.json.success && res.json.data) { title.textContent = res.json.data.eventName ? ('Concierge · ' + res.json.data.eventName) : 'Event Concierge'; var greet = res.json.data.greeting; if (greet) addMessage('assistant', greet.replace(/\{eventName\}/g, res.json.data.eventName || 'the event')); if (res.json.data.maxMessageLength) input.setAttribute('maxlength', String(res.json.data.maxMessageLength)); } }); function send() { var text = String(input.value || '').trim(); if (!text) return; setError(null); input.value = ''; addMessage('user', text); sendBtn.disabled = true; http('/public/concierge/' + encodeURIComponent(botId) + '/chat', { sessionId: sessionId || undefined, message: text }).then(function (res) { sendBtn.disabled = false; if (!res.json || !res.json.success) { setError((res.json && res.json.error && res.json.error.message) ? res.json.error.message : 'Request failed'); return; } if (res.json.data && res.json.data.sessionId) { sessionId = res.json.data.sessionId; try { localStorage.setItem(storageKey, sessionId); } catch {} } addMessage('assistant', (res.json.data && res.json.data.reply) ? res.json.data.reply : '…'); }).catch(function (e) { sendBtn.disabled = false; setError(e && e.message ? e.message : 'Network error'); }); } sendBtn.addEventListener('click', send); input.addEventListener('keydown', function (e) { if (e.key === 'Enter') send(); }); })();