Files
2026-06-13 11:24:58 +07:00

76 lines
4.8 KiB
JavaScript

/* =========================================================
skpl-map.js — Peta SKPL (operator & pimpinan)
Warga miskin (POI) + fasilitas publik + choropleth + heatmap
(choropleth/heatmap/legenda/pencarian via attachSkplLayers).
Role ditentukan global SKPL_ROLE ('operator' | 'pimpinan').
========================================================= */
(function () {
const API = APP_BASE + '/api';
const ROLE = (typeof SKPL_ROLE !== 'undefined') ? SKPL_ROLE : 'pimpinan';
let map, wargaLayer, fasilitasLayer;
const FAS_ICON = { sekolah: '🏫', puskesmas: '🏥', pasar: '🏪', kantor_kelurahan: '🏛️', rumah_ibadah: '🕌', lainnya: '📍' };
function divIcon(emoji, bg, size = 30) {
return L.divIcon({
className: 'div-icon-wrap',
html: `<div style="background:${bg};width:${size}px;height:${size}px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 5px rgba(0,0,0,.3);border:2px solid #fff;"><span style="transform:rotate(45deg);font-size:${size*0.45}px;">${emoji}</span></div>`,
iconSize: [size, size], iconAnchor: [size / 2, size], popupAnchor: [0, -size],
});
}
const wargaIcon = divIcon('👤', '#EF4444');
function wargaPopup(p) {
const vb = { terverifikasi: '#10B981', perlu_tinjauan: '#F59E0B', belum: '#9CA3AF' }[p.status_verifikasi] || '#9CA3AF';
let h = `<div style="min-width:200px;"><div style="font-weight:700;margin-bottom:4px;">${p.nama_kk}</div>`;
if (p.nik_kk) h += `<div style="font-size:.8rem;">NIK: ${p.nik_kk}</div>`;
if (p.alamat) h += `<div style="font-size:.8rem;">${p.alamat}</div>`;
h += `<div style="font-size:.8rem;">Penghasilan: Rp ${Number(p.penghasilan||0).toLocaleString('id-ID')}</div>`;
h += `<div style="font-size:.8rem;">Jiwa: ${p.jumlah_jiwa||'-'} · Tanggungan: ${p.jumlah_tanggungan||0}</div>`;
h += `<div style="font-size:.8rem;">Air: ${p.sumber_air||'-'} · Dinding: ${p.material_dinding||'-'}</div>`;
h += `<div style="font-size:.8rem;">Bantuan: <b>${p.bantuan_aktif||'Belum ada'}</b></div>`;
h += `<div style="font-size:.8rem;">Status: <b style="color:${vb}">${p.status_verifikasi||'belum'}</b>${p.jumlah_foto?' · 📷 '+p.jumlah_foto:''}</div>`;
if (ROLE === 'operator') {
h += `<div style="display:flex;gap:6px;margin-top:8px;">
<button onclick="window.location.href='${APP_BASE}/admin/data_warga.php'" style="flex:1;padding:6px;border:1px solid #2563EB;background:#2563EB;color:#fff;border-radius:6px;cursor:pointer;font-size:.78rem;">Kelola</button>
<button onclick="SKPLMAP_del(${p.id})" style="padding:6px 10px;border:1px solid #EF4444;background:#fff;color:#EF4444;border-radius:6px;cursor:pointer;font-size:.78rem;">Hapus</button>
</div>`;
}
return h + `</div>`;
}
async function loadWarga() {
const j = await (await fetch(`${API}/warga_miskin.php`)).json();
const data = j.status === 'success' ? j.data : { features: [] };
wargaLayer = L.geoJSON(data, {
pointToLayer: (f, ll) => L.marker(ll, { icon: wargaIcon }),
onEachFeature: (f, l) => l.bindPopup(wargaPopup(f.properties)),
}).addTo(map);
}
async function loadFasilitas() {
const j = await (await fetch(`${API}/fasilitas.php`)).json();
const data = j.status === 'success' ? j.data : { features: [] };
fasilitasLayer = L.geoJSON(data, {
pointToLayer: (f, ll) => L.marker(ll, { icon: divIcon(FAS_ICON[f.properties.jenis] || '📍', '#2563EB', 26) }),
onEachFeature: (f, l) => l.bindPopup(`<b>${f.properties.nama}</b><br><span style="font-size:.8rem;color:#6B7280;">${f.properties.jenis.replace('_',' ')}</span>`),
});
}
window.SKPLMAP_del = async function (id) {
if (!confirm('Hapus data warga ini?')) return;
const r = await (await fetch(`${API}/warga_miskin.php?id=${id}`, { method: 'DELETE' })).json();
if (r.status === 'success') { map.removeLayer(wargaLayer); loadWarga(); }
else alert(r.message || 'Gagal');
};
document.addEventListener('DOMContentLoaded', async () => {
map = L.map('skpl-map').setView([-0.0500, 109.3450], 13);
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', { subdomains: 'abcd', maxZoom: 19, attribution: '© OpenStreetMap, © CARTO' }).addTo(map);
await loadWarga();
await loadFasilitas();
if (window.attachSkplLayers) await window.attachSkplLayers(map);
// tambahkan toggle warga & fasilitas
L.control.layers(null, { '👤 Warga Miskin': wargaLayer, '🏢 Fasilitas Publik': fasilitasLayer }, { collapsed: true, position: 'topright' }).addTo(map);
});
})();