1107 lines
47 KiB
JavaScript
1107 lines
47 KiB
JavaScript
/* ============================================================
|
||
loadData.js – WebGIS Pemetaan Kemiskinan & Masjid v2.1
|
||
============================================================ */
|
||
|
||
/* ── Toast ── */
|
||
window.showToast = function (message, type) {
|
||
type = type || "info";
|
||
var container = document.getElementById("toast-wrap");
|
||
if (!container) { return; }
|
||
var toast = document.createElement("div");
|
||
toast.className = "toast " + type;
|
||
var icon = type === "success" ? "<i class='fa-solid fa-check'></i>" : type === "error" ? "<i class='fa-solid fa-xmark'></i>" : "<i class='fa-solid fa-circle-info'></i>";
|
||
toast.innerHTML = icon + " " + message;
|
||
container.appendChild(toast);
|
||
setTimeout(function () {
|
||
toast.classList.add("removing");
|
||
setTimeout(function () { toast.remove(); }, 300);
|
||
}, 3500);
|
||
};
|
||
|
||
/* ── Label helpers ── */
|
||
window.labelStatusKeluarga = {
|
||
aktif: '<i class="fa-solid fa-check"></i> Aktif', meninggal: '<i class="fa-solid fa-heart-crack"></i> Meninggal', pindah: '<i class="fa-solid fa-box-open"></i> Pindah', sudah_mampu: '<i class="fa-solid fa-arrow-trend-up"></i> Sudah Mampu'
|
||
};
|
||
|
||
/* ── Detail Panel state ── */
|
||
window._currentDetailItem = null;
|
||
window._currentDetailKemiskinanId = null;
|
||
|
||
/* ── Open Detail Panel ── */
|
||
window.openDetailPanel = function (item) {
|
||
window._currentDetailItem = item;
|
||
window._currentDetailKemiskinanId = item.id;
|
||
|
||
document.getElementById('detail-panel-nama').textContent = item.nama_kepala_keluarga;
|
||
document.getElementById('detail-panel-alamat').textContent = item.alamat;
|
||
|
||
var banner = document.getElementById('detail-status-banner');
|
||
var status = item.status_keluarga || 'aktif';
|
||
var statusLabels = {
|
||
aktif: '<i class="fa-solid fa-check"></i> Aktif – Membutuhkan Bantuan',
|
||
meninggal: '<i class="fa-solid fa-heart-crack"></i> Meninggal',
|
||
pindah: '<i class="fa-solid fa-box-open"></i> Pindah',
|
||
sudah_mampu: '<i class="fa-solid fa-arrow-trend-up"></i> Sudah Mampu'
|
||
};
|
||
banner.className = 'dp-status ' + status;
|
||
banner.innerHTML = statusLabels[status] || status;
|
||
|
||
/* Actions bar */
|
||
var actBar = document.getElementById('detail-actions-bar');
|
||
actBar.innerHTML = '';
|
||
|
||
var btnLaporan = document.createElement('button');
|
||
btnLaporan.className = 'btn btn-lapor';
|
||
btnLaporan.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> Laporkan Kondisi';
|
||
btnLaporan.onclick = function () { window.openLaporanPublikModal(item.id, item.nama_kepala_keluarga); };
|
||
actBar.appendChild(btnLaporan);
|
||
|
||
if (window.appAuth.role === 'pengurus_masjid') {
|
||
var btnEdit = document.createElement('button');
|
||
btnEdit.className = 'btn btn-edit';
|
||
btnEdit.innerHTML = '<i class="fa-solid fa-pen"></i> Edit Data KK';
|
||
btnEdit.onclick = function () { window.openEditKemiskinanModal(item); };
|
||
actBar.appendChild(btnEdit);
|
||
}
|
||
|
||
document.getElementById('detail-panel').classList.add('open');
|
||
window.switchDetailTab('anggota');
|
||
};
|
||
|
||
window.closeDetailPanel = function () {
|
||
document.getElementById('detail-panel').classList.remove('open');
|
||
window._currentDetailItem = null;
|
||
window._currentDetailKemiskinanId = null;
|
||
};
|
||
|
||
window.switchDetailTab = function (tabName) {
|
||
['anggota', 'bantuan', 'laporan-detail'].forEach(function (t) {
|
||
var btnId = 'tab-btn-' + t;
|
||
var contentId = 'detail-tab-' + t;
|
||
var btn = document.getElementById(btnId);
|
||
var content = document.getElementById(contentId);
|
||
if (!btn || !content) return;
|
||
var isActive = (t === tabName);
|
||
btn.classList.toggle('active', isActive);
|
||
content.classList.toggle('hidden', !isActive);
|
||
});
|
||
|
||
if (!window._currentDetailItem) return;
|
||
if (tabName === 'anggota') window.renderTabAnggota(window._currentDetailItem);
|
||
if (tabName === 'bantuan') window.renderTabBantuan(window._currentDetailItem);
|
||
if (tabName === 'laporan-detail') window.renderTabLaporanDetail(window._currentDetailItem);
|
||
};
|
||
|
||
/* Laporan per KK */
|
||
window.renderTabLaporanDetail = async function (item) {
|
||
var container = document.getElementById('detail-tab-laporan-detail');
|
||
if (!container) return;
|
||
container.innerHTML = '<div class="loading">Memuat laporan...</div>';
|
||
|
||
var data = await window.fetchJson('php/read_laporan.php?kemiskinan_id=' + item.id, []);
|
||
container.innerHTML = '';
|
||
|
||
var btnLapor = document.createElement('button');
|
||
btnLapor.className = 'btn btn-add';
|
||
btnLapor.innerHTML = '+ Laporkan Kondisi Baru';
|
||
btnLapor.onclick = function () { window.openLaporanPublikModal(item.id, item.nama_kepala_keluarga); };
|
||
container.appendChild(btnLapor);
|
||
|
||
if (!data.length) {
|
||
var emptyMsg = document.createElement('div');
|
||
emptyMsg.className = 'empty';
|
||
emptyMsg.textContent = 'Belum ada laporan untuk keluarga ini.';
|
||
container.appendChild(emptyMsg);
|
||
return;
|
||
}
|
||
|
||
data.forEach(function (l) {
|
||
var card = document.createElement('div');
|
||
card.className = 'l-card ' + l.status_laporan;
|
||
card.innerHTML =
|
||
'<div class="l-head">' +
|
||
'<span class="l-cat">' + (window.labelKategoriLaporan[l.kategori] || l.kategori) + '</span>' +
|
||
'<span class="chip chip-' + { menunggu:'amber', diproses:'blue', selesai:'green', ditolak:'gray' }[l.status_laporan] + '">' +
|
||
(window.labelStatusLaporan[l.status_laporan] || l.status_laporan) + '</span>' +
|
||
'</div>' +
|
||
'<div class="l-desc">' + window.escapeHtml(l.deskripsi) + '</div>' +
|
||
'<div class="l-meta">👤 ' + window.escapeHtml(l.nama_pelapor) + ' · 🕐 ' + l.created_fmt + '</div>';
|
||
container.appendChild(card);
|
||
});
|
||
};
|
||
|
||
|
||
/* ── Modal: Kemiskinan ── */
|
||
window.openKemiskinanModal = function (lat, lng) {
|
||
var latVal = Number(lat).toFixed(6);
|
||
var lngVal = Number(lng).toFixed(6);
|
||
document.getElementById("kem-lat").value = latVal;
|
||
document.getElementById("kem-lng").value = lngVal;
|
||
document.getElementById("kem-nama").value = "";
|
||
document.getElementById("kem-jumlah").value = "";
|
||
document.getElementById("kem-status").value = "aktif";
|
||
|
||
var alamatInput = document.getElementById("kem-alamat");
|
||
alamatInput.value = "";
|
||
alamatInput.placeholder = "Mencari alamat...";
|
||
alamatInput.dataset.geoLat = latVal;
|
||
alamatInput.dataset.geoLng = lngVal;
|
||
|
||
fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${latVal}&lon=${lngVal}&accept-language=id`)
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
if (alamatInput.dataset.geoLat === latVal && alamatInput.dataset.geoLng === lngVal) {
|
||
if (data && data.display_name) {
|
||
alamatInput.value = data.display_name;
|
||
} else {
|
||
alamatInput.placeholder = "Gagal memuat alamat. Silakan isi manual.";
|
||
}
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error("Reverse geocoding failed", err);
|
||
if (alamatInput.dataset.geoLat === latVal && alamatInput.dataset.geoLng === lngVal) {
|
||
alamatInput.placeholder = "Gagal memuat alamat. Silakan isi manual.";
|
||
}
|
||
});
|
||
|
||
var overlay = document.getElementById("modal-kemiskinan");
|
||
overlay.style.display = "flex";
|
||
document.getElementById("kem-nama").focus();
|
||
overlay.onclick = function (e) { if (e.target === overlay) window.closeModal("kemiskinan"); };
|
||
};
|
||
|
||
window._submitKemiskinan = async function (event) {
|
||
if (event && event.preventDefault) event.preventDefault();
|
||
var btn = document.getElementById("btn-submit-kemiskinan");
|
||
var nama = document.getElementById("kem-nama").value.trim();
|
||
var jumlah = parseInt(document.getElementById("kem-jumlah").value, 10);
|
||
var alamat = document.getElementById("kem-alamat").value.trim();
|
||
var status = document.getElementById("kem-status").value;
|
||
var lat = document.getElementById("kem-lat").value.trim();
|
||
var lng = document.getElementById("kem-lng").value.trim();
|
||
|
||
if (!nama) { window.showToast("Nama kepala keluarga wajib diisi.", "error"); return; }
|
||
if (!Number.isInteger(jumlah) || jumlah < 1) { window.showToast("Jumlah KK harus minimal 1.", "error"); return; }
|
||
if (!lat || isNaN(Number(lat)) || Number(lat) < -90 || Number(lat) > 90) {
|
||
window.showToast("Latitude harus berupa angka antara -90 dan 90.", "error"); return;
|
||
}
|
||
if (!lng || isNaN(Number(lng)) || Number(lng) < -180 || Number(lng) > 180) {
|
||
window.showToast("Longitude harus berupa angka antara -180 dan 180.", "error"); return;
|
||
}
|
||
if (!alamat) { window.showToast("Alamat wajib diisi.", "error"); return; }
|
||
|
||
btn.disabled = true; btn.textContent = "Menyimpan...";
|
||
try {
|
||
await window.postForm("php/create_kemiskinan.php", {
|
||
nama_kepala_keluarga: nama, jumlah_kk: jumlah, alamat: alamat,
|
||
status_keluarga: status,
|
||
lat: Number(lat).toFixed(6), lng: Number(lng).toFixed(6)
|
||
});
|
||
window.closeModal("kemiskinan");
|
||
await window.loadAllData();
|
||
window.showToast("Data berhasil disimpan.", "success");
|
||
} catch (err) {
|
||
window.showToast("Gagal: " + err.message, "error");
|
||
} finally {
|
||
btn.disabled = false; btn.textContent = "Simpan";
|
||
}
|
||
};
|
||
|
||
/* ── Modal: Masjid ── */
|
||
window.openMasjidModal = function (lat, lng) {
|
||
var latVal = Number(lat).toFixed(6);
|
||
var lngVal = Number(lng).toFixed(6);
|
||
document.getElementById("msj-lat").value = latVal;
|
||
document.getElementById("msj-lng").value = lngVal;
|
||
document.getElementById("msj-jenis").value = "masjid";
|
||
document.getElementById("msj-nama").value = "";
|
||
document.getElementById("msj-pic").value = "";
|
||
document.getElementById("msj-radius").value = "500";
|
||
|
||
var alamatInput = document.getElementById("msj-alamat");
|
||
alamatInput.value = "";
|
||
alamatInput.placeholder = "Mencari alamat...";
|
||
alamatInput.dataset.geoLat = latVal;
|
||
alamatInput.dataset.geoLng = lngVal;
|
||
|
||
fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${latVal}&lon=${lngVal}&accept-language=id`)
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
if (alamatInput.dataset.geoLat === latVal && alamatInput.dataset.geoLng === lngVal) {
|
||
if (data && data.display_name) {
|
||
alamatInput.value = data.display_name;
|
||
} else {
|
||
alamatInput.placeholder = "Gagal memuat alamat. Silakan isi manual.";
|
||
}
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error("Reverse geocoding failed", err);
|
||
if (alamatInput.dataset.geoLat === latVal && alamatInput.dataset.geoLng === lngVal) {
|
||
alamatInput.placeholder = "Gagal memuat alamat. Silakan isi manual.";
|
||
}
|
||
});
|
||
|
||
var overlay = document.getElementById("modal-masjid");
|
||
overlay.style.display = "flex";
|
||
document.getElementById("msj-nama").focus();
|
||
overlay.onclick = function (e) { if (e.target === overlay) window.closeModal("masjid"); };
|
||
};
|
||
|
||
window._submitMasjid = async function (event) {
|
||
if (event && event.preventDefault) event.preventDefault();
|
||
var btn = document.getElementById("btn-submit-masjid");
|
||
var jenis = document.getElementById("msj-jenis").value;
|
||
var nama = document.getElementById("msj-nama").value.trim();
|
||
var pic = document.getElementById("msj-pic").value.trim();
|
||
var alamat = document.getElementById("msj-alamat").value.trim();
|
||
var radius = parseInt(document.getElementById("msj-radius").value, 10);
|
||
var lat = document.getElementById("msj-lat").value.trim();
|
||
var lng = document.getElementById("msj-lng").value.trim();
|
||
|
||
if (!nama) { window.showToast("Nama rumah ibadah wajib diisi.", "error"); return; }
|
||
if (!pic) { window.showToast("PIC wajib diisi.", "error"); return; }
|
||
if (!lat || isNaN(Number(lat)) || Number(lat) < -90 || Number(lat) > 90) {
|
||
window.showToast("Latitude harus berupa angka antara -90 dan 90.", "error"); return;
|
||
}
|
||
if (!lng || isNaN(Number(lng)) || Number(lng) < -180 || Number(lng) > 180) {
|
||
window.showToast("Longitude harus berupa angka antara -180 dan 180.", "error"); return;
|
||
}
|
||
if (!alamat) { window.showToast("Alamat wajib diisi.", "error"); return; }
|
||
if (!Number.isInteger(radius) || radius < 100 || radius > 5000) {
|
||
window.showToast("Radius harus antara 100–5000 m.", "error"); return;
|
||
}
|
||
btn.disabled = true; btn.textContent = "Menyimpan...";
|
||
try {
|
||
await window.postForm("php/create_masjid.php", {
|
||
jenis_ibadah: jenis, nama_masjid: nama, pic_masjid: pic, alamat: alamat,
|
||
radius: radius, lat: Number(lat).toFixed(6), lng: Number(lng).toFixed(6)
|
||
});
|
||
window.closeModal("masjid");
|
||
await window.loadAllData();
|
||
window.showToast("Rumah ibadah berhasil disimpan.", "success");
|
||
} catch (err) {
|
||
window.showToast("Gagal: " + err.message, "error");
|
||
} finally {
|
||
btn.disabled = false; btn.textContent = "Simpan";
|
||
}
|
||
};
|
||
|
||
window.closeModal = function (type) {
|
||
var overlay = document.getElementById("modal-" + type);
|
||
if (overlay) overlay.style.display = "none";
|
||
};
|
||
|
||
/* ── Modal: Edit Kemiskinan ── */
|
||
window.openEditKemiskinanModal = function (item) {
|
||
document.getElementById("edit-kem-id").value = item.id;
|
||
document.getElementById("edit-kem-nama").value = item.nama_kepala_keluarga;
|
||
document.getElementById("edit-kem-jumlah").value = item.jumlah_kk;
|
||
document.getElementById("edit-kem-alamat").value = item.alamat;
|
||
document.getElementById("edit-kem-status").value = item.status_keluarga || 'aktif';
|
||
|
||
var overlay = document.getElementById("modal-edit-kemiskinan");
|
||
overlay.style.display = "flex";
|
||
document.getElementById("edit-kem-nama").focus();
|
||
overlay.onclick = function (e) { if (e.target === overlay) window.closeModal("edit-kemiskinan"); };
|
||
};
|
||
|
||
window._submitEditKemiskinan = async function (event) {
|
||
if (event && event.preventDefault) event.preventDefault();
|
||
var btn = document.getElementById("btn-submit-edit-kemiskinan");
|
||
var id = document.getElementById("edit-kem-id").value;
|
||
var nama = document.getElementById("edit-kem-nama").value.trim();
|
||
var jumlah = parseInt(document.getElementById("edit-kem-jumlah").value, 10);
|
||
var alamat = document.getElementById("edit-kem-alamat").value.trim();
|
||
var status = document.getElementById("edit-kem-status").value;
|
||
|
||
if (!nama) { window.showToast("Nama wajib diisi.", "error"); return; }
|
||
if (!Number.isInteger(jumlah) || jumlah < 1) { window.showToast("Jumlah KK minimal 1.", "error"); return; }
|
||
if (!alamat) { window.showToast("Alamat wajib diisi.", "error"); return; }
|
||
|
||
btn.disabled = true; btn.textContent = "Menyimpan...";
|
||
try {
|
||
await window.postForm("php/update_kemiskinan.php", {
|
||
id, nama_kepala_keluarga: nama, jumlah_kk: jumlah, alamat, status_keluarga: status
|
||
});
|
||
window.closeModal("edit-kemiskinan");
|
||
await window.loadAllData();
|
||
window.showToast("Data berhasil diperbarui.", "success");
|
||
if (window._currentDetailKemiskinanId === parseInt(id)) {
|
||
var updatedItem = Object.assign({}, window._currentDetailItem, { nama_kepala_keluarga: nama, jumlah_kk: jumlah, alamat, status_keluarga: status });
|
||
window.openDetailPanel(updatedItem);
|
||
}
|
||
} catch (err) {
|
||
window.showToast("Gagal: " + err.message, "error");
|
||
} finally {
|
||
btn.disabled = false; btn.textContent = "Simpan Perubahan";
|
||
}
|
||
};
|
||
|
||
/* ── Modal: Edit Rumah Ibadah ── */
|
||
window.openEditMasjidModal = function (item) {
|
||
document.getElementById("edit-msj-id").value = item.id;
|
||
document.getElementById("edit-msj-jenis").value = item.jenis_ibadah || 'masjid';
|
||
document.getElementById("edit-msj-nama").value = item.nama_masjid;
|
||
document.getElementById("edit-msj-pic").value = item.pic_masjid;
|
||
document.getElementById("edit-msj-alamat").value = item.alamat;
|
||
|
||
var overlay = document.getElementById("modal-edit-masjid");
|
||
overlay.style.display = "flex";
|
||
document.getElementById("edit-msj-nama").focus();
|
||
overlay.onclick = function (e) { if (e.target === overlay) window.closeModal("edit-masjid"); };
|
||
};
|
||
|
||
window._submitEditMasjid = async function (event) {
|
||
if (event && event.preventDefault) event.preventDefault();
|
||
var btn = document.getElementById("btn-submit-edit-masjid");
|
||
var id = document.getElementById("edit-msj-id").value;
|
||
var jenis = document.getElementById("edit-msj-jenis").value;
|
||
var nama = document.getElementById("edit-msj-nama").value.trim();
|
||
var pic = document.getElementById("edit-msj-pic").value.trim();
|
||
var alamat = document.getElementById("edit-msj-alamat").value.trim();
|
||
|
||
if (!nama) { window.showToast("Nama rumah ibadah wajib diisi.", "error"); return; }
|
||
if (!pic) { window.showToast("PIC wajib diisi.", "error"); return; }
|
||
if (!alamat) { window.showToast("Alamat wajib diisi.", "error"); return; }
|
||
|
||
btn.disabled = true; btn.textContent = "Menyimpan...";
|
||
try {
|
||
await window.postForm("php/update_masjid.php", { id, jenis_ibadah: jenis, nama_masjid: nama, pic_masjid: pic, alamat });
|
||
window.closeModal("edit-masjid");
|
||
await window.loadAllData();
|
||
window.showToast("Data rumah ibadah diperbarui.", "success");
|
||
} catch (err) {
|
||
window.showToast("Gagal: " + err.message, "error");
|
||
} finally {
|
||
btn.disabled = false; btn.textContent = "Simpan Perubahan";
|
||
}
|
||
};
|
||
|
||
/* ── Fetch helper ── */
|
||
window.fetchJson = async function (url, fallback) {
|
||
var response = await fetch(url, { cache: "no-store" });
|
||
var text = await response.text();
|
||
if (!response.ok) { console.error("HTTP " + response.status, url); return fallback !== undefined ? fallback : []; }
|
||
if (!text.trim()) { return fallback !== undefined ? fallback : []; }
|
||
try { return JSON.parse(text); } catch (e) { console.error("JSON parse:", e); return fallback !== undefined ? fallback : []; }
|
||
};
|
||
|
||
/* ── Delete ── */
|
||
window.deleteRecord = async function (url, id, label) {
|
||
if (window.appState.mode !== "edit") { window.showToast("Aktifkan Mode Edit untuk menghapus.", "error"); return; }
|
||
if (!confirm("Hapus data " + label + "? Tidak dapat dibatalkan.")) return;
|
||
try {
|
||
await window.postForm(url, { id });
|
||
await window.loadAllData();
|
||
window.showToast("Data dihapus.", "success");
|
||
} catch (err) { window.showToast("Gagal: " + err.message, "error"); }
|
||
};
|
||
|
||
/* ── Update radius ── */
|
||
window.updateMasjidRadiusFromCard = async function (masjidId, inputEl, circle, btnEl) {
|
||
if (window.appState.mode !== "edit") { window.showToast("Aktifkan Mode Edit.", "error"); return; }
|
||
var radius = parseInt(inputEl.value, 10);
|
||
if (!Number.isInteger(radius) || radius < 100 || radius > 5000) {
|
||
window.showToast("Radius harus 100–5000 m.", "error"); return;
|
||
}
|
||
btnEl.disabled = true; btnEl.textContent = "...";
|
||
try {
|
||
await window.postForm("php/update_masjid_radius.php", { id: masjidId, radius });
|
||
if (circle) circle.setRadius(radius);
|
||
window.showToast("Radius diperbarui: " + radius + " m.", "success");
|
||
await window.loadAllData();
|
||
} catch (err) {
|
||
window.showToast("Gagal: " + err.message, "error");
|
||
btnEl.disabled = false; btnEl.textContent = "Simpan";
|
||
}
|
||
};
|
||
|
||
/* ── Layer filter section ── */
|
||
window.createLayerFilterSection = function () {
|
||
var section = document.createElement("div");
|
||
section.className = "sec";
|
||
|
||
var hd = document.createElement("div");
|
||
hd.className = "sec-hd";
|
||
hd.innerHTML = '<span class="sec-hd-label">Filter Layer</span>';
|
||
section.appendChild(hd);
|
||
|
||
var filters = [
|
||
{ key: "kemiskinan", label: "Keluarga Prasejahtera", color: "#ef4444" },
|
||
{ key: "masjid", label: "Masjid / Rumah Ibadah", color: "#3b82f6" }
|
||
];
|
||
filters.forEach(function (f) {
|
||
var row = document.createElement("label");
|
||
row.className = "filter-row";
|
||
var cb = document.createElement("input");
|
||
cb.type = "checkbox"; cb.dataset.layerKey = f.key;
|
||
cb.checked = !!window.appState.layerVisibility[f.key];
|
||
cb.onchange = function () { window.setLayerVisibility(f.key, cb.checked); };
|
||
var dot = document.createElement("span");
|
||
dot.className = "filter-dot"; dot.style.background = f.color;
|
||
var txt = document.createElement("span"); txt.textContent = f.label;
|
||
row.appendChild(cb); row.appendChild(dot); row.appendChild(txt);
|
||
section.appendChild(row);
|
||
});
|
||
return section;
|
||
};
|
||
|
||
window.refreshLayerFilterUI = function () {
|
||
document.querySelectorAll("input[data-layer-key]").forEach(function (cb) {
|
||
cb.checked = !!window.appState.layerVisibility[cb.dataset.layerKey];
|
||
});
|
||
};
|
||
|
||
/* ── loadAllData ── */
|
||
window.loadAllData = async function () {
|
||
var sidebarBody = document.getElementById("sidebar-body");
|
||
var sidebarSub = document.getElementById("sidebar-sub");
|
||
if (!sidebarBody || !window.map) return;
|
||
|
||
sidebarBody.innerHTML = '<div class="loading">Memuat data...</div>';
|
||
if (sidebarSub) sidebarSub.textContent = 'Memuat...';
|
||
|
||
if (window.appState.layers.kemiskinan) window.appState.layers.kemiskinan.clearLayers();
|
||
if (window.appState.layers.masjid) window.appState.layers.masjid.clearLayers();
|
||
|
||
try {
|
||
var results = await Promise.all([
|
||
window.fetchJson("php/read_kemiskinan.php", []),
|
||
window.fetchJson("php/read_masjid.php", [])
|
||
]);
|
||
var dataKem = results[0];
|
||
var dataMsj = results[1];
|
||
|
||
var totalKeluarga = 0;
|
||
var perluBantuan = 0;
|
||
var countMasjid = 0, countGereja = 0, countVihara = 0;
|
||
var totalJiwa = 0;
|
||
var keluargaMentas = 0;
|
||
var heatData = [];
|
||
|
||
if (dataMsj && Array.isArray(dataMsj)) {
|
||
dataMsj.forEach(function(m) {
|
||
var j = (m.jenis_ibadah || 'masjid').toLowerCase();
|
||
if(j === 'masjid') countMasjid++;
|
||
else if(j === 'gereja') countGereja++;
|
||
else if(j === 'vihara') countVihara++;
|
||
});
|
||
}
|
||
|
||
if (dataKem && Array.isArray(dataKem)) {
|
||
dataKem.forEach(function(item) {
|
||
if (!window.isValidCoordinate(item.latitude, item.longitude)) return;
|
||
totalKeluarga++;
|
||
|
||
// Add jiwa count
|
||
totalJiwa += parseInt(item.jumlah_kk) || 0;
|
||
|
||
var kemLL = L.latLng(item.latitude, item.longitude);
|
||
var status = item.status_keluarga || 'aktif';
|
||
|
||
if (status === 'sudah_mampu') {
|
||
keluargaMentas++;
|
||
}
|
||
|
||
var isIn = false;
|
||
if (dataMsj && dataMsj.length) {
|
||
for (var i = 0; i < dataMsj.length; i++) {
|
||
var m = dataMsj[i], r = Number(m.radius);
|
||
if (window.isValidCoordinate(m.latitude, m.longitude) && window.isValidRadius(r)) {
|
||
if (window.map.distance(kemLL, L.latLng(m.latitude, m.longitude)) <= r) {
|
||
isIn = true; break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (!isIn && status === 'aktif') {
|
||
perluBantuan++;
|
||
var lat = parseFloat(item.latitude);
|
||
var lng = parseFloat(item.longitude);
|
||
if (!isNaN(lat) && !isNaN(lng)) {
|
||
heatData.push([lat, lng, 100]); // Use higher intensity
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Render Heatmap
|
||
if (window.appState.layers.heatmap) {
|
||
window.appState.layers.heatmap.clearLayers();
|
||
if (heatData.length > 0 && typeof L.heatLayer === 'function') {
|
||
var heat = L.heatLayer(heatData, {
|
||
radius: 35,
|
||
blur: 25,
|
||
maxZoom: 15,
|
||
max: 100,
|
||
gradient: {0.4: 'blue', 0.6: 'lime', 0.8: 'yellow', 1.0: 'red'}
|
||
});
|
||
heat.addTo(window.appState.layers.heatmap);
|
||
}
|
||
}
|
||
|
||
var statTotalEl = document.getElementById('stat-total-keluarga');
|
||
var statPerluEl = document.getElementById('stat-perlu-bantuan');
|
||
var statJiwaEl = document.getElementById('stat-total-jiwa');
|
||
var statMentasEl = document.getElementById('stat-keluarga-mentas');
|
||
var statProgText = document.getElementById('stat-progress-text');
|
||
var statProgFill = document.getElementById('stat-progress-fill');
|
||
|
||
if (statTotalEl) statTotalEl.textContent = totalKeluarga;
|
||
if (statPerluEl) statPerluEl.textContent = perluBantuan;
|
||
if (statJiwaEl) statJiwaEl.textContent = totalJiwa;
|
||
if (statMentasEl) statMentasEl.textContent = keluargaMentas;
|
||
|
||
if (statProgText && statProgFill) {
|
||
var pct = 0;
|
||
if (totalKeluarga > 0) {
|
||
var terjangkau = totalKeluarga - perluBantuan;
|
||
pct = Math.round((terjangkau / totalKeluarga) * 100);
|
||
}
|
||
statProgText.textContent = pct + '%';
|
||
statProgFill.style.width = pct + '%';
|
||
}
|
||
|
||
var sm = document.getElementById('stat-masjid');
|
||
var sg = document.getElementById('stat-gereja');
|
||
var sv = document.getElementById('stat-vihara');
|
||
if(sm) sm.textContent = countMasjid;
|
||
if(sg) sg.textContent = countGereja;
|
||
if(sv) sv.textContent = countVihara;
|
||
|
||
if (sidebarSub) {
|
||
var hint = window.appState.mode === "edit"
|
||
? "Mode Edit — klik peta untuk tambah data"
|
||
: "Mode Lihat — klik Detail untuk info lengkap";
|
||
sidebarSub.textContent = hint;
|
||
}
|
||
|
||
sidebarBody.innerHTML = '';
|
||
|
||
var divider = document.createElement('div');
|
||
divider.className = 'sec-divider';
|
||
sidebarBody.appendChild(divider);
|
||
|
||
var secKem = window.renderKemiskinan(dataKem, dataMsj);
|
||
secKem.id = 'sec-kemiskinan';
|
||
var secMsj = window.renderMasjid(dataMsj);
|
||
secMsj.id = 'sec-masjid';
|
||
|
||
sidebarBody.appendChild(secKem);
|
||
sidebarBody.appendChild(secMsj);
|
||
|
||
if (typeof window.filterSidebar === 'function') {
|
||
window.filterSidebar('semua');
|
||
}
|
||
|
||
} catch (err) {
|
||
sidebarBody.innerHTML = '<div class="empty">Terjadi kendala saat membaca data.<br>' + window.escapeHtml(err.message) + '</div>';
|
||
console.error(err);
|
||
}
|
||
};
|
||
|
||
/* ── Render: Kemiskinan ── */
|
||
window.renderKemiskinan = function (dataKem, dataMsj) {
|
||
var sec = document.createElement('div');
|
||
sec.className = 'sec';
|
||
|
||
var hd = document.createElement('div');
|
||
hd.className = 'sec-hd';
|
||
hd.innerHTML = '<span class="sec-hd-label">Keluarga Prasejahtera</span>' +
|
||
'<span class="sec-count">' + dataKem.length + '</span>';
|
||
sec.appendChild(hd);
|
||
|
||
if (!dataKem.length) {
|
||
var empty = document.createElement('div');
|
||
empty.className = 'empty';
|
||
empty.textContent = 'Belum ada data. Aktifkan Mode Edit dan klik peta.';
|
||
sec.appendChild(empty);
|
||
return sec;
|
||
}
|
||
|
||
dataKem.forEach(function (item) {
|
||
if (!window.isValidCoordinate(item.latitude, item.longitude)) return;
|
||
|
||
var kemLL = L.latLng(item.latitude, item.longitude);
|
||
var status = item.status_keluarga || 'aktif';
|
||
var isIn = false;
|
||
|
||
if (dataMsj && dataMsj.length) {
|
||
for (var i = 0; i < dataMsj.length; i++) {
|
||
var m = dataMsj[i], r = Number(m.radius);
|
||
if (window.isValidCoordinate(m.latitude, m.longitude) && window.isValidRadius(r)) {
|
||
if (window.map.distance(kemLL, L.latLng(m.latitude, m.longitude)) <= r) {
|
||
isIn = true; break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
var icon = isIn ? window.greenIcon : window.redIcon;
|
||
if (status !== 'aktif') icon = window.orangeIcon;
|
||
|
||
var marker = L.marker([item.latitude, item.longitude], { icon, searchName: (item.nama_kepala_keluarga || '').toLowerCase() })
|
||
.addTo(window.appState.layers.kemiskinan)
|
||
.bindPopup(
|
||
'<b>' + window.escapeHtml(item.nama_kepala_keluarga) + '</b><br>' +
|
||
'Status: ' + (window.labelStatusKeluarga[status] || status) + '<br>' +
|
||
'Anggota: ' + item.jumlah_kk + ' jiwa<br>' +
|
||
window.escapeHtml(item.alamat)
|
||
);
|
||
|
||
marker.on('click', function(e) {
|
||
if (window.appState && window.appState.isRouting) {
|
||
window.handleRoutingClick(item.latitude, item.longitude, item.nama_kepala_keluarga);
|
||
marker.closePopup();
|
||
}
|
||
});
|
||
|
||
var card = document.createElement('div');
|
||
card.dataset.searchName = (item.nama_kepala_keluarga || '').toLowerCase();
|
||
card.className = 'card' +
|
||
(isIn ? ' in-radius' : ' out-radius') +
|
||
(status === 'meninggal' ? ' st-meninggal' : '') +
|
||
(status === 'pindah' ? ' st-pindah' : '') +
|
||
(status === 'sudah_mampu' ? ' st-mampu' : '');
|
||
|
||
var chipClass = isIn ? 'chip-green' : 'chip-red';
|
||
if (status === 'meninggal') chipClass = 'chip-gray';
|
||
if (status === 'pindah') chipClass = 'chip-amber';
|
||
if (status === 'sudah_mampu') chipClass = 'chip-green';
|
||
|
||
var chipText = isIn ? 'Terjangkau' : 'Luar Radius';
|
||
if (status !== 'aktif') chipText = window.labelStatusKeluarga[status] || status;
|
||
|
||
var updTs = item.updated_at_fmt ? '<div class="card-ts"><i class="fa-regular fa-clock"></i> ' + item.updated_at_fmt + '</div>' : '';
|
||
|
||
card.innerHTML =
|
||
'<div class="card-name">' + window.escapeHtml(item.nama_kepala_keluarga) + '</div>' +
|
||
'<div class="card-sub">' + item.jumlah_kk + ' anggota keluarga</div>' +
|
||
'<div class="card-addr">' + window.escapeHtml(item.alamat) + '</div>' +
|
||
updTs;
|
||
|
||
var foot = document.createElement('div');
|
||
foot.className = 'card-foot';
|
||
|
||
var chip = document.createElement('span');
|
||
chip.className = 'chip ' + chipClass;
|
||
chip.innerHTML = chipText;
|
||
foot.appendChild(chip);
|
||
|
||
var btns = document.createElement('div');
|
||
btns.className = 'card-btns';
|
||
|
||
var btnF = document.createElement('button');
|
||
btnF.className = 'btn btn-focus'; btnF.innerHTML = '<i class="fa-solid fa-location-dot"></i>';
|
||
btnF.title = 'Fokus ke peta';
|
||
btnF.onclick = (function(it, mk){ return function(e){
|
||
e.stopPropagation();
|
||
window.map.setView([it.latitude, it.longitude], 17);
|
||
mk.openPopup();
|
||
}; })(item, marker);
|
||
btns.appendChild(btnF);
|
||
|
||
var btnD = document.createElement('button');
|
||
btnD.className = 'btn btn-detail'; btnD.innerHTML = '<i class="fa-solid fa-eye"></i> Detail';
|
||
btnD.onclick = (function(it){ return function(e){
|
||
e.stopPropagation(); window.openDetailPanel(it);
|
||
}; })(item);
|
||
btns.appendChild(btnD);
|
||
|
||
var btnL = document.createElement('button');
|
||
btnL.className = 'btn btn-lapor'; btnL.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i>';
|
||
btnL.title = 'Laporkan kondisi';
|
||
btnL.onclick = (function(it){ return function(e){
|
||
e.stopPropagation(); window.openLaporanPublikModal(it.id, it.nama_kepala_keluarga);
|
||
}; })(item);
|
||
btns.appendChild(btnL);
|
||
|
||
if (window.appAuth && window.appAuth.role === 'pengurus_masjid') {
|
||
var btnE = document.createElement('button');
|
||
btnE.className = 'btn btn-edit'; btnE.innerHTML = '<i class="fa-solid fa-pen"></i>';
|
||
btnE.title = 'Edit data';
|
||
btnE.disabled = window.appState.mode !== 'edit';
|
||
btnE.onclick = (function(it){ return function(e){
|
||
e.stopPropagation(); window.openEditKemiskinanModal(it);
|
||
}; })(item);
|
||
btns.appendChild(btnE);
|
||
|
||
var btnH = document.createElement('button');
|
||
btnH.className = 'btn btn-delete'; btnH.innerHTML = '<i class="fa-solid fa-trash"></i>';
|
||
btnH.title = 'Hapus data';
|
||
btnH.disabled = window.appState.mode !== 'edit';
|
||
btnH.onclick = (function(it){ return function(e){
|
||
e.stopPropagation(); window.deleteRecord('php/delete_kemiskinan.php', it.id, 'Kemiskinan');
|
||
}; })(item);
|
||
btns.appendChild(btnH);
|
||
}
|
||
|
||
foot.appendChild(btns);
|
||
card.appendChild(foot);
|
||
sec.appendChild(card);
|
||
});
|
||
|
||
return sec;
|
||
};
|
||
|
||
/* ── Jenis ibadah helpers ── */
|
||
window._jenisIbadahEmoji = {
|
||
masjid: '<i class="fa-solid fa-mosque"></i>', gereja: '<i class="fa-solid fa-church"></i>', vihara: '<i class="fa-solid fa-vihara"></i>', pura: '<i class="fa-solid fa-om"></i>',
|
||
klenteng: '<i class="fa-solid fa-vihara"></i>', kapel: '<i class="fa-solid fa-church"></i>', lainnya: '<i class="fa-solid fa-place-of-worship"></i>'
|
||
};
|
||
window._jenisIbadahLabel = {
|
||
masjid: 'Masjid', gereja: 'Gereja', vihara: 'Vihara', pura: 'Pura',
|
||
klenteng: 'Klenteng', kapel: 'Kapel', lainnya: 'Rumah Ibadah'
|
||
};
|
||
window._jenisIbadahColor = {
|
||
masjid: '#1d4ed8', gereja: '#7c3aed', vihara: '#b45309',
|
||
pura: '#b91c1c', klenteng: '#b45309', kapel: '#4338ca', lainnya: '#6b7280'
|
||
};
|
||
window._jenisIbadahFill = {
|
||
masjid: '#93c5fd', gereja: '#c4b5fd', vihara: '#fcd34d',
|
||
pura: '#fca5a5', klenteng: '#fcd34d', kapel: '#a5b4fc', lainnya: '#d1d5db'
|
||
};
|
||
|
||
/* ── Render: Rumah Ibadah ── */
|
||
window.renderMasjid = function (dataMsj) {
|
||
var sec = document.createElement('div');
|
||
sec.className = 'sec';
|
||
|
||
var hd = document.createElement('div');
|
||
hd.className = 'sec-hd';
|
||
hd.innerHTML = '<span class="sec-hd-label">Rumah Ibadah</span>' +
|
||
'<span class="sec-count">' + dataMsj.length + '</span>';
|
||
sec.appendChild(hd);
|
||
|
||
if (!dataMsj.length) {
|
||
var empty = document.createElement('div');
|
||
empty.className = 'empty';
|
||
empty.textContent = 'Belum ada data. Aktifkan Mode Edit dan klik peta.';
|
||
sec.appendChild(empty);
|
||
return sec;
|
||
}
|
||
|
||
dataMsj.forEach(function (item) {
|
||
var radius = Number(item.radius);
|
||
if (!window.isValidCoordinate(item.latitude, item.longitude) || !window.isValidRadius(radius)) return;
|
||
|
||
var jenis = item.jenis_ibadah || 'masjid';
|
||
var emoji = window._jenisIbadahEmoji[jenis] || '<i class="fa-solid fa-place-of-worship"></i>';
|
||
var label = window._jenisIbadahLabel[jenis] || 'Rumah Ibadah';
|
||
var color = window._jenisIbadahColor[jenis] || '#6b7280';
|
||
var fill = window._jenisIbadahFill[jenis] || '#d1d5db';
|
||
|
||
/* Ikon pin warna sesuai jenis */
|
||
var pinIcon = window.createPinIcon(color,
|
||
'<text x="16" y="19" text-anchor="middle" font-size="11" fill="white" font-family="Arial">&#' +
|
||
({ masjid: 128332, gereja: 9962, vihara: 127983, pura: 128469, klenteng: 127982, kapel: 9769, lainnya: 127963 }[jenis] || 127963) +
|
||
';</text>'
|
||
);
|
||
|
||
var popup = '<b>' + emoji + ' ' + window.escapeHtml(item.nama_masjid) + '</b><br>' +
|
||
'Jenis: ' + label + '<br>' +
|
||
'PIC: ' + window.escapeHtml(item.pic_masjid) + '<br>' +
|
||
'Radius: ' + window.formatMeters(radius);
|
||
|
||
var circle = L.circle([item.latitude, item.longitude], {
|
||
radius, color, fillColor: fill,
|
||
fillOpacity: 0.12, weight: 1.5,
|
||
interactive: false /* ← jangan tangkap klik peta, biarkan map.on('click') jalan */
|
||
}).addTo(window.appState.layers.masjid);
|
||
|
||
var marker = L.marker([item.latitude, item.longitude], {
|
||
icon: pinIcon,
|
||
searchName: (item.nama_masjid || '').toLowerCase(),
|
||
type: 'masjid'
|
||
})
|
||
.addTo(window.appState.layers.masjid).bindPopup(popup);
|
||
|
||
marker.on('click', function(e) {
|
||
if (window.appState && window.appState.isRouting) {
|
||
window.handleRoutingClick(item.latitude, item.longitude, item.nama_masjid);
|
||
marker.closePopup();
|
||
}
|
||
});
|
||
|
||
var card = document.createElement('div');
|
||
card.dataset.searchName = (item.nama_masjid || '').toLowerCase();
|
||
card.dataset.type = 'masjid';
|
||
card.className = 'card masjid-card';
|
||
|
||
card.innerHTML =
|
||
'<div class="card-name">' + emoji + ' ' + window.escapeHtml(item.nama_masjid) + '</div>' +
|
||
'<div class="card-sub">PIC: ' + window.escapeHtml(item.pic_masjid) + '</div>' +
|
||
'<div class="card-addr">' + window.escapeHtml(item.alamat) + '</div>';
|
||
|
||
/* Radius row */
|
||
var canEdit = window.appAuth && window.appAuth.role === 'pengurus_masjid';
|
||
var rr = document.createElement('div');
|
||
rr.className = 'radius-row';
|
||
rr.innerHTML = '<label>Radius</label>';
|
||
var ri = document.createElement('input');
|
||
ri.type = 'number'; ri.min = '100'; ri.max = '5000';
|
||
ri.value = Math.round(radius);
|
||
ri.disabled = !canEdit || window.appState.mode !== 'edit';
|
||
var ru = document.createElement('span');
|
||
ru.className = 'radius-unit'; ru.textContent = 'm';
|
||
var rb = document.createElement('button');
|
||
rb.className = 'btn btn-update'; rb.textContent = 'Simpan';
|
||
rb.disabled = !canEdit || window.appState.mode !== 'edit';
|
||
rb.onclick = (function(mid, rinput, ci, rbt){ return function(e){
|
||
e.stopPropagation(); window.updateMasjidRadiusFromCard(mid, rinput, ci, rbt);
|
||
}; })(item.id, ri, circle, rb);
|
||
rr.appendChild(ri); rr.appendChild(ru); rr.appendChild(rb);
|
||
card.appendChild(rr);
|
||
|
||
var foot = document.createElement('div');
|
||
foot.className = 'card-foot';
|
||
|
||
var chip = document.createElement('span');
|
||
chip.className = 'chip chip-blue';
|
||
chip.innerHTML = emoji + ' ' + label;
|
||
chip.style.background = fill;
|
||
chip.style.color = color;
|
||
chip.style.border = '1px solid ' + color + '40';
|
||
foot.appendChild(chip);
|
||
|
||
var btns = document.createElement('div');
|
||
btns.className = 'card-btns';
|
||
|
||
var btnF = document.createElement('button');
|
||
btnF.className = 'btn btn-focus'; btnF.innerHTML = '<i class="fa-solid fa-location-dot"></i>';
|
||
btnF.title = 'Fokus ke peta';
|
||
btnF.onclick = (function(ci, mk){ return function(e){
|
||
e.stopPropagation(); window.map.fitBounds(ci.getBounds(), { padding:[40,40] }); mk.openPopup();
|
||
}; })(circle, marker);
|
||
btns.appendChild(btnF);
|
||
|
||
if (canEdit) {
|
||
var btnE = document.createElement('button');
|
||
btnE.className = 'btn btn-edit'; btnE.innerHTML = '<i class="fa-solid fa-pen"></i>';
|
||
btnE.title = 'Edit';
|
||
btnE.disabled = window.appState.mode !== 'edit';
|
||
btnE.onclick = (function(it){ return function(e){ e.stopPropagation(); window.openEditMasjidModal(it); }; })(item);
|
||
btns.appendChild(btnE);
|
||
|
||
var btnH = document.createElement('button');
|
||
btnH.className = 'btn btn-delete'; btnH.innerHTML = '<i class="fa-solid fa-trash"></i>';
|
||
btnH.title = 'Hapus';
|
||
btnH.disabled = window.appState.mode !== 'edit';
|
||
btnH.onclick = (function(it){ return function(e){ e.stopPropagation(); window.deleteRecord('php/delete_masjid.php', it.id, label); }; })(item);
|
||
btns.appendChild(btnH);
|
||
}
|
||
|
||
foot.appendChild(btns);
|
||
card.appendChild(foot);
|
||
sec.appendChild(card);
|
||
});
|
||
|
||
return sec;
|
||
};
|
||
|
||
/* ── Search Map Data ── */
|
||
window.searchMapData = function(query) {
|
||
var q = (query || '').toLowerCase().trim();
|
||
|
||
// Filter Kemiskinan
|
||
if (window.appState && window.appState.layers && window.appState.layers.kemiskinan) {
|
||
window.appState.layers.kemiskinan.eachLayer(function(layer) {
|
||
if(layer instanceof L.Marker && layer.options.searchName !== undefined) {
|
||
if(q === '' || layer.options.searchName.includes(q)) {
|
||
layer.setOpacity(1);
|
||
} else {
|
||
layer.setOpacity(0.15);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Filter Masjid
|
||
if (window.appState && window.appState.layers && window.appState.layers.masjid) {
|
||
window.appState.layers.masjid.eachLayer(function(layer) {
|
||
if(layer instanceof L.Marker && layer.options.searchName !== undefined) {
|
||
if(q === '' || layer.options.searchName.includes(q)) {
|
||
layer.setOpacity(1);
|
||
} else {
|
||
layer.setOpacity(0.15);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Filter Cards in Sidebar
|
||
var sidebarBody = document.getElementById('sidebar-body');
|
||
if (sidebarBody) {
|
||
var cards = sidebarBody.getElementsByClassName('card');
|
||
for (var i = 0; i < cards.length; i++) {
|
||
var cName = cards[i].dataset.searchName || '';
|
||
if (q === '' || cName.includes(q)) {
|
||
cards[i].style.display = 'block';
|
||
} else {
|
||
cards[i].style.display = 'none';
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/* ── Extra Filters ── */
|
||
window.toggleFilterPerluBantuan = function(isActive) {
|
||
if (window.appState && window.appState.layers && window.appState.layers.kemiskinan) {
|
||
window.appState.layers.kemiskinan.eachLayer(function(layer) {
|
||
if (layer instanceof L.Marker) {
|
||
// If filter is active, only show markers that are NOT 'in-radius' (which use the greenIcon or have a specific property).
|
||
// Wait, how do we know if it's in-radius? In loadData we assigned icon: window.greenIcon or window.redIcon.
|
||
// An easy way is to check the icon URL or just rely on the DOM cards. But markers are drawn.
|
||
// Let's check the layer.options.icon.options.iconUrl.
|
||
var isRed = layer.options.icon && layer.options.icon.options && layer.options.icon.options.iconUrl && layer.options.icon.options.iconUrl.includes('red');
|
||
if (isActive) {
|
||
if (isRed) layer.setOpacity(1);
|
||
else layer.setOpacity(0); // Hide completely
|
||
} else {
|
||
layer.setOpacity(1); // Restore
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// Filter Cards in Sidebar
|
||
var sidebarBody = document.getElementById('sidebar-body');
|
||
if (sidebarBody) {
|
||
var ObjectCards = sidebarBody.getElementsByClassName('card');
|
||
for (var i = 0; i < ObjectCards.length; i++) {
|
||
var c = ObjectCards[i];
|
||
// The card has class 'out-radius' if it's red
|
||
if (isActive) {
|
||
if (c.classList.contains('out-radius')) {
|
||
c.style.display = 'block';
|
||
} else {
|
||
// Don't hide masjid cards! Check if it's kemiskinan
|
||
if (!c.classList.contains('masjid-card')) {
|
||
c.style.display = 'none';
|
||
}
|
||
}
|
||
} else {
|
||
c.style.display = 'block';
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
/* ── Export Data ── */
|
||
window.exportToCSV = async function() {
|
||
Swal.fire({
|
||
title: 'Menyiapkan Laporan...',
|
||
text: 'Mohon tunggu, sistem sedang merangkum data dari database.',
|
||
allowOutsideClick: false,
|
||
didOpen: () => { Swal.showLoading(); }
|
||
});
|
||
|
||
try {
|
||
var response = await fetch('php/export_csv.php');
|
||
if (!response.ok) throw new Error('Gagal menghubungi server.');
|
||
|
||
var blob = await response.blob();
|
||
var url = window.URL.createObjectURL(blob);
|
||
var a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = "Data_Keluarga_Prasejahtera_GeoPoverty.csv";
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
a.remove();
|
||
window.URL.revokeObjectURL(url);
|
||
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Unduhan Berhasil!',
|
||
text: 'File laporan CSV telah tersimpan di komputermu.',
|
||
timer: 2500,
|
||
showConfirmButton: false
|
||
});
|
||
} catch (e) {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Ekspor Gagal',
|
||
text: 'Terjadi kesalahan: ' + e.message
|
||
});
|
||
}
|
||
};
|
||
|
||
/* ── Export Map PDF ── */
|
||
window.downloadMapPDF = async function() {
|
||
Swal.fire({
|
||
title: 'Mencetak Peta...',
|
||
text: 'Sistem sedang mengambil tangkapan layar peta. Mohon tunggu...',
|
||
allowOutsideClick: false,
|
||
didOpen: () => { Swal.showLoading(); }
|
||
});
|
||
|
||
try {
|
||
var mapElement = document.getElementById('map');
|
||
|
||
// Hide map controls (zoom, layers, dll) to make it clean
|
||
var controls = document.querySelectorAll('.leaflet-control-container');
|
||
controls.forEach(c => c.style.display = 'none');
|
||
|
||
// Capture map as JPEG
|
||
var rect = mapElement.getBoundingClientRect();
|
||
var imgData = await domtoimage.toJpeg(mapElement, {
|
||
quality: 0.95,
|
||
bgcolor: '#e2e8f0',
|
||
width: rect.width,
|
||
height: rect.height,
|
||
style: {
|
||
// Ensure no unexpected offset during render
|
||
transform: 'none',
|
||
left: '0',
|
||
top: '0',
|
||
margin: '0'
|
||
}
|
||
});
|
||
|
||
// Restore controls
|
||
controls.forEach(c => c.style.display = '');
|
||
|
||
// Setup jsPDF (Landscape A4)
|
||
var pdf = new jspdf.jsPDF('l', 'mm', 'a4');
|
||
var pdfWidth = pdf.internal.pageSize.getWidth();
|
||
var pdfHeight = pdf.internal.pageSize.getHeight();
|
||
|
||
var imgProps = pdf.getImageProperties(imgData);
|
||
var ratio = imgProps.width / imgProps.height;
|
||
|
||
var renderWidth = pdfWidth;
|
||
var renderHeight = pdfWidth / ratio;
|
||
|
||
if (renderHeight > pdfHeight) {
|
||
renderHeight = pdfHeight;
|
||
renderWidth = pdfHeight * ratio;
|
||
}
|
||
|
||
// Center image
|
||
var x = (pdfWidth - renderWidth) / 2;
|
||
var y = (pdfHeight - renderHeight) / 2;
|
||
|
||
pdf.addImage(imgData, 'JPEG', x, y, renderWidth, renderHeight);
|
||
pdf.save('Peta_GeoPoverty.pdf');
|
||
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Berhasil!',
|
||
text: 'Peta murni telah berhasil diunduh sebagai PDF.',
|
||
timer: 2500,
|
||
showConfirmButton: false
|
||
});
|
||
} catch(e) {
|
||
var controls = document.querySelectorAll('.leaflet-control-container');
|
||
controls.forEach(c => c.style.display = '');
|
||
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Gagal Mencetak',
|
||
text: 'Terjadi kesalahan saat mengekspor peta: ' + e.message
|
||
});
|
||
}
|
||
};
|