${escapeHtml(CONFIG.botName)}
Online
Jätä viesti asiakaspalveluun / Leave a message for support
`; messages.appendChild(card); scrollToBottom(); document.getElementById('pm-contact-submit').addEventListener('click', async function () { const name = document.getElementById('pm-contact-name').value.trim(); const email = document.getElementById('pm-contact-email').value.trim(); const question = document.getElementById('pm-contact-question').value.trim(); const errorEl = document.getElementById('pm-contact-error'); if (!name || !email || !question) { errorEl.textContent = 'Täytä kaikki kentät / Please fill in all fields'; return; } const btn = document.getElementById('pm-contact-submit'); btn.disabled = true; btn.textContent = '...'; errorEl.textContent = ''; try { const contactEndpoint = CONFIG.endpoint.replace('/chat', '/contact'); const res = await fetch(contactEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(CONFIG.token && { 'X-Widget-Token': CONFIG.token }), }, body: JSON.stringify({ name, email, question, hp: document.getElementById('pm-hp').value }), }); const data = await res.json(); if (data.success) { card.innerHTML = '✓ Viestisi on lähetetty! / Your message has been sent!
'; } else { errorEl.textContent = 'Jokin meni pieleen / Something went wrong. Please try again.'; btn.disabled = false; btn.textContent = 'Lähetä / Send'; } } catch (e) { errorEl.textContent = 'Jokin meni pieleen / Something went wrong. Please try again.'; btn.disabled = false; btn.textContent = 'Lähetä / Send'; } }); } // ── Quick replies ───────────────────────────────────────────────────────── function showQuickReplies() { const messages = document.getElementById('pm-messages'); const container = document.createElement('div'); container.id = 'pm-quick-replies'; QUICK_REPLIES.forEach(function (label) { const btn = document.createElement('button'); btn.className = 'pm-quick-btn'; btn.textContent = label; btn.addEventListener('click', function () { container.remove(); document.getElementById('pm-input').value = label; handleSend(); }); container.appendChild(btn); }); messages.appendChild(container); scrollToBottom(); } // ── Panel toggle ────────────────────────────────────────────────────────── function togglePanel() { isOpen = !isOpen; const toggle = document.getElementById('pm-toggle'); const panel = document.getElementById('pm-panel'); toggle.classList.toggle('pm-open', isOpen); panel.classList.toggle('pm-visible', isOpen); toggle.setAttribute('aria-label', isOpen ? 'Close chat' : 'Open chat'); if (isOpen) { setTimeout(() => document.getElementById('pm-input').focus(), 220); } } // ── Send message ────────────────────────────────────────────────────────── async function handleSend() { if (isLoading) return; const input = document.getElementById('pm-input'); const text = input.value.trim(); if (!text) return; input.value = ''; autoResize.call(input); // Remove quick replies once user sends any message const qr = document.getElementById('pm-quick-replies'); if (qr) qr.remove(); // Show user message appendMessage('user', text); // Add to history history.push({ role: 'user', content: text }); // Show typing indicator const typingId = showTyping(); isLoading = true; setSendDisabled(true); try { const response = await fetch(CONFIG.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(CONFIG.token && { 'X-Widget-Token': CONFIG.token }), }, body: JSON.stringify({ message: text, history: history.slice(0, -1), }), }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); const reply = data.reply || 'Sorry, I could not process your request.'; removeTyping(typingId); appendMessage('bot', reply); history.push({ role: 'assistant', content: reply }); if (data.escalate) showEscalationButton(text); } catch (err) { console.error('[Promarine chatbot] Error:', err); removeTyping(typingId); appendMessage('bot', 'Sorry, something went wrong. Please try again in a moment.'); } finally { isLoading = false; setSendDisabled(false); document.getElementById('pm-input').focus(); } } // ── DOM helpers ─────────────────────────────────────────────────────────── function appendMessage(role, text) { const messages = document.getElementById('pm-messages'); const wrapper = document.createElement('div'); wrapper.className = `pm-msg pm-${role}`; const bubble = document.createElement('div'); bubble.className = 'pm-bubble'; // Use innerHTML with sanitized content to preserve line breaks bubble.innerHTML = formatMessage(text); wrapper.appendChild(bubble); messages.appendChild(wrapper); scrollToBottom(); return wrapper; } function showTyping() { const messages = document.getElementById('pm-messages'); const wrapper = document.createElement('div'); const id = 'pm-typing-' + Date.now(); wrapper.id = id; wrapper.className = 'pm-msg pm-bot pm-typing'; wrapper.innerHTML = `