138 lines
6.4 KiB
JavaScript
138 lines
6.4 KiB
JavaScript
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: `<div style="width:32px;height:32px;background:#f59e0b;border:3px solid #fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:15px;box-shadow:0 3px 10px rgba(0,0,0,.2);cursor:grab;">⛪</div>`,
|
|
iconSize: [32, 32], iconAnchor: [16, 16]
|
|
});
|
|
|
|
const marker = L.marker([r.latitude, r.longitude], {
|
|
icon,
|
|
draggable: (window.currentUser && window.currentUser.role === 'admin')
|
|
}).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();
|
|
switchTab(currentTab);
|
|
} else {
|
|
toast('Gagal update lokasi: ' + res.message, 'error');
|
|
marker.setLatLng([r.latitude, r.longitude]);
|
|
}
|
|
});
|
|
|
|
layers.rumahIbadah.addLayer(marker);
|
|
});
|
|
}
|
|
|
|
function riPopup(r) {
|
|
const canEdit = window.currentUser && (window.currentUser.role === 'admin' || (window.currentUser.role === 'petugas_lapangan' && String(window.currentUser.rumah_ibadah_id) === String(r.id)));
|
|
const isAdmin = window.currentUser && window.currentUser.role === 'admin';
|
|
return `<h4>⛪ ${esc(r.nama)}</h4>
|
|
<p><b>Jenis:</b> ${r.jenis}</p>
|
|
<p><b>Radius:</b> ${r.radius_meter} m</p>
|
|
${r.alamat ? `<p><b>Alamat:</b> ${esc(r.alamat)}</p>` : ''}
|
|
${r.no_wa ? `<p><b>WA:</b> ${r.no_wa}</p>` : ''}
|
|
|
|
<div class="popup-actions">
|
|
${canEdit ? `<button class="btn btn-ghost btn-sm" onclick="editRI(${r.id})">✏ Edit</button>` : ''}
|
|
${isAdmin ? `<button class="btn btn-danger btn-sm" onclick="deleteRI(${r.id})">✕ Hapus</button>` : ''}
|
|
</div>`;
|
|
}
|
|
|
|
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 = `<div style="position:absolute;top:-3px;right:-3px;width:9px;height:9px;background:#2563eb;border:1.5px solid #fff;border-radius:50%"></div>`;
|
|
if (hasKons && !hasPemb) dot = `<div style="position:absolute;top:-3px;right:-3px;width:9px;height:9px;background:#f59e0b;border:1.5px solid #fff;border-radius:50%"></div>`;
|
|
|
|
const icon = L.divIcon({
|
|
className: '',
|
|
html: `<div style="position:relative"><div style="width:26px;height:26px;background:${color};border:3px solid #fff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;box-shadow:0 3px 10px ${color}66;cursor:grab;">👤</div>${dot}</div>`,
|
|
iconSize: [26, 26], iconAnchor: [13, 13]
|
|
});
|
|
|
|
const isAdmin = window.currentUser && window.currentUser.role === 'admin';
|
|
const isPetugas = window.currentUser && window.currentUser.role === 'petugas_lapangan';
|
|
const isResidentInRadiusOfPetugas = isPetugas && inR && String(p.rumah_ibadah_id) === String(window.currentUser.rumah_ibadah_id);
|
|
const canDrag = isAdmin || isResidentInRadiusOfPetugas;
|
|
|
|
const marker = L.marker([p.latitude, p.longitude], {
|
|
icon,
|
|
draggable: canDrag
|
|
}).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('penduduk_miskin');
|
|
} 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';
|
|
const isAdmin = window.currentUser && window.currentUser.role === 'admin';
|
|
const isPetugas = window.currentUser && window.currentUser.role === 'petugas_lapangan';
|
|
const isResidentInRadiusOfPetugas = isPetugas && inR && String(p.rumah_ibadah_id) === String(window.currentUser.rumah_ibadah_id);
|
|
const canEditOrLog = isAdmin || isResidentInRadiusOfPetugas;
|
|
|
|
return `<h4>👤 ${esc(p.nama)}</h4>
|
|
<div class="proximity-info ${inR ? 'dalam' : 'luar'}">
|
|
${inR ? `✅ Dalam radius — ${esc(p.nama_rumah_ibadah || '')}` : '❌ Di luar radius rumah ibadah'}
|
|
</div>
|
|
${p.no_wa ? `<p><b>WA:</b> ${p.no_wa}</p>` : ''}
|
|
${p.nik ? `<p><b>NIK:</b> ${p.nik}</p>` : ''}
|
|
${p.alamat ? `<p><b>Alamat:</b> ${esc(p.alamat)}</p>` : ''}
|
|
<p><b>Keluarga:</b> ${p.jumlah_anggota} jiwa</p>
|
|
<p><b>Bantuan:</b> 📚${p.bantuan_pemberdayaan} · 🛍${p.bantuan_konsumtif}</p>
|
|
|
|
<div class="popup-actions">
|
|
${canEditOrLog ? `<button class="btn btn-primary btn-sm" onclick="openLogBantuan(${p.id},'${esc(p.nama)}',${p.latitude},${p.longitude})">📋 Log Bantuan</button>` : ''}
|
|
${canEditOrLog ? `<button class="btn btn-ghost btn-sm" onclick="editPM(${p.id})">✏ Edit</button>` : ''}
|
|
${isAdmin ? `<button class="btn btn-danger btn-sm" onclick="deletePM(${p.id})">✕</button>` : ''}
|
|
</div>`;
|
|
}
|
|
|