/** * Admin Email Broadcasting Module * Handles email composition, broadcasting to all users, and progress tracking */ // Email state let allUsersData = []; // Email All Users Functions async function showEmailUsersModal() { // Load current users data try { const response = await fetch('/api/users'); const data = await response.json(); if (data.success && data.users) { allUsersData = data.users; // Update recipients count const recipientsCount = document.getElementById('recipients-count'); if (recipientsCount) { recipientsCount.textContent = `${allUsersData.length}`; } } } catch (error) { console.error('Error loading users for email:', error); window.adminCore.showStatus('Failed to load user data', 'error'); return; } // Show modal const modal = document.getElementById('email-users-modal'); if (modal) { modal.style.display = 'flex'; // Clear previous content const subjectInput = document.getElementById('email-subject'); const contentEditor = document.getElementById('email-content'); const previewCheckbox = document.getElementById('show-preview'); const previewDiv = document.getElementById('email-preview'); if (subjectInput) subjectInput.value = ''; if (contentEditor) contentEditor.innerHTML = ''; if (previewCheckbox) previewCheckbox.checked = false; if (previewDiv) previewDiv.style.display = 'none'; } } function closeEmailUsersModal() { const modal = document.getElementById('email-users-modal'); if (modal) { modal.style.display = 'none'; } } function setupRichTextEditor() { const toolbar = document.querySelector('.rich-text-toolbar'); const editor = document.getElementById('email-content'); if (!toolbar || !editor) return; // Handle toolbar button clicks toolbar.addEventListener('click', (e) => { if (e.target.classList.contains('toolbar-btn')) { e.preventDefault(); const command = e.target.getAttribute('data-command'); if (command === 'createLink') { const url = prompt('Enter the URL:'); if (url) { document.execCommand(command, false, url); } } else { document.execCommand(command, false, null); } // Update preview if visible updateEmailPreview(); } }); // Update preview on content change editor.addEventListener('input', updateEmailPreview); // Handle preview toggle const showPreviewCheckbox = document.getElementById('show-preview'); if (showPreviewCheckbox) { showPreviewCheckbox.addEventListener('change', togglePreview); } // Update preview when subject changes const subjectInput = document.getElementById('email-subject'); if (subjectInput) { subjectInput.addEventListener('input', updateEmailPreview); } } function togglePreview() { const preview = document.getElementById('email-preview'); const checkbox = document.getElementById('show-preview'); if (preview && checkbox) { if (checkbox.checked) { preview.style.display = 'block'; updateEmailPreview(); } else { preview.style.display = 'none'; } } } function updateEmailPreview() { const previewSubject = document.getElementById('preview-subject'); const previewBody = document.getElementById('preview-body'); const subjectInput = document.getElementById('email-subject'); const contentEditor = document.getElementById('email-content'); if (previewSubject && subjectInput) { previewSubject.textContent = subjectInput.value || 'Your subject will appear here'; } if (previewBody && contentEditor) { const content = contentEditor.innerHTML || 'Your message will appear here'; previewBody.innerHTML = content; } } async function sendEmailToAllUsers(e) { e.preventDefault(); const subjectInput = document.getElementById('email-subject'); const contentEditor = document.getElementById('email-content'); const subject = subjectInput?.value.trim(); const content = contentEditor?.innerHTML.trim(); if (!subject) { window.adminCore.showStatus('Please enter an email subject', 'error'); return; } if (!content || content === '
' || content === '') { window.adminCore.showStatus('Please enter email content', 'error'); return; } if (allUsersData.length === 0) { window.adminCore.showStatus('No users found to email', 'error'); return; } const confirmMessage = `Send this email to all ${allUsersData.length} users?`; if (!confirm(confirmMessage)) { return; } // Initialize progress tracking initializeEmailProgress(allUsersData.length); try { const response = await fetch('/api/users/email-all', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ subject: subject, content: content }) }); const data = await response.json(); if (data.success) { // Display detailed results updateEmailProgress(data.results); window.adminCore.showStatus(data.message, 'success'); console.log('Email results:', data.results); } else { showEmailError(data.error || 'Failed to send emails'); if (data.details) { console.error('Failed email details:', data.details); } } } catch (error) { console.error('Error sending emails to all users:', error); showEmailError('Failed to send emails - Network error'); } } // Initialize email progress display function initializeEmailProgress(totalCount) { const progressContainer = document.getElementById('email-progress-container'); const statusList = document.getElementById('email-status-list'); const pendingCountEl = document.getElementById('pending-count'); const successCountEl = document.getElementById('success-count'); const errorCountEl = document.getElementById('error-count'); const progressBar = document.getElementById('email-progress-bar'); const progressText = document.getElementById('progress-text'); const closeBtn = document.getElementById('close-progress-btn'); if (!progressContainer) return; // Show progress container progressContainer.classList.add('show'); // Reset counters if (pendingCountEl) pendingCountEl.textContent = totalCount; if (successCountEl) successCountEl.textContent = '0'; if (errorCountEl) errorCountEl.textContent = '0'; // Reset progress bar if (progressBar) { progressBar.style.width = '0%'; progressBar.classList.remove('complete', 'error'); } if (progressText) progressText.textContent = '0%'; // Clear status list if (statusList) statusList.innerHTML = ''; // Hide close button initially if (closeBtn) closeBtn.style.display = 'none'; // Add status items for each user allUsersData.forEach(user => { if (statusList) { const statusItem = document.createElement('div'); statusItem.className = 'email-status-item'; statusItem.innerHTML = `
${user.Name || user.Email}
Sending...
`; statusList.appendChild(statusItem); } }); } // Update progress with results function updateEmailProgress(results) { const statusList = document.getElementById('email-status-list'); const pendingCountEl = document.getElementById('pending-count'); const successCountEl = document.getElementById('success-count'); const errorCountEl = document.getElementById('error-count'); const progressBar = document.getElementById('email-progress-bar'); const progressText = document.getElementById('progress-text'); const closeBtn = document.getElementById('close-progress-btn'); const successful = results.successful || []; const failed = results.failed || []; const total = results.total || (successful.length + failed.length); // Update counters if (successCountEl) successCountEl.textContent = successful.length; if (errorCountEl) errorCountEl.textContent = failed.length; if (pendingCountEl) pendingCountEl.textContent = '0'; // Update progress bar const percentage = ((successful.length + failed.length) / total * 100).toFixed(1); if (progressBar && progressText) { progressBar.style.width = percentage + '%'; progressText.textContent = percentage + '%'; if (failed.length > 0) { progressBar.classList.add('error'); } else { progressBar.classList.add('complete'); } } // Update individual status items if (statusList) { const statusItems = statusList.children; // Update successful emails successful.forEach(result => { const statusItem = Array.from(statusItems).find(item => item.querySelector('.email-status-recipient').textContent.includes(result.email) || item.querySelector('.email-status-recipient').textContent.includes(result.name) ); if (statusItem) { statusItem.querySelector('.email-status-result').innerHTML = ` ✓ Sent `; } }); // Update failed emails failed.forEach(result => { const statusItem = Array.from(statusItems).find(item => item.querySelector('.email-status-recipient').textContent.includes(result.email) || item.querySelector('.email-status-recipient').textContent.includes(result.name) ); if (statusItem) { statusItem.querySelector('.email-status-result').innerHTML = ` ✗ Failed `; } }); } // Show close button if (closeBtn) { closeBtn.style.display = 'block'; closeBtn.onclick = () => { const progressContainer = document.getElementById('email-progress-container'); if (progressContainer) { progressContainer.classList.remove('show'); } closeEmailUsersModal(); }; } } // Show email error function showEmailError(message) { const progressContainer = document.getElementById('email-progress-container'); const progressBar = document.getElementById('email-progress-bar'); const progressText = document.getElementById('progress-text'); const closeBtn = document.getElementById('close-progress-btn'); // Show progress container if not visible if (progressContainer) { progressContainer.classList.add('show'); } // Update progress bar to show error if (progressBar && progressText) { progressBar.style.width = '100%'; progressBar.classList.add('error'); progressText.textContent = 'Error'; } // Show close button if (closeBtn) { closeBtn.style.display = 'block'; closeBtn.onclick = () => { if (progressContainer) { progressContainer.classList.remove('show'); } }; } window.adminCore.showStatus(message, 'error'); } // Setup email modal event listeners function setupEmailModalEventListeners() { // Email all users functionality const closeEmailModalBtn = document.getElementById('close-email-modal'); const cancelEmailBtn = document.getElementById('cancel-email-btn'); const emailUsersForm = document.getElementById('email-users-form'); const emailModal = document.getElementById('email-users-modal'); if (closeEmailModalBtn) { closeEmailModalBtn.addEventListener('click', closeEmailUsersModal); } if (cancelEmailBtn) { cancelEmailBtn.addEventListener('click', closeEmailUsersModal); } if (emailUsersForm) { emailUsersForm.addEventListener('submit', sendEmailToAllUsers); } // Close modal when clicking outside if (emailModal) { emailModal.addEventListener('click', function(e) { if (e.target === emailModal) { closeEmailUsersModal(); } }); } // Setup rich text editor functionality setupRichTextEditor(); } // Export email broadcasting functions window.adminEmail = { showEmailUsersModal, closeEmailUsersModal, setupRichTextEditor, togglePreview, updateEmailPreview, sendEmailToAllUsers, setupEmailModalEventListeners, getAllUsersData: () => allUsersData, setAllUsersData: (data) => { allUsersData = data; } };