Files
2026-06-11 02:38:02 +00:00

254 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Detail Warga & Peta Lokal - Admin</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; }
</style>
</head>
<body class="bg-gray-100 text-gray-950 min-h-screen flex flex-col">
<nav class="bg-white border-b border-gray-200 p-4 flex items-center gap-4 sticky top-0 z-30 px-6">
<a href="admin_dasbor.html" class="hover:bg-gray-100 p-2 rounded-lg transition-colors text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
</a>
<h1 class="text-md font-bold text-gray-800">Detail Rekaman Data Validasi</h1>
</nav>
<main class="flex-grow p-4 md:p-6 max-w-5xl mx-auto w-full grid grid-cols-1 md:grid-cols-3 gap-6 mb-10">
<div class="md:col-span-2 space-y-6">
<div class="bg-white p-6 rounded-xl shadow-sm border border-gray-200 space-y-4">
<div class="flex justify-between items-start border-b pb-3">
<div>
<h2 id="det_nama_kk" class="text-xl font-bold text-gray-900">-</h2>
<p class="text-xs text-gray-400 font-mono mt-1">Sistem ID: <span id="det_id_sistem">-</span></p>
</div>
<span id="det_badge_status" class="inline-block px-2.5 py-1 text-[10px] font-bold rounded-md">Pending</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm">
<div>
<span class="text-xs text-gray-400 block">Nomor Induk Kependudukan (NIK)</span>
<p id="det_nik" class="font-mono font-medium mt-0.5">-</p>
</div>
<div>
<span class="text-xs text-gray-400 block">Nomor Kartu Keluarga (No KK)</span>
<p id="det_no_kk" class="font-mono font-medium mt-0.5">-</p>
</div>
<div>
<span class="text-xs text-gray-400 block">Jumlah Tanggungan Keluarga</span>
<p id="det_tanggungan" class="font-medium mt-0.5">-</p>
</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="bg-gray-50 p-4 border-b border-gray-200">
<h3 class="text-xs font-bold uppercase tracking-wider text-gray-500">Evaluasi Parameter Instrumen Kemiskinan BPS</h3>
</div>
<div class="divide-y divide-gray-100 text-sm">
<div class="p-4 flex justify-between"><span class="text-gray-500">Luas Lantai Per Kapita</span><span id="det_luas_lantai" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Material Bahan Lantai</span><span id="det_mat_lantai" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Material Bahan Dinding</span><span id="det_mat_dinding" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Fasilitas Sanitasi (MCK)</span><span id="det_sanitasi" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Sumber Air Minum Utama</span><span id="det_air_minum" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Sumber Penerangan Rumah</span><span id="det_penerangan" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Pekerjaan Utama Kepala Keluarga</span><span id="det_pekerjaan" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Estimasi Pendapatan Bulanan</span><span id="det_pendapatan" class="font-semibold text-emerald-700">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Frekuensi Makan Harian</span><span id="det_frekuensi_makan" class="font-semibold text-gray-800">-</span></div>
<div class="p-4 flex justify-between"><span class="text-gray-500">Kepemilikan Aset Kendaraan</span><span id="det_kepemilikan_aset" class="font-semibold text-gray-800">-</span></div>
</div>
</div>
</div>
<div class="space-y-6">
<div class="bg-white p-4 rounded-xl shadow-sm border border-gray-200 space-y-3">
<h3 class="text-xs font-bold uppercase tracking-wider text-gray-400">Verifikasi Lokasi Spasial</h3>
<div class="h-56 w-full rounded-lg overflow-hidden border border-gray-200 z-0 relative">
<div id="map_detail_container" class="absolute inset-0"></div>
</div>
<div class="text-[11px] font-mono text-gray-500 space-y-0.5">
<p>Lat: <span id="det_lat">-</span></p>
<p>Lng: <span id="det_lng">-</span></p>
</div>
</div>
<div class="bg-white p-5 rounded-xl shadow-sm border border-gray-200 space-y-3 text-center">
<h3 class="text-xs font-bold uppercase tracking-wider text-gray-500 mb-2">Aksi Otoritas Dokumen</h3>
<button onclick="ubah_status_verifikasi(id_warga_terpilih, 'Verified')" class="w-full py-3 bg-emerald-600 hover:bg-emerald-700 text-white text-xs font-bold rounded-lg transition-colors shadow-sm">Setujui Sebagai Mustahik</button>
<button onclick="ubah_status_verifikasi(id_warga_terpilih, 'Rejected')" class="w-full py-3 bg-red-600 hover:bg-red-700 text-white text-xs font-bold rounded-lg transition-colors shadow-sm">Tolak Pengajuan Bantuan</button>
</div>
</div>
</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>
const parameter_url = new URLSearchParams(window.location.search);
const id_warga_terpilih = parameter_url.get('id');
let instansi_peta_detail = null;
let antrean_id_warga = null;
let antrean_status_baru = null;
function format_mata_uang_rupiah(angka) {
return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }).format(angka);
}
function petakan_lokasi_warga(lat, lng, nama) {
if (!lat || !lng) return;
instansi_peta_detail = L.map('map_detail_container').setView([lat, lng], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors'
}).addTo(instansi_peta_detail);
L.marker([lat, lng]).addTo(instansi_peta_detail)
.bindPopup(`<b>${nama}</b><br>Titik Lokasi Rumah`)
.openPopup();
}
function isi_komponen_antarmuka(data) {
document.getElementById('det_id_sistem').textContent = data.id;
document.getElementById('det_nama_kk').textContent = data.nama_kk;
document.getElementById('det_nik').textContent = data.nik;
document.getElementById('det_no_kk').textContent = data.no_kk || '-';
document.getElementById('det_tanggungan').textContent = `${data.jumlah_tanggungan} Jiwa`;
document.getElementById('det_luas_lantai').textContent = data.luas_lantai_per_kapita || 'Belum diisi';
document.getElementById('det_mat_lantai').textContent = data.material_lantai || 'Belum diisi';
document.getElementById('det_mat_dinding').textContent = data.material_dinding || 'Belum diisi';
document.getElementById('det_sanitasi').textContent = data.fasilitas_sanitasi || 'Belum diisi';
document.getElementById('det_air_minum').textContent = data.sumber_air_minum || 'Belum diisi';
document.getElementById('det_penerangan').textContent = data.sumber_penerangan || 'Belum diisi';
document.getElementById('det_pekerjaan').textContent = data.pekerjaan_utama || 'Belum diisi';
document.getElementById('det_pendapatan').textContent = data.pendapatan_bulanan ? format_mata_uang_rupiah(data.pendapatan_bulanan) : 'Belum diisi';
document.getElementById('det_frekuensi_makan').textContent = data.frekuensi_makan || 'Belum diisi';
document.getElementById('det_kepemilikan_aset').textContent = data.kepemilikan_aset || 'Belum diisi';
document.getElementById('det_lat').textContent = data.lat;
document.getElementById('det_lng').textContent = data.lng;
const badge = document.getElementById('det_badge_status');
badge.textContent = data.status_validasi;
if (data.status_validasi.toLowerCase() === 'verified') {
badge.className = 'inline-block px-2.5 py-1 text-[10px] font-bold rounded-md bg-emerald-50 text-emerald-700 border border-emerald-200';
} else if (data.status_validasi.toLowerCase() === 'rejected') {
badge.className = 'inline-block px-2.5 py-1 text-[10px] font-bold rounded-md bg-red-50 text-red-700 border border-red-200';
} else {
badge.className = 'inline-block px-2.5 py-1 text-[10px] font-bold rounded-md bg-yellow-50 text-yellow-700 border border-yellow-200';
}
petakan_lokasi_warga(parseFloat(data.lat), parseFloat(data.lng), data.nama_kk);
}
async function ambil_data_detail_warga() {
if (!id_warga_terpilih) {
return alert('ID parameter tidak ditemukan pada URL peramban.');
}
try {
// Diubah ke relative path
const http_response = await fetch(`/api/admin/mustahik/${id_warga_terpilih}`);
const json_result = await http_response.json();
if (!http_response.ok) throw new Error(json_result.error || 'Gagal mengambil data detail.');
isi_komponen_antarmuka(json_result);
} catch (error_sistem) {
alert('Kegagalan Koneksi Sistem: ' + error_sistem.message);
}
}
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 memvalidasi data ini dengan status <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 tombol_setuju = document.getElementById('btn_modal_setuju');
tombol_setuju.disabled = true;
tombol_setuju.textContent = 'Memproses...';
try {
// 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: antrean_status_baru })
});
const json_result = await http_response.json();
if (!http_response.ok) throw new Error(json_result.error || 'Gagal mengubah status.');
tutup_modal();
alert('Status otorisasi data berhasil diperbarui!');
window.location.reload();
} catch (error_sistem) {
tutup_modal();
alert('Gagal mengeksekusi perintah: ' + error_sistem.message);
} finally {
tombol_setuju.disabled = false;
tombol_setuju.textContent = 'Ya, Lanjutkan';
}
}
ambil_data_detail_warga();
</script>
</body>
</html>