/home/ejrndhmu/.trash/reseller.6/js/panel.js
// Panel Reseller JavaScript Functions
// Add User Modal Functions
function openAddUserModal() {
document.getElementById('addUserModal').classList.remove('hidden');
}
function closeAddUserModal() {
document.getElementById('addUserModal').classList.add('hidden');
document.getElementById('addUserForm').reset();
}
// Product Access Modal Functions
function openProductModal(userId, userName) {
document.getElementById('productModal').classList.remove('hidden');
document.getElementById('modalUserName').textContent = userName;
document.getElementById('modalUserId').value = userId;
// Load user products
loadUserProducts(userId);
}
function closeProductModal() {
document.getElementById('productModal').classList.add('hidden');
document.getElementById('productsList').innerHTML = '';
}
// Quota Modal Functions
function openQuotaModal(userId, userName, currentQuota) {
document.getElementById('quotaModal').classList.remove('hidden');
document.getElementById('quotaModalUserName').textContent = userName;
document.getElementById('quotaModalUserId').value = userId;
document.getElementById('userQuota').value = currentQuota || 0;
}
function closeQuotaModal() {
document.getElementById('quotaModal').classList.add('hidden');
document.getElementById('quotaForm').reset();
}
// Edit User Modal Functions
function openEditUserModal(userId, username, email, fullName, role, whatsappNumber) {
document.getElementById('editUserModal').classList.remove('hidden');
document.getElementById('editUserId').value = userId;
document.getElementById('editUsername').value = username;
document.getElementById('editEmail').value = email;
document.getElementById('editFullName').value = fullName;
document.getElementById('editRole').value = role;
document.getElementById('editWhatsappNumber').value = whatsappNumber || '';
document.getElementById('editPassword').value = ''; // Clear password field
document.getElementById('editExpiredDuration').value = ''; // Reset duration
// Load user expiry data
loadUserExpiryData(userId);
}
function loadUserExpiryData(userId) {
const formData = new FormData();
formData.append('action', 'get_user_data');
formData.append('user_id', userId);
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
const user = data.user;
const expiryStatus = document.getElementById('editExpiryStatus');
const expiryDate = document.getElementById('editExpiryDate');
if (user.expired_at) {
const expiredDate = new Date(user.expired_at);
const now = new Date();
const isExpired = expiredDate < now;
expiryStatus.textContent = isExpired ? 'Kedaluwarsa' : 'Aktif';
expiryStatus.className = isExpired ? 'font-medium text-red-600' : 'font-medium text-green-600';
expiryDate.textContent = expiredDate.toLocaleDateString('id-ID', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
} else {
expiryStatus.textContent = 'Tidak terbatas';
expiryStatus.className = 'font-medium text-blue-600';
expiryDate.textContent = '-';
}
}
})
.catch(error => {
console.error('Error loading user expiry data:', error);
});
}
function closeEditUserModal() {
document.getElementById('editUserModal').classList.add('hidden');
document.getElementById('editUserForm').reset();
}
function editUser() {
console.log('editUser function called');
const form = document.getElementById('editUserForm');
const formData = new FormData(form);
formData.append('action', 'edit_user');
// Debug: Log form data
for (let [key, value] of formData.entries()) {
console.log(key + ': ' + value);
}
// Check if CSRF token is present
const csrfToken = formData.get('csrf_token');
console.log('CSRF token present:', csrfToken ? 'Yes' : 'No');
if (csrfToken) {
console.log('CSRF token value:', csrfToken.substring(0, 10) + '...');
}
// Show loading state
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Menyimpan...';
submitBtn.disabled = true;
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => {
console.log('Response status:', response.status);
console.log('Response headers:', response.headers);
return response.text();
})
.then(text => {
console.log('Raw response:', text);
console.log('Response length:', text.length);
// Check if response is empty
if (!text || text.trim() === '') {
throw new Error('Empty response from server');
}
try {
const data = JSON.parse(text);
console.log('Parsed data:', data);
if (data.success) {
showAlert('success', data.message);
closeEditUserModal();
// Reload page to show updated user data
setTimeout(() => {
location.reload();
}, 1000);
} else {
showAlert('error', data.message);
}
} catch (e) {
console.error('JSON parse error:', e);
console.error('Failed to parse:', text.substring(0, 200));
showAlert('error', 'Response tidak valid dari server: ' + e.message);
}
})
.catch(error => {
console.error('Error:', error);
showAlert('error', 'Terjadi kesalahan saat memperbarui user');
})
.finally(() => {
// Reset button state
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
});
}
function updateUserQuota() {
const form = document.getElementById('quotaForm');
const formData = new FormData(form);
formData.append('action', 'update_user_quota');
// Show loading state
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Menyimpan...';
submitBtn.disabled = true;
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert('success', data.message);
closeQuotaModal();
// Reload page to show updated quota
setTimeout(() => {
location.reload();
}, 1000);
} else {
showAlert('error', data.message);
}
})
.catch(error => {
console.error('Error:', error);
showAlert('error', 'Terjadi kesalahan saat memperbarui quota');
})
.finally(() => {
// Reset button state
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
});
}
// AJAX Functions
function addUser() {
const form = document.getElementById('addUserForm');
const formData = new FormData(form);
formData.append('action', 'add_user');
// Show loading state
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Menambahkan...';
submitBtn.disabled = true;
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert('success', data.message);
closeAddUserModal();
// Reload the page to show new user
setTimeout(() => {
window.location.reload();
}, 1500);
} else {
showAlert('error', data.message);
}
})
.catch(error => {
console.error('Error:', error);
showAlert('error', 'Terjadi kesalahan saat menambahkan user');
})
.finally(() => {
submitBtn.innerHTML = originalText;
submitBtn.disabled = false;
});
}
function toggleUserStatus(userId, currentStatus) {
if (!confirm('Apakah Anda yakin ingin mengubah status user ini?')) {
return;
}
const formData = new FormData();
formData.append('action', 'toggle_user_status');
formData.append('user_id', userId);
formData.append('csrf_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert('success', data.message);
// Update the status badge
const statusBadge = document.querySelector(`[data-user-id="${userId}"] .status-badge`);
if (statusBadge) {
if (data.new_status === 'active') {
statusBadge.className = 'status-badge bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs font-medium';
statusBadge.innerHTML = '<i class="fas fa-check mr-1"></i>Aktif';
} else {
statusBadge.className = 'status-badge bg-red-100 text-red-800 px-2 py-1 rounded-full text-xs font-medium';
statusBadge.innerHTML = '<i class="fas fa-times mr-1"></i>Tidak Aktif';
}
}
} else {
showAlert('error', data.message);
}
})
.catch(error => {
console.error('Error:', error);
showAlert('error', 'Terjadi kesalahan saat mengubah status user');
});
}
function deleteUser(userId, userName) {
if (!confirm(`Apakah Anda yakin ingin menghapus user "${userName}"? Tindakan ini tidak dapat dibatalkan.`)) {
return;
}
const formData = new FormData();
formData.append('action', 'delete_user');
formData.append('user_id', userId);
formData.append('csrf_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert('success', data.message);
// Remove the user row
const userRow = document.querySelector(`[data-user-id="${userId}"]`);
if (userRow) {
userRow.remove();
}
} else {
showAlert('error', data.message);
}
})
.catch(error => {
console.error('Error:', error);
showAlert('error', 'Terjadi kesalahan saat menghapus user');
});
}
function loadUserProducts(userId) {
const productsList = document.getElementById('productsList');
productsList.innerHTML = '<div class="text-center py-4"><i class="fas fa-spinner fa-spin text-blue-primary"></i> Memuat produk...</div>';
const formData = new FormData();
formData.append('action', 'get_user_products');
formData.append('user_id', userId);
formData.append('csrf_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(text => {
// Clean response from PHP warnings/errors
let cleanText = text;
const lines = text.split('\n');
for (let line of lines) {
line = line.trim();
if (line.startsWith('{') || line.startsWith('[')) {
cleanText = line;
break;
}
}
try {
const data = JSON.parse(cleanText);
if (data.success) {
displayProducts(data.products, userId);
} else {
productsList.innerHTML = `<div class="text-center py-4 text-red-600">${data.message}</div>`;
}
} catch (e) {
productsList.innerHTML = '<div class="text-center py-4 text-red-600">Terjadi kesalahan saat memuat produk</div>';
}
})
.catch(error => {
productsList.innerHTML = '<div class="text-center py-4 text-red-600">Terjadi kesalahan saat memuat produk</div>';
});
}
function displayProducts(products, userId) {
const productsList = document.getElementById('productsList');
if (!products || products.length === 0) {
productsList.innerHTML = '<div class="text-center py-4 text-gray-500">Tidak ada produk tersedia</div>';
return;
}
let html = '';
products.forEach((product, index) => {
const hasAccess = product.has_access;
const buttonClass = hasAccess ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600';
const buttonText = hasAccess ? 'Cabut Akses' : 'Berikan Akses';
const buttonAction = hasAccess ? `revokeAccess(${userId}, ${product.id})` : `grantAccess(${userId}, ${product.id})`;
html += `
<div class="bg-white rounded-lg shadow-md p-6 border border-gray-200">
<div class="flex justify-between items-start mb-4">
<div>
<h3 class="text-lg font-semibold text-gray-800">${product.name}</h3>
<p class="text-gray-600 text-sm mt-1">${product.description || 'Tidak ada deskripsi'}</p>
</div>
<div class="text-right">
<span class="text-lg font-bold text-blue-600">Rp ${parseInt(product.price).toLocaleString('id-ID')}</span>
</div>
</div>
<div class="flex justify-between items-center">
<div class="text-sm text-gray-500">
${hasAccess ? `<span class="text-green-600"><i class="fas fa-check-circle"></i> Akses diberikan ${product.granted_date ? 'pada ' + product.granted_date : ''}</span>` : '<span class="text-gray-400"><i class="fas fa-times-circle"></i> Belum memiliki akses</span>'}
</div>
<button
onclick="${buttonAction}"
class="px-4 py-2 text-white text-sm font-medium rounded-lg transition-colors ${buttonClass}"
>
${buttonText}
</button>
</div>
</div>
`;
});
productsList.innerHTML = html;
}
function grantAccess(userId, productId) {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
const formData = new FormData();
formData.append('action', 'grant_product_access');
formData.append('user_id', userId);
formData.append('product_id', productId);
formData.append('csrf_token', csrfToken);
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(text => {
// Clean response from PHP warnings/errors
let cleanText = text;
const lines = text.split('\n');
for (let line of lines) {
line = line.trim();
if (line.startsWith('{') || line.startsWith('[')) {
cleanText = line;
break;
}
}
try {
const data = JSON.parse(cleanText);
if (data.success) {
showAlert('success', data.message);
// Force reload products list with a small delay to ensure backend is updated
setTimeout(() => {
loadUserProducts(userId);
}, 500);
} else {
showAlert('error', data.message);
}
} catch (e) {
showAlert('error', 'Terjadi kesalahan dalam memproses response');
}
})
.catch(error => {
showAlert('error', 'Terjadi kesalahan saat memberikan akses');
});
}
function revokeAccess(userId, productId) {
if (!confirm('Apakah Anda yakin ingin mencabut akses produk ini?')) {
return;
}
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
if (!csrfToken) {
showAlert('error', 'CSRF token tidak ditemukan');
return;
}
const formData = new FormData();
formData.append('action', 'revoke_product_access');
formData.append('user_id', userId);
formData.append('product_id', productId);
formData.append('csrf_token', csrfToken);
fetch('ajax_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(text => {
// Clean response from PHP warnings/errors
let cleanText = text;
const lines = text.split('\n');
for (let line of lines) {
line = line.trim();
if (line.startsWith('{') || line.startsWith('[')) {
cleanText = line;
break;
}
}
try {
const data = JSON.parse(cleanText);
if (data.success) {
showAlert('success', data.message);
setTimeout(() => {
loadUserProducts(userId);
}, 500);
} else {
showAlert('error', data.message);
}
} catch (e) {
console.error('JSON parse error:', e);
showAlert('error', 'Terjadi kesalahan dalam memproses response');
}
})
.catch(error => {
console.error('Fetch error:', error);
showAlert('error', 'Terjadi kesalahan saat mencabut akses');
});
}
// Alert Functions
function showAlert(type, message) {
// Remove existing alerts
const existingAlerts = document.querySelectorAll('.alert-message');
existingAlerts.forEach(alert => alert.remove());
// Create new alert
const alertDiv = document.createElement('div');
alertDiv.className = `alert-message fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg max-w-sm transition-all duration-300 transform translate-x-full`;
if (type === 'success') {
alertDiv.className += ' bg-green-100 border border-green-200 text-green-800';
alertDiv.innerHTML = `
<div class="flex items-center">
<i class="fas fa-check-circle mr-2"></i>
<span>${message}</span>
<button onclick="this.parentElement.parentElement.remove()" class="ml-auto text-green-600 hover:text-green-800">
<i class="fas fa-times"></i>
</button>
</div>
`;
} else {
alertDiv.className += ' bg-red-100 border border-red-200 text-red-800';
alertDiv.innerHTML = `
<div class="flex items-center">
<i class="fas fa-exclamation-circle mr-2"></i>
<span>${message}</span>
<button onclick="this.parentElement.parentElement.remove()" class="ml-auto text-red-600 hover:text-red-800">
<i class="fas fa-times"></i>
</button>
</div>
`;
}
document.body.appendChild(alertDiv);
// Animate in
setTimeout(() => {
alertDiv.classList.remove('translate-x-full');
}, 100);
// Auto remove after 5 seconds
setTimeout(() => {
if (alertDiv.parentElement) {
alertDiv.classList.add('translate-x-full');
setTimeout(() => {
if (alertDiv.parentElement) {
alertDiv.remove();
}
}, 300);
}
}, 5000);
}
// Form validation
document.addEventListener('DOMContentLoaded', function() {
// Add User Form validation
const addUserForm = document.getElementById('addUserForm');
if (addUserForm) {
addUserForm.addEventListener('submit', function(e) {
e.preventDefault();
// Basic validation
const username = this.username.value.trim();
const fullName = this.full_name.value.trim();
const email = this.email.value.trim();
const password = this.password.value;
if (!username || !fullName || !email || !password) {
showAlert('error', 'Semua field harus diisi');
return;
}
if (username.length < 3) {
showAlert('error', 'Username minimal 3 karakter');
return;
}
if (password.length < 6) {
showAlert('error', 'Password minimal 6 karakter');
return;
}
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
showAlert('error', 'Format email tidak valid');
return;
}
addUser();
});
}
// Edit User Form validation
const editUserForm = document.getElementById('editUserForm');
if (editUserForm) {
editUserForm.addEventListener('submit', function(e) {
e.preventDefault();
editUser();
});
}
// Quota Form validation
const quotaForm = document.getElementById('quotaForm');
if (quotaForm) {
quotaForm.addEventListener('submit', function(e) {
e.preventDefault();
const userQuota = parseInt(this.user_quota.value);
if (isNaN(userQuota) || userQuota < 0) {
showAlert('error', 'Quota harus berupa angka positif');
return;
}
updateUserQuota();
});
}
// Close modals when clicking outside
document.addEventListener('click', function(e) {
if (e.target.classList.contains('modal-backdrop')) {
closeAddUserModal();
closeProductModal();
closeQuotaModal();
closeEditUserModal();
}
});
// Close modals with Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeAddUserModal();
closeProductModal();
closeQuotaModal();
closeEditUserModal();
}
});
});