// Customers page JavaScript
let routes = {};
let csrfToken = '';
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
if (window.customerRoutes) {
routes = window.customerRoutes;
csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || '';
}
// Attach event listener to the button instead of using inline onclick
const startButton = document.getElementById('startCustomerMigrationBtn');
if (startButton) {
startButton.addEventListener('click', function(e) {
e.preventDefault();
startCustomerMigration();
});
}
});
function startCustomerMigration() {
try {
const button = document.getElementById('startCustomerMigrationBtn');
if (!button) {
console.error('Start customer migration button not found');
alert('Error: Button not found. Please refresh the page.');
return;
}
const logContent = document.getElementById('customerMigrationLogContent');
if (!logContent) {
console.error('Customer migration log content not found');
alert('Error: Log container not found. Please refresh the page.');
return;
}
const originalText = button.textContent || 'Start Customer Migration';
if (button) {
button.disabled = true;
button.textContent = 'Migrating...';
button.style.cursor = 'not-allowed';
}
const progressContainer = document.getElementById('migrationProgressContainer');
// Show progress bar
if (progressContainer) {
progressContainer.style.display = 'block';
updateProgressBar(0, 0, 0, 0, 0, 'Starting migration...', '');
}
logContent.innerHTML = '
Starting migration...
';
// Generate progress key for tracking
const progressKey = 'customer_migration_progress_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
let progressInterval = null;
// Check if routes are available
if (!routes || !routes.migrateCustomers) {
console.error('Customer routes not available', routes);
if (button) {
button.disabled = false;
button.textContent = originalText;
button.style.cursor = 'pointer';
}
alert('Error: Routes not initialized. Please refresh the page.');
return;
}
progressInterval = pollMigrationProgress(progressKey, button, originalText, logContent);
fetch(routes.migrateCustomers, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken,
'Accept': 'application/json'
},
body: JSON.stringify({ dry_run: false, progress_key: progressKey })
})
.then(async response => {
const contentType = response.headers.get('content-type');
// Check if response is JSON
if (contentType && contentType.includes('application/json')) {
return response.json();
} else {
// Response is HTML (error page), get text and show error
const text = await response.text();
throw new Error(`Server returned HTML instead of JSON. Status: ${response.status}. This usually means there was a server error. Check the browser console or server logs for details.`);
}
})
.then(data => {
// Stop polling
if (progressInterval) {
clearInterval(progressInterval);
}
// Hide progress bar
if (progressContainer) {
progressContainer.style.display = 'none';
}
if (button) {
button.disabled = false;
button.textContent = originalText;
button.style.cursor = 'pointer';
}
if (data.success) {
// Update progress bar to 100% before hiding
if (progressContainer) {
updateProgressBar(100, data.added + data.updated, data.added + data.updated, data.added, data.updated, data.errors, 'completed', '');
}
const successEntry = document.createElement('div');
successEntry.className = 'log-entry success';
successEntry.textContent = `✓ Migration completed! Added: ${data.added || 0}, Updated: ${data.updated || 0}, Errors: ${data.errors || 0}`;
logContent.appendChild(successEntry);
if (data.log && data.log.length > 0) {
data.log.forEach(log => {
const entry = document.createElement('div');
entry.className = 'log-entry ' + (log.includes('ERROR') ? 'error' : 'success');
entry.textContent = log;
logContent.appendChild(entry);
});
}
const logContainer = document.getElementById('customerMigrationLogContainer');
logContainer.scrollTop = logContainer.scrollHeight;
} else {
const errorEntry = document.createElement('div');
errorEntry.className = 'log-entry error';
errorEntry.textContent = '✗ Migration failed: ' + (data.message || 'Unknown error');
logContent.appendChild(errorEntry);
}
})
.catch(error => {
// Stop polling
if (progressInterval) {
clearInterval(progressInterval);
}
// Hide progress bar
if (progressContainer) {
progressContainer.style.display = 'none';
}
if (button) {
button.disabled = false;
button.textContent = originalText;
button.style.cursor = 'pointer';
}
if (logContent) {
const errorEntry = document.createElement('div');
errorEntry.className = 'log-entry error';
errorEntry.textContent = '✗ Error: ' + error.message;
logContent.appendChild(errorEntry);
} else {
console.error('Error during migration:', error);
alert('Error: ' + error.message);
}
});
} catch (error) {
console.error('Error in startCustomerMigration:', error);
alert('An unexpected error occurred. Please refresh the page and try again.');
}
}
function pollMigrationProgress(progressKey, button, originalText, logContent) {
return setInterval(() => {
if (!routes.migrationProgress) {
console.error('Migration progress route not available');
return;
}
fetch(routes.migrationProgress + '?progress_key=' + encodeURIComponent(progressKey), {
method: 'GET',
headers: {
'X-CSRF-TOKEN': csrfToken
}
})
.then(response => response.json())
.then(data => {
if (data.success && data.progress) {
const progress = data.progress;
const percentage = progress.total > 0 ? Math.round((progress.current / progress.total) * 100) : 0;
updateProgressBar(
percentage,
progress.current,
progress.total,
progress.added,
progress.updated,
progress.errors,
progress.status,
progress.current_email
);
} else if (data.success === false && data.message === 'Progress not found') {
// Progress not found yet, migration might not have started
// This is okay, just continue polling
}
})
.catch(error => {
console.error('Error polling progress:', error);
});
}, 500); // Poll every 500ms for smoother updates
}
function updateProgressBar(percentage, current, total, added, updated, errors, status, currentEmail) {
const progressBar = document.getElementById('progressBar');
const progressPercentage = document.getElementById('progressPercentage');
const progressStatus = document.getElementById('progressStatus');
const currentCustomer = document.getElementById('currentCustomer');
const progressAdded = document.getElementById('progressAdded');
const progressUpdated = document.getElementById('progressUpdated');
const progressErrors = document.getElementById('progressErrors');
if (progressBar) {
progressBar.style.width = percentage + '%';
}
if (progressPercentage) {
progressPercentage.textContent = percentage + '%';
}
if (progressStatus) {
const statusText = status === 'running' ? 'Migrating...' :
status === 'completed' ? 'Migration completed!' :
status === 'failed' ? 'Migration failed!' : 'Starting...';
progressStatus.textContent = statusText;
}
if (currentCustomer) {
currentCustomer.textContent = currentEmail ? `Current: ${currentEmail}` : `Processing ${current} of ${total}`;
}
if (progressAdded) {
progressAdded.textContent = added;
}
if (progressUpdated) {
progressUpdated.textContent = updated;
}
if (progressErrors) {
progressErrors.textContent = errors;
}
}
function deleteM2Customer(customerId, email, firstname, lastname) {
const customerName = firstname !== 'N/A' && lastname !== 'N/A'
? `${firstname} ${lastname}`
: email !== 'N/A'
? email
: `ID ${customerId}`;
if (!confirm(`Are you sure you want to delete customer "${customerName}" (Email: ${email})?`)) {
return;
}
const url = routes.deleteCustomer.replace(':id', customerId);
fetch(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Customer deleted successfully!');
location.reload();
} else {
alert('Error: ' + (data.message || 'Failed to delete customer'));
}
})
.catch(error => {
alert('Error: ' + error.message);
});
}
// Make functions available globally
window.startCustomerMigration = startCustomerMigration;
window.deleteM2Customer = deleteM2Customer;