2025-12-11 19:33:33 +00:00

197 lines
7.7 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function () {
const addMemberModal = new bootstrap.Modal(document.getElementById('addMemberModal'));
const editMemberModal = new bootstrap.Modal(document.getElementById('editMemberModal'));
const addMemberForm = document.getElementById('addMemberForm');
const editMemberForm = document.getElementById('editMemberForm');
const memberTableBody = document.getElementById('memberTableBody');
// Function to show a toast notification
function showToast(message, success = true) {
const toastContainer = document.getElementById('toastContainer');
const toast = document.createElement('div');
toast.className = `toast align-items-center text-white ${success ? 'bg-success' : 'bg-danger'} border-0 show`;
toast.role = 'alert';
toast.ariaLive = 'assertive';
toast.ariaAtomic = 'true';
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">${message}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
`;
toastContainer.appendChild(toast);
const bsToast = new bootstrap.Toast(toast);
bsToast.show();
setTimeout(() => {
bsToast.hide();
setTimeout(() => {
toast.remove();
}, 500);
}, 3000);
}
function loadMembers() {
fetch('api_members.php?action=list')
.then(response => response.json())
.then(data => {
memberTableBody.innerHTML = '';
if (data.success) {
if (data.members.length === 0) {
memberTableBody.innerHTML = '<tr><td colspan="6" class="text-center">Belum ada anggota.</td></tr>';
} else {
data.members.forEach(member => {
const row = `<tr>
<td>${member.id}</td>
<td>${escapeHTML(member.name)}</td>
<td>${escapeHTML(member.nik)}</td>
<td>${escapeHTML(member.address)}</td>
<td>${escapeHTML(member.phone)}</td>
<td>
<button class="btn btn-sm btn-warning btn-edit" data-id="${member.id}" title="Edit"><i class="bi bi-pencil-square"></i></button>
<button class="btn btn-sm btn-danger btn-delete" data-id="${member.id}" title="Hapus"><i class="bi bi-trash-fill"></i></button>
</td>
</tr>`;
memberTableBody.innerHTML += row;
});
}
// Update total members card
document.getElementById('totalMembers').innerText = data.members.length;
} else {
memberTableBody.innerHTML = `<tr><td colspan="6" class="text-center text-danger">Gagal memuat data: ${data.error}</td></tr>`;
}
})
.catch(error => {
memberTableBody.innerHTML = `<tr><td colspan="6" class="text-center text-danger">Error: ${error}</td></tr>`;
});
}
// Helper to prevent XSS
function escapeHTML(str) {
return str.toString().replace(/[&<>"']/g, function (tag) {
var chars = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
return chars[tag] || tag;
});
}
// Handle Add Member form submission
addMemberForm.addEventListener('submit', function (event) {
event.preventDefault();
const formData = new FormData(addMemberForm);
fetch('api_members.php', {
method: 'POST',
body: new URLSearchParams(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('Anggota berhasil ditambahkan!');
addMemberModal.hide();
addMemberForm.reset();
loadMembers();
} else {
showToast('Gagal menambahkan anggota: ' + data.error, false);
}
})
.catch(error => {
showToast('Terjadi kesalahan. Silakan coba lagi.', false);
});
});
''' // Delegated event listener for edit and delete buttons
memberTableBody.addEventListener('click', function (event) {
const editButton = event.target.closest('.btn-edit');
const deleteButton = event.target.closest('.btn-delete');
if (editButton) {
const memberId = editButton.dataset.id;
openEditModal(memberId);
} else if (deleteButton) {
const memberId = deleteButton.dataset.id;
deleteMember(memberId);
}
});
// Function to open and populate the edit modal
function openEditModal(memberId) {
fetch(`api_members.php?action=get&id=${memberId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
const member = data.member;
document.getElementById('editMemberId').value = member.id;
document.getElementById('editName').value = member.name;
document.getElementById('editNik').value = member.nik;
document.getElementById('editAddress').value = member.address;
document.getElementById('editPhone').value = member.phone;
editMemberModal.show();
} else {
showToast('Gagal mengambil data anggota: ' + data.error, false);
}
})
.catch(() => showToast('Terjadi kesalahan jaringan.', false));
}
// Handle Edit Member form submission
editMemberForm.addEventListener('submit', function (event) {
event.preventDefault();
const formData = new FormData(editMemberForm);
formData.append('action', 'update');
fetch('api_members.php', {
method: 'POST',
body: new URLSearchParams(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('Data anggota berhasil diperbarui!');
editMemberModal.hide();
loadMembers();
} else {
showToast('Gagal memperbarui data: ' + data.error, false);
}
})
.catch(() => {
showToast('Terjadi kesalahan. Silakan coba lagi.', false);
});
});
// Function to delete a member
function deleteMember(memberId) {
if (confirm('Apakah Anda yakin ingin menghapus anggota ini?')) {
const formData = new FormData();
formData.append('action', 'delete');
formData.append('id', memberId);
fetch('api_members.php', {
method: 'POST',
body: new URLSearchParams(formData)
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast('Anggota berhasil dihapus.');
loadMembers();
} else {
showToast('Gagal menghapus anggota: ' + data.error, false);
}
})
.catch(() => showToast('Terjadi kesalahan jaringan.', false));
}
}
// Initial load
loadMembers();
});''