// User Dashboard JavaScript class UserDashboard { constructor() { this.user = null; this.campaigns = []; this.analytics = {}; this.authManager = null; this.currentCampaign = null; // Track campaign being edited } async init() { // Check authentication first if (typeof authManager !== 'undefined') { this.authManager = authManager; const isAuth = await this.authManager.checkSession(); if (!isAuth) { window.location.href = '/login.html'; return; } this.user = this.authManager.user; this.setupUserInterface(); } else { // Fallback if authManager not loaded window.location.href = '/login.html'; return; } this.setupEventListeners(); this.loadUserCampaigns(); this.loadAnalytics(); } setupUserInterface() { if (!this.user) return; // Update user info display const userNameEl = document.getElementById('user-name'); const userEmailEl = document.getElementById('user-email'); const userRoleBadge = document.getElementById('user-role-badge'); if (userNameEl) userNameEl.textContent = this.user.name || this.user.email; if (userEmailEl) userEmailEl.textContent = this.user.email; if (userRoleBadge) { const userType = this.user.userType || 'user'; userRoleBadge.className = `user-badge ${userType}`; userRoleBadge.textContent = userType === 'admin' ? 'Administrator' : userType === 'temp' ? 'Temporary User' : 'User'; } // Update account form this.populateAccountForm(); // Show admin link if user is admin const createBtn = document.getElementById('create-campaign-btn'); if (createBtn && this.user.isAdmin) { createBtn.textContent = 'Admin Panel'; } else if (createBtn) { createBtn.style.display = 'none'; } } populateAccountForm() { if (!this.user) return; const nameInput = document.getElementById('account-name'); const emailInput = document.getElementById('account-email'); const phoneInput = document.getElementById('account-phone'); const roleInput = document.getElementById('account-role'); const expiresInput = document.getElementById('account-expires'); const expirationGroup = document.getElementById('account-expiration'); if (nameInput) nameInput.value = this.user.name || ''; if (emailInput) emailInput.value = this.user.email || ''; if (phoneInput) phoneInput.value = this.user.phone || ''; if (roleInput) { const roleText = this.user.isAdmin ? 'Administrator' : this.user.userType === 'temp' ? 'Temporary User' : 'Standard User'; roleInput.value = roleText; } // Show expiration info for temp users if (this.user.userType === 'temp' && expiresInput && expirationGroup) { if (this.user.expiresAt) { expiresInput.value = new Date(this.user.expiresAt).toLocaleDateString(); expirationGroup.style.display = 'block'; } } } setupEventListeners() { // Tab navigation document.querySelectorAll('.nav-btn').forEach(btn => { btn.addEventListener('click', (e) => { const tab = e.target.dataset.tab; this.switchTab(tab); }); }); // Logout button const logoutBtn = document.getElementById('logout-btn'); if (logoutBtn) { logoutBtn.addEventListener('click', () => { this.authManager.logout(); }); } // Form submissions const createForm = document.getElementById('create-campaign-form'); if (createForm) { createForm.addEventListener('submit', (e) => { this.handleCreateCampaign(e); }); } const editForm = document.getElementById('edit-campaign-form'); if (editForm) { editForm.addEventListener('submit', (e) => { this.handleUpdateCampaign(e); }); } // Campaign actions using event delegation document.addEventListener('click', (e) => { if (e.target.matches('[data-action="view-campaign"]')) { this.viewCampaign(e.target.dataset.campaignSlug); } if (e.target.matches('[data-action="edit-campaign"]')) { this.editCampaign(e.target.dataset.campaignId); } if (e.target.matches('[data-action="view-analytics"]')) { this.viewCampaignAnalytics(e.target.dataset.campaignId); } if (e.target.matches('[data-action="cancel-create"]')) { this.switchTab('campaigns'); } if (e.target.matches('[data-action="cancel-edit"]')) { this.switchTab('campaigns'); } if (e.target.matches('[data-action="go-to-create"]')) { this.switchTab('create'); } }); // Setup campaign selector dropdowns this.setupCampaignSelectors(); } setupCampaignSelectors() { // Setup Create Campaign Selector const createSelector = document.getElementById('create-campaign-selector'); const createDropdown = document.getElementById('create-dropdown-menu'); if (createSelector && createDropdown) { this.setupDropdown(createSelector, createDropdown, 'create'); } // Setup Edit Campaign Selector const editSelector = document.getElementById('edit-campaign-selector'); const editDropdown = document.getElementById('edit-dropdown-menu'); if (editSelector && editDropdown) { this.setupDropdown(editSelector, editDropdown, 'edit'); } } setupDropdown(input, dropdown, type) { // Show dropdown on focus input.addEventListener('focus', () => { this.populateDropdown(dropdown, type); dropdown.classList.add('show'); }); // Hide dropdown when clicking outside document.addEventListener('click', (e) => { if (!input.contains(e.target) && !dropdown.contains(e.target)) { dropdown.classList.remove('show'); } }); // Filter campaigns on input input.addEventListener('input', () => { this.filterDropdown(input, dropdown, type); }); // Handle dropdown item selection dropdown.addEventListener('click', (e) => { if (e.target.classList.contains('dropdown-item')) { const campaignId = e.target.dataset.campaignId; const campaignTitle = e.target.textContent; input.value = campaignTitle; dropdown.classList.remove('show'); if (type === 'create' && campaignId !== 'new') { this.populateCreateFormFromCampaign(campaignId); } else if (type === 'edit' && campaignId) { this.loadCampaignForEdit(campaignId); } else if (type === 'create' && campaignId === 'new') { this.clearCreateForm(); } } }); } populateDropdown(dropdown, type) { dropdown.innerHTML = ''; if (type === 'create') { dropdown.innerHTML = ''; } else { dropdown.innerHTML = ''; } if (this.campaigns && this.campaigns.length > 0) { // Filter campaigns based on what user can do const availableCampaigns = type === 'edit' ? this.campaigns.filter(campaign => this.canEditCampaign(campaign)) : this.campaigns; availableCampaigns.forEach(campaign => { const item = document.createElement('div'); item.className = 'dropdown-item'; item.dataset.campaignId = campaign.id; item.textContent = `${campaign.title} (${campaign.status})`; dropdown.appendChild(item); }); if (type === 'edit' && availableCampaigns.length === 0) { const noResults = document.createElement('div'); noResults.className = 'dropdown-item no-results'; noResults.textContent = 'No editable campaigns found'; dropdown.appendChild(noResults); } } else { const noResults = document.createElement('div'); noResults.className = 'dropdown-item no-results'; noResults.textContent = 'No campaigns found'; dropdown.appendChild(noResults); } } filterDropdown(input, dropdown, type) { const searchTerm = input.value.toLowerCase(); // Re-populate the dropdown to ensure we have the right campaigns this.populateDropdown(dropdown, type); const items = dropdown.querySelectorAll('.dropdown-item:not(.no-results)'); let hasVisibleItems = false; items.forEach(item => { if (item.dataset.campaignId === 'new' || item.dataset.campaignId === '') { // Always show default items item.style.display = 'block'; hasVisibleItems = true; } else { const text = item.textContent.toLowerCase(); if (text.includes(searchTerm)) { item.style.display = 'block'; hasVisibleItems = true; } else { item.style.display = 'none'; } } }); // Show/hide no results message let noResultsItem = dropdown.querySelector('.no-results'); if (!hasVisibleItems && searchTerm) { if (!noResultsItem) { noResultsItem = document.createElement('div'); noResultsItem.className = 'dropdown-item no-results'; dropdown.appendChild(noResultsItem); } noResultsItem.textContent = 'No campaigns found'; noResultsItem.style.display = 'block'; } else if (noResultsItem && searchTerm) { noResultsItem.style.display = 'none'; } dropdown.classList.add('show'); } populateCreateFormFromCampaign(campaignId) { const campaign = this.campaigns.find(c => c.id === campaignId); if (!campaign) return; // Populate form fields with campaign data as template document.getElementById('create-title').value = `Copy of ${campaign.title}`; document.getElementById('create-description').value = campaign.description || ''; document.getElementById('create-email-subject').value = campaign.email_subject || ''; document.getElementById('create-email-body').value = campaign.email_body || ''; document.getElementById('create-call-to-action').value = campaign.call_to_action || ''; // Set checkboxes document.getElementById('create-allow-smtp').checked = campaign.allow_smtp_email !== false; document.getElementById('create-allow-mailto').checked = campaign.allow_mailto_link !== false; document.getElementById('create-collect-info').checked = campaign.collect_user_info !== false; document.getElementById('create-show-count').checked = campaign.show_email_count !== false; document.getElementById('create-allow-editing').checked = campaign.allow_email_editing === true; // Set government levels const targetLevels = campaign.target_government_levels || []; document.querySelectorAll('input[name="target_government_levels"]').forEach(checkbox => { checkbox.checked = targetLevels.includes(checkbox.value); }); } clearCreateForm() { // Clear all form fields document.getElementById('create-title').value = ''; document.getElementById('create-description').value = ''; document.getElementById('create-email-subject').value = ''; document.getElementById('create-email-body').value = ''; document.getElementById('create-call-to-action').value = ''; // Reset checkboxes to defaults document.getElementById('create-allow-smtp').checked = true; document.getElementById('create-allow-mailto').checked = true; document.getElementById('create-collect-info').checked = true; document.getElementById('create-show-count').checked = true; document.getElementById('create-allow-editing').checked = false; // Reset government levels to defaults document.querySelectorAll('input[name="target_government_levels"]').forEach(checkbox => { checkbox.checked = ['Federal', 'Provincial', 'Municipal'].includes(checkbox.value); }); } async loadCampaignForEdit(campaignId) { // Find campaign in already loaded campaigns array const campaign = this.campaigns.find(c => String(c.id) === String(campaignId)); if (!campaign) { this.showMessage('Campaign not found', 'error'); return; } if (!this.canEditCampaign(campaign)) { this.showMessage('You do not have permission to edit this campaign', 'error'); return; } this.currentCampaign = campaign; this.populateEditForm(); this.switchTab('edit'); } switchTab(tabName) { // Hide all tabs document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); // Remove active class from nav buttons document.querySelectorAll('.nav-btn').forEach(btn => { btn.classList.remove('active'); }); // Show selected tab const targetTab = document.getElementById(`${tabName}-tab`); if (targetTab) { targetTab.classList.add('active'); } // Update nav button const targetNavBtn = document.querySelector(`[data-tab="${tabName}"]`); if (targetNavBtn) { targetNavBtn.classList.add('active'); } // Load data for specific tabs if (tabName === 'campaigns') { this.loadUserCampaigns(); } else if (tabName === 'analytics') { this.loadAnalytics(); } } async loadUserCampaigns() { const loadingDiv = document.getElementById('campaigns-loading'); const listDiv = document.getElementById('campaigns-list'); if (loadingDiv) loadingDiv.classList.remove('hidden'); if (listDiv) listDiv.innerHTML = ''; try { const endpoint = this.user.isAdmin ? '/admin/campaigns' : '/campaigns'; const response = await window.apiClient.get(endpoint); if (response.success) { const campaigns = Array.isArray(response.campaigns) ? response.campaigns : []; this.campaigns = campaigns .map(campaign => this.normalizeCampaignFromApi(campaign)) .filter(Boolean); this.renderCampaignList(); } else { throw new Error(response.error || 'Failed to load campaigns'); } } catch (error) { console.error('Load campaigns error:', error); this.showMessage('Failed to load campaigns: ' + error.message, 'error'); } finally { if (loadingDiv) loadingDiv.classList.add('hidden'); } } normalizeCampaignFromApi(campaign) { if (!campaign) return null; const normalized = { ...campaign, id: campaign.id ?? campaign.ID ?? campaign.Id ?? null, created_by_user_id: campaign.created_by_user_id ?? campaign['Created By User ID'] ?? null, created_by_user_email: campaign.created_by_user_email ?? campaign['Created By User Email'] ?? null, created_by_user_name: campaign.created_by_user_name ?? campaign['Created By User Name'] ?? null }; // Ensure IDs are comparable as strings if (normalized.created_by_user_id !== undefined && normalized.created_by_user_id !== null) { normalized.created_by_user_id = String(normalized.created_by_user_id); } if (typeof normalized.status === 'string') { normalized.status = normalized.status.toLowerCase(); } ['allow_smtp_email', 'allow_mailto_link', 'collect_user_info', 'show_email_count', 'allow_email_editing'].forEach(key => { if (normalized[key] !== undefined) { normalized[key] = normalized[key] === true || normalized[key] === 'true' || normalized[key] === 1 || normalized[key] === '1'; } }); // Normalize target government levels to an array if (Array.isArray(normalized.target_government_levels)) { normalized.target_government_levels = normalized.target_government_levels; } else if (typeof normalized.target_government_levels === 'string' && normalized.target_government_levels.length > 0) { normalized.target_government_levels = normalized.target_government_levels.split(',').map(level => level.trim()).filter(Boolean); } else { normalized.target_government_levels = []; } return normalized; } isCampaignOwner(campaign) { if (!campaign || !this.user) return false; const userId = this.user.id != null ? String(this.user.id) : (this.user.userId != null ? String(this.user.userId) : null); const userEmail = this.user.email ? String(this.user.email).toLowerCase() : null; const campaignOwnerId = campaign.created_by_user_id != null ? String(campaign.created_by_user_id) : null; const campaignOwnerEmail = campaign.created_by_user_email ? String(campaign.created_by_user_email).toLowerCase() : null; return ( (userId && campaignOwnerId && userId === campaignOwnerId) || (userEmail && campaignOwnerEmail && userEmail === campaignOwnerEmail) ); } canEditCampaign(campaign) { if (this.user?.isAdmin) { return true; } return this.isCampaignOwner(campaign); } renderCampaignList() { const listDiv = document.getElementById('campaigns-list'); if (!listDiv) return; if (this.campaigns.length === 0) { listDiv.innerHTML = `

No campaigns yet

You haven't created any campaigns yet.

`; return; } listDiv.innerHTML = this.campaigns.map(campaign => `

${this.escapeHtml(campaign.title)}

${campaign.status}

Slug: /campaign/${campaign.slug}

Emails Sent: ${campaign.emailCount || 0}

Created: ${this.formatDate(campaign.created_at)}

${campaign.description ? `

Description: ${this.escapeHtml(campaign.description)}

` : ''}
${this.canEditCampaign(campaign) ? ` ` : ''}
`).join(''); } async loadAnalytics() { const loadingDiv = document.getElementById('analytics-loading'); if (loadingDiv) loadingDiv.classList.remove('hidden'); try { // Calculate analytics from campaigns data const totalCampaigns = this.campaigns.length; const activeCampaigns = this.campaigns.filter(c => c.status === 'active').length; const totalEmails = this.campaigns.reduce((sum, c) => sum + (c.emailCount || 0), 0); // Update analytics display const totalCampaignsEl = document.getElementById('total-campaigns'); const activeCampaignsEl = document.getElementById('active-campaigns'); const totalEmailsEl = document.getElementById('total-emails'); const totalUsersReachedEl = document.getElementById('total-users-reached'); if (totalCampaignsEl) totalCampaignsEl.textContent = totalCampaigns; if (activeCampaignsEl) activeCampaignsEl.textContent = activeCampaigns; if (totalEmailsEl) totalEmailsEl.textContent = totalEmails; if (totalUsersReachedEl) totalUsersReachedEl.textContent = Math.floor(totalEmails * 0.8); // Estimate } catch (error) { console.error('Analytics error:', error); this.showMessage('Failed to load analytics: ' + error.message, 'error'); } finally { if (loadingDiv) loadingDiv.classList.add('hidden'); } } viewCampaign(slug) { window.open(`/campaign/${slug}`, '_blank'); } editCampaign(campaignId) { const campaign = this.campaigns.find(c => String(c.id) === String(campaignId)); if (!campaign) { this.showMessage('Campaign not found', 'error'); return; } if (!this.canEditCampaign(campaign)) { this.showMessage('You do not have permission to edit this campaign', 'error'); return; } this.currentCampaign = campaign; this.switchTab('edit'); this.populateEditForm(); } async viewCampaignAnalytics(campaignId) { try { const endpoint = this.user.isAdmin ? `/admin/campaigns/${campaignId}/analytics` : `/campaigns/${campaignId}/analytics`; const response = await window.apiClient.get(endpoint); if (response.success) { this.showAnalyticsModal(response.analytics); } else { throw new Error(response.error || 'Failed to load campaign analytics'); } } catch (error) { console.error('Campaign analytics error:', error); this.showMessage('Failed to load campaign analytics: ' + error.message, 'error'); } } showAnalyticsModal(analytics) { // Create a simple analytics modal const modal = document.createElement('div'); modal.className = 'modal-overlay'; modal.innerHTML = ` `; document.body.appendChild(modal); // Close modal handlers modal.querySelector('.modal-close').addEventListener('click', () => { document.body.removeChild(modal); }); modal.addEventListener('click', (e) => { if (e.target === modal) { document.body.removeChild(modal); } }); } openEditModal(campaign) { const modal = document.createElement('div'); modal.className = 'modal-overlay'; const isAdmin = !!this.user?.isAdmin; modal.innerHTML = ` `; document.body.appendChild(modal); const form = modal.querySelector('#edit-campaign-form'); this.populateEditForm(form, campaign); form.addEventListener('submit', (event) => this.handleEditCampaignSubmit(event, campaign.id, modal)); const closeModal = () => this.closeModal(modal); modal.querySelector('.modal-close').addEventListener('click', closeModal); modal.addEventListener('click', (event) => { if (event.target === modal) { closeModal(); } }); const cancelBtn = modal.querySelector('[data-action="cancel-modal"]'); if (cancelBtn) { cancelBtn.addEventListener('click', closeModal); } } populateEditForm(form, campaign) { if (!form || !campaign) return; // Populate basic fields form.querySelector('[name="title"]').value = campaign.title || ''; form.querySelector('[name="description"]').value = campaign.description || ''; form.querySelector('[name="email_subject"]').value = campaign.email_subject || ''; form.querySelector('[name="email_body"]').value = campaign.email_body || ''; form.querySelector('[name="call_to_action"]').value = campaign.call_to_action || ''; // Status select const statusSelect = form.querySelector('[name="status"]'); if (statusSelect) { statusSelect.value = campaign.status || 'draft'; } // Campaign settings checkboxes form.querySelector('[name="allow_smtp_email"]').checked = !!campaign.allow_smtp_email; form.querySelector('[name="allow_mailto_link"]').checked = !!campaign.allow_mailto_link; form.querySelector('[name="collect_user_info"]').checked = !!campaign.collect_user_info; form.querySelector('[name="show_email_count"]').checked = !!campaign.show_email_count; form.querySelector('[name="allow_email_editing"]').checked = !!campaign.allow_email_editing; // Target government levels const targetLevels = Array.isArray(campaign.target_government_levels) ? campaign.target_government_levels : (campaign.target_government_levels ? campaign.target_government_levels.split(',').map(l => l.trim()) : []); form.querySelectorAll('input[name="target_government_levels"]').forEach(checkbox => { checkbox.checked = targetLevels.includes(checkbox.value); }); } // New method for edit tab form population populateEditForm() { if (!this.currentCampaign) return; const form = document.getElementById('edit-campaign-form'); const campaign = this.currentCampaign; // Populate form fields form.querySelector('[name="title"]').value = campaign.title || ''; form.querySelector('[name="description"]').value = campaign.description || ''; form.querySelector('[name="email_subject"]').value = campaign.email_subject || ''; form.querySelector('[name="email_body"]').value = campaign.email_body || ''; form.querySelector('[name="call_to_action"]').value = campaign.call_to_action || ''; // Status select form.querySelector('[name="status"]').value = campaign.status || 'draft'; // Checkboxes form.querySelector('[name="allow_smtp_email"]').checked = !!campaign.allow_smtp_email; form.querySelector('[name="allow_mailto_link"]').checked = !!campaign.allow_mailto_link; form.querySelector('[name="collect_user_info"]').checked = !!campaign.collect_user_info; form.querySelector('[name="show_email_count"]').checked = !!campaign.show_email_count; form.querySelector('[name="allow_email_editing"]').checked = !!campaign.allow_email_editing; // Government levels const targetLevels = Array.isArray(campaign.target_government_levels) ? campaign.target_government_levels : (campaign.target_government_levels ? campaign.target_government_levels.split(',').map(l => l.trim()) : []); form.querySelectorAll('[name="target_government_levels"]').forEach(checkbox => { checkbox.checked = targetLevels.includes(checkbox.value); }); } async handleUpdateCampaign(e) { e.preventDefault(); if (!this.currentCampaign) return; const formData = new FormData(e.target); const updates = { title: formData.get('title'), description: formData.get('description'), email_subject: formData.get('email_subject'), email_body: formData.get('email_body'), call_to_action: formData.get('call_to_action'), status: formData.get('status'), // Allow all users to change status for campaigns they own allow_smtp_email: formData.get('allow_smtp_email') === 'on', allow_mailto_link: formData.get('allow_mailto_link') === 'on', collect_user_info: formData.get('collect_user_info') === 'on', show_email_count: formData.get('show_email_count') === 'on', allow_email_editing: formData.get('allow_email_editing') === 'on', target_government_levels: Array.from(formData.getAll('target_government_levels')) }; console.log('Updating campaign with data:', updates); console.log('Current campaign:', this.currentCampaign); console.log('User info:', this.user); try { const endpoint = this.user?.isAdmin ? `/admin/campaigns/${this.currentCampaign.id}` : `/campaigns/${this.currentCampaign.id}`; console.log('Using endpoint:', endpoint); const response = await window.apiClient.makeRequest(endpoint, { method: 'PUT', body: JSON.stringify(updates) }); console.log('Update response:', response); if (response.success) { this.showMessage('Campaign updated successfully!', 'success'); const updatedCampaign = this.normalizeCampaignFromApi(response.campaign); this.updateCampaignInState(updatedCampaign); this.renderCampaignList(); this.loadAnalytics(); this.switchTab('campaigns'); } else { throw new Error(response.error || 'Failed to update campaign'); } } catch (error) { console.error('Update campaign error:', error); const errorMsg = error?.data?.error || error.message || 'Failed to update campaign'; this.showMessage('Failed to update campaign: ' + errorMsg, 'error'); } } async handleEditCampaignSubmit(event, campaignId, modal) { event.preventDefault(); const form = event.target; const formData = new FormData(form); const updates = { title: formData.get('title'), description: formData.get('description'), email_subject: formData.get('email_subject'), email_body: formData.get('email_body'), call_to_action: formData.get('call_to_action'), status: this.user?.isAdmin ? (formData.get('status') || 'draft') : 'draft', allow_smtp_email: formData.get('allow_smtp_email') === 'on', allow_mailto_link: formData.get('allow_mailto_link') === 'on', collect_user_info: formData.get('collect_user_info') === 'on', show_email_count: formData.get('show_email_count') === 'on', allow_email_editing: formData.get('allow_email_editing') === 'on', target_government_levels: Array.from(formData.getAll('target_government_levels')) }; try { const endpoint = this.user?.isAdmin ? `/admin/campaigns/${campaignId}` : `/campaigns/${campaignId}`; const response = await window.apiClient.makeRequest(endpoint, { method: 'PUT', body: JSON.stringify(updates) }); if (response.success) { this.closeModal(modal); const updatedCampaign = this.normalizeCampaignFromApi(response.campaign); this.updateCampaignInState(updatedCampaign); this.renderCampaignList(); this.loadAnalytics(); this.showMessage('Campaign updated successfully!', 'success'); } else { throw new Error(response.error || 'Failed to update campaign'); } } catch (error) { console.error('Update campaign error:', error); const errorMsg = error?.data?.error || error.message || 'Failed to update campaign'; this.showMessage('Failed to update campaign: ' + errorMsg, 'error'); } } updateCampaignInState(updatedCampaign) { if (!updatedCampaign) return; const updatedId = updatedCampaign.id != null ? String(updatedCampaign.id) : null; const index = this.campaigns.findIndex(c => String(c.id) === updatedId); if (index >= 0) { this.campaigns[index] = this.normalizeCampaignFromApi({ ...this.campaigns[index], ...updatedCampaign }); } else { this.campaigns.unshift(this.normalizeCampaignFromApi(updatedCampaign)); } } closeModal(modal) { if (modal && modal.parentNode) { modal.parentNode.removeChild(modal); } } showMessage(message, type = 'info') { const container = document.getElementById('message-container'); if (container) { container.className = `message-${type}`; container.textContent = message; container.classList.remove('hidden'); setTimeout(() => { container.classList.add('hidden'); }, 5000); } } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } formatDate(dateString) { if (!dateString) return 'N/A'; try { return new Date(dateString).toLocaleDateString('en-CA', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } catch (error) { return dateString; } } // Campaign Creation Methods async handleCreateCampaign(e) { e.preventDefault(); const formData = new FormData(e.target); const campaignData = { title: formData.get('title'), description: formData.get('description'), email_subject: formData.get('email_subject'), email_body: formData.get('email_body'), call_to_action: formData.get('call_to_action'), status: formData.get('status'), allow_smtp_email: formData.get('allow_smtp_email') === 'on', allow_mailto_link: formData.get('allow_mailto_link') === 'on', collect_user_info: formData.get('collect_user_info') === 'on', show_email_count: formData.get('show_email_count') === 'on', allow_email_editing: formData.get('allow_email_editing') === 'on', target_government_levels: Array.from(formData.getAll('target_government_levels')) }; try { if (!this.user.isAdmin) { campaignData.status = 'draft'; } const endpoint = this.user.isAdmin ? '/admin/campaigns' : '/campaigns'; const response = await window.apiClient.post(endpoint, campaignData); if (response.success) { this.showMessage('Campaign created successfully!', 'success'); e.target.reset(); this.switchTab('campaigns'); // Reload campaigns to show the new one this.loadUserCampaigns(); } else { throw new Error(response.error || 'Failed to create campaign'); } } catch (error) { console.error('Create campaign error:', error); this.showMessage('Failed to create campaign: ' + error.message, 'error'); } } } // Initialize dashboard when DOM is loaded document.addEventListener('DOMContentLoaded', async () => { window.userDashboard = new UserDashboard(); await window.userDashboard.init(); });