Files
docupulse/static/js/settings/pricing.js
2025-06-26 15:15:16 +02:00

312 lines
12 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
// Feature management for add form
const addFeatureBtn = document.getElementById('addFeatureBtn');
const featuresContainer = document.getElementById('featuresContainer');
if (addFeatureBtn) {
addFeatureBtn.addEventListener('click', function() {
addFeatureField(featuresContainer);
});
}
// Feature management for edit form
const editAddFeatureBtn = document.getElementById('editAddFeatureBtn');
const editFeaturesContainer = document.getElementById('editFeaturesContainer');
if (editAddFeatureBtn) {
editAddFeatureBtn.addEventListener('click', function() {
addFeatureField(editFeaturesContainer);
});
}
// Remove feature buttons
document.addEventListener('click', function(e) {
if (e.target.classList.contains('remove-feature-btn')) {
e.target.closest('.input-group').remove();
}
});
// Add Pricing Plan Form
const addPricingPlanForm = document.getElementById('addPricingPlanForm');
if (addPricingPlanForm) {
addPricingPlanForm.addEventListener('submit', function(e) {
e.preventDefault();
submitPricingPlanForm(this, 'POST', '/api/admin/pricing-plans');
});
}
// Edit Pricing Plan Form
const editPricingPlanForm = document.getElementById('editPricingPlanForm');
if (editPricingPlanForm) {
editPricingPlanForm.addEventListener('submit', function(e) {
e.preventDefault();
const planId = document.getElementById('editPlanId').value;
submitPricingPlanForm(this, 'PUT', `/api/admin/pricing-plans/${planId}`);
});
}
// Edit Plan Buttons
document.addEventListener('click', function(e) {
if (e.target.classList.contains('edit-plan-btn')) {
const planId = e.target.getAttribute('data-plan-id');
loadPlanForEdit(planId);
}
});
// Delete Plan Buttons
document.addEventListener('click', function(e) {
if (e.target.classList.contains('delete-plan-btn')) {
const planId = e.target.getAttribute('data-plan-id');
const planName = e.target.closest('.card').querySelector('.card-header h5').textContent;
showDeleteConfirmation(planId, planName);
}
});
// Confirm Delete Button
const confirmDeleteBtn = document.getElementById('confirmDeletePlan');
if (confirmDeleteBtn) {
confirmDeleteBtn.addEventListener('click', function() {
const planId = this.getAttribute('data-plan-id');
deletePricingPlan(planId);
});
}
// Toggle switches
document.addEventListener('change', function(e) {
if (e.target.classList.contains('plan-status-toggle')) {
const planId = e.target.getAttribute('data-plan-id');
const isActive = e.target.checked;
updatePlanStatus(planId, 'is_active', isActive);
}
if (e.target.classList.contains('plan-popular-toggle')) {
const planId = e.target.getAttribute('data-plan-id');
const isPopular = e.target.checked;
updatePlanStatus(planId, 'is_popular', isPopular);
}
if (e.target.classList.contains('plan-custom-toggle')) {
const planId = e.target.getAttribute('data-plan-id');
const isCustom = e.target.checked;
updatePlanStatus(planId, 'is_custom', isCustom);
}
});
});
function addFeatureField(container) {
const featureGroup = document.createElement('div');
featureGroup.className = 'input-group mb-2';
featureGroup.innerHTML = `
<input type="text" class="form-control feature-input" name="features[]" required>
<button type="button" class="btn btn-outline-danger remove-feature-btn">
<i class="fas fa-times"></i>
</button>
`;
container.appendChild(featureGroup);
}
function submitPricingPlanForm(form, method, url) {
const formData = new FormData(form);
// Convert features array
const features = [];
form.querySelectorAll('input[name="features[]"]').forEach(input => {
if (input.value.trim()) {
features.push(input.value.trim());
}
});
// Remove features from formData and add as JSON
formData.delete('features[]');
formData.append('features', JSON.stringify(features));
// Convert checkboxes to boolean values
const checkboxes = ['is_popular', 'is_custom', 'is_active'];
checkboxes.forEach(field => {
formData.set(field, formData.get(field) === 'on');
});
fetch(url, {
method: method,
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showNotification('Pricing plan saved successfully!', 'success');
setTimeout(() => {
window.location.reload();
}, 1000);
} else {
showNotification(data.error || 'Error saving pricing plan', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showNotification('Error saving pricing plan', 'error');
});
}
function loadPlanForEdit(planId) {
fetch(`/api/admin/pricing-plans/${planId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
const plan = data.plan;
// Populate form fields
document.getElementById('editPlanId').value = plan.id;
document.getElementById('editPlanName').value = plan.name;
document.getElementById('editPlanDescription').value = plan.description || '';
document.getElementById('editMonthlyPrice').value = plan.monthly_price;
document.getElementById('editAnnualPrice').value = plan.annual_price;
document.getElementById('editButtonText').value = plan.button_text;
document.getElementById('stripeProductId').value = plan.stripe_product_id || '';
document.getElementById('stripeMonthlyPriceId').value = plan.stripe_monthly_price_id || '';
document.getElementById('stripeAnnualPriceId').value = plan.stripe_annual_price_id || '';
document.getElementById('editIsPopular').checked = plan.is_popular;
document.getElementById('editIsCustom').checked = plan.is_custom;
document.getElementById('editIsActive').checked = plan.is_active;
// Populate quota fields
document.getElementById('editRoomQuota').value = plan.room_quota || 0;
document.getElementById('editConversationQuota').value = plan.conversation_quota || 0;
document.getElementById('editStorageQuota').value = plan.storage_quota_gb || 0;
document.getElementById('editManagerQuota').value = plan.manager_quota || 0;
document.getElementById('editAdminQuota').value = plan.admin_quota || 0;
// Populate features
const editFeaturesContainer = document.getElementById('editFeaturesContainer');
editFeaturesContainer.innerHTML = '';
plan.features.forEach(feature => {
const featureGroup = document.createElement('div');
featureGroup.className = 'input-group mb-2';
featureGroup.innerHTML = `
<input type="text" class="form-control feature-input" name="features[]" value="${feature}" required>
<button type="button" class="btn btn-outline-danger remove-feature-btn">
<i class="fas fa-times"></i>
</button>
`;
editFeaturesContainer.appendChild(featureGroup);
});
// Add one empty feature field if no features
if (plan.features.length === 0) {
addFeatureField(editFeaturesContainer);
}
} else {
showNotification(data.error || 'Error loading plan', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showNotification('Error loading plan', 'error');
});
}
function showDeleteConfirmation(planId, planName) {
document.getElementById('deletePlanName').textContent = planName;
document.getElementById('confirmDeletePlan').setAttribute('data-plan-id', planId);
const deleteModal = new bootstrap.Modal(document.getElementById('deletePricingPlanModal'));
deleteModal.show();
}
function deletePricingPlan(planId) {
fetch(`/api/admin/pricing-plans/${planId}`, {
method: 'DELETE',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': document.querySelector('input[name="csrf_token"]').value
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
showNotification('Pricing plan deleted successfully!', 'success');
// Close modal
const deleteModal = bootstrap.Modal.getInstance(document.getElementById('deletePricingPlanModal'));
deleteModal.hide();
// Remove from DOM
const planElement = document.querySelector(`[data-plan-id="${planId}"]`);
if (planElement) {
planElement.remove();
}
// Check if no plans left
const remainingPlans = document.querySelectorAll('[data-plan-id]');
if (remainingPlans.length === 0) {
window.location.reload();
}
} else {
showNotification(data.error || 'Error deleting plan', 'error');
}
})
.catch(error => {
console.error('Error:', error);
showNotification('Error deleting plan', 'error');
});
}
function updatePlanStatus(planId, field, value) {
fetch(`/api/admin/pricing-plans/${planId}/status`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': document.querySelector('input[name="csrf_token"]').value
},
body: JSON.stringify({
field: field,
value: value
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
showNotification('Plan status updated successfully!', 'success');
} else {
showNotification(data.error || 'Error updating plan status', 'error');
// Revert the toggle
const toggle = document.querySelector(`[data-plan-id="${planId}"].${field.replace('is_', 'plan-')}-toggle`);
if (toggle) {
toggle.checked = !value;
}
}
})
.catch(error => {
console.error('Error:', error);
showNotification('Error updating plan status', 'error');
// Revert the toggle
const toggle = document.querySelector(`[data-plan-id="${planId}"].${field.replace('is_', 'plan-')}-toggle`);
if (toggle) {
toggle.checked = !value;
}
});
}
function showNotification(message, type) {
// Create notification element
const notification = document.createElement('div');
notification.className = `alert alert-${type === 'success' ? 'success' : 'danger'} alert-dismissible fade show position-fixed`;
notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
notification.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(notification);
// Auto-remove after 5 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 5000);
}