Files
UAS/index.html
T
2026-06-05 03:08:55 +00:00

861 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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 &amp; 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 &amp; 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: '&copy; 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: '&copy; Google Maps', maxZoom: 20
}),
osm: L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; 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>