document.addEventListener('DOMContentLoaded', () => { const convoForm = document.getElementById('new-conversation-form'); const messageForm = document.getElementById('message-form'); const messagesWrap = document.getElementById('chat-messages'); const realtimeBadge = document.getElementById('realtime-status'); const toastEl = document.getElementById('app-toast'); const convoId = messagesWrap ? Number(messagesWrap.dataset.conversationId) : 0; const toast = toastEl ? new bootstrap.Toast(toastEl) : null; const showToast = (text) => { if (!toastEl || !toast) return; toastEl.querySelector('.toast-body').textContent = text; toast.show(); }; const renderMessages = (messages) => { if (!messagesWrap) return; messagesWrap.innerHTML = ''; messages.forEach((msg) => { const bubble = document.createElement('div'); bubble.className = `message-bubble ${msg.direction === 'outbound' ? 'outbound' : ''}`; bubble.innerHTML = `
${msg.body}
${msg.direction} · ${msg.status} · ${msg.created_at}
`; messagesWrap.appendChild(bubble); }); messagesWrap.scrollTop = messagesWrap.scrollHeight; }; const fetchMessages = async () => { if (!convoId) return; const res = await fetch(`api/messages.php?conversation_id=${convoId}`); if (!res.ok) return; const data = await res.json(); renderMessages(data.messages || []); }; if (convoForm) { convoForm.addEventListener('submit', async (event) => { event.preventDefault(); const formData = new FormData(convoForm); const payload = { contact_name: formData.get('contact_name'), phone: formData.get('phone'), channel: formData.get('channel') }; const res = await fetch('api/conversations.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await res.json(); if (data.success) { window.location = `index.php?conversation_id=${data.conversation_id}`; } else { showToast(data.error || 'Unable to create conversation.'); } }); } if (messageForm) { messageForm.addEventListener('submit', async (event) => { event.preventDefault(); const formData = new FormData(messageForm); const body = String(formData.get('body') || '').trim(); if (!body) return; const res = await fetch('api/messages.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ conversation_id: convoId, body }) }); const data = await res.json(); if (data.success) { messageForm.reset(); fetchMessages(); showToast('Message queued for delivery.'); } else { showToast(data.error || 'Message failed.'); } }); } const connectWebSocket = () => { if (!realtimeBadge || !window.WebSocket) return; const wsUrl = `ws://${window.location.hostname}:8081`; let ws; try { ws = new WebSocket(wsUrl); } catch (e) { realtimeBadge.textContent = 'Polling'; return; } ws.addEventListener('open', () => { realtimeBadge.textContent = 'WebSocket'; }); ws.addEventListener('message', (event) => { if (event.data === 'refresh') { fetchMessages(); } }); ws.addEventListener('close', () => { realtimeBadge.textContent = 'Polling'; }); ws.addEventListener('error', () => { realtimeBadge.textContent = 'Polling'; }); }; if (messagesWrap) { fetchMessages(); setInterval(fetchMessages, 5000); connectWebSocket(); } const processBtn = document.getElementById('process-queue'); if (processBtn) { processBtn.addEventListener('click', async () => { processBtn.disabled = true; const res = await fetch('api/queue_process.php', { method: 'POST' }); const data = await res.json(); showToast(`Processed ${data.processed || 0} queued messages.`); setTimeout(() => window.location.reload(), 800); }); } });