document.addEventListener('DOMContentLoaded', () => { const cards = document.querySelectorAll('.kanban-card'); const columns = document.querySelectorAll('.kanban-cards'); const leadModal = new bootstrap.Modal(document.getElementById('leadModal')); const chatTab = document.getElementById('chat-tab'); const chatMessages = document.querySelector('.chat-messages'); const chatInput = document.querySelector('.chat-input input'); const chatSendButton = document.querySelector('.chat-input button'); let currentLeadId = null; cards.forEach(card => { card.addEventListener('dragstart', () => { card.classList.add('dragging'); }); card.addEventListener('dragend', () => { card.classList.remove('dragging'); }); card.addEventListener('click', () => { const name = card.dataset.name; const company = card.dataset.company; const value = card.dataset.value; const status = card.dataset.status; currentLeadId = card.dataset.id; document.getElementById('leadName').textContent = name; document.getElementById('leadCompany').textContent = company; document.getElementById('leadValue').textContent = '$' + value; document.getElementById('leadStatus').textContent = status; document.getElementById('leadModalLabel').textContent = name; leadModal.show(); }); }); columns.forEach(column => { column.addEventListener('dragover', e => { e.preventDefault(); const afterElement = getDragAfterElement(column, e.clientY); const draggable = document.querySelector('.dragging'); if (afterElement == null) { column.appendChild(draggable); } else { column.insertBefore(draggable, afterElement); } column.parentElement.classList.add('drag-over'); }); column.addEventListener('dragleave', () => { column.parentElement.classList.remove('drag-over'); }); column.addEventListener('drop', (e) => { e.preventDefault(); const draggable = document.querySelector('.dragging'); const newStatus = column.dataset.status; const leadId = draggable.dataset.id; // Optimistically update the UI column.appendChild(draggable); draggable.dataset.status = newStatus; column.parentElement.classList.remove('drag-over'); // Update the status in the database fetch('api/update_lead_status.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: leadId, status: newStatus }) }) .then(response => response.json()) .then(data => { if (!data.success) { console.error('Failed to update lead status'); } }) .catch(error => { console.error('Error updating lead status:', error); }); }); }); chatTab.addEventListener('shown.bs.tab', () => { if (currentLeadId) { fetch(`api/get_messages.php?lead_id=${currentLeadId}`) .then(response => response.json()) .then(messages => { renderMessages(messages); }); } }); chatSendButton.addEventListener('click', () => { const message = chatInput.value.trim(); if (message && currentLeadId) { sendMessage(currentLeadId, message); chatInput.value = ''; } }); chatInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { chatSendButton.click(); } }); function sendMessage(leadId, message) { fetch('api/send_message.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ lead_id: leadId, message: message }) }) .then(response => response.json()) .then(data => { if (data.success) { renderMessages(data.messages, true); } }); } function renderMessages(messages, append = false) { if (!append) { chatMessages.innerHTML = ''; } messages.forEach(message => { const messageEl = document.createElement('div'); messageEl.classList.add('message', message.sender === 'user' ? 'sent' : 'received'); const textEl = document.createElement('p'); textEl.textContent = message.message; const timeEl = document.createElement('span'); timeEl.classList.add('timestamp'); const messageTime = new Date(message.created_at); timeEl.textContent = messageTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); messageEl.appendChild(textEl); messageEl.appendChild(timeEl); chatMessages.appendChild(messageEl); }); chatMessages.scrollTop = chatMessages.scrollHeight; } function getDragAfterElement(container, y) { const draggableElements = [...container.querySelectorAll('.kanban-card:not(.dragging)')]; return draggableElements.reduce((closest, child) => { const box = child.getBoundingClientRect(); const offset = y - box.top - box.height / 2; if (offset < 0 && offset > closest.offset) { return { offset: offset, element: child }; } else { return closest; } }, { offset: Number.NEGATIVE_INFINITY }).element; } });