128 lines
4.6 KiB
JavaScript
128 lines
4.6 KiB
JavaScript
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 = `
|
|
<div>${msg.body}</div>
|
|
<div class="meta">${msg.direction} · ${msg.status} · ${msg.created_at}</div>
|
|
`;
|
|
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);
|
|
});
|
|
}
|
|
});
|