// ========================================== // 1. INISIALISASI PETA & LAYER // ========================================== var map = L.map('map', { zoomControl: false }).setView([-0.0227, 109.3425], 14); // Zoom control di kanan bawah (lebih bersih) L.control.zoom({ position: 'bottomright' }).addTo(map); // Membuat panel khusus untuk Jalan map.createPane('jalanPane'); map.getPane('jalanPane').style.zIndex = 450; L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); // Layer Group untuk masing-masing data var markersLayer = L.layerGroup().addTo(map); var jalanLayer = L.layerGroup().addTo(map); var parsilLayer = L.layerGroup().addTo(map); var drawnItems = new L.FeatureGroup().addTo(map); //var batasKotaLayer = L.layerGroup().addTo(map); //var sungaiLayer = L.layerGroup().addTo(map); var rumahIbadahLayer = L.layerGroup().addTo(map); var radiusLayer = L.layerGroup().addTo(map); var pendudukMiskinLayer = L.layerGroup().addTo(map); // Inisialisasi Heatmap kosong (akan diisi datanya saat load data) var povertyHeatLayer = L.heatLayer([], { radius: 22, blur: 18, maxZoom: 17 }).addTo(map); // Inisialisasi Layers Control (di kanan atas) var overlayMaps = { "⛽ Stasiun SPBU": markersLayer, "🛣️ Jaringan Jalan": jalanLayer, "🏘️ Parsil Bangunan": parsilLayer, "🕌 Rumah Ibadah": rumahIbadahLayer, "🔥 Kepadatan Kemiskinan (Heatmap)": povertyHeatLayer, "👥 Penduduk Terdekat (Analisis)": pendudukMiskinLayer }; L.control.layers(null, overlayMaps, { collapsed: true, position: 'bottomleft' }).addTo(map); // ========================================== // ICON DEFINITIONS // ========================================== var greenIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }); var redIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }); var blueIcon = L.icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-blue.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }); // Icon Rumah Ibadah Kustom — bangunan rumah ibadah bergaya universal var rumahIbadahIcon = L.divIcon({ className: '', html: `
`, iconSize: [38, 38], iconAnchor: [19, 38], popupAnchor: [0, -38] }); // ========================================== // 2. TOOLBAR LEAFLET DRAW // ========================================== var drawControl = new L.Control.Draw({ draw: { polyline: true, polygon: true, marker: true, circle: false, rectangle: false, circlemarker: false }, edit: false }); //map.addControl(drawControl); // ========================================== // 3. FUNGSI LOAD DATA DARI DATABASE // ========================================== function loadSPBU() { markersLayer.clearLayers(); spbuMarkers = {}; fetch('load.php?jenis=spbu').then(res => res.json()).then(data => { data.forEach(item => { var actionButtons = ''; if (IS_ADMIN) { actionButtons = `
`; } var statusBuka = item.kategori === 'Ya' ? 'Buka 24 Jam' : 'Reguler'; var icon = item.kategori === 'Ya' ? greenIcon : redIcon; var statusColor = item.kategori === 'Ya' ? '#10b981' : '#ef4444'; var viewHTML = ` `; var marker = L.marker([item.latitude, item.longitude], { icon: icon, draggable: false }) .bindPopup(viewHTML).addTo(markersLayer); spbuMarkers[String(item.id)] = marker; marker.on('click', function () { map.flyTo(marker.getLatLng(), 17, { animate: true }); }); databasePencarian.push({ namaLower: item.nama_spbu.toLowerCase(), namaAsli: item.nama_spbu, kategori: 'SPBU', ikon: '⛽', tipe: 'titik', layer: marker }); marker.on('dragend', function (e) { var position = marker.getLatLng(); if (document.getElementById('edit_lat')) { document.getElementById('edit_lat').value = position.lat; document.getElementById('edit_lng').value = position.lng; } marker.openPopup(); }); }); }).catch(e => console.log('Belum ada data SPBU')); } function openEditKonfirmasi(id, nama, hp, kategori, lat, lng) { var marker = spbuMarkers[String(id)]; var editHTML = ` `; marker.setPopupContent(editHTML); marker.openPopup(); } function loadJalan() { jalanLayer.clearLayers(); fetch('load.php?jenis=jalan').then(res => res.json()).then(data => { data.forEach(item => { try { var actionButtons = ''; if (IS_ADMIN) { actionButtons = `
`; } var geom = JSON.parse(item.koordinat); var warna = item.status === 'Jalan Nasional' ? '#ef4444' : item.status === 'Jalan Provinsi' ? '#eab308' : '#10b981'; var viewHTML = ` `; var layerJalan = L.geoJSON(geom, { style: { color: warna, weight: 5 } }) .bindPopup(viewHTML).addTo(jalanLayer); layerJalan.on('click', function () { map.fitBounds(layerJalan.getBounds()); }); databasePencarian.push({ namaLower: item.nama_jalan.toLowerCase(), namaAsli: item.nama_jalan, kategori: 'Jalan', ikon: '🛣️', tipe: 'area', layer: layerJalan }); } catch (error) { console.error("Error parse koordinat jalan", error); } }); }).catch(e => console.log('Belum ada data Jalan')); } function loadParsil() { parsilLayer.clearLayers(); fetch('load.php?jenis=parsil').then(res => res.json()).then(data => { data.forEach(item => { var actionButtons = ''; if (IS_ADMIN) { actionButtons = `
`; } var geom = JSON.parse(item.koordinat); var warna = item.status === 'SHM' ? 'green' : item.status === 'HGB' ? 'blue' : item.status === 'HGU' ? 'purple' : 'orange'; var viewHTML = ` `; var layerParsil = L.geoJSON(geom, { style: { fillColor: warna, color: warna, weight: 2, fillOpacity: 0.5 } }) .bindPopup(viewHTML).addTo(parsilLayer); layerParsil.on('click', function () { map.fitBounds(layerParsil.getBounds()); }); databasePencarian.push({ namaLower: item.nama_pemilik.toLowerCase(), namaAsli: item.nama_pemilik, kategori: 'Parsil', ikon: '🏘️', tipe: 'area', layer: layerParsil }); }); }).catch(e => console.log('Belum ada data Parsil')); } /* function loadBatasKota() { batasKotaLayer.clearLayers(); var grupKecamatan = {}; fetch('adminKecamatan.json') .then(res => res.json()) .then(data => { L.geoJSON(data, { style: function () { return { color: "#00FF00", weight: 2, opacity: 1, fillOpacity: 0.1 }; }, onEachFeature: function (feature, layer) { var namaKec = feature.properties.Ket; var popupHTML = ` `; layer.bindPopup(popupHTML); if (!grupKecamatan[namaKec]) grupKecamatan[namaKec] = L.featureGroup(); grupKecamatan[namaKec].addLayer(layer); } }).addTo(batasKotaLayer); }) .catch(e => console.log('Gagal memuat adminKecamatan.json', e)); } function loadSungai() { sungaiLayer.clearLayers(); fetch('sungai.json') .then(res => res.json()) .then(data => { L.geoJSON(data, { style: function () { return { color: "#0ea5e9", weight: 2, opacity: 1, fillOpacity: 0.1 }; }, onEachFeature: function (feature, layer) { var namaSung = feature.properties.Ket; var popupHTML = ` `; layer.bindPopup(popupHTML); } }).addTo(sungaiLayer); }) .catch(e => console.log('Gagal memuat sungai.json', e)); } */ var databasePendudukMiskin = []; function loadRumahIbadah() { rumahIbadahLayer.clearLayers(); fetch('load.php?jenis=rumah_ibadah') .then(res => res.json()) .then(dataRumahIbadah => { fetch('load.php?jenis=penduduk_miskin') .then(res => res.json()) .then(dataPendudukMiskin => { databasePendudukMiskin = dataPendudukMiskin; // Mengisi koordinat data kemiskinan ke dalam Heatmap var heatPoints = dataPendudukMiskin.map(p => [ parseFloat(p.lat || p.latitude), parseFloat(p.lng || p.longitude), 1.0 ]); povertyHeatLayer.setLatLngs(heatPoints); dataRumahIbadah.forEach(ibadah => { var latIbadah = ibadah.lat || ibadah.latitude; var lngIbadah = ibadah.lng || ibadah.longitude; var radiusMeter = 500; var ibadahId = ibadah.id; var actionButtons = ''; if (IS_ADMIN) { actionButtons = `
`; } // HTML untuk Popup Rumah Ibadah dengan range slider untuk mengatur radius analisis var htmlIbadah = ` `; var ibadahMarker = L.marker([latIbadah, lngIbadah], { icon: rumahIbadahIcon }) .bindPopup(htmlIbadah) .addTo(rumahIbadahLayer); databasePencarian.push({ namaLower: ibadah.nama.toLowerCase(), namaAsli: ibadah.nama, kategori: 'Rumah Ibadah', ikon: '🕌', tipe: 'titik', layer: ibadahMarker }); // Saat popup dibuka, jalankan fungsi updatePopupRadius ibadahMarker.on('popupopen', function (e) { map.flyTo(e.target.getLatLng(), 16, { animate: true }); setTimeout(function () { updatePopupRadius(ibadahId, latIbadah, lngIbadah); }, 50); }); }); }); }) .catch(e => console.log('Belum ada data Rumah Ibadah', e)); } // Fungsi untuk memperbarui lingkaran radius dan penduduk miskin terdekat secara interaktif function updatePopupRadius(ibadahId, lat, lng) { var slider = document.getElementById('radius-slider-' + ibadahId); var label = document.getElementById('radius-val-' + ibadahId); if (!slider || !label) return; var newRadius = parseInt(slider.value); label.textContent = newRadius + ' meter'; var centerPoint = L.latLng(lat, lng); radiusLayer.clearLayers(); pendudukMiskinLayer.clearLayers(); // Gambar lingkaran radius baru var areaRadius = L.circle(centerPoint, { color: '#2563eb', fillColor: '#3b82f6', fillOpacity: 0.1, radius: newRadius, interactive: true }).addTo(radiusLayer); areaRadius.on('click', function (evt) { L.DomEvent.stopPropagation(evt); }); // Saring dan tampilkan penduduk miskin yang berada dalam radius baru databasePendudukMiskin.forEach(penduduk => { var latPenduduk = penduduk.lat || penduduk.latitude; var lngPenduduk = penduduk.lng || penduduk.longitude; var pendudukLatLng = L.latLng(latPenduduk, lngPenduduk); var jarak = centerPoint.distanceTo(pendudukLatLng); if (jarak <= newRadius) { var redDot = L.circleMarker(pendudukLatLng, { radius: 6, color: '#dc2626', fillColor: '#ef4444', fillOpacity: 1, weight: 2 }).addTo(pendudukMiskinLayer); redDot.on('click', function (e) { L.DomEvent.stopPropagation(e); var pendudukId = penduduk.id; var namaKeluarga = penduduk.nama_kk ? penduduk.nama_kk : "Tanpa Nama"; var alamatLengkap = penduduk.alamat ? penduduk.alamat : "Alamat belum diinput manual"; var latAngka = parseFloat(latPenduduk); var lngAngka = parseFloat(lngPenduduk); var actionButtons = ''; if (IS_ADMIN) { actionButtons = `
`; } var htmlIsi = ` `; redDot.bindPopup(htmlIsi).openPopup(); }); } }); } map.on('click', function () { if (sidebarPickMode) return; // Ditangani oleh listener sidebar radiusLayer.clearLayers(); pendudukMiskinLayer.clearLayers(); }); loadSPBU(); loadJalan(); loadParsil(); loadRumahIbadah(); var koordinatSementara = ""; var tempLat = 0; var tempLng = 0; var spbuMarkers = {}; // ========================================== // 4. EVENT SAAT MENGGAMBAR SELESAI // ========================================== /* map.on(L.Draw.Event.CREATED, function (e) { var type = e.layerType, layer = e.layer; var geojson = layer.toGeoJSON(); koordinatSementara = JSON.stringify(geojson.geometry); var popupContent = ""; if (type === 'polyline') { var panjangMeter = turf.length(geojson, { units: 'meters' }).toFixed(2); popupContent = ` `; } else if (type === 'polygon') { var luasMeter = turf.area(geojson).toFixed(2); popupContent = ` `; } else if (type === 'marker') { tempLat = layer.getLatLng().lat; tempLng = layer.getLatLng().lng; popupContent = ` `; } layer.bindPopup(popupContent).openPopup(); drawnItems.addLayer(layer); }); */ /* // ========================================== // 6. FUNGSI SIMPAN DATA // ========================================== function saveSPBU(e) { e.preventDefault(); var formData = new FormData(); formData.append('nama_spbu', document.getElementById('new_nama').value); formData.append('no_hp', document.getElementById('new_nohp').value); formData.append('kategori', document.getElementById('new_kategori').value); formData.append('latitude', tempLat); formData.append('longitude', tempLng); fetch('save.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); drawnItems.clearLayers(); loadSPBU(); }) .catch(error => console.error('Error:', error)); } function saveJalan(e) { e.preventDefault(); var formData = new FormData(); formData.append('nama_jalan', document.getElementById('j_nama').value); formData.append('status', document.getElementById('j_status').value); formData.append('panjang', document.getElementById('j_panjang').value); formData.append('koordinat', koordinatSementara); fetch('save_jalan.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); drawnItems.clearLayers(); loadJalan(); }) .catch(error => console.error('Error:', error)); } function saveParsil(e) { e.preventDefault(); var formData = new FormData(); formData.append('nama_pemilik', document.getElementById('p_nama').value); formData.append('status', document.getElementById('p_status').value); formData.append('luas', document.getElementById('p_luas').value); formData.append('koordinat', koordinatSementara); fetch('save_parsil.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); drawnItems.clearLayers(); loadParsil(); }) .catch(error => console.error('Error:', error)); } function toggleFormMarker() { var pilihan = document.getElementById('kategori_marker').value; document.getElementById('form_spbu').style.display = pilihan === 'spbu' ? 'block' : 'none'; document.getElementById('form_rumah_ibadah').style.display = pilihan === 'rumah_ibadah' ? 'block' : 'none'; document.getElementById('form_penduduk').style.display = pilihan === 'penduduk' ? 'block' : 'none'; } function saveRumahIbadah(e) { e.preventDefault(); var formData = new FormData(); formData.append('nama', document.getElementById('ri_nama').value); formData.append('latitude', tempLat); formData.append('longitude', tempLng); fetch('save_rumah_ibadah.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); drawnItems.clearLayers(); loadRumahIbadah(); }) .catch(error => console.error('Error:', error)); } function savePenduduk(e) { e.preventDefault(); var formData = new FormData(); formData.append('nama', document.getElementById('pm_nama').value); formData.append('latitude', tempLat); formData.append('longitude', tempLng); fetch('save_penduduk_miskin.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); drawnItems.clearLayers(); loadRumahIbadah(); }) .catch(error => console.error('Error:', error)); } */ // ========================================== // 7. HAPUS DATA // ========================================== function deleteData(tabel, id) { if (confirm('Apakah Anda yakin ingin menghapus data ini?')) { var formData = new FormData(); formData.append('id', id); formData.append('tabel', tabel); fetch('delete_data.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); loadSPBU(); loadJalan(); loadParsil(); loadRumahIbadah(); }); } } // ========================================== // 8. EDIT DATA // ========================================== function formEditSPBU(id, nama, hp, kategori) { var markerId = String(id); var currentMarker = spbuMarkers[markerId]; if (currentMarker) currentMarker.dragging.enable(); setTimeout(function () { var lat = currentMarker.getLatLng().lat; var lng = currentMarker.getLatLng().lng; var formHTML = ` `; currentMarker.setPopupContent(formHTML); }, 50); } function formEditJalan(id, nama, status) { setTimeout(function () { document.getElementById(`popup-jalan-${id}`).innerHTML = ` `; }, 50); } function formEditParsil(id, nama, status) { setTimeout(function () { document.getElementById(`popup-parsil-${id}`).innerHTML = ` `; }, 50); } function formEditRumahIbadah(id, nama, lat, lng) { setTimeout(function () { document.getElementById(`popup-ibadah-${id}`).innerHTML = ` `; }, 50); } function formEditPenduduk(id, nama, alamat, lat, lng) { setTimeout(function () { document.getElementById(`popup-penduduk-${id}`).innerHTML = ` `; }, 50); } // ========================================== // 9. UPDATE DATA // ========================================== function updateData(e, tabel, id) { e.preventDefault(); var formData = new FormData(); formData.append('tabel', tabel); formData.append('id', id); if (tabel === 'spbu_locations') { formData.append('nama_spbu', document.getElementById('edit_nama').value); formData.append('no_hp', document.getElementById('edit_hp').value); formData.append('kategori', document.getElementById('edit_kategori').value); var markerPosisi = spbuMarkers[String(id)].getLatLng(); formData.append('latitude', markerPosisi.lat); formData.append('longitude', markerPosisi.lng); } else if (tabel === 'jalan') { formData.append('nama_jalan', document.getElementById('edit_nama').value); formData.append('status', document.getElementById('edit_status').value); } else if (tabel === 'parsil') { formData.append('nama_pemilik', document.getElementById('edit_nama').value); formData.append('status', document.getElementById('edit_status').value); } else if (tabel === 'rumah_ibadah') { formData.append('nama', document.getElementById('edit_nama_ibadah').value); formData.append('latitude', document.getElementById('edit_lat_ibadah').value); formData.append('longitude', document.getElementById('edit_lng_ibadah').value); } else if (tabel === 'penduduk_miskin') { formData.append('nama', document.getElementById('edit_nama_penduduk').value); formData.append('alamat', document.getElementById('edit_alamat_penduduk').value); formData.append('latitude', document.getElementById('edit_lat_penduduk').value); formData.append('longitude', document.getElementById('edit_lng_penduduk').value); } fetch('update_data.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); map.closePopup(); if (tabel === 'spbu_locations') loadSPBU(); if (tabel === 'jalan') loadJalan(); if (tabel === 'parsil') loadParsil(); if (tabel === 'rumah_ibadah' || tabel === 'penduduk_miskin') { loadRumahIbadah(); } }); } // ========================================== // 10. LEGENDA PETA // ========================================== var legend = L.control({ position: 'bottomleft' }); legend.onAdd = function (map) { var div = L.DomUtil.create('div', 'info legend'); div.innerHTML = `

Legenda Peta

SPBU
Buka 24 Jam
Reguler
Jaringan Jalan
Jalan Nasional
Jalan Provinsi
Jalan Kabupaten
Parsil Bangunan
SHM
HGB
HGU
HP
Sosial & Keagamaan
Rumah Ibadah
Penduduk Miskin
`; return div; }; legend.addTo(map); // ========================================== // 11. SISTEM PENCARIAN // ========================================== var databasePencarian = []; var ikonKategori = { 'SPBU': '⛽', 'Jalan': '🛣️', 'Parsil': '🏘️', 'Rumah Ibadah': '🕌', }; var warnaBadge = { 'SPBU': 'badge-SPBU', 'Jalan': 'badge-Jalan', 'Parsil': 'badge-Parsil', 'Rumah Ibadah': 'badge-Rumah-Ibadah', }; function jalankanPencarian() { var kataKunci = document.getElementById('search-input').value.toLowerCase(); var kategori = document.getElementById('search-category').value; var wadahHasil = document.getElementById('search-results'); wadahHasil.innerHTML = ''; if (kataKunci.length < 2) { wadahHasil.style.display = 'none'; return; } var hasil = databasePencarian.filter(function (item) { var cocokNama = item.namaLower.includes(kataKunci); var cocokKategori = (kategori === 'Semua') || (item.kategori === kategori); return cocokNama && cocokKategori; }); if (hasil.length > 0) { wadahHasil.style.display = 'block'; wadahHasil.innerHTML = `
${hasil.length} hasil ditemukan
`; hasil.forEach(function (item) { var badgeClass = warnaBadge[item.kategori] || 'badge-default'; var ikon = ikonKategori[item.kategori] || '📍'; var bgColors = { 'SPBU': 'rgba(16,185,129,0.12)', 'Jalan': 'rgba(245,158,11,0.12)', 'Parsil': 'rgba(139,92,246,0.12)', 'Rumah Ibadah': 'rgba(59,130,246,0.12)' }; var div = document.createElement('div'); div.className = 'result-item'; div.innerHTML = `
${ikon}
${item.namaAsli}
Klik untuk zoom ke lokasi
${item.kategori}`; div.onclick = function () { if (item.tipe === 'titik') { map.flyTo(item.layer.getLatLng(), 17, { animate: true, duration: 1.5 }); } else { map.fitBounds(item.layer.getBounds()); } item.layer.openPopup(); wadahHasil.style.display = 'none'; document.getElementById('search-input').value = item.namaAsli; toggleClearBtn(); }; wadahHasil.appendChild(div); }); } else { wadahHasil.style.display = 'block'; wadahHasil.innerHTML = `
🔍
Data tidak ditemukan
Coba kata kunci lain
`; } } function toggleClearBtn() { var input = document.getElementById('search-input'); var clearBtn = document.getElementById('search-clear'); clearBtn.style.display = input.value.length > 0 ? 'flex' : 'none'; } function clearSearch() { document.getElementById('search-input').value = ''; document.getElementById('search-results').style.display = 'none'; document.getElementById('search-clear').style.display = 'none'; } // Tutup hasil saat klik di luar document.addEventListener('click', function (e) { var wrapper = document.querySelector('.search-wrapper'); if (!wrapper.contains(e.target)) { document.getElementById('search-results').style.display = 'none'; } }); // Shortcut Cmd/Ctrl + K document.addEventListener('keydown', function (e) { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); document.getElementById('search-input').focus(); } if (e.key === 'Escape') { clearSearch(); document.getElementById('search-input').blur(); } }); // ========================================== // 12. LOGIKA SIDEBAR INPUT TERPUSAT // ========================================== var sidebarPickMode = null; // 'spbu' | 'ibadah' | 'penduduk' var sidebarDrawMode = null; // 'polyline' | 'polygon' var sidebarTempLat = 0, sidebarTempLng = 0; var sidebarKoordinat = ""; var sidebarDrawHandler = null; // Buka/Tutup Sidebar document.getElementById('sidebar-toggle').addEventListener('click', function () { var sidebar = document.getElementById('input-sidebar'); sidebar.classList.toggle('open'); this.classList.toggle('open'); }); document.getElementById('sidebar-close').addEventListener('click', function () { document.getElementById('input-sidebar').classList.remove('open'); document.getElementById('sidebar-toggle').classList.remove('open'); }); // Ganti Tab function switchSidebarTab(tabName) { document.querySelectorAll('.stab').forEach(function (t) { t.classList.remove('active'); }); document.querySelectorAll('.stab-content').forEach(function (c) { c.classList.remove('active'); }); document.querySelector('.stab[data-tab="' + tabName + '"]').classList.add('active'); document.getElementById('tab-' + tabName).classList.add('active'); // batalkan mode pick/draw jika ganti tab deactivatePickMode(); } // Aktifkan mode pilih titik di peta function activatePickMode(jenis) { sidebarPickMode = jenis; document.getElementById('pick-overlay').classList.add('active'); var teks = { spbu: 'Klik di peta untuk posisi SPBU', ibadah: 'Klik di peta untuk posisi Rumah Ibadah', penduduk: 'Klik di peta untuk posisi Penduduk Miskin' }; document.getElementById('pick-overlay-text').textContent = teks[jenis] || 'Klik lokasi di peta...'; var btnMap = { spbu: 'btn-pick-spbu', ibadah: 'btn-pick-ibadah', penduduk: 'btn-pick-penduduk' }; if (btnMap[jenis]) document.getElementById(btnMap[jenis]).classList.add('active-pick'); map.getContainer().style.cursor = 'crosshair'; } // Aktifkan mode gambar garis/poligon function activateDrawMode(type) { deactivatePickMode(); sidebarDrawMode = type; if (type === 'polyline') { sidebarDrawHandler = new L.Draw.Polyline(map); document.getElementById('coords-jalan-val').textContent = 'Sedang menggambar...'; document.getElementById('btn-draw-jalan').classList.add('active-pick'); } else if (type === 'polygon') { sidebarDrawHandler = new L.Draw.Polygon(map); document.getElementById('coords-parsil-val').textContent = 'Sedang menggambar...'; document.getElementById('btn-draw-parsil').classList.add('active-pick'); } if (sidebarDrawHandler) sidebarDrawHandler.enable(); document.getElementById('pick-overlay').classList.add('active'); var teks = { polyline: 'Klik titik-titik jalur jalan. Klik dua kali selesai.', polygon: 'Klik titik-titik batas lahan. Klik dua kali selesai.' }; document.getElementById('pick-overlay-text').textContent = teks[type]; map.getContainer().style.cursor = 'crosshair'; } // Batalkan semua mode function deactivatePickMode() { sidebarPickMode = null; sidebarDrawMode = null; document.getElementById('pick-overlay').classList.remove('active'); document.querySelectorAll('.btn-pick-location').forEach(function (b) { b.classList.remove('active-pick'); }); map.getContainer().style.cursor = ''; if (sidebarDrawHandler) { try { sidebarDrawHandler.disable(); } catch (e) { } sidebarDrawHandler = null; } } // Tangkap klik peta untuk mode pick titik map.on('click', function (e) { if (!sidebarPickMode) return; var lat = e.latlng.lat.toFixed(6); var lng = e.latlng.lng.toFixed(6); sidebarTempLat = e.latlng.lat; sidebarTempLng = e.latlng.lng; radiusLayer.clearLayers(); pendudukMiskinLayer.clearLayers(); if (sidebarPickMode === 'spbu') { var el = document.getElementById('coords-spbu-val'); el.textContent = lat + ', ' + lng; el.classList.add('has-coords'); } else if (sidebarPickMode === 'ibadah') { var el = document.getElementById('coords-ibadah-val'); el.textContent = lat + ', ' + lng; el.classList.add('has-coords'); } else if (sidebarPickMode === 'penduduk') { var el = document.getElementById('coords-penduduk-val'); el.textContent = lat + ', ' + lng; el.classList.add('has-coords'); var alamatInput = document.getElementById('sb_alamat_penduduk'); alamatInput.value = "Sedang mencari alamat..."; // Indikator loading // Memanggil API Nominatim OpenStreetMap fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`) .then(response => response.json()) .then(data => { if (data && data.display_name) { // Isi textarea alamat dengan hasil dari Nominatim alamatInput.value = data.display_name; } else { alamatInput.value = "Alamat tidak ditemukan, silakan isi manual."; } }) .catch(error => { console.error("Error Reverse Geocoding:", error); alamatInput.value = ""; }); } deactivatePickMode(); }); // Tangkap hasil gambar polyline/polygon dari sidebar map.on(L.Draw.Event.CREATED, function (e) { var type = e.layerType, layer = e.layer; var geojson = layer.toGeoJSON(); drawnItems.clearLayers(); drawnItems.addLayer(layer); // Jika berasal dari sidebar draw mode (Tidak ada lagi fallback popup lama) if (sidebarDrawMode === 'polyline' && type === 'polyline') { var panjangMeter = turf.length(geojson, { units: 'meters' }).toFixed(2); sidebarKoordinat = JSON.stringify(geojson.geometry); var el = document.getElementById('coords-jalan-val'); el.textContent = 'Panjang: ' + panjangMeter + ' m'; el.classList.add('has-coords'); document.getElementById('sb_panjang_jalan').value = panjangMeter + ' m'; deactivatePickMode(); } else if (sidebarDrawMode === 'polygon' && type === 'polygon') { var luasMeter = turf.area(geojson).toFixed(2); sidebarKoordinat = JSON.stringify(geojson.geometry); var el = document.getElementById('coords-parsil-val'); el.textContent = 'Luas: ' + luasMeter + ' m²'; el.classList.add('has-coords'); document.getElementById('sb_luas_parsil').value = luasMeter + ' m²'; deactivatePickMode(); } }); // ===== FUNGSI SIMPAN DARI SIDEBAR ===== function saveSPBUSidebar() { if (!sidebarTempLat && sidebarTempLat !== 0) { alert('Pilih lokasi di peta terlebih dahulu!'); return; } var nama = document.getElementById('sb_nama_spbu').value.trim(); if (!nama) { alert('Nama SPBU wajib diisi!'); return; } var coords = document.getElementById('coords-spbu-val').textContent; if (coords === 'Belum dipilih') { alert('Pilih lokasi di peta terlebih dahulu!'); return; } var formData = new FormData(); formData.append('nama_spbu', nama); formData.append('no_hp', document.getElementById('sb_nohp_spbu').value); formData.append('kategori', document.getElementById('sb_kategori_spbu').value); formData.append('latitude', sidebarTempLat); formData.append('longitude', sidebarTempLng); fetch('save.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); document.getElementById('sb_nama_spbu').value = ''; document.getElementById('sb_nohp_spbu').value = ''; document.getElementById('coords-spbu-val').textContent = 'Belum dipilih'; document.getElementById('coords-spbu-val').classList.remove('has-coords'); sidebarTempLat = 0; sidebarTempLng = 0; loadSPBU(); }).catch(e => console.error(e)); } function saveJalanSidebar() { if (!sidebarKoordinat) { alert('Gambar jalur jalan di peta terlebih dahulu!'); return; } var nama = document.getElementById('sb_nama_jalan').value.trim(); if (!nama) { alert('Nama jalan wajib diisi!'); return; } var formData = new FormData(); formData.append('nama_jalan', nama); formData.append('status', document.getElementById('sb_status_jalan').value); formData.append('panjang', document.getElementById('sb_panjang_jalan').value); formData.append('koordinat', sidebarKoordinat); fetch('save_jalan.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); document.getElementById('sb_nama_jalan').value = ''; document.getElementById('sb_panjang_jalan').value = ''; document.getElementById('coords-jalan-val').textContent = 'Belum digambar'; document.getElementById('coords-jalan-val').classList.remove('has-coords'); sidebarKoordinat = ''; drawnItems.clearLayers(); loadJalan(); }).catch(e => console.error(e)); } function saveParsil_Sidebar() { if (!sidebarKoordinat) { alert('Gambar area parsil di peta terlebih dahulu!'); return; } var nama = document.getElementById('sb_nama_parsil').value.trim(); if (!nama) { alert('Nama pemilik wajib diisi!'); return; } var formData = new FormData(); formData.append('nama_pemilik', nama); formData.append('status', document.getElementById('sb_status_parsil').value); formData.append('luas', document.getElementById('sb_luas_parsil').value); formData.append('koordinat', sidebarKoordinat); fetch('save_parsil.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); document.getElementById('sb_nama_parsil').value = ''; document.getElementById('sb_luas_parsil').value = ''; document.getElementById('coords-parsil-val').textContent = 'Belum digambar'; document.getElementById('coords-parsil-val').classList.remove('has-coords'); sidebarKoordinat = ''; drawnItems.clearLayers(); loadParsil(); }).catch(e => console.error(e)); } function saveRumahIbadahSidebar() { var coords = document.getElementById('coords-ibadah-val').textContent; if (coords === 'Belum dipilih') { alert('Pilih lokasi di peta terlebih dahulu!'); return; } var nama = document.getElementById('sb_nama_ibadah').value.trim(); if (!nama) { alert('Nama rumah ibadah wajib diisi!'); return; } var formData = new FormData(); formData.append('nama', nama); formData.append('latitude', sidebarTempLat); formData.append('longitude', sidebarTempLng); fetch('save_rumah_ibadah.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); document.getElementById('sb_nama_ibadah').value = ''; document.getElementById('coords-ibadah-val').textContent = 'Belum dipilih'; document.getElementById('coords-ibadah-val').classList.remove('has-coords'); sidebarTempLat = 0; sidebarTempLng = 0; loadRumahIbadah(); }).catch(e => console.error(e)); } function savePendudukSidebar() { var coords = document.getElementById('coords-penduduk-val').textContent; if (coords === 'Belum dipilih') { alert('Pilih lokasi di peta terlebih dahulu!'); return; } var nama = document.getElementById('sb_nama_penduduk').value.trim(); var alamat = document.getElementById('sb_alamat_penduduk').value.trim(); // Ambil nilai alamat if (!nama) { alert('Nama kepala keluarga wajib diisi!'); return; } if (!alamat) { alert('Alamat wajib diisi!'); return; } // Validasi alamat var formData = new FormData(); formData.append('nama', nama); formData.append('alamat', alamat); // Masukkan ke dalam data form formData.append('latitude', sidebarTempLat); formData.append('longitude', sidebarTempLng); fetch('save_penduduk_miskin.php', { method: 'POST', body: formData }) .then(r => r.text()).then(res => { alert(res); document.getElementById('sb_nama_penduduk').value = ''; document.getElementById('sb_alamat_penduduk').value = ''; // Hanya kosongkan value document.getElementById('coords-penduduk-val').textContent = 'Belum dipilih'; document.getElementById('coords-penduduk-val').classList.remove('has-coords'); sidebarTempLat = 0; sidebarTempLng = 0; loadRumahIbadah(); }).catch(e => console.error(e)); } // ========================================== // 14. LOGIKA CUSTOM DROPDOWN // ========================================== document.addEventListener('DOMContentLoaded', function () { var wrap = document.getElementById('custom-select-wrap'); var trigger = document.getElementById('custom-select-trigger'); var options = document.getElementById('custom-select-options'); var hiddenInput = document.getElementById('search-category'); var optionItems = document.querySelectorAll('.custom-option'); // Buka/Tutup dropdown saat kotak di-klik wrap.addEventListener('click', function (e) { e.stopPropagation(); options.classList.toggle('show'); }); // Saat salah satu pilihan (seperti SPBU atau Jalan) diklik optionItems.forEach(function (item) { item.addEventListener('click', function (e) { e.stopPropagation(); // Hapus status aktif dari yang lain, pasang ke yang di-klik optionItems.forEach(opt => opt.classList.remove('selected')); this.classList.add('selected'); // Ganti teks yang tampil dan simpan nilainya ke input tersembunyi trigger.textContent = this.textContent; hiddenInput.value = this.getAttribute('data-value'); // Tutup dropdown options.classList.remove('show'); // Otomatis jalankan fungsi pencarian (kode aslimu) jalankanPencarian(); }); }); // Tutup dropdown otomatis jika klik area manapun di luar peta/header document.addEventListener('click', function () { options.classList.remove('show'); }); });