Whole new user interface and user system
This commit is contained in:
@@ -3,6 +3,7 @@ class AdminPanel {
|
||||
constructor() {
|
||||
this.currentCampaign = null;
|
||||
this.campaigns = [];
|
||||
this.users = [];
|
||||
this.authManager = null;
|
||||
}
|
||||
|
||||
@@ -47,9 +48,6 @@ class AdminPanel {
|
||||
}
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Tab navigation
|
||||
document.querySelectorAll('.nav-btn').forEach(btn => {
|
||||
@@ -68,6 +66,14 @@ class AdminPanel {
|
||||
this.handleUpdateCampaign(e);
|
||||
});
|
||||
|
||||
document.getElementById('user-form').addEventListener('submit', (e) => {
|
||||
this.handleCreateUser(e);
|
||||
});
|
||||
|
||||
document.getElementById('email-form').addEventListener('submit', (e) => {
|
||||
this.handleEmailAllUsers(e);
|
||||
});
|
||||
|
||||
// Cancel buttons - using event delegation for proper handling
|
||||
document.addEventListener('click', (e) => {
|
||||
if (e.target.matches('[data-action="cancel-create"]')) {
|
||||
@@ -76,8 +82,33 @@ class AdminPanel {
|
||||
if (e.target.matches('[data-action="cancel-edit"]')) {
|
||||
this.switchTab('campaigns');
|
||||
}
|
||||
if (e.target.matches('[data-action="create-user"]')) {
|
||||
this.showUserModal();
|
||||
}
|
||||
if (e.target.matches('[data-action="close-user-modal"]')) {
|
||||
this.hideUserModal();
|
||||
}
|
||||
if (e.target.matches('[data-action="close-email-modal"]')) {
|
||||
this.hideEmailModal();
|
||||
}
|
||||
if (e.target.matches('[data-action="delete-user"]')) {
|
||||
this.deleteUser(e.target.dataset.userId);
|
||||
}
|
||||
if (e.target.matches('[data-action="send-login-details"]')) {
|
||||
this.sendLoginDetails(e.target.dataset.userId);
|
||||
}
|
||||
if (e.target.matches('[data-action="email-all-users"]')) {
|
||||
this.showEmailModal();
|
||||
}
|
||||
});
|
||||
this.loadCampaigns();
|
||||
|
||||
// User type change handler
|
||||
const userTypeSelect = document.getElementById('user-type');
|
||||
if (userTypeSelect) {
|
||||
userTypeSelect.addEventListener('change', (e) => {
|
||||
this.handleUserTypeChange(e.target.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setupFormInteractions() {
|
||||
@@ -111,6 +142,230 @@ class AdminPanel {
|
||||
this.handleSettingsChange(checkbox);
|
||||
});
|
||||
});
|
||||
|
||||
// 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;
|
||||
|
||||
console.log('Dropdown item selected:', { campaignId, campaignTitle, type });
|
||||
|
||||
input.value = campaignTitle;
|
||||
dropdown.classList.remove('show');
|
||||
|
||||
if (type === 'create' && campaignId !== 'new') {
|
||||
console.log('Calling populateCreateFormFromCampaign with ID:', campaignId);
|
||||
this.populateCreateFormFromCampaign(campaignId);
|
||||
} else if (type === 'edit' && campaignId) {
|
||||
this.loadCampaignForEdit(campaignId);
|
||||
} else if (type === 'create' && campaignId === 'new') {
|
||||
this.clearCreateForm();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
populateDropdown(dropdown, type) {
|
||||
console.log('populateDropdown called:', { type, campaignsCount: this.campaigns?.length });
|
||||
|
||||
dropdown.innerHTML = '';
|
||||
|
||||
if (type === 'create') {
|
||||
dropdown.innerHTML = '<div class="dropdown-item" data-campaign-id="new">Create New Campaign</div>';
|
||||
} else {
|
||||
dropdown.innerHTML = '<div class="dropdown-item" data-campaign-id="">Select a campaign to edit...</div>';
|
||||
}
|
||||
|
||||
if (this.campaigns && this.campaigns.length > 0) {
|
||||
console.log('Adding campaigns to dropdown:', this.campaigns.map(c => ({ id: c.id, title: c.title })));
|
||||
|
||||
// Admin can edit all campaigns
|
||||
this.campaigns.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);
|
||||
});
|
||||
} else {
|
||||
console.log('No campaigns available for dropdown');
|
||||
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');
|
||||
}
|
||||
|
||||
refreshDropdowns() {
|
||||
// Refresh create dropdown if it exists
|
||||
const createDropdown = document.getElementById('create-dropdown-menu');
|
||||
if (createDropdown) {
|
||||
this.populateDropdown(createDropdown, 'create');
|
||||
}
|
||||
|
||||
// Refresh edit dropdown if it exists
|
||||
const editDropdown = document.getElementById('edit-dropdown-menu');
|
||||
if (editDropdown) {
|
||||
this.populateDropdown(editDropdown, 'edit');
|
||||
}
|
||||
}
|
||||
|
||||
populateCreateFormFromCampaign(campaignId) {
|
||||
console.log('populateCreateFormFromCampaign called with ID:', campaignId);
|
||||
console.log('Available campaigns:', this.campaigns);
|
||||
|
||||
const campaign = this.campaigns.find(c => String(c.id) === String(campaignId));
|
||||
console.log('Found campaign:', campaign);
|
||||
|
||||
if (!campaign) {
|
||||
console.error('Campaign not found for ID:', campaignId);
|
||||
console.error('Available campaign IDs:', this.campaigns?.map(c => c.id));
|
||||
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 || '';
|
||||
document.getElementById('create-status').value = 'draft'; // Always set to draft for new campaigns
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
console.log('Form populated successfully with campaign:', campaign.title);
|
||||
}
|
||||
|
||||
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 = '';
|
||||
document.getElementById('create-status').value = 'draft';
|
||||
|
||||
// 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) {
|
||||
try {
|
||||
const response = await window.apiClient.get(`/admin/campaigns/${campaignId}`);
|
||||
|
||||
if (response.success) {
|
||||
this.currentCampaign = response.campaign;
|
||||
this.populateEditForm();
|
||||
this.switchTab('edit');
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to load campaign');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Load campaign error:', error);
|
||||
this.showMessage('Failed to load campaign: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
switchTab(tabName) {
|
||||
@@ -139,8 +394,36 @@ class AdminPanel {
|
||||
// Special handling for different tabs
|
||||
if (tabName === 'campaigns') {
|
||||
this.loadCampaigns();
|
||||
} else if (tabName === 'edit' && this.currentCampaign) {
|
||||
this.populateEditForm();
|
||||
} else if (tabName === 'create') {
|
||||
// Ensure campaigns are loaded for template selection
|
||||
if (!this.campaigns || this.campaigns.length === 0) {
|
||||
this.loadCampaigns();
|
||||
}
|
||||
} else if (tabName === 'edit') {
|
||||
// Ensure campaigns are loaded for editing
|
||||
if (!this.campaigns || this.campaigns.length === 0) {
|
||||
this.loadCampaigns();
|
||||
}
|
||||
if (this.currentCampaign) {
|
||||
this.populateEditForm();
|
||||
}
|
||||
} else if (tabName === 'users') {
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
// Refresh dropdowns when switching to create or edit tabs
|
||||
if (tabName === 'create' || tabName === 'edit') {
|
||||
setTimeout(() => {
|
||||
const createDropdown = document.getElementById('create-dropdown-menu');
|
||||
const editDropdown = document.getElementById('edit-dropdown-menu');
|
||||
|
||||
if (tabName === 'create' && createDropdown) {
|
||||
this.populateDropdown(createDropdown, 'create');
|
||||
}
|
||||
if (tabName === 'edit' && editDropdown) {
|
||||
this.populateDropdown(editDropdown, 'edit');
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +440,7 @@ class AdminPanel {
|
||||
if (response.success) {
|
||||
this.campaigns = response.campaigns;
|
||||
this.renderCampaignList();
|
||||
this.refreshDropdowns(); // Refresh dropdowns when campaigns are loaded
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to load campaigns');
|
||||
}
|
||||
@@ -192,6 +476,8 @@ class AdminPanel {
|
||||
<p><strong>Slug:</strong> <code>/campaign/${campaign.slug}</code></p>
|
||||
<p><strong>Email Count:</strong> ${campaign.emailCount || 0}</p>
|
||||
<p><strong>Created:</strong> ${this.formatDate(campaign.created_at)}</p>
|
||||
${campaign.created_by_user_name || campaign.created_by_user_email ?
|
||||
`<p><strong>Created By:</strong> ${this.escapeHtml(campaign.created_by_user_name || campaign.created_by_user_email)}</p>` : ''}
|
||||
</div>
|
||||
|
||||
<div class="campaign-actions">
|
||||
@@ -306,8 +592,14 @@ class AdminPanel {
|
||||
form.querySelector('[name="allow_email_editing"]').checked = campaign.allow_email_editing;
|
||||
|
||||
// Government levels
|
||||
const targetLevels = campaign.target_government_levels ?
|
||||
campaign.target_government_levels.split(',').map(l => l.trim()) : [];
|
||||
let targetLevels = [];
|
||||
if (campaign.target_government_levels) {
|
||||
if (Array.isArray(campaign.target_government_levels)) {
|
||||
targetLevels = campaign.target_government_levels;
|
||||
} else if (typeof campaign.target_government_levels === 'string') {
|
||||
targetLevels = campaign.target_government_levels.split(',').map(l => l.trim());
|
||||
}
|
||||
}
|
||||
|
||||
form.querySelectorAll('[name="target_government_levels"]').forEach(checkbox => {
|
||||
checkbox.checked = targetLevels.includes(checkbox.value);
|
||||
@@ -491,7 +783,7 @@ class AdminPanel {
|
||||
|
||||
formatDate(dateString) {
|
||||
if (!dateString) return 'N/A';
|
||||
|
||||
|
||||
try {
|
||||
return new Date(dateString).toLocaleDateString('en-CA', {
|
||||
year: 'numeric',
|
||||
@@ -504,6 +796,216 @@ class AdminPanel {
|
||||
return dateString;
|
||||
}
|
||||
}
|
||||
|
||||
// User Management Methods
|
||||
async loadUsers() {
|
||||
const loadingDiv = document.getElementById('users-loading');
|
||||
const listDiv = document.getElementById('users-list');
|
||||
|
||||
loadingDiv.classList.remove('hidden');
|
||||
listDiv.innerHTML = '';
|
||||
|
||||
try {
|
||||
const response = await window.apiClient.get('/admin/users');
|
||||
|
||||
if (response.success) {
|
||||
this.users = response.users;
|
||||
this.renderUserList();
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to load users');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Load users error:', error);
|
||||
this.showMessage('Failed to load users: ' + error.message, 'error');
|
||||
} finally {
|
||||
loadingDiv.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
renderUserList() {
|
||||
const listDiv = document.getElementById('users-list');
|
||||
|
||||
if (this.users.length === 0) {
|
||||
listDiv.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<h3>No users yet</h3>
|
||||
<p>Create your first user to get started.</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add email all users button at the top
|
||||
listDiv.innerHTML = `
|
||||
<div style="margin-bottom: 2rem; text-align: center;">
|
||||
<button class="btn btn-secondary" data-action="email-all-users">📧 Email All Users</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const userCards = this.users.map(user => {
|
||||
const isExpired = user.userType === 'temp' && user.ExpiresAt && new Date(user.ExpiresAt) < new Date();
|
||||
const userTypeClass = isExpired ? 'expired' : (user.userType || 'user');
|
||||
|
||||
return `
|
||||
<div class="user-card" data-user-id="${user.Id || user.id}">
|
||||
<div class="user-header">
|
||||
<div class="user-info">
|
||||
<h4>${this.escapeHtml(user.Name || user.name || 'No Name')}</h4>
|
||||
<p>${this.escapeHtml(user.Email || user.email)}</p>
|
||||
${user.Phone || user.phone ? `<p>📞 ${this.escapeHtml(user.Phone || user.phone)}</p>` : ''}
|
||||
${user.ExpiresAt ? `<p>⏰ Expires: ${this.formatDate(user.ExpiresAt)}</p>` : ''}
|
||||
${user['Last Login'] ? `<p>🕒 Last Login: ${this.formatDate(user['Last Login'])}</p>` : ''}
|
||||
</div>
|
||||
<div class="user-badges">
|
||||
<span class="user-badge ${userTypeClass}">
|
||||
${isExpired ? 'EXPIRED' : (user.Admin || user.admin ? 'ADMIN' : userTypeClass.toUpperCase())}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-actions">
|
||||
<button class="btn btn-secondary btn-small" data-action="send-login-details" data-user-id="${user.Id || user.id}">
|
||||
📧 Send Login Details
|
||||
</button>
|
||||
${user.Id !== this.authManager?.user?.id ? `
|
||||
<button class="btn btn-danger btn-small" data-action="delete-user" data-user-id="${user.Id || user.id}">
|
||||
🗑️ Delete
|
||||
</button>
|
||||
` : '<span class="btn btn-secondary btn-small" style="opacity: 0.5;">Current User</span>'}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
listDiv.innerHTML += userCards;
|
||||
}
|
||||
|
||||
showUserModal() {
|
||||
const modal = document.getElementById('user-modal');
|
||||
const form = document.getElementById('user-form');
|
||||
|
||||
form.reset();
|
||||
document.getElementById('user-modal-title').textContent = 'Add New User';
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
hideUserModal() {
|
||||
const modal = document.getElementById('user-modal');
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
|
||||
showEmailModal() {
|
||||
const modal = document.getElementById('email-modal');
|
||||
const form = document.getElementById('email-form');
|
||||
|
||||
form.reset();
|
||||
modal.classList.remove('hidden');
|
||||
}
|
||||
|
||||
hideEmailModal() {
|
||||
const modal = document.getElementById('email-modal');
|
||||
modal.classList.add('hidden');
|
||||
}
|
||||
|
||||
handleUserTypeChange(userType) {
|
||||
const tempOptions = document.getElementById('temp-user-options');
|
||||
if (tempOptions) {
|
||||
tempOptions.style.display = userType === 'temp' ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async handleCreateUser(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const userData = {
|
||||
email: formData.get('email'),
|
||||
password: formData.get('password'),
|
||||
name: formData.get('name'),
|
||||
phone: formData.get('phone'),
|
||||
userType: formData.get('userType'),
|
||||
isAdmin: formData.get('isAdmin') === 'on' || formData.get('userType') === 'admin',
|
||||
expireDays: formData.get('userType') === 'temp' ? parseInt(formData.get('expireDays')) : undefined
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await window.apiClient.post('/admin/users', userData);
|
||||
|
||||
if (response.success) {
|
||||
this.showMessage('User created successfully!', 'success');
|
||||
this.hideUserModal();
|
||||
this.loadUsers();
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to create user');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Create user error:', error);
|
||||
this.showMessage('Failed to create user: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async deleteUser(userId) {
|
||||
const user = this.users.find(u => (u.Id || u.id) == userId);
|
||||
if (!user) return;
|
||||
|
||||
if (!confirm(`Are you sure you want to delete the user "${user.Email || user.email}"? This action cannot be undone.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await window.apiClient.makeRequest(`/admin/users/${userId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
this.showMessage('User deleted successfully!', 'success');
|
||||
this.loadUsers();
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to delete user');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Delete user error:', error);
|
||||
this.showMessage('Failed to delete user: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async sendLoginDetails(userId) {
|
||||
try {
|
||||
const response = await window.apiClient.post(`/admin/users/${userId}/send-login-details`);
|
||||
|
||||
if (response.success) {
|
||||
this.showMessage('Login details sent successfully!', 'success');
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to send login details');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Send login details error:', error);
|
||||
this.showMessage('Failed to send login details: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async handleEmailAllUsers(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const emailData = {
|
||||
subject: formData.get('subject'),
|
||||
content: formData.get('content')
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await window.apiClient.post('/admin/users/email-all', emailData);
|
||||
|
||||
if (response.success) {
|
||||
this.showMessage(`Email sent successfully! ${response.results.successful.length} sent, ${response.results.failed.length} failed.`, 'success');
|
||||
this.hideEmailModal();
|
||||
} else {
|
||||
throw new Error(response.error || 'Failed to send emails');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Email all users error:', error);
|
||||
this.showMessage('Failed to send emails: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize admin panel when DOM is loaded
|
||||
|
||||
@@ -119,7 +119,20 @@ class AuthManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Redirect to appropriate dashboard
|
||||
redirectToDashboard() {
|
||||
if (this.isAuthenticated && this.user) {
|
||||
if (this.user.isAdmin) {
|
||||
window.location.href = '/admin.html';
|
||||
} else {
|
||||
window.location.href = '/dashboard.html';
|
||||
}
|
||||
} else {
|
||||
window.location.href = '/login.html';
|
||||
}
|
||||
}
|
||||
|
||||
// Set up event listeners for auth-related actions
|
||||
setupAuthListeners() {
|
||||
// Global logout button
|
||||
|
||||
1057
influence/app/public/js/dashboard.js
Normal file
1057
influence/app/public/js/dashboard.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,8 +30,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
// Redirect to admin panel
|
||||
window.location.href = '/admin.html';
|
||||
// Redirect based on user role
|
||||
if (response.user && response.user.isAdmin) {
|
||||
window.location.href = '/admin.html';
|
||||
} else {
|
||||
window.location.href = '/dashboard.html';
|
||||
}
|
||||
} else {
|
||||
showError(response.error || 'Login failed');
|
||||
}
|
||||
@@ -46,9 +50,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
async function checkSession() {
|
||||
try {
|
||||
const response = await apiClient.get('/auth/session');
|
||||
if (response.authenticated) {
|
||||
// Already logged in, redirect to admin
|
||||
window.location.href = '/admin.html';
|
||||
if (response.authenticated && response.user) {
|
||||
// Already logged in, redirect based on user role
|
||||
if (response.user.isAdmin) {
|
||||
window.location.href = '/admin.html';
|
||||
} else {
|
||||
window.location.href = '/dashboard.html';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Not logged in, continue with login form
|
||||
|
||||
Reference in New Issue
Block a user