861 lines
36 KiB
HTML
861 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="id">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>WebGIS Pontianak - Pemetaan Rumah Ibadah & Penduduk Miskin</title>
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.css" />
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
|
||
#map { height: 100vh; width: 100%; }
|
||
|
||
/* LAYER CONTROL - POSISI OTOMATIS DI KANAN ATAS */
|
||
|
||
/* STATISTIK - DI BAWAH LAYER CONTROL */
|
||
.stats-panel {
|
||
position: absolute;
|
||
top: 110px;
|
||
right: 10px;
|
||
background: white;
|
||
padding: 8px 10px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||
z-index: 1000;
|
||
width: 190px;
|
||
font-size: 11px;
|
||
}
|
||
.stats-panel h4 {
|
||
margin: 0 0 5px 0;
|
||
color: #2c3e50;
|
||
border-bottom: 2px solid #3498db;
|
||
padding-bottom: 3px;
|
||
font-size: 12px;
|
||
}
|
||
.stats-panel .count { font-size: 15px; font-weight: bold; }
|
||
.stats-panel .green { color: #27ae60; }
|
||
.stats-panel .purple { color: #9b59b6; }
|
||
.stats-panel .red { color: #e74c3c; }
|
||
.stats-panel hr { margin: 4px 0; }
|
||
|
||
/* RADIUS - PALING BAWAH KANAN */
|
||
.radius-control {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
right: 20px;
|
||
background: white;
|
||
padding: 8px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||
z-index: 900;
|
||
width: 200px;
|
||
font-size: 11px;
|
||
}
|
||
.radius-control h4 {
|
||
margin: 0 0 6px 0;
|
||
color: #2c3e50;
|
||
font-size: 12px;
|
||
}
|
||
.radius-control input { width: 100%; padding: 4px; margin: 4px 0; }
|
||
.radius-control button {
|
||
width: 100%;
|
||
padding: 5px;
|
||
background: #3498db;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
margin-top: 4px;
|
||
font-size: 11px;
|
||
}
|
||
.radius-value {
|
||
font-weight: bold;
|
||
color: #e67e22;
|
||
text-align: center;
|
||
margin-top: 4px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
/* MAP SELECTOR - KIRI ATAS */
|
||
.map-selector {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
background: white;
|
||
padding: 6px 10px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||
z-index: 1000;
|
||
font-size: 11px;
|
||
}
|
||
|
||
/* FILTER BUTTONS - KIRI BAWAH MAP SELECTOR */
|
||
.filter-buttons {
|
||
position: absolute;
|
||
top: 70px;
|
||
left: 20px;
|
||
background: white;
|
||
padding: 6px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||
z-index: 1000;
|
||
display: flex;
|
||
gap: 5px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.filter-buttons button {
|
||
padding: 4px 8px;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 10px;
|
||
font-weight: bold;
|
||
}
|
||
.filter-btn-all { background: #3498db; color: white; }
|
||
.filter-btn-masjid { background: #27ae60; color: white; }
|
||
.filter-btn-gereja { background: #9b59b6; color: white; }
|
||
.filter-btn-poverty { background: #e74c3c; color: white; }
|
||
|
||
/* LEGEND - KIRI BAWAH */
|
||
.legend {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 20px;
|
||
background: white;
|
||
padding: 6px 8px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
||
z-index: 1000;
|
||
font-size: 10px;
|
||
pointer-events: none;
|
||
}
|
||
.legend span {
|
||
display: inline-block;
|
||
width: 12px;
|
||
height: 12px;
|
||
margin-right: 4px;
|
||
vertical-align: middle;
|
||
}
|
||
.legend .masjid-icon { background: #27ae60; border-radius: 50%; width: 8px; height: 8px; }
|
||
.legend .gereja-icon { background: #9b59b6; border-radius: 50%; width: 8px; height: 8px; }
|
||
.legend .poverty-icon { background: #e74c3c; border-radius: 50%; width: 8px; height: 8px; display: inline-block; }
|
||
.legend .radius-icon { background: #3498db; border-radius: 50%; width: 8px; height: 8px; }
|
||
|
||
/* INSTRUCTION - TENGAH BAWAH */
|
||
.instruction-box {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(0,0,0,0.7);
|
||
color: white;
|
||
padding: 4px 10px;
|
||
border-radius: 20px;
|
||
font-size: 10px;
|
||
z-index: 1000;
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* TOAST */
|
||
.toast-notification {
|
||
position: fixed;
|
||
bottom: 30px;
|
||
right: 30px;
|
||
background: #2c3e50;
|
||
color: white;
|
||
padding: 6px 12px;
|
||
border-radius: 8px;
|
||
z-index: 2000;
|
||
animation: fadeOut 3s ease forwards;
|
||
font-size: 11px;
|
||
}
|
||
@keyframes fadeOut {
|
||
0% { opacity: 1; }
|
||
70% { opacity: 1; }
|
||
100% { opacity: 0; visibility: hidden; }
|
||
}
|
||
|
||
/* POPUP */
|
||
.btn-hapus { background: #e74c3c !important; width: 100% !important; margin-top: 5px; padding: 4px !important; font-size: 10px !important; }
|
||
.btn-hapus:hover { background: #c0392b !important; }
|
||
|
||
.leaflet-popup-content { min-width: 240px; max-width: 260px; }
|
||
.popup-form { min-width: 230px; padding: 5px; }
|
||
.popup-form h4 { margin: 0 0 6px 0; color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 3px; font-size: 12px; }
|
||
.popup-form input, .popup-form textarea {
|
||
width: 100%;
|
||
margin-bottom: 6px;
|
||
padding: 4px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
}
|
||
.popup-form button {
|
||
width: 100%;
|
||
background: #27ae60;
|
||
color: white;
|
||
border: none;
|
||
padding: 5px;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
font-weight: bold;
|
||
font-size: 11px;
|
||
}
|
||
|
||
.info-card {
|
||
background: #f8f9fa;
|
||
border-radius: 5px;
|
||
padding: 5px;
|
||
margin-top: 4px;
|
||
border-left: 3px solid #27ae60;
|
||
font-size: 10px;
|
||
}
|
||
.info-card.masjid { border-left-color: #27ae60; }
|
||
.info-card.gereja { border-left-color: #9b59b6; }
|
||
.info-card.poverty { border-left-color: #e74c3c; }
|
||
.info-card .address { font-size: 9px; color: #666; margin-top: 3px; word-break: break-all; }
|
||
|
||
.masjid-icon-leaflet, .gereja-icon-leaflet, .poverty-icon-leaflet {
|
||
background: none;
|
||
border: none;
|
||
}
|
||
|
||
.leaflet-control-layers {
|
||
margin-top: 10px !important;
|
||
margin-right: 10px !important;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="map"></div>
|
||
|
||
<!-- TOMBOL PETUNJUK -->
|
||
<div id="btnPetunjuk" onclick="document.getElementById('modalPetunjuk').style.display='flex'" style="position:fixed;bottom:80px;left:20px;z-index:9999;background:#3498db;color:white;width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:bold;cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,0.3);transition:transform 0.2s;" onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">?</div>
|
||
|
||
<!-- MODAL PETUNJUK PENGGUNAAN -->
|
||
<div id="modalPetunjuk" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:99999;align-items:center;justify-content:center;">
|
||
<div style="background:white;width:520px;max-width:95vw;max-height:88vh;border-radius:14px;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,0.4);">
|
||
<div style="background:#2c3e50;color:white;padding:18px 22px;border-radius:14px 14px 0 0;display:flex;justify-content:space-between;align-items:center;">
|
||
<h2 style="margin:0;font-size:17px;">📖 Petunjuk Penggunaan WebGIS</h2>
|
||
<span onclick="document.getElementById('modalPetunjuk').style.display='none'" style="cursor:pointer;font-size:22px;line-height:1;opacity:0.7;" onmouseover="this.style.opacity=1" onmouseout="this.style.opacity=0.7">✕</span>
|
||
</div>
|
||
<div style="padding:20px 22px;">
|
||
|
||
<div style="background:#eaf4fd;border-left:4px solid #3498db;border-radius:0 8px 8px 0;padding:12px 14px;margin-bottom:18px;font-size:13px;color:#2c3e50;">
|
||
Selamat datang di <strong>WebGIS Pontianak</strong> — sistem pemetaan rumah ibadah & penduduk miskin berbasis peta interaktif.
|
||
</div>
|
||
|
||
<!-- Bagian 1 -->
|
||
<div style="margin-bottom:16px;">
|
||
<h4 style="margin:0 0 8px 0;color:#2c3e50;font-size:14px;border-bottom:2px solid #3498db;padding-bottom:5px;">🗺️ Navigasi Peta</h4>
|
||
<ul style="margin:0;padding-left:18px;font-size:13px;color:#444;line-height:1.9;">
|
||
<li><strong>Scroll mouse</strong> → Zoom in / zoom out</li>
|
||
<li><strong>Klik & drag</strong> → Geser tampilan peta</li>
|
||
<li><strong>Pilih Peta</strong> (pojok kiri atas) → Ganti tampilan Street/Satellite/OSM</li>
|
||
<li><strong>Layer Control</strong> (pojok kanan atas) → Tampilkan/sembunyikan layer data</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Bagian 2 -->
|
||
<div style="margin-bottom:16px;">
|
||
<h4 style="margin:0 0 8px 0;color:#2c3e50;font-size:14px;border-bottom:2px solid #27ae60;padding-bottom:5px;">📌 Melihat Data</h4>
|
||
<ul style="margin:0;padding-left:18px;font-size:13px;color:#444;line-height:1.9;">
|
||
<li><strong>Klik marker 🕌 / ⛪</strong> → Lihat detail rumah ibadah</li>
|
||
<li><strong>Klik marker ⚠️</strong> → Lihat detail penduduk miskin</li>
|
||
<li>Marker <span style="color:#27ae60;">✓ hijau</span> = dalam radius bantuan, <span style="color:#e74c3c;">⚠️ merah</span> = di luar radius</li>
|
||
<li>Tombol filter (Semua / Masjid / Gereja / Miskin) → Filter tampilan peta</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Bagian 3 -->
|
||
<div style="margin-bottom:16px;">
|
||
<h4 style="margin:0 0 8px 0;color:#2c3e50;font-size:14px;border-bottom:2px solid #e67e22;padding-bottom:5px;">⚙️ Radius Bantuan</h4>
|
||
<ul style="margin:0;padding-left:18px;font-size:13px;color:#444;line-height:1.9;">
|
||
<li>Geser <strong>slider Radius</strong> (pojok kanan bawah) untuk mengubah jangkauan</li>
|
||
<li>Klik <strong>"Terapkan Radius"</strong> agar perubahan berlaku</li>
|
||
<li>Lingkaran biru di sekitar rumah ibadah = area radius aktif</li>
|
||
<li>Statistik dalam/luar radius otomatis diperbarui</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Bagian 4 -->
|
||
<div style="margin-bottom:16px;">
|
||
<h4 style="margin:0 0 8px 0;color:#2c3e50;font-size:14px;border-bottom:2px solid #9b59b6;padding-bottom:5px;">🔐 Login Admin</h4>
|
||
<ul style="margin:0;padding-left:18px;font-size:13px;color:#444;line-height:1.9;">
|
||
<li>Halaman ini bersifat <strong>publik</strong> (hanya melihat)</li>
|
||
<li>Untuk tambah/edit/hapus data, masuk via <a href="login.php" style="color:#3498db;">Login Admin</a></li>
|
||
<li>Di dashboard admin, klik peta untuk menambah data baru</li>
|
||
<li>Tersedia fitur <strong>Download Laporan</strong> per bulan di dashboard admin</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Bagian 5 -->
|
||
<div style="margin-bottom:16px;">
|
||
<h4 style="margin:0 0 8px 0;color:#2c3e50;font-size:14px;border-bottom:2px solid #e74c3c;padding-bottom:5px;">🎨 Keterangan Ikon</h4>
|
||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;font-size:12px;">
|
||
<div style="background:#f8f9fa;border-radius:6px;padding:8px;">🕌 <strong>Masjid</strong> — marker hijau</div>
|
||
<div style="background:#f8f9fa;border-radius:6px;padding:8px;">⛪ <strong>Gereja</strong> — marker ungu</div>
|
||
<div style="background:#f8f9fa;border-radius:6px;padding:8px;">✅ <strong>Dalam radius</strong> — titik hijau</div>
|
||
<div style="background:#f8f9fa;border-radius:6px;padding:8px;">⚠️ <strong>Luar radius</strong> — titik merah</div>
|
||
</div>
|
||
</div>
|
||
|
||
<button onclick="document.getElementById('modalPetunjuk').style.display='none'" style="width:100%;padding:11px;background:#3498db;color:white;border:none;border-radius:8px;cursor:pointer;font-size:14px;font-weight:bold;margin-top:4px;">✅ Mengerti, Tutup Petunjuk</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- KIRI ATAS -->
|
||
<div class="map-selector">
|
||
<label>🗺️ Pilih Peta:</label>
|
||
<select id="mapSelector">
|
||
<option value="street">🌍 Street Map</option>
|
||
<option value="satellite">🛰️ Satellite</option>
|
||
<option value="osm">🗺️ OpenStreetMap</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="filter-buttons">
|
||
<button class="filter-btn-all" onclick="filterAll()">📌 Semua</button>
|
||
<button class="filter-btn-masjid" onclick="filterMasjid()">🕌 Masjid</button>
|
||
<button class="filter-btn-gereja" onclick="filterGereja()">⛪ Gereja</button>
|
||
<button class="filter-btn-poverty" onclick="filterPoverty()">⚠️ Miskin</button>
|
||
</div>
|
||
|
||
<!-- KANAN - STATISTIK (di bawah layer control) -->
|
||
<div class="stats-panel" id="statsPanel">
|
||
<h4>📊 Statistik</h4>
|
||
<div>🕌 Masjid: <span class="count green" id="masjidCount">0</span></div>
|
||
<div>⛪ Gereja: <span class="count purple" id="gerejaCount">0</span></div>
|
||
<div>⚠️ Miskin: <span class="count red" id="povertyCount">0</span></div>
|
||
<hr>
|
||
<div>✅ Dalam Radius: <span class="count green" id="insideRadiusCount">0</span></div>
|
||
<div>❌ Luar Radius: <span class="count red" id="outsideRadiusCount">0</span></div>
|
||
</div>
|
||
|
||
<!-- KANAN BAWAH - RADIUS -->
|
||
<div class="radius-control" id="radiusControl">
|
||
<h4>🎯 Radius Deteksi</h4>
|
||
<input type="range" id="radiusSlider" min="100" max="500" step="50" value="300">
|
||
<div class="radius-value">Radius: <span id="radiusValue">300</span> meter</div>
|
||
<button id="applyRadiusBtn">🔄 Terapkan Radius</button>
|
||
</div>
|
||
|
||
<!-- KIRI BAWAH - LEGEND -->
|
||
<div class="legend">
|
||
<strong>Legenda</strong><br>
|
||
<span class="masjid-icon">●</span> Masjid<br>
|
||
<span class="gereja-icon">●</span> Gereja<br>
|
||
<span class="poverty-icon">●</span> Penduduk Miskin<br>
|
||
<span class="radius-icon">●</span> Radius
|
||
</div>
|
||
|
||
<div class="instruction-box">
|
||
💡 Klik di peta untuk tambah data | Klik marker untuk detail
|
||
</div>
|
||
|
||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<script src="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.js"></script>
|
||
<script src="https://unpkg.com/leaflet-geometryutil@0.3.0/src/leaflet.geometryutil.js"></script>
|
||
|
||
<script>
|
||
// ==================== INISIALISASI ====================
|
||
var map = L.map('map').setView([-0.0263, 109.3425], 12);
|
||
|
||
var baseMaps = {
|
||
street: L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
|
||
attribution: '© OSM & CartoDB', subdomains: 'abcd', maxZoom: 19
|
||
}),
|
||
satellite: L.tileLayer('https://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', {
|
||
subdomains: ['mt0', 'mt1', 'mt2', 'mt3'], attribution: '© Google Maps', maxZoom: 20
|
||
}),
|
||
osm: L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
attribution: '© OpenStreetMap', maxZoom: 19
|
||
})
|
||
};
|
||
baseMaps.street.addTo(map);
|
||
|
||
document.getElementById('mapSelector').addEventListener('change', function(e) {
|
||
for (var key in baseMaps) map.removeLayer(baseMaps[key]);
|
||
baseMaps[e.target.value].addTo(map);
|
||
});
|
||
|
||
// Layer Groups
|
||
var masjidLayer = L.layerGroup();
|
||
var gerejaLayer = L.layerGroup();
|
||
var povertyLayer = L.layerGroup();
|
||
var radiusLayer = L.layerGroup();
|
||
|
||
masjidLayer.addTo(map);
|
||
gerejaLayer.addTo(map);
|
||
povertyLayer.addTo(map);
|
||
radiusLayer.addTo(map);
|
||
|
||
// Layer Control - muncul di kanan atas
|
||
var overlayMaps = {
|
||
"🕌 Masjid": masjidLayer,
|
||
"⛪ Gereja": gerejaLayer,
|
||
"⚠️ Penduduk Miskin": povertyLayer,
|
||
"🔵 Radius": radiusLayer
|
||
};
|
||
L.control.layers(null, overlayMaps, { collapsed: false, position: 'topright' }).addTo(map);
|
||
|
||
// Data
|
||
var masjidPoints = [];
|
||
var gerejaPoints = [];
|
||
var povertyPoints = [];
|
||
var allCircles = [];
|
||
var currentRadius = 300;
|
||
var currentFilter = 'all';
|
||
|
||
function showToast(message) {
|
||
var existingToasts = document.querySelectorAll('.toast-notification');
|
||
existingToasts.forEach(function(toast) { toast.remove(); });
|
||
var toast = document.createElement('div');
|
||
toast.className = 'toast-notification';
|
||
toast.innerHTML = message;
|
||
document.body.appendChild(toast);
|
||
setTimeout(function() { if (toast.parentNode) toast.remove(); }, 3000);
|
||
}
|
||
|
||
async function reverseGeocode(lat, lng) {
|
||
try {
|
||
var url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
|
||
var response = await fetch(url, { headers: { 'User-Agent': 'WebGIS-Pontianak/1.0' } });
|
||
var data = await response.json();
|
||
if (data && data.display_name) return data.display_name;
|
||
return lat.toFixed(6) + ", " + lng.toFixed(6);
|
||
} catch (error) {
|
||
return lat.toFixed(6) + ", " + lng.toFixed(6);
|
||
}
|
||
}
|
||
|
||
function createMasjidIcon() {
|
||
return L.divIcon({
|
||
className: 'masjid-icon-leaflet',
|
||
html: '<div style="background: #27ae60; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid white; box-shadow: 0 2px 5px rgba(0,0,0,0.3);"><span style="font-size: 13px;">🕌</span></div>',
|
||
iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12]
|
||
});
|
||
}
|
||
|
||
function createGerejaIcon() {
|
||
return L.divIcon({
|
||
className: 'gereja-icon-leaflet',
|
||
html: '<div style="background: #9b59b6; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid white; box-shadow: 0 2px 5px rgba(0,0,0,0.3);"><span style="font-size: 13px;">⛪</span></div>',
|
||
iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12]
|
||
});
|
||
}
|
||
|
||
function createPovertyIcon(isInside) {
|
||
var color = isInside ? '#27ae60' : '#e74c3c';
|
||
var iconChar = isInside ? '✓' : '⚠️';
|
||
return L.divIcon({
|
||
className: 'poverty-icon-leaflet',
|
||
html: '<div style="background: ' + color + '; width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 2px solid white; box-shadow: 0 2px 5px rgba(0,0,0,0.3);"><span style="font-size: 10px; color: white; font-weight: bold;">' + iconChar + '</span></div>',
|
||
iconSize: [20, 20], iconAnchor: [10, 10], popupAnchor: [0, -10]
|
||
});
|
||
}
|
||
|
||
function updateAllRadii() {
|
||
radiusLayer.clearLayers();
|
||
allCircles = [];
|
||
|
||
for (var i = 0; i < masjidPoints.length; i++) {
|
||
var m = masjidPoints[i];
|
||
var circle = L.circle([m.lat, m.lng], {
|
||
radius: currentRadius, color: '#27ae60', fillColor: '#27ae60', fillOpacity: 0.1, weight: 1.5
|
||
});
|
||
circle.addTo(radiusLayer);
|
||
allCircles.push(circle);
|
||
}
|
||
|
||
for (var j = 0; j < gerejaPoints.length; j++) {
|
||
var g = gerejaPoints[j];
|
||
var circle2 = L.circle([g.lat, g.lng], {
|
||
radius: currentRadius, color: '#9b59b6', fillColor: '#9b59b6', fillOpacity: 0.1, weight: 1.5
|
||
});
|
||
circle2.addTo(radiusLayer);
|
||
allCircles.push(circle2);
|
||
}
|
||
|
||
updatePovertyStatus();
|
||
}
|
||
|
||
function updatePovertyStatus() {
|
||
povertyLayer.clearLayers();
|
||
var insideCount = 0, outsideCount = 0;
|
||
|
||
for (var k = 0; k < povertyPoints.length; k++) {
|
||
var poor = povertyPoints[k];
|
||
var isInside = false;
|
||
for (var c = 0; c < allCircles.length; c++) {
|
||
var center = allCircles[c].getLatLng();
|
||
var distance = map.distance(center, L.latLng(poor.lat, poor.lng));
|
||
if (distance <= currentRadius) {
|
||
isInside = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
var marker = L.marker([poor.lat, poor.lng], { icon: createPovertyIcon(isInside) });
|
||
marker.povertyData = poor;
|
||
marker.isInside = isInside;
|
||
marker.on('click', function(e) {
|
||
showPovertyPopup(e.target.povertyData, e.target.isInside);
|
||
});
|
||
marker.addTo(povertyLayer);
|
||
|
||
if (isInside) insideCount++; else outsideCount++;
|
||
}
|
||
|
||
document.getElementById('insideRadiusCount').innerHTML = insideCount;
|
||
document.getElementById('outsideRadiusCount').innerHTML = outsideCount;
|
||
}
|
||
|
||
async function showPovertyPopup(data, isInside) {
|
||
var address = await reverseGeocode(data.lat, data.lng);
|
||
var statusText = isInside ? '✅ Dalam Radius' : '❌ Luar Radius';
|
||
var statusColor = isInside ? '#27ae60' : '#e74c3c';
|
||
|
||
var content = '<div style="min-width:230px;">' +
|
||
'<h4 style="margin:0 0 5px 0;color:#2c3e50;">⚠️ PENDUDUK MISKIN</h4>' +
|
||
'<div class="info-card poverty">' +
|
||
'<strong>👤 Nama:</strong> ' + data.nama + '<br>' +
|
||
'<strong>📝 Keterangan:</strong> ' + data.keterangan + '<br>' +
|
||
'<strong>📍 Status:</strong> <span style="color:' + statusColor + '">' + statusText + '</span><br>' +
|
||
'<div class="address"><strong>🏠 Alamat:</strong><br>' + address + '</div>' +
|
||
'<button class="btn-hapus" onclick="hapusPoverty(' + data.id + ')">🗑️ Hapus Data</button>' +
|
||
'</div></div>';
|
||
L.popup().setLatLng([data.lat, data.lng]).setContent(content).openOn(map);
|
||
}
|
||
|
||
async function showMasjidPopup(data) {
|
||
var address = await reverseGeocode(data.lat, data.lng);
|
||
var content = '<div style="min-width:230px;">' +
|
||
'<h4 style="margin:0 0 5px 0;color:#2c3e50;">🕌 MASJID</h4>' +
|
||
'<div class="info-card masjid">' +
|
||
'<strong>🏛️ Nama:</strong> ' + data.nama + '<br>' +
|
||
'<strong>📝 Alamat:</strong> ' + data.alamat + '<br>' +
|
||
'<div class="address"><strong>📍 Lokasi:</strong><br>' + address + '</div>' +
|
||
'<button class="btn-hapus" onclick="hapusMasjid(' + data.id + ')">🗑️ Hapus Masjid</button>' +
|
||
'</div></div>';
|
||
L.popup().setLatLng([data.lat, data.lng]).setContent(content).openOn(map);
|
||
}
|
||
|
||
async function showGerejaPopup(data) {
|
||
var address = await reverseGeocode(data.lat, data.lng);
|
||
var content = '<div style="min-width:230px;">' +
|
||
'<h4 style="margin:0 0 5px 0;color:#2c3e50;">⛪ GEREJA</h4>' +
|
||
'<div class="info-card gereja">' +
|
||
'<strong>🏛️ Nama:</strong> ' + data.nama + '<br>' +
|
||
'<strong>📝 Alamat:</strong> ' + data.alamat + '<br>' +
|
||
'<div class="address"><strong>📍 Lokasi:</strong><br>' + address + '</div>' +
|
||
'<button class="btn-hapus" onclick="hapusGereja(' + data.id + ')">🗑️ Hapus Gereja</button>' +
|
||
'</div></div>';
|
||
L.popup().setLatLng([data.lat, data.lng]).setContent(content).openOn(map);
|
||
}
|
||
|
||
function loadMasjidData() {
|
||
fetch('api.php?action=get_masjid')
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
masjidLayer.clearLayers();
|
||
masjidPoints = [];
|
||
if (Array.isArray(data)) {
|
||
for (var i = 0; i < data.length; i++) {
|
||
var item = data[i];
|
||
var lat = parseFloat(item.lat);
|
||
var lng = parseFloat(item.lng);
|
||
var marker = L.marker([lat, lng], { icon: createMasjidIcon() });
|
||
marker.data = { id: item.id, nama: item.nama, alamat: item.alamat || '-', lat: lat, lng: lng };
|
||
marker.on('click', function(e) { showMasjidPopup(e.target.data); });
|
||
if (currentFilter === 'all' || currentFilter === 'masjid') {
|
||
marker.addTo(masjidLayer);
|
||
}
|
||
masjidPoints.push(marker.data);
|
||
}
|
||
}
|
||
document.getElementById('masjidCount').innerHTML = masjidPoints.length;
|
||
updateAllRadii();
|
||
}).catch(function(err) { showToast('Gagal load Masjid'); });
|
||
}
|
||
|
||
function loadGerejaData() {
|
||
fetch('api.php?action=get_gereja')
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
gerejaLayer.clearLayers();
|
||
gerejaPoints = [];
|
||
if (Array.isArray(data)) {
|
||
for (var i = 0; i < data.length; i++) {
|
||
var item = data[i];
|
||
var lat = parseFloat(item.lat);
|
||
var lng = parseFloat(item.lng);
|
||
var marker = L.marker([lat, lng], { icon: createGerejaIcon() });
|
||
marker.data = { id: item.id, nama: item.nama, alamat: item.alamat || '-', lat: lat, lng: lng };
|
||
marker.on('click', function(e) { showGerejaPopup(e.target.data); });
|
||
if (currentFilter === 'all' || currentFilter === 'gereja') {
|
||
marker.addTo(gerejaLayer);
|
||
}
|
||
gerejaPoints.push(marker.data);
|
||
}
|
||
}
|
||
document.getElementById('gerejaCount').innerHTML = gerejaPoints.length;
|
||
updateAllRadii();
|
||
}).catch(function(err) { showToast('Gagal load Gereja'); });
|
||
}
|
||
|
||
function loadPovertyData() {
|
||
fetch('api.php?action=get_poverty')
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
povertyPoints = [];
|
||
if (Array.isArray(data)) {
|
||
for (var i = 0; i < data.length; i++) {
|
||
var item = data[i];
|
||
povertyPoints.push({
|
||
id: item.id,
|
||
nama: item.nama || '-',
|
||
alamat: item.alamat || '-',
|
||
keterangan: item.keterangan || '-',
|
||
lat: parseFloat(item.lat),
|
||
lng: parseFloat(item.lng)
|
||
});
|
||
}
|
||
}
|
||
document.getElementById('povertyCount').innerHTML = povertyPoints.length;
|
||
updatePovertyStatus();
|
||
}).catch(function(err) { showToast('Gagal load Kemiskinan'); });
|
||
}
|
||
|
||
function hapusMasjid(id) {
|
||
if (confirm('Hapus masjid ini?')) {
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'delete_masjid', id: id })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Masjid dihapus');
|
||
loadMasjidData();
|
||
map.closePopup();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function hapusGereja(id) {
|
||
if (confirm('Hapus gereja ini?')) {
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'delete_gereja', id: id })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Gereja dihapus');
|
||
loadGerejaData();
|
||
map.closePopup();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function hapusPoverty(id) {
|
||
if (confirm('Hapus data penduduk miskin ini?')) {
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'delete_poverty', id: id })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Data dihapus');
|
||
loadPovertyData();
|
||
map.closePopup();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function simpanMasjid(lat, lng) {
|
||
var nama = document.getElementById('nama_masjid').value;
|
||
var alamat = document.getElementById('alamat_masjid').value;
|
||
if (!nama) { alert('Nama harus diisi!'); return; }
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'add_masjid', nama: nama, alamat: alamat, lat: lat, lng: lng })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Masjid tersimpan');
|
||
map.closePopup();
|
||
loadMasjidData();
|
||
}
|
||
});
|
||
}
|
||
|
||
function simpanGereja(lat, lng) {
|
||
var nama = document.getElementById('nama_gereja').value;
|
||
var alamat = document.getElementById('alamat_gereja').value;
|
||
if (!nama) { alert('Nama harus diisi!'); return; }
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'add_gereja', nama: nama, alamat: alamat, lat: lat, lng: lng })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Gereja tersimpan');
|
||
map.closePopup();
|
||
loadGerejaData();
|
||
}
|
||
});
|
||
}
|
||
|
||
function simpanPoverty(lat, lng) {
|
||
var nama = document.getElementById('nama_poverty').value;
|
||
var alamat = document.getElementById('alamat_poverty').value;
|
||
var keterangan = document.getElementById('keterangan_poverty').value;
|
||
if (!nama) { alert('Nama harus diisi!'); return; }
|
||
fetch('api.php', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ action: 'add_poverty', nama: nama, alamat: alamat, keterangan: keterangan, lat: lat, lng: lng })
|
||
}).then(function(r) { return r.json(); })
|
||
.then(function(res) {
|
||
if (res.status === 'ok') {
|
||
showToast('✅ Data tersimpan');
|
||
map.closePopup();
|
||
loadPovertyData();
|
||
}
|
||
});
|
||
}
|
||
|
||
map.on('click', function(e) {
|
||
var lat = e.latlng.lat;
|
||
var lng = e.latlng.lng;
|
||
var form = '<div class="popup-form">' +
|
||
'<h4>➕ Pilih Jenis Data</h4>' +
|
||
'<button onclick="showMasjidForm(' + lat + ', ' + lng + ')" style="background:#27ae60; margin-bottom:6px;">🕌 Tambah Masjid</button>' +
|
||
'<button onclick="showGerejaForm(' + lat + ', ' + lng + ')" style="background:#9b59b6; margin-bottom:6px;">⛪ Tambah Gereja</button>' +
|
||
'<button onclick="showPovertyForm(' + lat + ', ' + lng + ')" style="background:#e74c3c;">⚠️ Tambah Penduduk Miskin</button>' +
|
||
'</div>';
|
||
L.popup().setLatLng([lat, lng]).setContent(form).openOn(map);
|
||
});
|
||
|
||
function showMasjidForm(lat, lng) {
|
||
var form = '<div class="popup-form">' +
|
||
'<h4>🕌 Input Masjid</h4>' +
|
||
'<input type="text" id="nama_masjid" placeholder="Nama Masjid">' +
|
||
'<input type="text" id="alamat_masjid" placeholder="Alamat">' +
|
||
'<button onclick="simpanMasjid(' + lat + ', ' + lng + ')">💾 Simpan</button>' +
|
||
'</div>';
|
||
map.closePopup();
|
||
L.popup().setLatLng([lat, lng]).setContent(form).openOn(map);
|
||
}
|
||
|
||
function showGerejaForm(lat, lng) {
|
||
var form = '<div class="popup-form">' +
|
||
'<h4>⛪ Input Gereja</h4>' +
|
||
'<input type="text" id="nama_gereja" placeholder="Nama Gereja">' +
|
||
'<input type="text" id="alamat_gereja" placeholder="Alamat">' +
|
||
'<button onclick="simpanGereja(' + lat + ', ' + lng + ')">💾 Simpan</button>' +
|
||
'</div>';
|
||
map.closePopup();
|
||
L.popup().setLatLng([lat, lng]).setContent(form).openOn(map);
|
||
}
|
||
|
||
function showPovertyForm(lat, lng) {
|
||
var form = '<div class="popup-form">' +
|
||
'<h4>⚠️ Input Penduduk Miskin</h4>' +
|
||
'<input type="text" id="nama_poverty" placeholder="Nama Kepala Keluarga">' +
|
||
'<input type="text" id="alamat_poverty" placeholder="Alamat">' +
|
||
'<textarea id="keterangan_poverty" placeholder="Keterangan" rows="2"></textarea>' +
|
||
'<button onclick="simpanPoverty(' + lat + ', ' + lng + ')">💾 Simpan</button>' +
|
||
'</div>';
|
||
map.closePopup();
|
||
L.popup().setLatLng([lat, lng]).setContent(form).openOn(map);
|
||
}
|
||
|
||
function filterAll() {
|
||
currentFilter = 'all';
|
||
masjidLayer.clearLayers();
|
||
gerejaLayer.clearLayers();
|
||
for (var i = 0; i < masjidPoints.length; i++) {
|
||
var item = masjidPoints[i];
|
||
var marker = L.marker([item.lat, item.lng], { icon: createMasjidIcon() });
|
||
marker.data = item;
|
||
marker.on('click', function(e) { showMasjidPopup(e.target.data); });
|
||
marker.addTo(masjidLayer);
|
||
}
|
||
for (var j = 0; j < gerejaPoints.length; j++) {
|
||
var item2 = gerejaPoints[j];
|
||
var marker2 = L.marker([item2.lat, item2.lng], { icon: createGerejaIcon() });
|
||
marker2.data = item2;
|
||
marker2.on('click', function(e) { showGerejaPopup(e.target.data); });
|
||
marker2.addTo(gerejaLayer);
|
||
}
|
||
showToast('📌 Menampilkan semua data');
|
||
}
|
||
|
||
function filterMasjid() {
|
||
currentFilter = 'masjid';
|
||
masjidLayer.clearLayers();
|
||
gerejaLayer.clearLayers();
|
||
for (var i = 0; i < masjidPoints.length; i++) {
|
||
var item = masjidPoints[i];
|
||
var marker = L.marker([item.lat, item.lng], { icon: createMasjidIcon() });
|
||
marker.data = item;
|
||
marker.on('click', function(e) { showMasjidPopup(e.target.data); });
|
||
marker.addTo(masjidLayer);
|
||
}
|
||
showToast('🕌 Hanya menampilkan Masjid');
|
||
}
|
||
|
||
function filterGereja() {
|
||
currentFilter = 'gereja';
|
||
masjidLayer.clearLayers();
|
||
gerejaLayer.clearLayers();
|
||
for (var i = 0; i < gerejaPoints.length; i++) {
|
||
var item = gerejaPoints[i];
|
||
var marker = L.marker([item.lat, item.lng], { icon: createGerejaIcon() });
|
||
marker.data = item;
|
||
marker.on('click', function(e) { showGerejaPopup(e.target.data); });
|
||
marker.addTo(gerejaLayer);
|
||
}
|
||
showToast('⛪ Hanya menampilkan Gereja');
|
||
}
|
||
|
||
function filterPoverty() {
|
||
showToast('⚠️ Data kemiskinan tetap tampil');
|
||
}
|
||
|
||
var radiusSlider = document.getElementById('radiusSlider');
|
||
var radiusValue = document.getElementById('radiusValue');
|
||
radiusSlider.addEventListener('input', function(e) {
|
||
currentRadius = parseInt(e.target.value);
|
||
radiusValue.innerText = currentRadius;
|
||
});
|
||
document.getElementById('applyRadiusBtn').addEventListener('click', function() {
|
||
updateAllRadii();
|
||
showToast('Radius: ' + currentRadius + ' meter');
|
||
});
|
||
|
||
// Load kecamatan
|
||
fetch('Admin_Kecamatan.json')
|
||
.then(function(r) { return r.json(); })
|
||
.then(function(data) {
|
||
L.geoJSON(data, { style: { color: "#2c3e50", weight: 2, fillOpacity: 0.05, dashArray: '5,5' } }).addTo(map);
|
||
}).catch(function(err) { console.error("Gagal load GeoJSON:", err); });
|
||
|
||
// Start
|
||
loadMasjidData();
|
||
loadGerejaData();
|
||
loadPovertyData();
|
||
</script>
|
||
</body>
|
||
</html> |