function renderKemiskinanPanel(pb) { return Promise.all([callAPI('rumah_ibadah.php'), callAPI('penduduk_miskin.php')]).then(([riRes, pmRes]) => { const ri = riRes.data || []; const pm = pmRes.data || []; pb.innerHTML = `
Visibilitas Layer
${mkLayerItem('rumahIbadah', '#f59e0b', 'Rumah Ibadah', ri.length)} ${mkLayerItem('ibadahRadius', '#fbbf24', 'Radius Jangkauan', ri.length, true)} ${mkLayerItem('pendudukMiskin', '#16a34a', 'Penduduk Miskin', pm.length)}
Tambah Data
Rumah Ibadah (${ri.length})
${ri.length ? ri.map(r => `
${esc(r.nama)}
${r.jenis} · R=${r.radius_meter}m
`).join('') : '
Belum ada data
'}
Penduduk Miskin (${pm.length})
${pm.length ? pm.map(p => `
${pmEmoji(p)}
${esc(p.nama)}
${p.total_bantuan} bantuan · ${p.jumlah_anggota} jiwa
${p.status_proximity === 'dalam_radius' ? 'DALAM' : 'LUAR'}
`).join('') : '
Belum ada data
'}
`; loadRILayer(ri); loadPMLayer(pm); registerSearchEntries('ri', ri.map(r => ({ key: `ri:${r.id}`, label: r.nama, subtitle: `Rumah Ibadah · ${r.jenis}${r.alamat ? ` · ${r.alamat}` : ''}`, typeLabel: 'Rumah Ibadah', icon: '⛪', searchText: normalizeSearchText(`${r.nama} ${r.jenis} rumah ibadah`), focus: () => focusMarkerById('rumahIbadah', r.id) }))); registerSearchEntries('pm', pm.map(p => ({ key: `pm:${p.id}`, label: p.nama, subtitle: `Penduduk Miskin · ${p.jumlah_anggota} jiwa${p.alamat ? ` · ${p.alamat}` : ''}`, typeLabel: 'Penduduk Miskin', icon: '👤', searchText: normalizeSearchText(`${p.nama} ${p.nik || ''} penduduk miskin`), focus: () => focusMarkerById('pendudukMiskin', p.id) }))); updateStatusCount(); }); } function mkLayerItem(key, color, label, count, isRing = false) { const dot = isRing ? `
` : `
`; return `
${layerVisible[key] ? '✓' : ''}
${dot}
${label}
${count}
`; } function pmEmoji(p) { if (p.bantuan_pemberdayaan > 0 && p.bantuan_konsumtif > 0) return '🔗'; if (p.bantuan_pemberdayaan > 0) return '📚'; if (p.bantuan_konsumtif > 0) return '🛍'; return '👤'; } function loadRILayer(data) { layers.rumahIbadah.clearLayers(); layers.ibadahRadius.clearLayers(); data.forEach(r => { const circle = L.circle([r.latitude, r.longitude], { radius: r.radius_meter, color: '#f59e0b', fillColor: '#fef3c7', fillOpacity: 0.18, weight: 1.5, dashArray: '6,4' }); layers.ibadahRadius.addLayer(circle); const icon = L.divIcon({ className: '', html: `
`, iconSize: [32, 32], iconAnchor: [16, 16] }); const marker = L.marker([r.latitude, r.longitude], { icon, draggable: true }).bindPopup(riPopup(r)); marker._dataId = r.id; marker.on('dragend', async function (ev) { const { lat, lng } = ev.target.getLatLng(); circle.setLatLng([lat, lng]); const res = await callAPI(`rumah_ibadah.php?id=${r.id}`, 'PUT', { nama: r.nama, jenis: r.jenis, alamat: r.alamat, no_wa: r.no_wa, latitude: lat, longitude: lng, radius_meter: r.radius_meter }); if (res.status === 'success') { r.latitude = lat; r.longitude = lng; toast(`📍 ${r.nama} dipindahkan & koordinat diperbarui`, 'success'); await recalcAllProximity(); } else { toast('Gagal update lokasi: ' + res.message, 'error'); marker.setLatLng([r.latitude, r.longitude]); } }); layers.rumahIbadah.addLayer(marker); }); } function riPopup(r) { return `

⛪ ${esc(r.nama)}

Jenis: ${r.jenis}

Radius: ${r.radius_meter} m

${r.alamat ? `

Alamat: ${esc(r.alamat)}

` : ''} ${r.no_wa ? `

WA: ${r.no_wa}

` : ''} `; } function loadPMLayer(data) { layers.pendudukMiskin.clearLayers(); data.forEach(p => { const inR = p.status_proximity === 'dalam_radius'; const color = inR ? '#16a34a' : '#dc2626'; const hasBoth = p.bantuan_pemberdayaan > 0 && p.bantuan_konsumtif > 0; const hasPemb = p.bantuan_pemberdayaan > 0; const hasKons = p.bantuan_konsumtif > 0; let dot = ''; if (hasBoth || hasPemb) dot = `
`; if (hasKons && !hasPemb) dot = `
`; const icon = L.divIcon({ className: '', html: `
👤
${dot}
`, iconSize: [26, 26], iconAnchor: [13, 13] }); const marker = L.marker([p.latitude, p.longitude], { icon, draggable: true }).bindPopup(pmPopup(p)); marker._dataId = p.id; marker.on('dragend', async function (ev) { const { lat, lng } = ev.target.getLatLng(); const res = await callAPI(`penduduk_miskin.php?id=${p.id}`, 'PUT', { nama: p.nama, no_wa: p.no_wa, nik: p.nik, alamat: p.alamat, jumlah_anggota: p.jumlah_anggota, latitude: lat, longitude: lng }); if (res.status === 'success') { const prox = res.data?.proximity; const statusMsg = prox?.status === 'dalam_radius' ? '✅ Dalam radius' : '❌ Luar radius'; toast(`📍 ${p.nama} dipindahkan — ${statusMsg}`, 'success'); switchTab('kemiskinan'); } else { toast('Gagal update: ' + res.message, 'error'); marker.setLatLng([p.latitude, p.longitude]); } }); layers.pendudukMiskin.addLayer(marker); }); } function pmPopup(p) { const inR = p.status_proximity === 'dalam_radius'; return `

👤 ${esc(p.nama)}

${inR ? `✅ Dalam radius — ${esc(p.nama_rumah_ibadah || '')}` : '❌ Di luar radius rumah ibadah'}
${p.no_wa ? `

WA: ${p.no_wa}

` : ''} ${p.nik ? `

NIK: ${p.nik}

` : ''} ${p.alamat ? `

Alamat: ${esc(p.alamat)}

` : ''}

Keluarga: ${p.jumlah_anggota} jiwa

Bantuan: 📚${p.bantuan_pemberdayaan} · 🛍${p.bantuan_konsumtif}

`; } function startAdd(type) { cancelMapClick(); const btnId = type === 'ri' ? 'btn-add-ri' : 'btn-add-pm'; const label = type === 'ri' ? 'lokasi Rumah Ibadah' : 'lokasi Penduduk Miskin'; document.getElementById(btnId).classList.add('active'); showInstruction(`Klik di peta untuk menentukan ${label}`); onceMapClick((lat, lng) => { document.getElementById(btnId).classList.remove('active'); hideInstruction(); if (type === 'ri') openRIForm(null, lat, lng); else openPMForm(null, lat, lng); }); } function openRIForm(data, lat, lng) { const isEdit = !!data; const fLat = isEdit ? data.latitude : lat; const fLng = isEdit ? data.longitude : lng; openModal(isEdit ? 'Edit Rumah Ibadah' : 'Tambah Rumah Ibadah', `
📍 Koordinat: ${fLat.toFixed(7)}, ${fLng.toFixed(7)}
`, ` `); } async function saveRI(id, lat, lng) { const body = { nama: document.getElementById('ri-nama').value.trim(), jenis: document.getElementById('ri-jenis').value, alamat: document.getElementById('ri-alamat').value.trim(), no_wa: document.getElementById('ri-nowa').value.trim(), latitude: lat, longitude: lng, radius_meter: parseInt(document.getElementById('ri-radius').value) }; if (!body.nama) return toast('Nama wajib diisi', 'error'); const res = await callAPI(id ? `rumah_ibadah.php?id=${id}` : 'rumah_ibadah.php', id ? 'PUT' : 'POST', body); if (res.status === 'success') { toast(res.message, 'success'); closeModal(); await recalcAllProximity(); switchTab('kemiskinan'); } else { toast(res.message, 'error'); } } function openPMForm(data, lat, lng) { const isEdit = !!data; const fLat = isEdit ? data.latitude : lat; const fLng = isEdit ? data.longitude : lng; openModal(isEdit ? 'Edit Penduduk Miskin' : 'Tambah Penduduk Miskin', `
📍 Koordinat: ${fLat.toFixed(7)}, ${fLng.toFixed(7)}
`, ` `); } async function savePM(id, lat, lng) { const body = { nama: document.getElementById('pm-nama').value.trim(), no_wa: document.getElementById('pm-nowa').value.trim(), nik: document.getElementById('pm-nik').value.trim(), alamat: document.getElementById('pm-alamat').value.trim(), jumlah_anggota: parseInt(document.getElementById('pm-jml').value) || 1, latitude: lat, longitude: lng }; if (!body.nama) return toast('Nama wajib diisi', 'error'); const res = await callAPI(id ? `penduduk_miskin.php?id=${id}` : 'penduduk_miskin.php', id ? 'PUT' : 'POST', body); if (res.status === 'success') { toast(res.message, 'success'); closeModal(); switchTab('kemiskinan'); } else { toast(res.message, 'error'); } } async function editRI(id) { map.closePopup(); const res = await callAPI(`rumah_ibadah.php?id=${id}`); if (res.data) openRIForm(res.data, res.data.latitude, res.data.longitude); } async function deleteRI(id) { if (!confirm('Hapus rumah ibadah ini?')) return; const res = await callAPI(`rumah_ibadah.php?id=${id}`, 'DELETE'); if (res.status === 'success') { toast('Dihapus', 'success'); map.closePopup(); await recalcAllProximity(); switchTab('kemiskinan'); } } async function editPM(id) { map.closePopup(); const res = await callAPI(`penduduk_miskin.php?id=${id}`); if (res.data) openPMForm(res.data, res.data.latitude, res.data.longitude); } async function deletePM(id) { if (!confirm('Hapus data ini?')) return; const res = await callAPI(`penduduk_miskin.php?id=${id}`, 'DELETE'); if (res.status === 'success') { toast('Dihapus', 'success'); map.closePopup(); await recalcAllProximity(); switchTab('kemiskinan'); } } async function openLogBantuan(pmId, pmNama) { map.closePopup(); const [logRes, riRes] = await Promise.all([ callAPI(`log_bantuan.php?penduduk_miskin_id=${pmId}`), callAPI('rumah_ibadah.php') ]); const logs = logRes.data || []; const ris = riRes.data || []; openModal(`Log Bantuan — ${pmNama}`, `
Riwayat Bantuan
${logs.length ? logs.map(l => `
${l.tipe_bantuan === 'Pemberdayaan' ? '📚 Pemberdayaan' : '🛍 Konsumtif'}
${esc(l.sub_kategori) || ''} ${l.keterangan ? '— ' + esc(l.keterangan) : ''}
📅 ${l.tanggal_bantuan} · ${esc(l.nama_rumah_ibadah)}
`).join('') : '
Belum ada riwayat bantuan
'}
Tambah Bantuan Baru
`, ` `); } async function saveLog(pmId) { const body = { penduduk_miskin_id: pmId, rumah_ibadah_id: parseInt(document.getElementById('lb-ri').value), tipe_bantuan: document.getElementById('lb-tipe').value, tanggal_bantuan: document.getElementById('lb-tgl').value, sub_kategori: document.getElementById('lb-sub').value, keterangan: document.getElementById('lb-ket').value, nilai_bantuan: document.getElementById('lb-nilai').value || null }; const res = await callAPI('log_bantuan.php', 'POST', body); if (res.status === 'success') { toast('Log dicatat!', 'success'); closeModal(); switchTab('kemiskinan'); } else { toast(res.message, 'error'); } } async function recalcAllProximity() { await callAPI('penduduk_miskin.php?action=recalc_all', 'POST'); }