Files
WebGis/02/index.php
T
2026-06-09 13:50:00 +07:00

1231 lines
63 KiB
PHP

<?php session_start(); ?>
<!DOCTYPE html>
<html>
<head>
<title>WebGIS SPBU, Jalan & Parsil Pontianak</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css"/>
<!-- FontAwesome & AwesomeMarkers -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css" />
<style>
#map { height: 100vh; width: 100%; }
body { margin: 0; font-family: 'Segoe UI', sans-serif; }
/* Popup Modern Design */
.leaflet-popup-content-wrapper { border-radius: 15px; padding: 0; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.2); }
.leaflet-popup-content { width: 280px !important; margin: 0 !important; }
.popup-header { background: #f8f9fa; padding: 12px 15px; border-bottom: 1px solid #eee; }
.popup-header b { font-size: 16px; color: #2c3e50; display: block; }
.popup-body { padding: 12px 15px; font-size: 13px; color: #555; }
/* Layout Grid untuk Baris Informasi di Popup */
.info-row { display: grid; grid-template-columns: 85px 1fr; gap: 10px; margin-bottom: 10px; align-items: start; }
.info-row span { font-size: 12px; color: #7f8c8d; display: flex; align-items: center; gap: 6px; }
.info-row strong { font-size: 13px; font-weight: 600; color: #2c3e50; word-wrap: break-word; line-height: 1.4; }
/* Badges */
.badge { padding: 4px 10px; border-radius: 20px; font-size: 10px; font-weight: bold; text-transform: uppercase; }
.badge-ya { background: #e8f5e9; color: #2e7d32; border: 1px solid #a5d6a7; }
.badge-tidak { background: #ffebee; color: #c62828; border: 1px solid #ef9a9a; }
.popup-footer { display: flex; gap: 8px; padding: 0 15px 15px 15px; }
.btn-action { flex: 1; border: none; padding: 8px; border-radius: 8px; font-size: 12px; font-weight: 600; cursor: pointer; transition: 0.2s; }
.btn-edit { background: #e3f2fd; color: #1976d2; }
.btn-hapus { background: #ffebee; color: #c62828; }
.form-input { width: 100%; padding: 8px; margin-bottom: 8px; border: 1px solid #ddd; border-radius: 6px; box-sizing: border-box; }
/* Panel Tambah Data */
#tambah-panel {
position: fixed;
bottom: 30px;
right: 20px;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 10px;
}
.tambah-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 18px;
border: none;
border-radius: 12px;
font-size: 13px;
font-weight: 700;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
transition: all 0.2s;
white-space: nowrap;
color: white;
}
.tambah-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 15px rgba(0,0,0,0.2); }
.tambah-btn.ibadah { background: linear-gradient(135deg, #1565C0, #2196F3); }
.tambah-btn.penduduk { background: linear-gradient(135deg, #c62828, #ef5350); }
.tambah-btn.spbu { background: linear-gradient(135deg, #2e7d32, #43a047); }
.tambah-btn .btn-icon { font-size: 18px; }
/* Mode kursor saat aktif */
#map.mode-tambah { cursor: crosshair !important; }
/* Panel Dashboard Statistik */
.info-legend {
background: white;
padding: 15px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-size: 13px;
color: #333;
line-height: 1.6;
min-width: 200px;
margin-bottom: 30px !important;
margin-left: 20px !important;
}
.info-legend h4 { margin: 0 0 10px 0; font-size: 14px; color: #2c3e50; border-bottom: 2px solid #eee; padding-bottom: 5px; }
.stat-item { display: flex; justify-content: space-between; font-weight: bold; margin-bottom: 5px;}
.stat-merah { color: #c0392b; }
.stat-hijau { color: #27ae60; }
.stat-kuning { color: #f39c12; }
/* Toast notifikasi */
#toast {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
background: #323232;
color: white;
padding: 12px 24px;
border-radius: 8px;
font-size: 13px;
z-index: 9999;
display: none;
animation: fadeIn 0.3s;
}
@keyframes fadeIn { from { opacity: 0; top: 10px; } to { opacity: 1; top: 20px; } }
/* Modal Login */
.login-btn-top {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
background: #fff;
padding: 10px 24px;
border-radius: 20px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-weight: bold;
font-size: 13px;
cursor: pointer;
border: none;
transition: 0.2s;
display: flex;
align-items: center;
gap: 8px;
text-decoration: none;
color: #333;
}
.login-btn-top:hover { transform: translate(-50%, -2px); box-shadow: 0 6px 15px rgba(0,0,0,0.2); }
.modal-overlay {
display: none;
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 9999;
justify-content: center;
align-items: center;
backdrop-filter: blur(2px);
}
.modal-content {
background: #fff;
padding: 30px;
border-radius: 12px;
width: 100%;
max-width: 300px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
position: relative;
}
.modal-close {
position: absolute;
top: 15px; right: 15px;
cursor: pointer;
font-size: 20px;
color: #aaa;
line-height: 1;
}
.modal-close:hover { color: #333; }
.modal-title { font-size: 18px; font-weight: bold; margin-bottom: 20px; color: #2c3e50; text-align: center; }
</style>
</head>
<body>
<div id="map"></div>
<!-- Tombol Login / Info User -->
<?php if (isset($_SESSION['role'])): ?>
<div class="login-btn-top" style="cursor: default;">
<i class="fa-solid fa-user-shield" style="color:#3498db;"></i> Halo, <?php echo htmlspecialchars($_SESSION['role']); ?>
<a href="logout.php" style="margin-left: 10px; padding: 5px 12px; background: #e74c3c; color: #fff; border-radius: 15px; text-decoration: none; font-size: 11px; font-weight: bold;">🚪 Logout</a>
</div>
<?php else: ?>
<button class="login-btn-top" onclick="document.getElementById('loginModal').style.display='flex'">
🔑 Login Petugas
</button>
<?php endif; ?>
<!-- Modal Login -->
<div id="loginModal" class="modal-overlay">
<div class="modal-content">
<span class="modal-close" onclick="document.getElementById('loginModal').style.display='none'">&times;</span>
<div class="modal-title">🔑 Login WebGIS</div>
<form action="proses_login.php" method="POST">
<label style="font-size:12px; color:#555; display:block; margin-bottom:5px; font-weight:bold;">Username</label>
<input type="text" name="username" class="form-input" required placeholder="Masukkan username" autocomplete="off" style="margin-bottom:15px;">
<label style="font-size:12px; color:#555; display:block; margin-bottom:5px; font-weight:bold;">Password</label>
<input type="password" name="password" class="form-input" required placeholder="Masukkan password" style="margin-bottom:20px;">
<button type="submit" class="btn-action btn-edit" style="width:100%; padding:10px; font-size:14px; background:#3498db; color:white;">Login</button>
</form>
</div>
</div>
<!-- Panel Tombol Tambah Data -->
<div id="tambah-panel">
<?php if (!isset($_SESSION['role'])): ?>
<button class="tambah-btn" style="background: linear-gradient(135deg, #fbc02d, #f57f17); color: black;" onclick="aktivasiModeTambah('lapor_warga')">
<span class="btn-icon">🚨</span> Lapor Warga Telantar
</button>
<?php endif; ?>
<?php if (isset($_SESSION['role']) && $_SESSION['role'] === 'Admin'): ?>
<button class="tambah-btn ibadah" onclick="aktivasiModeTambah('ibadah')">
<span class="btn-icon">🕌</span> Tambah Rumah Ibadah
</button>
<button class="tambah-btn penduduk" onclick="aktivasiModeTambah('penduduk')">
<span class="btn-icon">🏠</span> Tambah Rumah Penduduk
</button>
<?php endif; ?>
</div>
<div id="toast"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.min.js"></script>
<script>
const userRole = '<?php echo isset($_SESSION["role"]) ? $_SESSION["role"] : "Publik"; ?>';
var tempGeoJSON = "";
var tempValue = 0;
var modeTambah = null; // 'ibadah' | 'penduduk' | null
// ── Fungsi toast notif ──────────────────────────────────────
function tampilToast(pesan, durasi = 3000) {
var t = document.getElementById('toast');
t.textContent = pesan;
t.style.display = 'block';
setTimeout(() => { t.style.display = 'none'; }, durasi);
}
// ── Fungsi aktivasi mode tambah via tombol panel ─────────────
function aktivasiModeTambah(jenis) {
if (modeTambah === jenis) {
// Klik lagi = batalkan mode
modeTambah = null;
document.getElementById('map').classList.remove('mode-tambah');
tampilToast('❌ Mode tambah dibatalkan.');
return;
}
modeTambah = jenis;
document.getElementById('map').classList.add('mode-tambah');
let label = jenis === 'ibadah' ? '🕌 Rumah Ibadah' : '🏠 Rumah Penduduk';
tampilToast('📍 Klik di peta untuk menentukan lokasi ' + label + '. Klik tombol lagi untuk batal.', 5000);
}
var map = L.map('map').setView([-0.0263, 109.3425], 13);
var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Layer Groups
var spbu24JamLayer = L.layerGroup();
var spbuBiasaLayer = L.layerGroup();
var ibadahLayer = L.layerGroup().addTo(map);
var pendudukLayer = L.layerGroup().addTo(map);
var jalanLayer = L.layerGroup();
var parsilLayer = L.layerGroup();
var batasWilayahLayer = L.layerGroup().addTo(map);
// ── Load GeoJSON Batas Wilayah ──
fetch('pontianak.geojson')
.then(res => res.json())
.then(data => {
L.geoJSON(data, {
style: {
color: '#34495e', // Warna garis batas (abu-abu gelap kebiruan)
weight: 3,
dashArray: '5, 5', // Efek dashed (putus-putus)
fillColor: 'transparent',
fillOpacity: 0
}
}).addTo(batasWilayahLayer);
})
.catch(err => console.log("Gagal memuat pontianak.geojson (Pastikan file ada):", err));
// Layers Control
var baseMaps = {
"OpenStreetMap": osm
};
var overlayMaps = {
"Batas Wilayah 🗺️": batasWilayahLayer,
"SPBU 24 Jam 🟢": spbu24JamLayer,
"SPBU Tutup Malam 🔴": spbuBiasaLayer,
"Rumah Ibadah 🕌": ibadahLayer,
"Rumah Penduduk 🏠": pendudukLayer,
"Jalan 🛣️": jalanLayer,
"Parsil 🌿": parsilLayer
};
L.control.layers(baseMaps, overlayMaps, { collapsed: false }).addTo(map);
// ── Inisiasi Mini Dashboard Statistik ──
var dashboardControl = L.control({position: 'bottomleft'});
dashboardControl.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info-legend');
this.update(0, 0, 0, 0); // Nilai awal
return this._div;
};
dashboardControl.update = function (total, cover, buta, darurat) {
this._div.innerHTML = `
<h4>📊 Statistik Kemiskinan</h4>
<div class="stat-item">Total Warga Miskin: <span>${total}</span></div>
<div class="stat-item stat-merah">Tercover (Merah): <span>${cover}</span></div>
<div class="stat-item stat-hijau">Titik Buta (Hijau): <span>${buta}</span></div>
<div class="stat-item stat-kuning">Laporan Darurat: <span>${darurat}</span></div>
`;
};
dashboardControl.addTo(map);
// Icons
var greenIcon = new 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 = new 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 yellowIcon = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-yellow.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] });
function hitungUmur(tanggalLahir) {
if (!tanggalLahir) return '-';
let today = new Date();
let birthDate = new Date(tanggalLahir);
let age = today.getFullYear() - birthDate.getFullYear();
let m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
// Fitur Draw (Menggambar)
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var drawControl = new L.Control.Draw({
draw: { polyline: true, polygon: true, circle: false, marker: true, rectangle: false, circlemarker: false },
edit: { featureGroup: drawnItems }
});
map.addControl(drawControl);
// Ikon khusus untuk Rumah Ibadah (biru)
var blueIcon = new 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] });
// ── EVENT KLIK PETA (mode tambah dari panel tombol) ─────────────
var tempMarkerRef = null; // referensi marker sementara global
map.on('click', function handleMapClick(e) {
if (!modeTambah) return;
var lat = e.latlng.lat;
var lng = e.latlng.lng;
var jenis = modeTambah;
// Nonaktifkan mode
modeTambah = null;
document.getElementById('map').classList.remove('mode-tambah');
// Buat marker sementara di peta
var iconTemp = redIcon;
if (jenis === 'ibadah') iconTemp = blueIcon;
if (jenis === 'lapor_warga') iconTemp = yellowIcon;
var tempMarker = L.marker([lat, lng], {
icon: iconTemp
}).addTo(map);
if (jenis === 'ibadah') {
var formHtml = `
<div class="popup-header"><b>🕌 Tambah Rumah Ibadah</b></div>
<div class="popup-body">
<label style="font-size:11px;color:#777;">Nama Rumah Ibadah</label>
<input type="text" id="i_nama" class="form-input" placeholder="Contoh: Masjid Raya">
<label style="font-size:11px;color:#777;">Jenis</label>
<select id="i_jenis" class="form-input">
<option value="Masjid">Masjid</option>
<option value="Gereja">Gereja</option>
<option value="Pura">Pura</option>
<option value="Vihara">Vihara</option>
<option value="Klenteng">Klenteng</option>
<option value="Lainnya">Lainnya</option>
</select>
<label style="font-size:11px;color:#777;">Alamat</label>
<input type="text" id="i_alamat" class="form-input" placeholder="Alamat lengkap">
<label style="font-size:11px;color:#777;">Radius Bantuan (Meter)</label>
<input type="number" id="i_radius" class="form-input" value="500">
<div style="display:flex;gap:5px;margin-top:8px;">
<button class="btn-action btn-edit" onclick="simpanIbadah(${lat}, ${lng})">💾 Simpan</button>
<button class="btn-action" style="background:#eee;color:#555;" onclick="map.closePopup(); map.removeLayer(tempMarkerRef)">Batal</button>
</div>
</div>`;
tempMarker.bindPopup(formHtml, { autoClose: false }).openPopup();
} else if (jenis === 'penduduk' || jenis === 'lapor_warga') {
let statusLaporan = (jenis === 'lapor_warga') ? 'Pending' : 'Terverifikasi';
let headerText = (jenis === 'lapor_warga') ? '🚨 Lapor Warga Telantar' : '🏠 Tambah Rumah Penduduk';
var formHtml = `
<div class="popup-header"><b>${headerText}</b></div>
<div class="popup-body">
<label style="font-size:11px;color:#777;">Nama Kepala Keluarga / Warga</label>
<input type="text" id="p_nama" class="form-input" placeholder="Contoh: Budi Santoso">
<label style="font-size:11px;color:#777;">Jumlah Jiwa</label>
<input type="number" id="p_jiwa" class="form-input" value="1" min="1">
<label style="font-size:11px;color:#777;">Tanggal Lahir</label>
<input type="date" id="p_tanggal_lahir" class="form-input">
<label style="font-size:11px;color:#777;">Pend. Kepala Keluarga</label>
<select id="p_pendidikan" class="form-input">
<option value="Tidak Sekolah">Tidak Sekolah</option>
<option value="SD">SD</option>
<option value="SMP">SMP</option>
<option value="SMA">SMA</option>
<option value="S1">S1</option>
</select>
<label style="font-size:11px;color:#777;">Kondisi Kesehatan Keluarga</label>
<textarea id="p_riwayat_penyakit" class="form-input" rows="2"></textarea>
<label style="font-size:11px;color:#777;">Penghasilan Perbulan (Rp)</label>
<input type="number" id="p_penghasilan" class="form-input" placeholder="Contoh: 1500000">
<input type="hidden" id="p_status_laporan" value="${statusLaporan}">
<div style="display:flex;gap:5px;margin-top:8px;">
<button class="btn-action btn-edit" onclick="simpanPenduduk(${lat}, ${lng})">💾 Simpan</button>
<button class="btn-action" style="background:#eee;color:#555;" onclick="map.closePopup(); map.removeLayer(tempMarkerRef)">Batal</button>
</div>
</div>`;
tempMarker.bindPopup(formHtml, { autoClose: false }).openPopup();
}
// Simpan referensi marker sementara ke variabel global agar bisa dihapus saat batal
tempMarkerRef = tempMarker;
tempMarker.on('popupclose', function() {
// Jika popup ditutup tanpa simpan, hapus marker sementara
setTimeout(() => { if (map.hasLayer(tempMarker)) map.removeLayer(tempMarker); }, 200);
});
});
// 1. LOAD SEMUA DATA (Point, Line, Polygon)
function loadMarkers() {
fetch('ambil.php')
.then(res => res.json())
.then(data => {
// Tampilkan SPBU (Point)
data.spbu.forEach(spbu => {
let is24 = (spbu.status_24jam === 'Ya');
let marker = L.marker([spbu.latitude, spbu.longitude], {
icon: is24 ? greenIcon : redIcon,
draggable: true
});
if (is24) {
spbu24JamLayer.addLayer(marker);
} else {
spbuBiasaLayer.addLayer(marker);
}
marker.on('dragend', function(e) {
updatePosisi(spbu.id, marker.getLatLng().lat, marker.getLatLng().lng);
});
let spbuPopup = `
<div class="popup-header"><b>⛽ ${spbu.nama_spbu}</b></div>
<div class="popup-body">
<div class="info-row"><span>📞 WhatsApp</span> <strong>${spbu.no_telp || '-'}</strong></div>
<div class="info-row"><span>🕒 Status</span> <span class="badge ${is24 ? 'badge-ya' : 'badge-tidak'}">${is24 ? 'Buka 24 Jam' : 'Tutup Malam'}</span></div>`;
if (userRole === 'Admin') {
spbuPopup += `
<div class="popup-footer" style="padding: 15px 0 0 0; margin-top: 10px; border-top: 1px solid #eee;">
<button class="btn-action btn-edit" onclick='tampilFormEditSPBU(${JSON.stringify(spbu)})'>Edit</button>
<button class="btn-action btn-hapus" onclick="hapusData(${spbu.id}, 'spbu')">Hapus</button>
</div>`;
}
spbuPopup += `</div>`;
marker.bindPopup(spbuPopup);
});
// Tampilkan Rumah Ibadah
var ibadahData = data.rumah_ibadah || [];
ibadahData.forEach(ib => {
let iconName = 'place-of-worship';
let ibJenis = ib.jenis.toLowerCase();
if (ibJenis === 'masjid') iconName = 'mosque';
else if (ibJenis === 'gereja') iconName = 'church';
else if (ibJenis === 'vihara') iconName = 'vihara';
else if (ibJenis === 'pura') iconName = 'om';
else if (ibJenis === 'klenteng') iconName = 'torii-gate';
let ibadahIcon = L.AwesomeMarkers.icon({
icon: iconName,
prefix: 'fa',
markerColor: 'blue'
});
let marker = L.marker([ib.latitude, ib.longitude], { icon: ibadahIcon, draggable: true });
ibadahLayer.addLayer(marker);
let radiusCircle = L.circle([ib.latitude, ib.longitude], {
radius: ib.radius_meter,
color: 'blue',
fillColor: '#3388ff',
fillOpacity: 0.1,
weight: 1
});
ibadahLayer.addLayer(radiusCircle);
marker.on('dragend', function(e) {
updatePosisi(ib.id, marker.getLatLng().lat, marker.getLatLng().lng, 'rumah_ibadah');
});
let ibadahPopup = `
<div class="popup-header">
<b><i class="fa-solid fa-${iconName}" style="color:#3498db; margin-right:5px;"></i> ${ib.nama}</b>
</div>
<div class="popup-body">
<div class="info-row"><span><i class="fa-solid fa-tag"></i> Jenis</span> <strong>${ib.jenis}</strong></div>
<div class="info-row"><span><i class="fa-solid fa-map-marker-alt"></i> Alamat</span> <strong>${ib.alamat}</strong></div>
<div class="info-row"><span><i class="fa-solid fa-ruler-horizontal"></i> Radius</span> <strong>${ib.radius_meter} m</strong></div>`;
if (userRole === 'Admin') {
ibadahPopup += `
<div class="popup-footer" style="padding: 15px 0 0 0; margin-top: 10px; border-top: 1px solid #eee;">
<button class="btn-action btn-edit" onclick='tampilFormEditIbadah(${JSON.stringify(ib).replace(/'/g, "\\'")})'><i class="fa-solid fa-pen"></i> Edit</button>
<button class="btn-action btn-hapus" onclick="hapusData(${ib.id}, 'rumah_ibadah')"><i class="fa-solid fa-trash"></i> Hapus</button>
</div>`;
}
ibadahPopup += `</div>`;
marker.bindPopup(ibadahPopup);
});
// Tampilkan Penduduk Miskin
var pendudukData = data.penduduk_miskin || [];
// Variabel Statistik
let statTotal = 0;
let statCover = 0;
let statButa = 0;
let statDarurat = 0;
pendudukData.forEach(p => {
statTotal++;
let isCovered = false;
let ibadahCoverName = '';
let pt = turf.point([p.longitude, p.latitude]);
ibadahData.forEach(ib => {
let ibPt = turf.point([ib.longitude, ib.latitude]);
let dist = turf.distance(pt, ibPt, {units: 'meters'});
if (dist <= ib.radius_meter) {
isCovered = true;
ibadahCoverName = ib.nama;
}
});
let pIconColor = isCovered ? 'red' : 'green';
if (p.status_laporan === 'Pending') {
pIconColor = 'orange'; // Untuk AwesomeMarkers
statDarurat++;
} else {
if (isCovered) statCover++;
else statButa++;
}
let pIconAwesome = L.AwesomeMarkers.icon({
icon: 'home',
prefix: 'fa',
markerColor: pIconColor
});
let umur = hitungUmur(p.tanggal_lahir);
let historiHtml = '';
if (p.histori_bantuan && p.histori_bantuan.length > 0) {
p.histori_bantuan.forEach(h => {
historiHtml += `<div style="font-size:11px; margin-bottom:4px; padding:4px; background:#f8f9fa; border-radius:4px; border-left:3px solid #28a745;">
<b style="color:#555;">[${h.tanggal}]</b> ${h.deskripsi_bantuan}
</div>`;
});
} else {
historiHtml = `<div style="font-size:11px; color:#888; font-style:italic;">Belum ada bantuan</div>`;
}
let penghasilanFormat = p.penghasilan_perbulan ? parseInt(p.penghasilan_perbulan).toLocaleString('id-ID') : '-';
let marker = L.marker([p.latitude, p.longitude], { icon: pIconAwesome, draggable: true });
pendudukLayer.addLayer(marker);
marker.on('dragend', function(e) {
updatePosisi(p.id, marker.getLatLng().lat, marker.getLatLng().lng, 'penduduk_miskin');
});
let pendudukPopup = `
<div class="popup-header"><b>🏠 ${p.nama_kepala}</b></div>
<div class="popup-body">
<div class="info-row"><span>👥 Jumlah Jiwa</span> <strong>${p.jumlah_jiwa}</strong></div>
<div class="info-row"><span>📅 Umur</span> <strong>${umur} thn</strong></div>
<div class="info-row"><span>🎓 Pend. Kepala Keluarga</span> <strong>${p.pendidikan || '-'}</strong></div>
<div class="info-row"><span>🏥 Kondisi Kesehatan Keluarga</span> <strong>${p.riwayat_penyakit || '-'}</strong></div>
<div class="info-row"><span>💰 Penghasilan</span> <strong>Rp ${penghasilanFormat}</strong></div>
<div class="info-row"><span>📌 Status</span> <strong>${p.status_laporan === 'Pending' ? '<span style="color:orange;">Pending Verifikasi</span>' : '<span style="color:green;">Terverifikasi</span>'}</strong></div>
<div class="info-row"><span>🆘 Cover Radius</span> <strong>${isCovered ? '<span style="color:red">Dari ' + ibadahCoverName + '</span>' : '<span style="color:green">Luar Radius</span>'}</strong></div>
<hr style="margin: 8px 0; border: 0; border-top: 1px solid #eee;">
<b style="font-size: 11px;">Riwayat Bantuan Sebelumnya:</b>
<div style="margin-bottom: 8px; max-height: 80px; overflow-y: auto;">
${historiHtml}
</div>`;
if (userRole === 'Rumah_Ibadah') {
pendudukPopup += `
<hr style="margin: 8px 0; border: 0; border-top: 1px solid #eee;">
<b style="font-size: 11px;">Catat Bantuan Diberikan:</b>
<div style="margin-bottom: 8px;">
<textarea id="deskripsi_bantuan_${p.id}" class="form-input" placeholder="Misal: Beras 5kg..." style="margin-bottom: 4px;" rows="2"></textarea>
<button type="button" class="btn-action" style="background:#28a745; color:white; width:100%;" onclick="submitBantuan(${p.id})">Simpan Bantuan</button>
</div>`;
}
if (userRole === 'Admin') {
let btnVerifikasi = '';
if (p.status_laporan === 'Pending') {
btnVerifikasi = `<button class="btn-action" style="background:#27ae60; color:white; width:100%; margin-bottom:8px; font-weight:bold;" onclick="verifikasiWarga(${p.id})">✅ Verifikasi Warga Ini</button>`;
}
pendudukPopup += `
<div class="popup-footer" style="padding: 10px 0 0 0; display:flex; flex-direction:column;">
${btnVerifikasi}
<div style="display:flex; gap:8px; width:100%;">
<button class="btn-action btn-edit" onclick='tampilFormEditPenduduk(${JSON.stringify(p).replace(/'/g, "\\'")})'>✏️ Edit</button>
<button class="btn-action btn-hapus" onclick="hapusData(${p.id}, 'penduduk_miskin')"><i class="fa-solid fa-trash"></i> Hapus</button>
</div>
</div>`;
}
pendudukPopup += `</div>`;
marker.bindPopup(pendudukPopup);
});
// Update Dashboard
dashboardControl.update(statTotal, statCover, statButa, statDarurat);
// Tampilkan Jalan (Line)
data.jalan.forEach(j => {
let warna = j.status_jalan == 'Nasional' ? 'red' : (j.status_jalan == 'Provinsi' ? 'blue' : 'green');
let jalanGeoJSON = L.geoJSON(JSON.parse(j.geojson), { style: {color: warna, weight: 5} });
let jalanPopup = `
<div class="popup-header"><b>🛣️ Jalan: ${j.nama_jalan}</b></div>
<div class="popup-body">
<div class="info-row"><span>📌 Status</span> <strong>${j.status_jalan}</strong></div>
<div class="info-row"><span>📏 Panjang</span> <strong>${j.panjang_m} m</strong></div>`;
if (userRole === 'Admin') {
jalanPopup += `
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick='tampilFormEditJalan(${JSON.stringify(j).replace(/'/g, "\\'")})'>✏️ Edit</button>
<button class="btn-action btn-hapus" onclick="hapusData(${j.id}, 'data_jalan')">🗑️ Hapus</button>
</div>`;
}
jalanPopup += `</div>`;
jalanGeoJSON.bindPopup(jalanPopup);
jalanLayer.addLayer(jalanGeoJSON);
});
// Tampilkan Parsil (Polygon)
data.parsil.forEach(p => {
let parsilGeoJSON = L.geoJSON(JSON.parse(p.geojson), { style: {fillColor: 'orange', color: 'black', weight: 1} });
let parsilPopup = `
<div class="popup-header"><b>🌿 Pemilik: ${p.pemilik}</b></div>
<div class="popup-body">
<div class="info-row"><span>📜 Status</span> <strong>${p.status_milik}</strong></div>
<div class="info-row"><span>📐 Luas</span> <strong>${p.luas_m2} m²</strong></div>`;
if (userRole === 'Admin') {
parsilPopup += `
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick='tampilFormEditParsil(${JSON.stringify(p).replace(/'/g, "\\'")})'>✏️ Edit</button>
<button class="btn-action btn-hapus" onclick="hapusData(${p.id}, 'data_parsil')">🗑️ Hapus</button>
</div>`;
}
parsilPopup += `</div>`;
parsilGeoJSON.bindPopup(parsilPopup);
parsilLayer.addLayer(parsilGeoJSON);
});
});
}
function tampilFormEditIbadah(data) {
let formEdit = `
<div class="popup-body">
<b>✏️ Edit Rumah Ibadah</b><br>
<input type="hidden" id="edit_i_id" value="${data.id}">
<label style="font-size:11px; color:#777;">Nama:</label>
<input type="text" id="edit_i_nama" class="form-input" value="${data.nama}">
<label style="font-size:11px; color:#777;">Jenis:</label>
<select id="edit_i_jenis" class="form-input">
<option value="Masjid" ${data.jenis=='Masjid'?'selected':''}>Masjid</option>
<option value="Gereja" ${data.jenis=='Gereja'?'selected':''}>Gereja</option>
<option value="Pura" ${data.jenis=='Pura'?'selected':''}>Pura</option>
<option value="Vihara" ${data.jenis=='Vihara'?'selected':''}>Vihara</option>
<option value="Klenteng" ${data.jenis=='Klenteng'?'selected':''}>Klenteng</option>
<option value="Lainnya" ${data.jenis=='Lainnya'?'selected':''}>Lainnya</option>
</select>
<label style="font-size:11px; color:#777;">Alamat:</label>
<input type="text" id="edit_i_alamat" class="form-input" value="${data.alamat}">
<label style="font-size:11px; color:#777;">Radius (m):</label>
<input type="number" id="edit_i_radius" class="form-input" value="${data.radius_meter}">
<div style="display:flex; gap:5px; margin-top:10px;">
<button class="btn-action btn-edit" onclick="prosesUpdateIbadah(${data.latitude}, ${data.longitude})">💾 Simpan</button>
<button class="btn-action" style="background:#eee; color:#333;" onclick="map.closePopup()">Batal</button>
</div>
</div>`;
L.popup().setLatLng([data.latitude, data.longitude]).setContent(formEdit).openOn(map);
}
function tampilFormEditPenduduk(data) {
let formEdit = `
<div class="popup-body" style="max-height:300px; overflow-y:auto;">
<b>✏️ Edit Rumah Penduduk</b><br>
<input type="hidden" id="edit_p_id" value="${data.id}">
<label style="font-size:11px; color:#777;">Nama Kepala:</label>
<input type="text" id="edit_p_nama" class="form-input" value="${data.nama_kepala}">
<label style="font-size:11px; color:#777;">Jumlah Jiwa:</label>
<input type="number" id="edit_p_jiwa" class="form-input" value="${data.jumlah_jiwa}">
<label style="font-size:11px; color:#777;">Tanggal Lahir:</label>
<input type="date" id="edit_p_tanggal_lahir" class="form-input" value="${data.tanggal_lahir || ''}">
<label style="font-size:11px; color:#777;">Pend. Kepala Keluarga:</label>
<select id="edit_p_pendidikan" class="form-input">
<option value="Tidak Sekolah" ${data.pendidikan=='Tidak Sekolah'?'selected':''}>Tidak Sekolah</option>
<option value="SD" ${data.pendidikan=='SD'?'selected':''}>SD</option>
<option value="SMP" ${data.pendidikan=='SMP'?'selected':''}>SMP</option>
<option value="SMA" ${data.pendidikan=='SMA'?'selected':''}>SMA</option>
<option value="S1" ${data.pendidikan=='S1'?'selected':''}>S1</option>
</select>
<label style="font-size:11px; color:#777;">Kondisi Kesehatan Keluarga:</label>
<textarea id="edit_p_riwayat_penyakit" class="form-input" rows="2">${data.riwayat_penyakit || ''}</textarea>
<label style="font-size:11px; color:#777;">Penghasilan Perbulan (Rp):</label>
<input type="number" id="edit_p_penghasilan" class="form-input" value="${data.penghasilan_perbulan || ''}">
<label style="font-size:11px; color:#777;">Pilih Ibadah Cover (ID):</label>
<input type="text" id="edit_p_ibadah_id" class="form-input" placeholder="Kosongkan jika tidak ada" value="${data.ibadah_id || ''}">
<div style="display:flex; gap:5px; margin-top:10px;">
<button class="btn-action btn-edit" onclick="prosesUpdatePenduduk(${data.latitude}, ${data.longitude})">💾 Simpan</button>
<button class="btn-action" style="background:#eee; color:#333;" onclick="map.closePopup()">Batal</button>
</div>
</div>`;
L.popup().setLatLng([data.latitude, data.longitude]).setContent(formEdit).openOn(map);
}
function tampilFormEditSPBU(data) {
// Membuat konten HTML formulir edit dengan data lama yang sudah terisi
let formEdit = `
<div class="popup-body">
<b>✏️ Edit Data SPBU</b><br>
<input type="hidden" id="edit_id" value="${data.id}">
<label style="font-size:11px; color:#777;">Nama SPBU:</label>
<input type="text" id="edit_nama" class="form-input" value="${data.nama_spbu}" placeholder="Nama SPBU">
<label style="font-size:11px; color:#777;">No. WhatsApp:</label>
<input type="text" id="edit_telp" class="form-input" value="${data.no_telp}" placeholder="No Telp">
<label style="font-size:11px; color:#777;">Status 24 Jam:</label>
<select id="edit_status" class="form-input">
<option value="Ya" ${data.status_24jam == 'Ya' ? 'selected' : ''}>Buka 24 Jam</option>
<option value="Tidak" ${data.status_24jam == 'Tidak' ? 'selected' : ''}>Tutup Malam</option>
</select>
<div style="display:flex; gap:5px;">
<button class="btn-action btn-edit" onclick="prosesUpdateSPBU(${data.latitude}, ${data.longitude})">💾 Simpan Perubahan</button>
<button class="btn-action" style="background:#eee; color:#333;" onclick="map.closePopup()">Batal</button>
</div>
</div>`;
// Membuka popup baru di lokasi SPBU tersebut dengan konten formulir edit
L.popup()
.setLatLng([data.latitude, data.longitude])
.setContent(formEdit)
.openOn(map);
}
/**
* 2. Fungsi Edit Data
*/
function tampilFormEditJalan(data) {
let formEdit = `
<div class="popup-header"><b>✏️ Edit Jalan</b></div>
<div class="popup-body">
<input type="hidden" id="edit_j_id" value="${data.id}">
<label style="font-size:11px; color:#777;">Nama Jalan:</label>
<input type="text" id="edit_j_nama" class="form-input" value="${data.nama_jalan}">
<label style="font-size:11px; color:#777;">Status Jalan:</label>
<select id="edit_j_status" class="form-input">
<option value="Nasional" ${data.status_jalan == 'Nasional' ? 'selected' : ''}>Nasional</option>
<option value="Provinsi" ${data.status_jalan == 'Provinsi' ? 'selected' : ''}>Provinsi</option>
<option value="Kabupaten" ${data.status_jalan == 'Kabupaten' ? 'selected' : ''}>Kabupaten</option>
</select>
<div style="display:flex; gap:5px;">
<button class="btn-action btn-edit" onclick="prosesUpdateJalan()">💾 Simpan Perubahan</button>
<button class="btn-action" style="background:#eee; color:#333;" onclick="map.closePopup()">Batal</button>
</div>
</div>`;
// Untuk jalan, popup kita taruh di koordinat pertama feature geojson
let geometry = JSON.parse(data.geojson).geometry;
let latlng = [geometry.coordinates[0][1], geometry.coordinates[0][0]];
if(geometry.type === "MultiLineString") latlng = [geometry.coordinates[0][0][1], geometry.coordinates[0][0][0]];
L.popup().setLatLng(latlng).setContent(formEdit).openOn(map);
}
function prosesUpdateJalan() {
let fd = new FormData();
fd.append('type', 'jalan');
fd.append('id', document.getElementById('edit_j_id').value);
fd.append('nama_jalan', document.getElementById('edit_j_nama').value);
fd.append('status_jalan', document.getElementById('edit_j_status').value);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => { alert(txt); location.reload(); });
}
function tampilFormEditParsil(data) {
let formEdit = `
<div class="popup-header"><b>✏️ Edit Parsil</b></div>
<div class="popup-body">
<input type="hidden" id="edit_p_id" value="${data.id}">
<label style="font-size:11px; color:#777;">Nama Pemilik:</label>
<input type="text" id="edit_p_pemilik" class="form-input" value="${data.pemilik}">
<label style="font-size:11px; color:#777;">Status Kepemilikan:</label>
<select id="edit_p_status" class="form-input">
<option value="SHM" ${data.status_milik == 'SHM' ? 'selected' : ''}>SHM</option>
<option value="HGB" ${data.status_milik == 'HGB' ? 'selected' : ''}>HGB</option>
</select>
<div style="display:flex; gap:5px;">
<button class="btn-action btn-edit" onclick="prosesUpdateParsil()">💾 Simpan Perubahan</button>
<button class="btn-action" style="background:#eee; color:#333;" onclick="map.closePopup()">Batal</button>
</div>
</div>`;
// Untuk parsil, popup ditaruh di koordinat pertama polygon
let geometry = JSON.parse(data.geojson).geometry;
let coords = geometry.coordinates[0][0];
if(geometry.type === "MultiPolygon") coords = geometry.coordinates[0][0][0];
let latlng = [coords[1], coords[0]];
L.popup().setLatLng(latlng).setContent(formEdit).openOn(map);
}
function prosesUpdateParsil() {
let fd = new FormData();
fd.append('type', 'parsil');
fd.append('id', document.getElementById('edit_p_id').value);
fd.append('pemilik', document.getElementById('edit_p_pemilik').value);
fd.append('status_milik', document.getElementById('edit_p_status').value);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => { alert(txt); location.reload(); });
}
function prosesUpdateIbadah(lat, lng) {
let fd = new FormData();
fd.append('type', 'rumah_ibadah');
fd.append('id', document.getElementById('edit_i_id').value);
fd.append('nama', document.getElementById('edit_i_nama').value);
fd.append('jenis', document.getElementById('edit_i_jenis').value);
fd.append('alamat', document.getElementById('edit_i_alamat').value);
fd.append('radius_meter', document.getElementById('edit_i_radius').value);
fd.append('latitude', lat);
fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => { alert(txt); location.reload(); });
}
function prosesUpdatePenduduk(lat, lng) {
let fd = new FormData();
fd.append('type', 'penduduk_miskin');
fd.append('id', document.getElementById('edit_p_id').value);
fd.append('nama_kepala', document.getElementById('edit_p_nama').value);
fd.append('jumlah_jiwa', document.getElementById('edit_p_jiwa').value);
fd.append('tanggal_lahir', document.getElementById('edit_p_tanggal_lahir').value);
fd.append('pendidikan', document.getElementById('edit_p_pendidikan').value);
fd.append('riwayat_penyakit', document.getElementById('edit_p_riwayat_penyakit').value);
fd.append('penghasilan_perbulan', document.getElementById('edit_p_penghasilan').value);
fd.append('ibadah_id', document.getElementById('edit_p_ibadah_id').value);
fd.append('latitude', lat);
fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => { alert(txt); location.reload(); });
}
function prosesUpdateSPBU(lat, lng) {
const id = document.getElementById('edit_id').value;
const nama = document.getElementById('edit_nama').value;
const telp = document.getElementById('edit_telp').value;
const status = document.getElementById('edit_status').value;
let fd = new FormData();
fd.append('id', id);
fd.append('nama_spbu', nama);
fd.append('no_telp', telp);
fd.append('status_24jam', status);
fd.append('latitude', lat);
fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => {
if (txt.toLowerCase().includes("berhasil")) {
alert("✅ Perubahan disimpan!");
location.reload();
} else {
alert("Respon: " + txt);
location.reload();
}
});
}
// Fungsi Hapus Tambahan (Agar fitur di ambil.php terpakai)
function hapusData(id, tabel) {
if(confirm("Apakah Anda yakin ingin menghapus data ini?")) {
let fd = new FormData();
fd.append('hapus_id', id);
fd.append('tabel', tabel);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => {
if (txt.includes("Berhasil")) {
alert("🗑️ Data telah terhapus!");
location.reload(); // Hanya reload jika benar-benar berhasil
} else {
alert("Gagal: " + txt);
}
})
.catch(err => console.error("Error:", err));
}
}
loadMarkers();
var tempMarkerLat = 0;
var tempMarkerLng = 0;
var tempMarkerLayer = null;
// 2. EVENT SAAT SELESAI MENGGAMBAR
map.on(L.Draw.Event.CREATED, function (event) {
var layer = event.layer;
var type = event.layerType;
drawnItems.addLayer(layer);
// Simpan GeoJSON ke variabel global agar tidak perlu dikirim lewat parameter onclick
tempGeoJSON = JSON.stringify(layer.toGeoJSON());
if (type === 'marker') {
tempMarkerLat = layer.getLatLng().lat;
tempMarkerLng = layer.getLatLng().lng;
tempMarkerLayer = layer;
tampilPilihanMarker();
} else if (type === 'polyline') {
tempValue = turf.length(layer.toGeoJSON(), {units: 'meters'}).toFixed(2);
tampilFormJalan(layer);
} else if (type === 'polygon') {
tempValue = turf.area(layer.toGeoJSON()).toFixed(2);
tampilFormParsil(layer);
}
});
// --- FORM POPUP ---
function tampilPilihanMarker() {
let form = `
<div class="popup-header"><b>Pilih Jenis Marker</b></div>
<div class="popup-body" style="text-align:center; display:flex; flex-direction:column; gap:5px;">
<button class="btn-action" style="background:#4CAF50; color:white;" onclick="tampilFormSPBU()">⛽ SPBU</button>
<button class="btn-action" style="background:#2196F3; color:white;" onclick="tampilFormIbadah()">🕌 Rumah Ibadah</button>
<button class="btn-action" style="background:#f44336; color:white;" onclick="tampilFormPenduduk()">🏠 Rumah Penduduk</button>
</div>
`;
tempMarkerLayer.bindPopup(form).openPopup();
}
function tampilFormSPBU() {
let form = `<div class="popup-header"><b>⛽ Tambah SPBU</b></div>
<div class="popup-body">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Nama SPBU</label>
<input type="text" id="nama" class="form-input" placeholder="Contoh: SPBU Pertamina">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">No. WhatsApp</label>
<input type="text" id="telp" class="form-input" placeholder="Contoh: 08123456789">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Status 24 Jam</label>
<select id="status" class="form-input"><option value="Ya">Buka 24 Jam</option><option value="Tidak">Tutup Malam</option></select>
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick="simpanData(tempMarkerLat, tempMarkerLng)">💾 Simpan Lokasi</button>
</div>
</div>`;
tempMarkerLayer.bindPopup(form).openPopup();
}
function tampilFormIbadah() {
let form = `<div class="popup-header"><b>🕌 Tambah Rumah Ibadah</b></div>
<div class="popup-body">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Nama Rumah Ibadah</label>
<input type="text" id="i_nama" class="form-input" placeholder="Contoh: Masjid Raya">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Jenis</label>
<select id="i_jenis" class="form-input">
<option value="Masjid">Masjid</option>
<option value="Gereja">Gereja</option>
<option value="Pura">Pura</option>
<option value="Vihara">Vihara</option>
<option value="Klenteng">Klenteng</option>
<option value="Lainnya">Lainnya</option>
</select>
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Alamat</label>
<input type="text" id="i_alamat" class="form-input" placeholder="Alamat">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Radius (Meter)</label>
<input type="number" id="i_radius" class="form-input" value="500">
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick="simpanIbadah(tempMarkerLat, tempMarkerLng)">💾 Simpan Lokasi</button>
</div>
</div>`;
tempMarkerLayer.bindPopup(form).openPopup();
}
function tampilFormPenduduk() {
let form = `<div class="popup-header"><b>🏠 Tambah Rumah Penduduk</b></div>
<div class="popup-body" style="max-height:300px; overflow-y:auto;">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Nama Kepala Keluarga</label>
<input type="text" id="p_nama" class="form-input" placeholder="Contoh: Budi">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Jumlah Jiwa</label>
<input type="number" id="p_jiwa" class="form-input" value="1">
<label style="font-size:11px;color:#777;">Tanggal Lahir</label>
<input type="date" id="p_tanggal_lahir" class="form-input">
<label style="font-size:11px;color:#777;">Pend. Kepala Keluarga</label>
<select id="p_pendidikan" class="form-input">
<option value="Tidak Sekolah">Tidak Sekolah</option>
<option value="SD">SD</option>
<option value="SMP">SMP</option>
<option value="SMA">SMA</option>
<option value="S1">S1</option>
</select>
<label style="font-size:11px;color:#777;">Kondisi Kesehatan Keluarga</label>
<textarea id="p_riwayat_penyakit" class="form-input" rows="2"></textarea>
<label style="font-size:11px;color:#777;">Penghasilan Perbulan (Rp)</label>
<input type="number" id="p_penghasilan" class="form-input" placeholder="Contoh: 1500000">
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick="simpanPenduduk(tempMarkerLat, tempMarkerLng)">💾 Simpan Lokasi</button>
</div>
</div>`;
tempMarkerLayer.bindPopup(form).openPopup();
}
function tampilFormJalan(layer) {
let form = `<div class="popup-header"><b>🛣️ Tambah Jalan</b></div>
<div class="popup-body">
<div class="info-row"><span>Panjang</span><strong>${tempValue} m</strong></div>
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Nama Jalan</label>
<input type="text" id="nama_j" class="form-input" placeholder="Contoh: Jl. Gajah Mada">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Status Jalan</label>
<select id="status_j" class="form-input">
<option value="Nasional">Nasional</option>
<option value="Provinsi">Provinsi</option>
<option value="Kabupaten">Kabupaten</option>
</select>
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick="simpanJalan()">💾 Simpan Jalan</button>
</div>
</div>`;
layer.bindPopup(form).openPopup();
}
function tampilFormParsil(layer) {
let form = `<div class="popup-header"><b>🌿 Tambah Parsil</b></div>
<div class="popup-body">
<div class="info-row"><span>Luas</span><strong>${tempValue} m²</strong></div>
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Nama Pemilik</label>
<input type="text" id="pemilik" class="form-input" placeholder="Contoh: Budi Santoso">
<label style="font-size:12px; color:#555; margin-bottom:4px; display:block;">Status Kepemilikan</label>
<select id="status_p" class="form-input">
<option value="SHM">SHM</option>
<option value="HGB">HGB</option>
</select>
<div class="popup-footer" style="padding: 10px 0 0 0;">
<button class="btn-action btn-edit" onclick="simpanParsil()">💾 Simpan Parsil</button>
</div>
</div>`;
layer.bindPopup(form).openPopup();
}
// --- FUNGSI SIMPAN (AJAX) ---
function simpanData(lat, lng) {
let fd = new FormData();
fd.append('nama_spbu', document.getElementById('nama').value);
fd.append('no_telp', document.getElementById('telp').value);
fd.append('status_24jam', document.getElementById('status').value);
fd.append('latitude', lat); fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd }).then(() => location.reload());
}
function simpanIbadah(lat, lng) {
let fd = new FormData();
fd.append('type', 'rumah_ibadah');
fd.append('nama', document.getElementById('i_nama').value);
fd.append('jenis', document.getElementById('i_jenis').value);
fd.append('alamat', document.getElementById('i_alamat').value);
fd.append('radius_meter', document.getElementById('i_radius').value);
fd.append('latitude', lat);
fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd }).then(() => location.reload());
}
function simpanPenduduk(lat, lng) {
let fd = new FormData();
fd.append('type', 'penduduk_miskin');
fd.append('nama_kepala', document.getElementById('p_nama') ? document.getElementById('p_nama').value : '');
fd.append('jumlah_jiwa', document.getElementById('p_jiwa') ? document.getElementById('p_jiwa').value : 1);
if (document.getElementById('p_tanggal_lahir')) fd.append('tanggal_lahir', document.getElementById('p_tanggal_lahir').value);
if (document.getElementById('p_pendidikan')) fd.append('pendidikan', document.getElementById('p_pendidikan').value);
if (document.getElementById('p_riwayat_penyakit')) fd.append('riwayat_penyakit', document.getElementById('p_riwayat_penyakit').value);
if (document.getElementById('p_penghasilan')) fd.append('penghasilan_perbulan', document.getElementById('p_penghasilan').value);
if (document.getElementById('p_status_laporan')) fd.append('status_laporan', document.getElementById('p_status_laporan').value);
fd.append('latitude', lat);
fd.append('longitude', lng);
fetch('ambil.php', { method: 'POST', body: fd }).then(() => location.reload());
}
function submitBantuan(penduduk_id) {
let deskripsi = document.getElementById('deskripsi_bantuan_' + penduduk_id).value;
if (!deskripsi) { alert('Harap isi deskripsi bantuan.'); return; }
let fd = new FormData();
fd.append('type', 'catat_bantuan');
fd.append('penduduk_id', penduduk_id);
fd.append('deskripsi_bantuan', deskripsi);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => {
map.closePopup();
// Refresh data tanpa reload halaman penuh untuk UX yang halus
spbu24JamLayer.clearLayers();
spbuBiasaLayer.clearLayers();
ibadahLayer.clearLayers();
pendudukLayer.clearLayers();
jalanLayer.clearLayers();
parsilLayer.clearLayers();
loadMarkers();
tampilToast('✅ Bantuan berhasil dicatat!', 3000);
})
.catch(err => {
console.error(err);
alert('Gagal mencatat bantuan.');
});
}
function verifikasiWarga(id) {
let fd = new FormData();
fd.append('type', 'verifikasi_warga');
fd.append('id', id);
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.json())
.then(data => {
if(data.status === 'success') {
map.closePopup();
spbu24JamLayer.clearLayers();
spbuBiasaLayer.clearLayers();
ibadahLayer.clearLayers();
pendudukLayer.clearLayers();
jalanLayer.clearLayers();
parsilLayer.clearLayers();
loadMarkers();
tampilToast('✅ Warga berhasil diverifikasi!', 3000);
} else {
alert('Gagal: ' + data.message);
}
})
.catch(err => {
console.error(err);
alert('Gagal memverifikasi warga.');
});
}
function simpanJalan() {
const fd = new FormData();
fd.append('type', 'jalan');
fd.append('nama_jalan', document.getElementById('nama_j').value);
fd.append('status_jalan', document.getElementById('status_j').value);
fd.append('panjang_m', tempValue);
fd.append('geojson', tempGeoJSON); // Ambil dari variabel global
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => {
alert(txt);
location.reload();
});
}
function simpanParsil() {
let fd = new FormData();
fd.append('type', 'parsil');
fd.append('pemilik', document.getElementById('pemilik').value);
fd.append('status_milik', document.getElementById('status_p').value);
fd.append('luas_m2', tempValue);
fd.append('geojson', tempGeoJSON); // Ambil dari variabel global
fetch('ambil.php', { method: 'POST', body: fd })
.then(res => res.text())
.then(txt => {
alert(txt);
location.reload();
});
}
function updatePosisi(id, lat, lng, tabel = 'spbu') {
let fd = new FormData();
fd.append('action', 'update_posisi'); // Tambahkan flag action
fd.append('id', id);
fd.append('lat', lat);
fd.append('lng', lng);
fd.append('tabel', tabel);
fetch('ambil.php', { method: 'POST', body: fd });
}
// Handle Error Login via URL parameter
const urlParams = new URLSearchParams(window.location.search);
if(urlParams.has('error')) {
alert('❌ Login Gagal! Username atau Password salah.');
// Bersihkan URL agar alert tidak muncul terus-menerus saat di-reload
window.history.replaceState({}, document.title, window.location.pathname);
// Tampilkan modal lagi
document.getElementById('loginModal').style.display = 'flex';
}
</script>
</body>
</html>