// ======================================== // FILE: js/main.js // Main JavaScript untuk Pemetaan Kemiskinan // ======================================== // ========== KONFIGURASI ========== const MAP_CENTER = [-0.0612, 109.3449]; // Koordinat pusat peta (Pontianak) const MAP_ZOOM = 12; // Tingkat perbesaran bawaan peta const API_PATH = 'php/'; // Jalur relatif menuju berkas API PHP let map; const markers = { masyarakat: [], ibadah: [], spbu: [] }; const layers = { jalan: L.layerGroup(), polygon: L.layerGroup() }; let current_tab = 'masyarakat'; const all_data = { masyarakat: [], ibadah: [], jalan: [], polygon: [], spbu: [] }; let drawnItems; // ========== ICON MARKER ========== const iconMasyarakat = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', shadowSize: [41, 41] }); const iconIbadah = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', shadowSize: [41, 41] }); // ========== UTILITAS KEAMANAN & FORMAT ========== /** * Mengamankan string teks dari potensi serangan injeksi XSS. * @param {string} str - String mentah yang akan dibersihkan. * @returns {string} String yang aman untuk direndering ke DOM. */ function escapeHTML(str) { if (str === null || str === undefined) return '-'; return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } /** * Melakukan validasi dasar terhadap respons HTTP Fetch sebelum diproses menjadi JSON. * @param {Response} response - Objek respons dari Fetch API. * @returns {Promise} Mengembalikan Promise berupa objek JSON jika sukses. */ function handleFetchResponse(response) { if (!response.ok) { throw new Error(`Gagal memuat data dari server (Status: ${response.status})`); } return response.json(); } // ========== INISIALISASI ========== document.addEventListener('DOMContentLoaded', function() { initMap(); loadData(); attachEventListeners(); // Check initial active tab from landing page const activeTab = localStorage.getItem('activeTab'); const accs = document.querySelectorAll('.accordion'); if (activeTab === 'fasilitas') { if (accs.length > 0) { accs[0].style.display = 'flex'; // Show Fasilitas if (accs.length > 1) accs[1].style.display = 'none'; // Hide Sosial if (accs.length > 2) accs[2].style.display = 'none'; // Hide Publik accs[0].classList.add('active'); accs[0].nextElementSibling.style.display = 'block'; const firstTab = accs[0].nextElementSibling.querySelector('.tab-button'); if (firstTab) firstTab.click(); } } else if (activeTab === 'sosial') { if (accs.length > 1) { if (accs.length > 0) accs[0].style.display = 'none'; // Hide Fasilitas accs[1].style.display = 'flex'; // Show Sosial if (accs.length > 2) accs[2].style.display = 'none'; // Hide Publik accs[1].classList.add('active'); accs[1].nextElementSibling.style.display = 'block'; const firstTab = accs[1].nextElementSibling.querySelector('.tab-button'); if (firstTab) firstTab.click(); } } else if (activeTab === 'publik') { // Mode Publik: Sembunyikan semua tombol Add dan Form Input document.querySelectorAll('.btn-primary').forEach(btn => { if(btn.textContent.includes('+')) btn.style.display = 'none'; }); document.querySelector('.leaflet-draw').style.display = 'none'; // Sembunyikan toolbar Leaflet Draw // Buka Layanan Publik (Accordion 3) if (accs.length > 0) accs[0].style.display = 'none'; if (accs.length > 1) accs[1].style.display = 'none'; if (accs.length > 2) { accs[2].style.display = 'flex'; accs[2].classList.add('active'); accs[2].nextElementSibling.style.display = 'block'; const firstTab = accs[2].nextElementSibling.querySelector('.tab-button'); if (firstTab) firstTab.click(); } // Tambahkan badge Portal Publik di sidebar jika belum ada if (!document.getElementById('badge-publik')) { const sidebar = document.getElementById('sidebar'); const badge = document.createElement('div'); badge.id = 'badge-publik'; badge.innerHTML = '
Mode Akses Publik
'; sidebar.insertBefore(badge, sidebar.children[2]); } } }); /** * Menginisialisasi objek peta Leaflet dan menambahkan event listener klik. */ function initMap() { map = L.map('map').setView(MAP_CENTER, MAP_ZOOM); L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap contributors' }).addTo(map); // LEAFLET DRAW drawnItems = new L.FeatureGroup(); map.addLayer(drawnItems); const drawControl = new L.Control.Draw({ edit: { featureGroup: drawnItems }, draw: { polyline: true, polygon: true, circle: false, marker: false, circlemarker: false, rectangle: false } }); map.addControl(drawControl); map.on(L.Draw.Event.CREATED, function (e) { const type = e.layerType; const layer = e.layer; const geojson = JSON.stringify(layer.toGeoJSON()); if (type === 'polyline') { openModal('modal-form-jalan'); setTimeout(() => { document.getElementById('geojson-jalan').value = geojson; }, 100); } else if (type === 'polygon') { openModal('modal-form-polygon'); setTimeout(() => { document.getElementById('geojson-polygon').value = geojson; }, 100); } }); // Klik peta untuk memunculkan pilihan tambah data map.on('click', function(e) { const lat = e.latlng.lat.toFixed(8); const lng = e.latlng.lng.toFixed(8); document.querySelectorAll('input[name="latitude"]').forEach(el => el.value = lat); document.querySelectorAll('input[name="longitude"]').forEach(el => el.value = lng); let buttonsHTML = ''; if (current_tab === 'masyarakat') { buttonsHTML = ``; } else if (current_tab === 'ibadah') { buttonsHTML = ``; } else if (current_tab === 'spbu') { buttonsHTML = ``; } else { buttonsHTML = `Silakan pilih tab yang sesuai (Warga, Ibadah, atau SPBU) di menu kiri terlebih dahulu.`; } // Buat konten popup pilihan const popupContent = `
Pilih Data untuk Ditambah ${lat}, ${lng}
${buttonsHTML}
`; L.popup() .setLatLng(e.latlng) .setContent(popupContent) .openOn(map); }); } /** * Memicu proses memuat seluruh data dari API secara paralel. */ function loadData() { loadMasyarakat(); loadRumahIbadah(); loadJalan(); loadPolygon(); loadSPBU(); } function loadJalan() { fetch(API_PATH + 'ambil_fasilitas_jalan.php').then(handleFetchResponse).then(result => { if (result.status === 'success') { all_data.jalan = result.data || []; tampilkanDataJalan(all_data.jalan); } }).catch(e => console.error(e)); } function loadPolygon() { fetch(API_PATH + 'ambil_fasilitas_polygon.php').then(handleFetchResponse).then(result => { if (result.status === 'success') { all_data.polygon = result.data || []; tampilkanDataPolygon(all_data.polygon); } }).catch(e => console.error(e)); } function loadSPBU() { fetch(API_PATH + 'ambil_fasilitas_spbu.php').then(handleFetchResponse).then(result => { if (result.status === 'success') { all_data.spbu = result.data || []; tampilkanDataSPBU(all_data.spbu); } }).catch(e => console.error(e)); } /** * Memuat data masyarakat miskin dari server. */ function loadMasyarakat() { fetch(API_PATH + 'ambil_data_masyarakat.php') .then(handleFetchResponse) .then(result => { if (result.status === 'success') { all_data.masyarakat = result.data || []; tampilkanDataMasyarakat(all_data.masyarakat); } else { console.error('Gagal memuat data masyarakat:', result.message); } }) .catch(error => console.error('Error saat fetch data masyarakat:', error)); } /** * Memuat data fasilitas rumah ibadah dari server. */ function loadRumahIbadah() { fetch(API_PATH + 'ambil_rumah_ibadah.php') .then(handleFetchResponse) .then(result => { if (result.status === 'success') { all_data.ibadah = result.data || []; tampilkanDataIbadah(all_data.ibadah); } else { console.error('Gagal memuat data rumah ibadah:', result.message); } }) .catch(error => console.error('Error saat fetch data rumah ibadah:', error)); } /** * Merender penanda peta dan elemen daftar sidebar untuk kategori masyarakat. * @param {Array} data - Larik berisi data objek masyarakat. */ function tampilkanDataMasyarakat(data) { markers.masyarakat.forEach(m => map.removeLayer(m)); markers.masyarakat = []; const list = document.getElementById('list-masyarakat'); if (!list) return; list.innerHTML = ''; data.forEach(item => { const marker = L.marker( [parseFloat(item.latitude), parseFloat(item.longitude)], { icon: iconMasyarakat } ).addTo(map); const bpjs_class = item.status_bpjs === 'Ya' ? 'status-ya' : (item.status_bpjs === 'Proses' ? 'status-proses' : 'status-tidak'); // Penerapan escapeHTML untuk mencegah kerentanan XSS pada popup marker.bindPopup(`
${escapeHTML(item.nama)}
${escapeHTML(item.alamat)}
Status BPJS: ${escapeHTML(item.status_bpjs)}
`); markers.masyarakat.push(marker); const li = document.createElement('li'); li.innerHTML = ` ${escapeHTML(item.nama)} ${escapeHTML(item.kecamatan)} | BPJS: ${escapeHTML(item.status_bpjs)} `; li.onclick = () => { map.setView([item.latitude, item.longitude], 16); marker.openPopup(); }; list.appendChild(li); }); updateMapVisibility(); } /** * Merender penanda peta dan elemen daftar sidebar untuk kategori rumah ibadah. * @param {Array} data - Larik berisi data objek rumah ibadah. */ function tampilkanDataIbadah(data) { markers.ibadah.forEach(m => map.removeLayer(m)); markers.ibadah = []; const list = document.getElementById('list-ibadah'); if (!list) return; list.innerHTML = ''; data.forEach(item => { const marker = L.marker( [parseFloat(item.latitude), parseFloat(item.longitude)], { icon: iconIbadah } ).addTo(map); const info_pemimpin = item.nama_pemimpin ? 'Pemimpin: ' + escapeHTML(item.nama_pemimpin) + '
' : ''; const info_alamat = item.alamat ? '' + escapeHTML(item.alamat) + '' : ''; marker.bindPopup(`
${escapeHTML(item.nama)}
${escapeHTML(item.jenis)}
${info_pemimpin} ${info_alamat}
`); markers.ibadah.push(marker); const li = document.createElement('li'); li.innerHTML = ` ${escapeHTML(item.nama)} ${escapeHTML(item.jenis)} `; li.onclick = () => { map.setView([item.latitude, item.longitude], 16); marker.openPopup(); }; list.appendChild(li); }); updateMapVisibility(); } function tampilkanDataJalan(data) { if (layers.jalan) map.removeLayer(layers.jalan); layers.jalan = L.layerGroup().addTo(map); const list = document.getElementById('list-jalan'); if (!list) return; list.innerHTML = ''; data.forEach(item => { try { const geojson = JSON.parse(item.geojson); const layer = L.geoJSON(geojson, { style: { color: 'blue', weight: 4 } }).addTo(layers.jalan); layer.bindPopup(`${escapeHTML(item.nama)}
${escapeHTML(item.tipe)}
`); const li = document.createElement('li'); li.innerHTML = `${escapeHTML(item.nama)}
${escapeHTML(item.tipe)}`; li.onclick = () => { map.fitBounds(layer.getBounds()); layer.openPopup(); }; list.appendChild(li); } catch(e) { console.error('Invalid GeoJSON', e); } }); updateMapVisibility(); } function tampilkanDataPolygon(data) { if (layers.polygon) map.removeLayer(layers.polygon); layers.polygon = L.layerGroup().addTo(map); const list = document.getElementById('list-polygon'); if (!list) return; list.innerHTML = ''; data.forEach(item => { try { const geojson = JSON.parse(item.geojson); const layer = L.geoJSON(geojson, { style: { color: 'purple', fillColor: 'purple', fillOpacity: 0.4 } }).addTo(layers.polygon); layer.bindPopup(`${escapeHTML(item.nama)}
${escapeHTML(item.tipe)}
`); const li = document.createElement('li'); li.innerHTML = `${escapeHTML(item.nama)}
${escapeHTML(item.tipe)}`; li.onclick = () => { map.fitBounds(layer.getBounds()); layer.openPopup(); }; list.appendChild(li); } catch(e) { console.error('Invalid GeoJSON', e); } }); updateMapVisibility(); } function tampilkanDataSPBU(data) { markers.spbu.forEach(m => map.removeLayer(m)); markers.spbu = []; const list = document.getElementById('list-spbu'); if (!list) return; list.innerHTML = ''; data.forEach(item => { const is24 = item.is_24_jam === 'Ya'; // Reuse iconIbadah for green (24h) and iconMasyarakat for red (not 24h) const iconSPBU = is24 ? iconIbadah : iconMasyarakat; const statusText = is24 ? 'Buka 24 Jam' : 'Tidak 24 Jam'; const marker = L.marker([parseFloat(item.latitude), parseFloat(item.longitude)], { icon: iconSPBU, draggable: true }).addTo(map); marker.bindPopup(`${escapeHTML(item.nama)}
${escapeHTML(item.alamat)}
${statusText}
`); marker.on('dragend', function(e) { const newPos = marker.getLatLng(); if (confirm('Apakah Anda yakin ingin memperbarui lokasi SPBU ini?')) { const fd = new FormData(); fd.append('id', item.id); fd.append('latitude', newPos.lat.toFixed(8)); fd.append('longitude', newPos.lng.toFixed(8)); fetch(API_PATH + 'update_lokasi_spbu.php', { method: 'POST', body: fd }) .then(handleFetchResponse) .then(res => { if (res.status === 'success') { alert('Lokasi berhasil diperbarui'); item.latitude = newPos.lat; item.longitude = newPos.lng; } else { alert('Gagal: ' + res.message); marker.setLatLng([parseFloat(item.latitude), parseFloat(item.longitude)]); } }).catch(err => { alert('Error: ' + err.message); marker.setLatLng([parseFloat(item.latitude), parseFloat(item.longitude)]); }); } else { marker.setLatLng([parseFloat(item.latitude), parseFloat(item.longitude)]); } }); markers.spbu.push(marker); const li = document.createElement('li'); li.innerHTML = `${escapeHTML(item.nama)}
${escapeHTML(item.alamat)}
${statusText}`; li.onclick = () => { map.setView([item.latitude, item.longitude], 16); marker.openPopup(); }; list.appendChild(li); }); updateMapVisibility(); } /** * Memuat detail data spesifik masyarakat miskin termasuk riwayat bantuan dan status BPJS. * @param {string|number} id - ID unik entitas masyarakat miskin. */ function showDetail(id) { fetch(API_PATH + 'ambil_detail.php?id=' + encodeURIComponent(id)) .then(handleFetchResponse) .then(result => { if (result.status === 'success') { const data = result.data; const masyarakat = data.masyarakat; const bantuan = data.bantuan || []; const bpjs = data.bpjs; const bpjs_class = masyarakat.status_bpjs === 'Ya' ? 'status-ya' : (masyarakat.status_bpjs === 'Proses' ? 'status-proses' : 'status-tidak'); let html = `

👤 Data Pribadi

Nama${escapeHTML(masyarakat.nama)}
Tanggal Lahir${escapeHTML(masyarakat.tanggal_lahir)}
Jenis Kelamin${escapeHTML(masyarakat.jenis_kelamin)}
NIK${escapeHTML(masyarakat.nik)}
No. HP${escapeHTML(masyarakat.no_hp)}

🏠 Data Alamat

Alamat${escapeHTML(masyarakat.alamat)}
Kelurahan${escapeHTML(masyarakat.kelurahan)}
Kecamatan${escapeHTML(masyarakat.kecamatan)}
Status Rumah${escapeHTML(masyarakat.status_rumah)}

💼 Data Ekonomi

Pekerjaan${escapeHTML(masyarakat.pekerjaan)}
Pendapatan BulananRp. ${new Intl.NumberFormat('id-ID').format(masyarakat.pendapatan_bulanan || 0)}
Jumlah Tanggungan${escapeHTML(masyarakat.jumlah_tanggungan)} orang

🏥 Status BPJS

Status BPJS${escapeHTML(masyarakat.status_bpjs)}
`; if (bpjs) { html += `
No. Peserta BPJS${escapeHTML(bpjs.no_peserta)}
Jenis BPJS${escapeHTML(bpjs.jenis_bpjs)}
Tingkat${escapeHTML(bpjs.tingkat)}
`; } html += `
`; // Memperbaiki string penutup tag div yang sebelumnya memicu syntax error if (bantuan.length > 0) { html += `

💰 Riwayat Bantuan

`; bantuan.forEach(b => { html += `
${escapeHTML(b.jenis_bantuan)} (${escapeHTML(b.tanggal_bantuan)})
Nilai: Rp. ${new Intl.NumberFormat('id-ID').format(b.nilai)} ${escapeHTML(b.satuan)} ${b.keterangan ? '
' + escapeHTML(b.keterangan) + '' : ''}
`; }); html += `
`; } html += `
`; const modal_body = document.getElementById('modal-body'); if (modal_body) { modal_body.innerHTML = html; openModal('modal-detail'); } } }) .catch(error => console.error('Error saat fetch detail data:', error)); } /** * Menghubungkan fungsi penangan kejadian (event handler) ke elemen-elemen HTML DOM. */ function attachEventListeners() { // Accordion Logic document.querySelectorAll('.accordion').forEach(acc => { acc.addEventListener('click', function() { // Close other accordions document.querySelectorAll('.accordion').forEach(otherAcc => { if (otherAcc !== this) { otherAcc.classList.remove('active'); if (otherAcc.nextElementSibling) { otherAcc.nextElementSibling.style.display = "none"; } } }); // Toggle this one this.classList.toggle('active'); const panel = this.nextElementSibling; if (panel.style.display === "block") { panel.style.display = "none"; } else { panel.style.display = "block"; // Optionally auto-click the first tab in this accordion const firstTab = panel.querySelector('.tab-button'); if (firstTab && !firstTab.classList.contains('active')) { firstTab.click(); } } }); }); document.querySelectorAll('.tab-button').forEach(btn => { btn.addEventListener('click', function(e) { const tab = this.dataset.tab; switchTab(e, tab); }); }); const search_input = document.getElementById('search'); const f_kecamatan = document.getElementById('filter-kecamatan'); const f_bpjs = document.getElementById('filter-bpjs'); const f_jenis = document.getElementById('filter-jenis'); if (search_input) search_input.addEventListener('input', filterMasyarakat); if (f_kecamatan) f_kecamatan.addEventListener('change', filterMasyarakat); if (f_bpjs) f_bpjs.addEventListener('change', filterMasyarakat); if (f_jenis) f_jenis.addEventListener('change', filterIbadah); const form_masyarakat = document.getElementById('form-masyarakat'); const form_ibadah = document.getElementById('form-ibadah'); const form_jalan = document.getElementById('form-jalan'); const form_polygon = document.getElementById('form-polygon'); const form_spbu = document.getElementById('form-spbu'); const form_bantuan = document.getElementById('form-bantuan'); if (form_masyarakat) form_masyarakat.addEventListener('submit', function(e) { e.preventDefault(); submitFormMasyarakat(); }); if (form_ibadah) form_ibadah.addEventListener('submit', function(e) { e.preventDefault(); submitFormIbadah(); }); if (form_jalan) form_jalan.addEventListener('submit', function(e) { e.preventDefault(); submitFormJalan(); }); if (form_polygon) form_polygon.addEventListener('submit', function(e) { e.preventDefault(); submitFormPolygon(); }); if (form_spbu) form_spbu.addEventListener('submit', function(e) { e.preventDefault(); submitFormSPBU(); }); if (form_bantuan) form_bantuan.addEventListener('submit', function(e) { e.preventDefault(); submitFormBantuan(); }); // BPJS Fields Toggle const bpjs_status_select = document.getElementById('form-status-bpjs'); const bpjs_detail_fields = document.getElementById('bpjs-detail-fields'); if (bpjs_status_select && bpjs_detail_fields) { bpjs_status_select.addEventListener('change', function() { if (this.value === 'Ya') { bpjs_detail_fields.style.display = 'block'; const dateInput = bpjs_detail_fields.querySelector('input[type="date"]'); if (dateInput && !dateInput.value) { dateInput.value = new Date().toISOString().substring(0, 10); } } else { bpjs_detail_fields.style.display = 'none'; } }); } // Shortcut keyboard untuk membuka formulir penambahan data baru document.addEventListener('keydown', function(e) { if (e.key === 'n' || e.key === 'N') { const active_modal = document.querySelector('.modal.active'); if (active_modal) return; // Cegah konflik jika modal lain sudah terbuka if (current_tab === 'masyarakat') openModal('modal-form-masyarakat'); else if (current_tab === 'ibadah') openModal('modal-form-ibadah'); } }); } /** * Mengubah status visibilitas tab kategori aktif (Masyarakat / Rumah Ibadah). * @param {Event} e - Objek event klik dari DOM. * @param {string} tab - Nama tab penanda tujuan ('masyarakat' / 'ibadah'). */ function switchTab(e, tab) { current_tab = tab; document.querySelectorAll('.tab-button').forEach(btn => { btn.classList.remove('active'); }); if (e && e.target) { e.target.classList.add('active'); } document.querySelectorAll('.list-container').forEach(container => { container.classList.remove('active'); }); const target_tab = document.getElementById('tab-' + tab); if (target_tab) target_tab.classList.add('active'); updateMapVisibility(); } function updateMapVisibility() { markers.masyarakat.forEach(m => map.removeLayer(m)); markers.ibadah.forEach(m => map.removeLayer(m)); markers.spbu.forEach(m => map.removeLayer(m)); if (layers.jalan) map.removeLayer(layers.jalan); if (layers.polygon) map.removeLayer(layers.polygon); if (current_tab === 'masyarakat' || current_tab === 'info-fasilitas') { markers.masyarakat.forEach(m => map.addLayer(m)); } if (current_tab === 'ibadah' || current_tab === 'info-fasilitas') { markers.ibadah.forEach(m => map.addLayer(m)); } if (current_tab === 'spbu' || current_tab === 'info-fasilitas') { markers.spbu.forEach(m => map.addLayer(m)); } if (current_tab === 'jalan' || current_tab === 'info-fasilitas') { if (layers.jalan) map.addLayer(layers.jalan); } if (current_tab === 'polygon' || current_tab === 'info-fasilitas') { if (layers.polygon) map.addLayer(layers.polygon); } } /** * Memfilter kumpulan data masyarakat berdasarkan kata kunci pencarian, kecamatan, dan status BPJS. */ function filterMasyarakat() { const search_el = document.getElementById('search'); const kec_el = document.getElementById('filter-kecamatan'); const bpjs_el = document.getElementById('filter-bpjs'); const keyword = search_el ? search_el.value.toLowerCase() : ''; const kecamatan = kec_el ? kec_el.value : ''; const bpjs = bpjs_el ? bpjs_el.value : ''; const filtered = all_data.masyarakat.filter(item => { const item_nama = item.nama ? item.nama.toLowerCase() : ''; const item_alamat = item.alamat ? item.alamat.toLowerCase() : ''; const match_keyword = item_nama.includes(keyword) || item_alamat.includes(keyword); const match_kecamatan = !kecamatan || item.kecamatan === kecamatan; const match_bpjs = !bpjs || item.status_bpjs === bpjs; return match_keyword && match_kecamatan && match_bpjs; }); tampilkanDataMasyarakat(filtered); } /** * Memfilter kumpulan data tempat ibadah berdasarkan jenis kategori tempat ibadah. */ function filterIbadah() { const jenis_el = document.getElementById('filter-jenis'); const jenis = jenis_el ? jenis_el.value : ''; const filtered = all_data.ibadah.filter(item => { return !jenis || item.jenis === jenis; }); tampilkanDataIbadah(filtered); } /** * Mengirimkan formulir data masyarakat baru ke berkas PHP pemroses menggunakan Fetch FormData. */ function submitFormMasyarakat() { const form = document.getElementById('form-masyarakat'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_masyarakat.php', { method: 'POST', body: form_data }) .then(handleFetchResponse) .then(result => { if (result.status === 'success') { // Tambahkan detail BPJS jika status_bpjs adalah Ya const status_bpjs = form_data.get('status_bpjs'); if (status_bpjs === 'Ya') { const bpjs_data = new FormData(); bpjs_data.append('id_masyarakat', result.data.id); bpjs_data.append('no_peserta', form_data.get('bpjs_no_peserta')); bpjs_data.append('jenis_bpjs', form_data.get('bpjs_jenis_bpjs')); bpjs_data.append('tingkat', form_data.get('bpjs_tingkat')); bpjs_data.append('status_aktif', form_data.get('bpjs_status_aktif')); bpjs_data.append('tanggal_daftar', form_data.get('bpjs_tanggal_daftar')); bpjs_data.append('faskes_tingkat_1', form_data.get('bpjs_faskes_tingkat_1')); fetch(API_PATH + 'simpan_bpjs.php', { method: 'POST', body: bpjs_data }) .then(handleFetchResponse) .catch(err => console.error("Gagal menyimpan detail BPJS:", err)); } showAlert('alert-form', 'Data berhasil disimpan!', 'success'); form.reset(); const bpjs_detail_fields = document.getElementById('bpjs-detail-fields'); if (bpjs_detail_fields) bpjs_detail_fields.style.display = 'none'; setTimeout(() => { closeModal('modal-form-masyarakat'); loadMasyarakat(); }, 1500); } else { showAlert('alert-form', result.message || 'Gagal menyimpan data.', 'error'); } }) .catch(error => { showAlert('alert-form', 'Terjadi kesalahan sistem: ' + error.message, 'error'); }); } /** * Mengirimkan formulir data rumah ibadah baru ke berkas PHP pemroses menggunakan Fetch FormData. */ function submitFormIbadah() { const form = document.getElementById('form-ibadah'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_rumah_ibadah.php', { method: 'POST', body: form_data }) .then(handleFetchResponse) .then(result => { if (result.status === 'success') { showAlert('alert-form-ibadah', 'Data berhasil disimpan!', 'success'); form.reset(); setTimeout(() => { closeModal('modal-form-ibadah'); loadRumahIbadah(); }, 1500); } else { showAlert('alert-form-ibadah', result.message || 'Gagal menyimpan data.', 'error'); } }) .catch(error => { showAlert('alert-form-ibadah', 'Terjadi kesalahan sistem: ' + error.message, 'error'); }); } function submitFormJalan() { const form = document.getElementById('form-jalan'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_fasilitas_jalan.php', { method: 'POST', body: form_data }) .then(handleFetchResponse).then(result => { if (result.status === 'success') { showAlert('alert-form-jalan', 'Berhasil disimpan', 'success'); form.reset(); drawnItems.clearLayers(); setTimeout(() => { closeModal('modal-form-jalan'); loadJalan(); }, 1000); } else showAlert('alert-form-jalan', result.message, 'error'); }).catch(e => showAlert('alert-form-jalan', e.message, 'error')); } function submitFormPolygon() { const form = document.getElementById('form-polygon'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_fasilitas_polygon.php', { method: 'POST', body: form_data }) .then(handleFetchResponse).then(result => { if (result.status === 'success') { showAlert('alert-form-polygon', 'Berhasil disimpan', 'success'); form.reset(); drawnItems.clearLayers(); setTimeout(() => { closeModal('modal-form-polygon'); loadPolygon(); }, 1000); } else showAlert('alert-form-polygon', result.message, 'error'); }).catch(e => showAlert('alert-form-polygon', e.message, 'error')); } function submitFormSPBU() { const form = document.getElementById('form-spbu'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_fasilitas_spbu.php', { method: 'POST', body: form_data }) .then(handleFetchResponse).then(result => { if (result.status === 'success') { showAlert('alert-form-spbu', 'Berhasil disimpan', 'success'); form.reset(); setTimeout(() => { closeModal('modal-form-spbu'); loadSPBU(); }, 1000); } else showAlert('alert-form-spbu', result.message, 'error'); }).catch(e => showAlert('alert-form-spbu', e.message, 'error')); } /** * Mengirimkan instruksi penghapusan data spesifik (masyarakat/ibadah) ke sistem basis data backend. * @param {string} tipe - Jenis kategori data yang akan dihapus ('masyarakat' / 'ibadah'). * @param {string|number} id - ID baris data target. */ function hapusData(tipe, id) { if (!confirm('Apakah Anda yakin ingin menghapus data ini? Tindakan ini tidak dapat dibatalkan.')) { return; } const form_data = new FormData(); form_data.append('tipe', tipe); form_data.append('id', id); fetch(API_PATH + 'hapus_data.php', { method: 'POST', body: form_data }) .then(handleFetchResponse) .then(result => { if (result.status === 'success') { alert('Data berhasil dihapus'); closeModal('modal-detail'); if (tipe === 'masyarakat') loadMasyarakat(); else if (tipe === 'ibadah') loadRumahIbadah(); else if (tipe === 'jalan') loadJalan(); else if (tipe === 'polygon') loadPolygon(); else if (tipe === 'spbu') loadSPBU(); } else { alert('Gagal menghapus: ' + (result.message || 'Error tidak diketahui')); } }) .catch(error => { alert('Terjadi kesalahan jaringan atau sistem: ' + error.message); }); } function editBantuan(id) { const form = document.getElementById('form-bantuan'); if (form) form.reset(); const idInput = document.getElementById('bantuan-id-masyarakat'); if (idInput) idInput.value = id; const dateInput = document.querySelector('#form-bantuan input[name="tanggal_bantuan"]'); if (dateInput) dateInput.value = new Date().toISOString().substring(0, 10); openModal('modal-form-bantuan'); } function submitFormBantuan() { const form = document.getElementById('form-bantuan'); if (!form) return; const form_data = new FormData(form); fetch(API_PATH + 'simpan_bantuan.php', { method: 'POST', body: form_data }) .then(handleFetchResponse) .then(result => { if (result.status === 'success') { showAlert('alert-form-bantuan', 'Riwayat bantuan berhasil disimpan!', 'success'); form.reset(); const citizenId = form_data.get('id_masyarakat'); setTimeout(() => { closeModal('modal-form-bantuan'); // Refresh detail modal showDetail(citizenId); }, 1000); } else { showAlert('alert-form-bantuan', result.message || 'Gagal menyimpan riwayat bantuan.', 'error'); } }) .catch(error => { showAlert('alert-form-bantuan', 'Terjadi kesalahan sistem: ' + error.message, 'error'); }); } function openModal(modalId) { const modal = document.getElementById(modalId); if (modal) modal.classList.add('active'); } function closeModal(modalId) { const modal = document.getElementById(modalId); if (modal) modal.classList.remove('active'); } function showAlert(elementId, message, type) { const alert_el = document.getElementById(elementId); if (!alert_el) return; alert_el.textContent = message; alert_el.className = 'alert active alert-' + type; setTimeout(() => { alert_el.classList.remove('active'); }, 5000); } // Menutup jendela modal otomatis jika pengguna mengklik area luar modal (overlay) document.addEventListener('click', function(e) { if (e.target && e.target.classList.contains('modal')) { e.target.classList.remove('active'); } });