1231 lines
63 KiB
PHP
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'">×</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>
|