EventBuzz_Backend/public/embed/concierge-widget.js

144 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(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);
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 : '…');
// Log detected intent to browser console when backend returns it
if (res.json.data && res.json.data.intent) {
// eslint-disable-next-line no-console
console.info('[EventBuzz Concierge] detected intent:', res.json.data.intent);
}
}).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();
});
})();