freealberta/map/app/public/js/admin-email.js

395 lines
13 KiB
JavaScript

/**
* 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 === '<br>' || 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 = `
<div class="email-status-recipient">${user.Name || user.Email}</div>
<div class="email-status-result pending">
<div class="progress-spinner"></div>
<span>Sending...</span>
</div>
`;
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 = `
<span class="email-status-result success">✓ Sent</span>
`;
}
});
// 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 = `
<span class="email-status-result error" title="${result.error || 'Unknown error'}">✗ Failed</span>
`;
}
});
}
// 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; }
};