feat : fix fetch bug

This commit is contained in:
unknown
2026-06-09 12:28:44 +07:00
parent 1d55676e3e
commit f6231c1475
7 changed files with 152 additions and 128 deletions
+67 -24
View File
@@ -66,7 +66,7 @@
</tr>
</thead>
<tbody id="tabel_body_mustahik" class="divide-y divide-gray-200 text-sm text-gray-700">
</tbody>
</tbody>
</table>
</div>
<div id="pesan_tabel_kosong" class="p-10 text-center text-gray-400 text-sm hidden">Tidak ada rekaman data warga di dalam sistem.</div>
@@ -74,8 +74,33 @@
</main>
<div id="modal_konfirmasi" class="fixed inset-0 z-50 flex items-center justify-center hidden bg-gray-900 bg-opacity-50 backdrop-blur-sm transition-opacity">
<div class="bg-white p-6 rounded-2xl shadow-2xl w-full max-w-sm border border-gray-200 transform transition-all">
<div class="flex items-center gap-4 mb-4">
<div class="w-12 h-12 rounded-full bg-yellow-50 flex items-center justify-center text-yellow-500 flex-shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
</div>
<div>
<h3 class="text-lg font-bold text-gray-900">Konfirmasi Aksi</h3>
<p class="text-xs text-gray-500 mt-1">Tindakan ini akan mengubah basis data.</p>
</div>
</div>
<p id="teks_pesan_modal" class="text-sm text-gray-700 mb-6 py-2 border-y border-gray-100">
Apakah Anda yakin ingin mengubah status data ini?
</p>
<div class="flex justify-end gap-3">
<button onclick="tutup_modal()" class="px-4 py-2.5 text-xs font-bold text-gray-600 bg-gray-100 hover:bg-gray-200 rounded-xl transition-colors">Batalkan</button>
<button onclick="eksekusi_perubahan_status()" id="btn_modal_setuju" class="px-4 py-2.5 text-xs font-bold text-white bg-gray-900 hover:bg-gray-800 rounded-xl transition-colors shadow-sm">Ya, Lanjutkan</button>
</div>
</div>
</div>
<script>
// Fungsi membersihkan dan memperbarui isi baris tabel secara aman (XSS Prevention)
let antrean_id_warga = null;
let antrean_status_baru = null;
function muat_data_ke_tabel_admin(daftar_mustahik) {
const tbody = document.getElementById('tabel_body_mustahik');
const pesan_kosong = document.getElementById('pesan_tabel_kosong');
@@ -100,9 +125,6 @@
const baris = document.createElement('tr');
baris.className = 'hover:bg-gray-50 transition-colors';
/* Baris Kompleks: Kita menyusun kerangka visual baris menggunakan template literal,
namun pengisian teks string sensitif tetap diserahkan ke fungsi properti textContent
pada sub-elemen guna meminimalkan celah eksploitasi kode HTML injeksi berbahaya. */
baris.innerHTML = `
<td class="p-4 text-xs font-mono text-gray-400">${indeks + 1}</td>
<td class="p-4 font-semibold text-gray-900 kolom-nama"></td>
@@ -119,7 +141,6 @@
</td>
`;
// Menyuntikkan nilai teks string secara terisolasi dan aman
baris.querySelector('.kolom-nama').textContent = warga.nama_kk;
baris.querySelector('.kolom-nik').textContent = warga.nik;
baris.querySelector('.kolom-nokk').textContent = warga.no_kk || '-';
@@ -139,7 +160,6 @@
tbody.appendChild(baris);
});
// Perbarui papan indikator agregat atas secara asinkron
document.getElementById('label_total_baris').textContent = `${daftar_mustahik.length} Rekaman`;
document.getElementById('stat_total_warga').textContent = daftar_mustahik.length;
document.getElementById('stat_pending_warga').textContent = hitung_pending;
@@ -147,13 +167,13 @@
document.getElementById('stat_rejected_warga').textContent = hitung_rejected;
}
// Meminta daftar seluruh entitas warga dari sistem peladen Express
async function ambil_data_admin_mustahik() {
const banner_error = document.getElementById('banner_error_admin');
try {
banner_error.classList.add('hidden');
const http_response = await fetch('http://localhost:3000/api/admin/mustahik');
// Diubah ke relative path
const http_response = await fetch('/api/admin/mustahik');
const json_result = await http_response.json();
if (!http_response.ok) throw new Error(json_result.error || 'Gagal menarik data dari server.');
@@ -166,44 +186,67 @@
}
}
// Mengubah status persetujuan verifikasi warga via metode AJAX PATCH menuju backend
async function ubah_status_verifikasi(id_warga, status_baru) {
const banner_error = document.getElementById('banner_error_admin');
if (!confirm(`Apakah Anda yakin ingin mengubah status data ini menjadi ${status_baru}?`)) {
return;
function ubah_status_verifikasi(id_warga, status_baru) {
antrean_id_warga = id_warga;
antrean_status_baru = status_baru;
const teks_pesan = document.getElementById('teks_pesan_modal');
teks_pesan.innerHTML = `Apakah Anda yakin ingin mengubah status validasi menjadi <span class="font-bold text-gray-900">${status_baru}</span>?`;
const tombol_setuju = document.getElementById('btn_modal_setuju');
if (status_baru === 'Verified') {
tombol_setuju.className = 'px-4 py-2.5 text-xs font-bold text-white bg-emerald-600 hover:bg-emerald-700 rounded-xl transition-colors shadow-sm';
} else {
tombol_setuju.className = 'px-4 py-2.5 text-xs font-bold text-white bg-red-600 hover:bg-red-700 rounded-xl transition-colors shadow-sm';
}
document.getElementById('modal_konfirmasi').classList.remove('hidden');
}
function tutup_modal() {
document.getElementById('modal_konfirmasi').classList.add('hidden');
antrean_id_warga = null;
antrean_status_baru = null;
}
async function eksekusi_perubahan_status() {
if (!antrean_id_warga || !antrean_status_baru) return;
const banner_error = document.getElementById('banner_error_admin');
const tombol_setuju = document.getElementById('btn_modal_setuju');
tombol_setuju.disabled = true;
tombol_setuju.textContent = 'Memproses...';
try {
/* Baris Kompleks: Melakukan transmisi parsial status data menggunakan metode HTTP PATCH
menuju endpoint verifikasi admin, membawa payload status terenkapsulasi JSON
sehingga perubahan status langsung tercermin di file SQLite tanpa memuat ulang layar. */
const http_response = await fetch(`http://localhost:3000/api/admin/verifikasi/${id_warga}`, {
// Diubah ke relative path
const http_response = await fetch(`/api/admin/verifikasi/${antrean_id_warga}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status_validasi: status_baru })
body: JSON.stringify({ status_validasi: antrean_status_baru })
});
const json_result = await http_response.json();
if (!http_response.ok) throw new Error(json_result.error || 'Gagal mengubah status verifikasi.');
// Segera sinkronkan ulang isi tabel setelah proses mutasi data berhasil
tutup_modal();
ambil_data_admin_mustahik();
} catch (error_sistem) {
tutup_modal();
banner_error.textContent = 'Gagal memproses mutasi data: ' + error_sistem.message;
banner_error.classList.remove('hidden');
} finally {
tombol_setuju.disabled = false;
tombol_setuju.textContent = 'Ya, Lanjutkan';
}
}
// Mengakhiri sesi masuk administrator utama
function eksekusi_logout_admin() {
localStorage.removeItem('token_admin');
window.location.href = 'index.html';
}
// Inisialisasi awal penarikan data saat halaman terbuka sempurna
ambil_data_admin_mustahik();
</script>
</body>