Upload files to "/"
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,611 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<?php
|
||||
session_start();
|
||||
if (!isset($_SESSION['login']) || $_SESSION['login'] !== true) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<meta charset="UTF-8">
|
||||
<title>WebGIS Kemiskinan - Dashboard Admin</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<style>
|
||||
* { box-sizing: border-box; }
|
||||
body { margin:0; font-family:Arial,sans-serif; display:flex; background:#f0f2f5; }
|
||||
|
||||
.sidebar {
|
||||
width: 360px;
|
||||
min-width: 360px;
|
||||
background: #2c3e50;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
text-align: center;
|
||||
margin: 0 0 5px 0;
|
||||
font-size: 16px;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
.sidebar .user-info {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #bdc3c7;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: white;
|
||||
color: #2c3e50;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
color: #2c3e50;
|
||||
border-bottom: 2px solid #3498db;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.card input,
|
||||
.card select,
|
||||
.card textarea {
|
||||
width: 100%;
|
||||
padding: 7px 9px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.card input:focus,
|
||||
.card select:focus,
|
||||
.card textarea:focus { border-color: #3498db; }
|
||||
|
||||
.card button {
|
||||
width: 100%;
|
||||
padding: 9px;
|
||||
background: #27ae60;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.card button:hover { background: #219a52; }
|
||||
|
||||
.card button.btn-logout {
|
||||
background: #e74c3c;
|
||||
}
|
||||
.card button.btn-logout:hover { background: #c0392b; }
|
||||
|
||||
.stat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
.stat-item {
|
||||
background: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
.stat-item .num {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
.stat-item.green .num { color: #27ae60; }
|
||||
.stat-item.red .num { color: #e74c3c; }
|
||||
.stat-item.blue .num { color: #3498db; }
|
||||
.stat-item.orange .num { color: #e67e22; }
|
||||
|
||||
.table-box { max-height: 180px; overflow-y: auto; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 11px; }
|
||||
table th { background: #3498db; color: white; padding: 5px 6px; text-align: left; }
|
||||
table td { padding: 5px 6px; border-bottom: 1px solid #eee; }
|
||||
table tr:hover td { background: #f5f5f5; }
|
||||
|
||||
.radius-val { font-size: 20px; font-weight: bold; color: #e67e22; text-align: center; }
|
||||
|
||||
#map { flex: 1; height: 100vh; }
|
||||
|
||||
.btn-edit {
|
||||
background: #f39c12 !important;
|
||||
color: white !important;
|
||||
width: 48% !important;
|
||||
display: inline-block !important;
|
||||
margin-top: 5px !important;
|
||||
padding: 5px !important;
|
||||
font-size: 10px !important;
|
||||
border: none !important;
|
||||
border-radius: 4px !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
.btn-hapus {
|
||||
background: #e74c3c !important;
|
||||
color: white !important;
|
||||
width: 48% !important;
|
||||
display: inline-block !important;
|
||||
margin-top: 5px !important;
|
||||
padding: 5px !important;
|
||||
font-size: 10px !important;
|
||||
border: none !important;
|
||||
border-radius: 4px !important;
|
||||
cursor: pointer !important;
|
||||
float: right !important;
|
||||
}
|
||||
.btn-edit:hover { background: #e67e22 !important; }
|
||||
.btn-hapus:hover { background: #c0392b !important; }
|
||||
.clearfix::after { content: ""; clear: both; display: table; }
|
||||
|
||||
.popup-form input, .popup-form textarea, .popup-form select {
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
margin-bottom: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.foto-preview {
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.foto-preview img {
|
||||
max-width: 100%;
|
||||
max-height: 120px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="sidebar">
|
||||
<h2>🗺️ Dashboard Admin</h2>
|
||||
<div class="user-info">Login sebagai: <strong><?= htmlspecialchars($_SESSION['username']) ?></strong></div>
|
||||
|
||||
<div class="card">
|
||||
<h3>📊 Statistik</h3>
|
||||
<div class="stat-grid">
|
||||
<div class="stat-item blue"><span class="num" id="ibadah">0</span> Rumah Ibadah</div>
|
||||
<div class="stat-item red"><span class="num" id="miskin">0</span> Penduduk Miskin</div>
|
||||
<div class="stat-item green"><span class="num" id="dalam">0</span> ✅ Dalam Radius</div>
|
||||
<div class="stat-item orange"><span class="num" id="luar">0</span> ❌ Luar Radius</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>🎯 Radius Bantuan</h3>
|
||||
<input type="range" min="100" max="500" step="50" value="300" id="radiusSlider" style="padding:0; border:none; background:transparent;">
|
||||
<div class="radius-val"><span id="radiusValue">300</span> Meter</div>
|
||||
<button onclick="terapkanRadius()" style="margin-top:8px;">🔄 Terapkan Radius</button>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>➕ Tambah Bantuan</h3>
|
||||
<select id="bJenis">
|
||||
<option value="Beras">🌾 Beras</option>
|
||||
<option value="Sembako">🛒 Sembako</option>
|
||||
<option value="Uang Tunai">💰 Uang Tunai</option>
|
||||
<option value="Pendidikan">📚 Pendidikan</option>
|
||||
<option value="Kesehatan">🏥 Kesehatan</option>
|
||||
</select>
|
||||
<input type="text" id="bJumlah" placeholder="Jumlah (misal: 10 kg / Rp 500.000)">
|
||||
<input type="date" id="bTanggal">
|
||||
<textarea id="bKeterangan" placeholder="Keterangan tambahan" rows="2"></textarea>
|
||||
<button onclick="simpanBantuan()">💾 Simpan Bantuan</button>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>📋 Histori Bantuan</h3>
|
||||
<div class="table-box"><table id="tabelBantuan"><tr><th>Tanggal</th><th>Nama</th><th>Bantuan</th></tr></table></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>📈 Grafik Bantuan (Bulanan)</h3>
|
||||
<canvas id="grafik" height="150"></canvas>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<button onclick="window.location='laporan.php'" style="background:#8e44ad;margin-bottom:8px;">📋 Download Laporan</button>
|
||||
<button class="btn-logout" onclick="window.location='logout.php'">🚪 Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL TAMBAH PENDUDUK MISKIN -->
|
||||
<div id="modalPoverty" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; align-items:center; justify-content:center;">
|
||||
<div style="background:white; width:400px; max-width:95vw; border-radius:12px; padding:25px; max-height:90vh; overflow-y:auto; box-shadow: 0 20px 60px rgba(0,0,0,0.4);">
|
||||
<h3 style="margin:0 0 15px 0; color:#e74c3c; font-size:16px;">⚠️ Tambah Penduduk Miskin</h3>
|
||||
<input type="text" id="fNamaPoverty" placeholder="Nama Kepala Keluarga *" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="fNikPoverty" placeholder="NIK" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="fAlamatPoverty" placeholder="Alamat" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="fPekerjaanPoverty" placeholder="Pekerjaan" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="fPenghasilanPoverty" placeholder="Penghasilan (Rp)" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="fAnggotaPoverty" placeholder="Jumlah Anggota Keluarga" value="1" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="fTanggunganPoverty" placeholder="Jumlah Tanggungan" value="0" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<select id="fKategoriPoverty" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<option value="Miskin">Miskin</option><option value="Miskin Ekstrem">Miskin Ekstrem</option><option value="Hampir Miskin">Hampir Miskin</option>
|
||||
</select>
|
||||
<select id="fStatusBantuanPoverty" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<option value="Belum">Belum Menerima</option><option value="Pernah">Pernah Menerima</option><option value="Sedang">Sedang Menerima</option>
|
||||
</select>
|
||||
<textarea id="fKetPoverty" placeholder="Keterangan" rows="2" style="width:100%;padding:9px;margin-bottom:12px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;"></textarea>
|
||||
|
||||
<input type="file" id="fFotoPoverty" accept="image/*" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;" onchange="previewFoto(this)">
|
||||
<div id="previewFotoPoverty" class="foto-preview" style="display:none;"><img id="previewImgPoverty" src=""></div>
|
||||
|
||||
<p id="modalKoordinat" style="font-size:12px;color:#888;margin:0 0 12px 0;"></p>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button onclick="simpanPoverty()" style="flex:1;padding:10px;background:#e74c3c;color:white;border:none;border-radius:5px;cursor:pointer;font-size:14px;font-weight:bold;">💾 Simpan</button>
|
||||
<button onclick="tutupModalPoverty()" style="flex:1;padding:10px;background:#95a5a6;color:white;border:none;border-radius:5px;cursor:pointer;font-size:14px;">✖ Batal</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL EDIT PENDUDUK MISKIN -->
|
||||
<div id="modalEditPoverty" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; align-items:center; justify-content:center;">
|
||||
<div style="background:white; width:400px; max-width:95vw; border-radius:12px; padding:25px; max-height:90vh; overflow-y:auto; box-shadow: 0 20px 60px rgba(0,0,0,0.4);">
|
||||
<h3 style="margin:0 0 15px 0; color:#f39c12; font-size:16px;">✏️ Edit Penduduk Miskin</h3>
|
||||
<input type="hidden" id="eIdPoverty">
|
||||
<input type="text" id="eNamaPoverty" placeholder="Nama Kepala Keluarga *" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="eNikPoverty" placeholder="NIK" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="eAlamatPoverty" placeholder="Alamat" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="text" id="ePekerjaanPoverty" placeholder="Pekerjaan" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="ePenghasilanPoverty" placeholder="Penghasilan (Rp)" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="eAnggotaPoverty" placeholder="Jumlah Anggota Keluarga" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<input type="number" id="eTanggunganPoverty" placeholder="Jumlah Tanggungan" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<select id="eKategoriPoverty" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<option value="Miskin">Miskin</option><option value="Miskin Ekstrem">Miskin Ekstrem</option><option value="Hampir Miskin">Hampir Miskin</option>
|
||||
</select>
|
||||
<select id="eStatusBantuanPoverty" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;">
|
||||
<option value="Belum">Belum Menerima</option><option value="Pernah">Pernah Menerima</option><option value="Sedang">Sedang Menerima</option>
|
||||
</select>
|
||||
<textarea id="eKetPoverty" placeholder="Keterangan" rows="2" style="width:100%;padding:9px;margin-bottom:12px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;"></textarea>
|
||||
|
||||
<input type="file" id="eFotoPoverty" accept="image/*" style="width:100%;padding:9px;margin-bottom:8px;border:1px solid #ddd;border-radius:5px;font-size:13px;box-sizing:border-box;" onchange="previewEditFoto(this)">
|
||||
<input type="hidden" id="eFotoLama" value="">
|
||||
<div id="editPreviewFoto" class="foto-preview" style="display:none;"><img id="editPreviewImg" src=""></div>
|
||||
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button onclick="simpanEditPoverty()" style="flex:1;padding:10px;background:#f39c12;color:white;border:none;border-radius:5px;cursor:pointer;font-size:14px;font-weight:bold;">💾 Simpan</button>
|
||||
<button onclick="tutupModalEditPoverty()" style="flex:1;padding:10px;background:#95a5a6;color:white;border:none;border-radius:5px;cursor:pointer;font-size:14px;">✖ Batal</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL HAPUS DAN BERI BANTUAN (SEDERHANA) -->
|
||||
<div id="modalHapusPoverty" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; align-items:center; justify-content:center;">
|
||||
<div style="background:white; width:340px; border-radius:12px; padding:25px; text-align:center;">
|
||||
<h3 style="color:#e74c3c;">Hapus Data?</h3>
|
||||
<p id="modalHapusNama" style="margin:15px 0;"></p>
|
||||
<button onclick="konfirmasiHapusPoverty()" style="background:#e74c3c;color:white;padding:10px 20px;border:none;border-radius:5px;cursor:pointer;">Ya, Hapus</button>
|
||||
<button onclick="document.getElementById('modalHapusPoverty').style.display='none'" style="background:#95a5a6;color:white;padding:10px 20px;border:none;border-radius:5px;cursor:pointer;">Batal</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modalBeriBantuan" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; align-items:center; justify-content:center;">
|
||||
<div style="background:white; width:380px; border-radius:12px; padding:25px;">
|
||||
<h3 style="color:#27ae60;">🎁 Beri Bantuan</h3>
|
||||
<p id="beriNamaPenduduk"></p>
|
||||
<input type="hidden" id="beriPendudukId">
|
||||
<select id="beriJenis" style="width:100%;padding:8px;margin:10px 0;"><option value="Beras">🌾 Beras</option><option value="Sembako">🛒 Sembako</option><option value="Uang Tunai">💰 Uang Tunai</option></select>
|
||||
<input type="text" id="beriJumlah" placeholder="Jumlah" style="width:100%;padding:8px;margin:10px 0;">
|
||||
<input type="date" id="beriTanggal" style="width:100%;padding:8px;margin:10px 0;">
|
||||
<textarea id="beriKeterangan" placeholder="Keterangan" rows="2" style="width:100%;padding:8px;margin:10px 0;"></textarea>
|
||||
<button onclick="simpanBeriBantuan()" style="background:#27ae60;color:white;padding:10px;width:100%;border:none;border-radius:5px;cursor:pointer;">💾 Simpan</button>
|
||||
<button onclick="document.getElementById('modalBeriBantuan').style.display='none'" style="background:#95a5a6;color:white;padding:10px;width:100%;border:none;border-radius:5px;cursor:pointer;margin-top:5px;">Batal</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="map"></div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script>
|
||||
|
||||
// ==================== MAP INIT ====================
|
||||
var map = L.map('map').setView([-0.0263, 109.3425], 13);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap' }).addTo(map);
|
||||
|
||||
var masjidLayer = L.layerGroup().addTo(map);
|
||||
var gerejaLayer = L.layerGroup().addTo(map);
|
||||
var povertyLayer = L.layerGroup().addTo(map);
|
||||
var radiusLayer = L.layerGroup().addTo(map);
|
||||
|
||||
var masjidPoints = [], gerejaPoints = [], povertyPoints = [];
|
||||
var currentRadius = 300;
|
||||
|
||||
// ==================== IKON ====================
|
||||
function createMasjidIcon() {
|
||||
return L.divIcon({ className: 'masjid-icon', html: '<div style="background:#27ae60; width:28px; height:28px; 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:14px;">🕌</span></div>', iconSize: [28,28], iconAnchor: [14,14], popupAnchor: [0,-14] });
|
||||
}
|
||||
function createGerejaIcon() {
|
||||
return L.divIcon({ className: 'gereja-icon', html: '<div style="background:#9b59b6; width:28px; height:28px; 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:14px;">⛪</span></div>', iconSize: [28,28], iconAnchor: [14,14], popupAnchor: [0,-14] });
|
||||
}
|
||||
function createPovertyIcon(isInside) {
|
||||
var color = isInside ? '#27ae60' : '#e74c3c';
|
||||
var iconChar = isInside ? '✓' : '⚠️';
|
||||
return L.divIcon({ className: 'poverty-icon', html: '<div style="background:'+color+'; width:22px; height:22px; 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:11px; color:white; font-weight:bold;">'+iconChar+'</span></div>', iconSize: [22,22], iconAnchor: [11,11], popupAnchor: [0,-11] });
|
||||
}
|
||||
function escapeHtml(str) { if (!str) return ''; return str.replace(/['"\\]/g, '\\$&').replace(/\n/g, '\\n'); }
|
||||
|
||||
// ==================== PREVIEW FOTO ====================
|
||||
function previewFoto(input) {
|
||||
var previewDiv = document.getElementById('previewFotoPoverty');
|
||||
var previewImg = document.getElementById('previewImgPoverty');
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) { previewImg.src = e.target.result; previewDiv.style.display = 'block'; }
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
} else { previewDiv.style.display = 'none'; previewImg.src = ''; }
|
||||
}
|
||||
function previewEditFoto(input) {
|
||||
var previewDiv = document.getElementById('editPreviewFoto');
|
||||
var previewImg = document.getElementById('editPreviewImg');
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) { previewImg.src = e.target.result; previewDiv.style.display = 'block'; }
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
} else if (document.getElementById('eFotoLama').value) { previewImg.src = document.getElementById('eFotoLama').value; previewDiv.style.display = 'block'; }
|
||||
else { previewDiv.style.display = 'none'; previewImg.src = ''; }
|
||||
}
|
||||
|
||||
// ==================== LOAD DATA ====================
|
||||
function loadSemua() { loadMasjid(); loadGereja(); loadPoverty(); loadBantuan(); loadGrafik(); }
|
||||
|
||||
function loadMasjid() {
|
||||
fetch('api.php?action=get_masjid').then(r=>r.json()).then(data=>{
|
||||
masjidLayer.clearLayers(); masjidPoints = Array.isArray(data)?data:[];
|
||||
masjidPoints.forEach(item=>{
|
||||
var marker = L.marker([parseFloat(item.lat), parseFloat(item.lng)], {icon: createMasjidIcon()});
|
||||
marker.data = item; marker.on('click', e=>showMasjidPopup(e.target.data));
|
||||
marker.addTo(masjidLayer);
|
||||
});
|
||||
updateStats();
|
||||
}).catch(()=>console.error('Gagal load masjid'));
|
||||
}
|
||||
function loadGereja() {
|
||||
fetch('api.php?action=get_gereja').then(r=>r.json()).then(data=>{
|
||||
gerejaLayer.clearLayers(); gerejaPoints = Array.isArray(data)?data:[];
|
||||
gerejaPoints.forEach(item=>{
|
||||
var marker = L.marker([parseFloat(item.lat), parseFloat(item.lng)], {icon: createGerejaIcon()});
|
||||
marker.data = item; marker.on('click', e=>showGerejaPopup(e.target.data));
|
||||
marker.addTo(gerejaLayer);
|
||||
});
|
||||
updateStats();
|
||||
}).catch(()=>console.error('Gagal load gereja'));
|
||||
}
|
||||
function loadPoverty() {
|
||||
fetch('api.php?action=get_poverty').then(r=>r.json()).then(data=>{
|
||||
povertyPoints = Array.isArray(data)?data:[];
|
||||
document.getElementById('miskin').innerHTML = povertyPoints.length;
|
||||
updateStats();
|
||||
}).catch(()=>console.error('Gagal load poverty'));
|
||||
}
|
||||
function loadBantuan() {
|
||||
fetch('api.php?action=get_bantuan').then(r=>r.json()).then(data=>{
|
||||
var tabel = document.getElementById('tabelBantuan');
|
||||
while(tabel.rows.length>1) tabel.deleteRow(1);
|
||||
if(Array.isArray(data)) data.forEach(b=>{ var row=tabel.insertRow(); row.insertCell(0).innerHTML=b.tanggal_bantuan||'-'; row.insertCell(1).innerHTML=b.nama_penduduk||'-'; row.insertCell(2).innerHTML=b.jenis_bantuan||'-'; });
|
||||
}).catch(()=>{});
|
||||
}
|
||||
var grafikChart=null;
|
||||
function loadGrafik() {
|
||||
fetch('api.php?action=get_stats_bantuan').then(r=>r.json()).then(data=>{
|
||||
var labels=['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agt','Sep','Okt','Nov','Des'], values=new Array(12).fill(0);
|
||||
if(Array.isArray(data)) data.forEach(d=>{ var idx=labels.indexOf(d.bulan); if(idx>=0) values[idx]=parseInt(d.jumlah); });
|
||||
var ctx=document.getElementById('grafik'); if(grafikChart) grafikChart.destroy();
|
||||
grafikChart=new Chart(ctx,{type:'bar',data:{labels:labels,datasets:[{label:'Jumlah Bantuan',data:values,backgroundColor:'#3498db'}]},options:{responsive:true,plugins:{legend:{display:false}},scales:{y:{beginAtZero:true,ticks:{stepSize:1}}}}});
|
||||
}).catch(()=>{ var ctx=document.getElementById('grafik'); if(grafikChart) grafikChart.destroy(); grafikChart=new Chart(ctx,{type:'bar',data:{labels:['Jan','Feb','Mar','Apr','Mei'],datasets:[{label:'Jumlah Bantuan',data:[0,0,0,0,0],backgroundColor:'#3498db'}]},options:{responsive:true,plugins:{legend:{display:false}}}}); });
|
||||
}
|
||||
|
||||
// ==================== POPUP ====================
|
||||
function showMasjidPopup(data){
|
||||
var content='<div style="min-width:250px;"><h4 style="margin:0 0 8px 0;color:#2c3e50;">🕌 MASJID</h4><div><strong>Nama:</strong> '+(data.nama||'-')+'</div><div><strong>Alamat:</strong> '+(data.alamat||'-')+'</div><div><strong>Koordinat:</strong> '+data.lat+', '+data.lng+'</div><div class="clearfix"><button class="btn-edit" onclick="editMasjid('+data.id+',\''+escapeHtml(data.nama)+'\',\''+escapeHtml(data.alamat)+'\','+data.lat+','+data.lng+')">✏️ Edit</button><button class="btn-hapus" onclick="hapusMasjid('+data.id+')">🗑️ Hapus</button></div></div>';
|
||||
L.popup().setLatLng([data.lat,data.lng]).setContent(content).openOn(map);
|
||||
}
|
||||
function showGerejaPopup(data){
|
||||
var content='<div style="min-width:250px;"><h4 style="margin:0 0 8px 0;color:#2c3e50;">⛪ GEREJA</h4><div><strong>Nama:</strong> '+(data.nama||'-')+'</div><div><strong>Alamat:</strong> '+(data.alamat||'-')+'</div><div><strong>Koordinat:</strong> '+data.lat+', '+data.lng+'</div><div class="clearfix"><button class="btn-edit" onclick="editGereja('+data.id+',\''+escapeHtml(data.nama)+'\',\''+escapeHtml(data.alamat)+'\','+data.lat+','+data.lng+')">✏️ Edit</button><button class="btn-hapus" onclick="hapusGereja('+data.id+')">🗑️ Hapus</button></div></div>';
|
||||
L.popup().setLatLng([data.lat,data.lng]).setContent(content).openOn(map);
|
||||
}
|
||||
|
||||
function editMasjid(id,namaLama,alamatLama,lat,lng){
|
||||
map.closePopup();
|
||||
var form='<div class="popup-form"><h4>✏️ Edit Masjid</h4><input type="text" id="editNama" value="'+escapeHtml(namaLama)+'" placeholder="Nama Masjid"><input type="text" id="editAlamat" value="'+escapeHtml(alamatLama)+'" placeholder="Alamat"><button onclick="simpanEditMasjid('+id+','+lat+','+lng+')" style="width:100%;padding:8px;background:#27ae60;color:white;border:none;border-radius:4px;cursor:pointer;">💾 Simpan Perubahan</button></div>';
|
||||
L.popup().setLatLng([lat,lng]).setContent(form).openOn(map);
|
||||
}
|
||||
function simpanEditMasjid(id,lat,lng){
|
||||
var namaBaru=document.getElementById('editNama').value.trim(), alamatBaru=document.getElementById('editAlamat').value.trim();
|
||||
if(!namaBaru){ alert('Nama masjid wajib diisi!'); return; }
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'update_masjid',id:id,nama:namaBaru,alamat:alamatBaru,lat:lat,lng:lng})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Masjid berhasil diupdate!'); map.closePopup(); loadMasjid(); loadGereja(); } else { alert('❌ Gagal: '+(res.msg||'')); } });
|
||||
}
|
||||
function editGereja(id,namaLama,alamatLama,lat,lng){
|
||||
map.closePopup();
|
||||
var form='<div class="popup-form"><h4>✏️ Edit Gereja</h4><input type="text" id="editNama" value="'+escapeHtml(namaLama)+'" placeholder="Nama Gereja"><input type="text" id="editAlamat" value="'+escapeHtml(alamatLama)+'" placeholder="Alamat"><button onclick="simpanEditGereja('+id+','+lat+','+lng+')" style="width:100%;padding:8px;background:#9b59b6;color:white;border:none;border-radius:4px;cursor:pointer;">💾 Simpan Perubahan</button></div>';
|
||||
L.popup().setLatLng([lat,lng]).setContent(form).openOn(map);
|
||||
}
|
||||
function simpanEditGereja(id,lat,lng){
|
||||
var namaBaru=document.getElementById('editNama').value.trim(), alamatBaru=document.getElementById('editAlamat').value.trim();
|
||||
if(!namaBaru){ alert('Nama gereja wajib diisi!'); return; }
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'update_gereja',id:id,nama:namaBaru,alamat:alamatBaru,lat:lat,lng:lng})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Gereja berhasil diupdate!'); map.closePopup(); loadMasjid(); loadGereja(); } else { alert('❌ Gagal: '+(res.msg||'')); } });
|
||||
}
|
||||
function hapusMasjid(id){ if(confirm('Yakin ingin menghapus masjid ini?')){ fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'delete_masjid',id:id})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Masjid dihapus!'); map.closePopup(); loadMasjid(); loadGereja(); } }); } }
|
||||
function hapusGereja(id){ if(confirm('Yakin ingin menghapus gereja ini?')){ fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'delete_gereja',id:id})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Gereja dihapus!'); map.closePopup(); loadMasjid(); loadGereja(); } }); } }
|
||||
var _hapusPovertyId=0;
|
||||
function hapusPoverty(id){ _hapusPovertyId=id; var p=povertyPoints.find(x=>x.id==id); var nama=p?p.nama:'data ini'; document.getElementById('modalHapusNama').innerHTML='Data "'+nama+'" akan dihapus permanen.'; map.closePopup(); document.getElementById('modalHapusPoverty').style.display='flex'; }
|
||||
function konfirmasiHapusPoverty(){ document.getElementById('modalHapusPoverty').style.display='none'; fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'delete_poverty',id:_hapusPovertyId})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Data berhasil dihapus!'); loadPoverty(); } else { alert('❌ Gagal: '+(res.msg||'')); } }).catch(err=>{ alert('❌ Error: '+err.message); }); }
|
||||
|
||||
// ==================== STATISTIK & RADIUS ====================
|
||||
function updateStats(){
|
||||
var allIbadah=masjidPoints.length+gerejaPoints.length;
|
||||
document.getElementById('ibadah').innerHTML=allIbadah;
|
||||
document.getElementById('miskin').innerHTML=povertyPoints.length;
|
||||
radiusLayer.clearLayers();
|
||||
var allIbadahPoints=masjidPoints.concat(gerejaPoints);
|
||||
allIbadahPoints.forEach(item=>{ L.circle([parseFloat(item.lat),parseFloat(item.lng)],{radius:currentRadius,color:'#3498db',fillColor:'#3498db',fillOpacity:0.1,weight:1.5}).addTo(radiusLayer); });
|
||||
povertyLayer.clearLayers();
|
||||
var dalam=0,luar=0;
|
||||
povertyPoints.forEach(p=>{
|
||||
var isInside=false, pLat=parseFloat(p.lat), pLng=parseFloat(p.lng);
|
||||
allIbadahPoints.forEach(item=>{ if(map.distance([parseFloat(item.lat),parseFloat(item.lng)],[pLat,pLng])<=currentRadius) isInside=true; });
|
||||
if(isInside) dalam++; else luar++;
|
||||
var fotoHtml=(p.foto && p.foto!='')?'<img src="'+p.foto+'" style="max-width:100%; max-height:100px; border-radius:8px; margin:5px 0;"><br>':'';
|
||||
L.marker([pLat,pLng],{icon:createPovertyIcon(isInside)}).bindPopup('<b>👤 '+(p.nama||'-')+'</b><br>'+fotoHtml+'NIK: '+(p.nik||'-')+'<br>Pekerjaan: '+(p.pekerjaan||'-')+'<br>Penghasilan: Rp '+(parseInt(p.penghasilan||0)).toLocaleString('id-ID')+'<br>Anggota: '+(p.jumlah_anggota_keluarga||'1')+'<br>Kategori: '+(p.kategori_kemiskinan||'-')+'<br>Status Bantuan: '+(p.status_bantuan||'-')+'<br>Status: '+(isInside?'✅ Dalam Radius':'❌ Luar Radius')+'<br><div style="margin-top:8px;"><button onclick="bukaBeriBantuan('+p.id+',\''+(p.nama||'')+'\')" style="width:100%;padding:6px;background:#27ae60;color:white;border:none;border-radius:4px;cursor:pointer;margin-bottom:4px;font-size:11px;">🎁 Beri Bantuan</button></div><div class="clearfix"><button class="btn-edit" onclick="bukaEditPoverty('+p.id+')">✏️ Edit</button><button class="btn-hapus" onclick="hapusPoverty('+p.id+')">🗑️ Hapus</button></div>').addTo(povertyLayer);
|
||||
});
|
||||
document.getElementById('dalam').innerHTML=dalam;
|
||||
document.getElementById('luar').innerHTML=luar;
|
||||
}
|
||||
document.getElementById('radiusSlider').addEventListener('input',function(){ document.getElementById('radiusValue').innerHTML=this.value; });
|
||||
function terapkanRadius(){ currentRadius=parseInt(document.getElementById('radiusSlider').value); updateStats(); }
|
||||
|
||||
function simpanBantuan(){
|
||||
var jenis=document.getElementById('bJenis').value, jumlah=document.getElementById('bJumlah').value.trim(), tanggal=document.getElementById('bTanggal').value, ket=document.getElementById('bKeterangan').value.trim();
|
||||
if(!jumlah||!tanggal){ alert('Jumlah dan tanggal wajib diisi!'); return; }
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'add_bantuan',jenis_bantuan:jenis,jumlah:jumlah,tanggal:tanggal,keterangan:ket})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Bantuan berhasil disimpan!'); document.getElementById('bJumlah').value=''; document.getElementById('bTanggal').value=''; document.getElementById('bKeterangan').value=''; loadBantuan(); loadGrafik(); } else { alert('❌ Gagal: '+(res.msg||'')); } });
|
||||
}
|
||||
|
||||
|
||||
// ==================== KLIK PETA ====================
|
||||
map.on('click',function(e){ var lat=e.latlng.lat, lng=e.latlng.lng; var form='<div class="popup-form"><b>📍 Tambah Data</b><br><br><button onclick="bukaFormMasjid('+lat+','+lng+')" style="width:100%;padding:7px;margin-bottom:5px;background:#27ae60;color:white;border:none;border-radius:4px;cursor:pointer;">🕌 Tambah Masjid</button><button onclick="bukaFormGereja('+lat+','+lng+')" style="width:100%;padding:7px;margin-bottom:5px;background:#9b59b6;color:white;border:none;border-radius:4px;cursor:pointer;">⛪ Tambah Gereja</button><button onclick="bukaFormPoverty('+lat+','+lng+')" style="width:100%;padding:7px;background:#e74c3c;color:white;border:none;border-radius:4px;cursor:pointer;">⚠️ Tambah Penduduk Miskin</button></div>'; L.popup().setLatLng([lat,lng]).setContent(form).openOn(map); });
|
||||
function bukaFormMasjid(lat,lng){ map.closePopup(); var form='<div class="popup-form"><b>🕌 Input Masjid</b><br><br><input type="text" id="fNamaMasjid" placeholder="Nama Masjid *"><input type="text" id="fAlamatMasjid" placeholder="Alamat"><button onclick="simpanMasjid('+lat+','+lng+')" style="width:100%;padding:7px;background:#27ae60;color:white;border:none;border-radius:4px;cursor:pointer;">💾 Simpan</button></div>'; L.popup().setLatLng([lat,lng]).setContent(form).openOn(map); }
|
||||
function bukaFormGereja(lat,lng){ map.closePopup(); var form='<div class="popup-form"><b>⛪ Input Gereja</b><br><br><input type="text" id="fNamaGereja" placeholder="Nama Gereja *"><input type="text" id="fAlamatGereja" placeholder="Alamat"><button onclick="simpanGereja('+lat+','+lng+')" style="width:100%;padding:7px;background:#9b59b6;color:white;border:none;border-radius:4px;cursor:pointer;">💾 Simpan</button></div>'; L.popup().setLatLng([lat,lng]).setContent(form).openOn(map); }
|
||||
var _povertyLat=0,_povertyLng=0;
|
||||
function bukaFormPoverty(lat,lng){ map.closePopup(); _povertyLat=lat; _povertyLng=lng; document.getElementById('fNamaPoverty').value=''; document.getElementById('fNikPoverty').value=''; document.getElementById('fAlamatPoverty').value=''; document.getElementById('fPekerjaanPoverty').value=''; document.getElementById('fPenghasilanPoverty').value=''; document.getElementById('fAnggotaPoverty').value='1'; document.getElementById('fTanggunganPoverty').value='0'; document.getElementById('fKategoriPoverty').value='Miskin'; document.getElementById('fStatusBantuanPoverty').value='Belum'; document.getElementById('fKetPoverty').value=''; document.getElementById('fFotoPoverty').value=''; document.getElementById('previewFotoPoverty').style.display='none'; document.getElementById('modalKoordinat').innerHTML='📍 Koordinat: '+lat.toFixed(6)+', '+lng.toFixed(6); document.getElementById('modalPoverty').style.display='flex'; }
|
||||
function tutupModalPoverty(){ document.getElementById('modalPoverty').style.display='none'; }
|
||||
|
||||
function bukaEditPoverty(id){
|
||||
map.closePopup();
|
||||
var p=povertyPoints.find(x=>x.id==id);
|
||||
if(!p){ alert('Data tidak ditemukan!'); return; }
|
||||
document.getElementById('eIdPoverty').value=p.id;
|
||||
document.getElementById('eNamaPoverty').value=p.nama||'';
|
||||
document.getElementById('eNikPoverty').value=p.nik||'';
|
||||
document.getElementById('eAlamatPoverty').value=p.alamat||'';
|
||||
document.getElementById('ePekerjaanPoverty').value=p.pekerjaan||'';
|
||||
document.getElementById('ePenghasilanPoverty').value=p.penghasilan||0;
|
||||
document.getElementById('eAnggotaPoverty').value=p.jumlah_anggota_keluarga||1;
|
||||
document.getElementById('eTanggunganPoverty').value=p.jumlah_tanggungan||0;
|
||||
document.getElementById('eKategoriPoverty').value=p.kategori_kemiskinan||'Miskin';
|
||||
document.getElementById('eStatusBantuanPoverty').value=p.status_bantuan||'Belum';
|
||||
document.getElementById('eKetPoverty').value=p.keterangan||'';
|
||||
var previewDiv=document.getElementById('editPreviewFoto'), previewImg=document.getElementById('editPreviewImg');
|
||||
if(p.foto && p.foto!=''){ previewImg.src=p.foto; previewDiv.style.display='block'; document.getElementById('eFotoLama').value=p.foto; }
|
||||
else{ previewDiv.style.display='none'; document.getElementById('eFotoLama').value=''; }
|
||||
document.getElementById('eFotoPoverty').value='';
|
||||
document.getElementById('modalEditPoverty').style.display='flex';
|
||||
}
|
||||
function tutupModalEditPoverty(){ document.getElementById('modalEditPoverty').style.display='none'; }
|
||||
|
||||
function bukaBeriBantuan(id,nama){ map.closePopup(); document.getElementById('beriPendudukId').value=id; document.getElementById('beriNamaPenduduk').innerHTML='Penerima: '+nama; document.getElementById('beriJenis').value='Sembako'; document.getElementById('beriJumlah').value=''; document.getElementById('beriTanggal').value=new Date().toISOString().split('T')[0]; document.getElementById('beriKeterangan').value=''; document.getElementById('modalBeriBantuan').style.display='flex'; }
|
||||
function simpanBeriBantuan(){
|
||||
var penduduk_id=parseInt(document.getElementById('beriPendudukId').value), jenis=document.getElementById('beriJenis').value, jumlah=document.getElementById('beriJumlah').value.trim(), tanggal=document.getElementById('beriTanggal').value, ket=document.getElementById('beriKeterangan').value.trim();
|
||||
if(!jumlah||!tanggal){ alert('Jumlah dan tanggal wajib diisi!'); return; }
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'add_bantuan',id_penduduk:penduduk_id,jenis_bantuan:jenis,jumlah:jumlah,tanggal:tanggal,keterangan:ket})}).then(r=>r.json()).then(res=>{ if(res.status==='ok'){ return fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'update_poverty',id:penduduk_id,status_bantuan:'Pernah'})}).then(r=>r.json()); } else { throw new Error(res.msg||'Gagal simpan bantuan'); } }).then(res2=>{ document.getElementById('modalBeriBantuan').style.display='none'; alert('✅ Bantuan berhasil dicatat!'); loadPoverty(); loadBantuan(); loadGrafik(); }).catch(err=>{ alert('❌ Error: '+err.message); });
|
||||
}
|
||||
|
||||
// ==================== SIMPAN POVERTY DENGAN FOTO (YANG DIPERBAIKI) ====================
|
||||
function simpanPoverty(){
|
||||
var nama=document.getElementById('fNamaPoverty').value.trim();
|
||||
var nik=document.getElementById('fNikPoverty').value.trim();
|
||||
var alamat=document.getElementById('fAlamatPoverty').value.trim();
|
||||
var pekerjaan=document.getElementById('fPekerjaanPoverty').value.trim();
|
||||
var penghasilan=parseInt(document.getElementById('fPenghasilanPoverty').value)||0;
|
||||
var anggota=parseInt(document.getElementById('fAnggotaPoverty').value)||1;
|
||||
var tanggungan=parseInt(document.getElementById('fTanggunganPoverty').value)||0;
|
||||
var kategori=document.getElementById('fKategoriPoverty').value;
|
||||
var status_bantuan=document.getElementById('fStatusBantuanPoverty').value;
|
||||
var ket=document.getElementById('fKetPoverty').value.trim();
|
||||
var lat=_povertyLat;
|
||||
var lng=_povertyLng;
|
||||
var fotoFile=document.getElementById('fFotoPoverty').files[0];
|
||||
|
||||
if(!nama){ alert('Nama wajib diisi!'); return; }
|
||||
|
||||
if(fotoFile){
|
||||
var formData=new FormData();
|
||||
formData.append('action','upload_foto');
|
||||
formData.append('foto',fotoFile);
|
||||
fetch('api.php',{method:'POST',body:formData})
|
||||
.then(r=>r.json())
|
||||
.then(uploadRes=>{
|
||||
if(uploadRes.status==='ok'){
|
||||
simpanPovertyData(uploadRes.foto_url,nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket,lat,lng);
|
||||
} else { alert('Gagal upload foto: '+uploadRes.msg); }
|
||||
}).catch(err=>{ alert('Error upload: '+err.message); });
|
||||
} else {
|
||||
simpanPovertyData('',nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket,lat,lng);
|
||||
}
|
||||
}
|
||||
function simpanPovertyData(fotoUrl,nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket,lat,lng){
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'add_poverty',nama:nama,nik:nik,alamat:alamat,pekerjaan:pekerjaan,penghasilan:penghasilan,anggota:anggota,tanggungan:tanggungan,kategori:kategori,status_bantuan:status_bantuan,keterangan:ket,foto:fotoUrl,lat:lat,lng:lng})})
|
||||
.then(r=>r.json())
|
||||
.then(res=>{
|
||||
if(res.status==='ok'){
|
||||
alert('✅ Data penduduk miskin berhasil ditambahkan!');
|
||||
tutupModalPoverty();
|
||||
document.getElementById('fFotoPoverty').value='';
|
||||
document.getElementById('previewFotoPoverty').style.display='none';
|
||||
loadPoverty();
|
||||
} else { alert('❌ Gagal: '+(res.msg||'')); }
|
||||
}).catch(err=>{ alert('❌ Error: '+err.message); });
|
||||
}
|
||||
function simpanEditPoverty(){
|
||||
var id=parseInt(document.getElementById('eIdPoverty').value);
|
||||
var nama=document.getElementById('eNamaPoverty').value.trim();
|
||||
var nik=document.getElementById('eNikPoverty').value.trim();
|
||||
var alamat=document.getElementById('eAlamatPoverty').value.trim();
|
||||
var pekerjaan=document.getElementById('ePekerjaanPoverty').value.trim();
|
||||
var penghasilan=parseInt(document.getElementById('ePenghasilanPoverty').value)||0;
|
||||
var anggota=parseInt(document.getElementById('eAnggotaPoverty').value)||1;
|
||||
var tanggungan=parseInt(document.getElementById('eTanggunganPoverty').value)||0;
|
||||
var kategori=document.getElementById('eKategoriPoverty').value;
|
||||
var status_bantuan=document.getElementById('eStatusBantuanPoverty').value;
|
||||
var ket=document.getElementById('eKetPoverty').value.trim();
|
||||
var fotoLama=document.getElementById('eFotoLama').value;
|
||||
var fotoFile=document.getElementById('eFotoPoverty').files[0];
|
||||
if(!nama){ alert('Nama wajib diisi!'); return; }
|
||||
if(fotoFile){
|
||||
var formData=new FormData();
|
||||
formData.append('action','upload_foto');
|
||||
formData.append('foto',fotoFile);
|
||||
fetch('api.php',{method:'POST',body:formData})
|
||||
.then(r=>r.json())
|
||||
.then(uploadRes=>{
|
||||
if(uploadRes.status==='ok'){ updatePovertyData(id,uploadRes.foto_url,nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket); }
|
||||
else{ alert('Gagal upload foto: '+uploadRes.msg); }
|
||||
}).catch(err=>{ alert('Error upload: '+err.message); });
|
||||
} else { updatePovertyData(id,fotoLama,nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket); }
|
||||
}
|
||||
function updatePovertyData(id,fotoUrl,nama,nik,alamat,pekerjaan,penghasilan,anggota,tanggungan,kategori,status_bantuan,ket){
|
||||
fetch('api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'update_poverty',id:id,nama:nama,nik:nik,alamat:alamat,pekerjaan:pekerjaan,penghasilan:penghasilan,anggota:anggota,tanggungan:tanggungan,kategori:kategori,status_bantuan:status_bantuan,keterangan:ket,foto:fotoUrl})})
|
||||
.then(r=>r.json())
|
||||
.then(res=>{
|
||||
if(res.status==='ok'){ alert('✅ Data berhasil diupdate!'); tutupModalEditPoverty(); loadPoverty(); }
|
||||
else{ alert('❌ Gagal: '+(res.msg||'')); }
|
||||
}).catch(err=>{ alert('❌ Error: '+err.message); });
|
||||
}
|
||||
function simpanMasjid(lat,lng){ var nama=document.getElementById('fNamaMasjid').value.trim(), alamat=document.getElementById('fAlamatMasjid').value.trim(); if(!nama){ alert('Nama masjid wajib 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(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Masjid berhasil ditambahkan!'); map.closePopup(); loadMasjid(); } else { alert('❌ Gagal: '+(res.msg||'')); } }); }
|
||||
function simpanGereja(lat,lng){ var nama=document.getElementById('fNamaGereja').value.trim(), alamat=document.getElementById('fAlamatGereja').value.trim(); if(!nama){ alert('Nama gereja wajib 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(r=>r.json()).then(res=>{ if(res.status==='ok'){ alert('✅ Gereja berhasil ditambahkan!'); map.closePopup(); loadGereja(); } else { alert('❌ Gagal: '+(res.msg||'')); } }); }
|
||||
|
||||
// ==================== LOAD KECAMATAN & START ====================
|
||||
fetch('Admin_Kecamatan.json').then(r=>r.json()).then(data=>{ L.geoJSON(data,{style:{color:'#2c3e50',weight:2,fillOpacity:0.04,dashArray:'5,5'}}).addTo(map); }).catch(err=>console.warn('GeoJSON tidak ditemukan:',err));
|
||||
loadSemua();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,465 @@
|
||||
<?php
|
||||
ob_start();
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('log_errors', 0);
|
||||
|
||||
header('Content-Type: application/json');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
||||
http_response_code(200);
|
||||
exit();
|
||||
}
|
||||
|
||||
include 'koneksi.php';
|
||||
ob_clean();
|
||||
|
||||
function sendJson($data) {
|
||||
ob_end_clean();
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($conn->connect_error) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Database connection failed: ' . $conn->connect_error]);
|
||||
}
|
||||
|
||||
$action = $_GET['action'] ?? $_POST['action'] ?? '';
|
||||
|
||||
$input = [];
|
||||
$rawBody = file_get_contents('php://input');
|
||||
if (!empty($rawBody)) {
|
||||
$decoded = json_decode($rawBody, true);
|
||||
if ($decoded) {
|
||||
$input = $decoded;
|
||||
if (isset($input['action'])) {
|
||||
$action = $input['action'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== UPLOAD FOTO ====================
|
||||
if ($action == 'upload_foto') {
|
||||
// Pakai path absolut supaya tidak bergantung letak file yang memanggil
|
||||
$base_dir = dirname(__FILE__);
|
||||
$target_dir = $base_dir . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
|
||||
$web_path = 'uploads/'; // path relatif untuk disimpan ke DB & ditampilkan di browser
|
||||
|
||||
if (!file_exists($target_dir)) {
|
||||
if (!mkdir($target_dir, 0777, true)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Gagal membuat folder uploads. Cek permission direktori parent.']);
|
||||
}
|
||||
}
|
||||
if (!is_writable($target_dir)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Folder uploads tidak bisa ditulis. Jalankan di server: chmod 777 uploads/']);
|
||||
}
|
||||
|
||||
if (!isset($_FILES['foto']) || $_FILES['foto']['error'] === UPLOAD_ERR_NO_FILE) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Tidak ada file yang diupload']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_FILES['foto']['error'] !== UPLOAD_ERR_OK) {
|
||||
$err_map = [
|
||||
UPLOAD_ERR_INI_SIZE => 'Ukuran file melebihi batas server (upload_max_filesize)',
|
||||
UPLOAD_ERR_FORM_SIZE => 'Ukuran file melebihi MAX_FILE_SIZE',
|
||||
UPLOAD_ERR_PARTIAL => 'File hanya terupload sebagian, coba lagi',
|
||||
UPLOAD_ERR_NO_TMP_DIR=> 'Folder temporary tidak ditemukan',
|
||||
UPLOAD_ERR_CANT_WRITE=> 'Gagal menulis file ke disk, cek permission',
|
||||
UPLOAD_ERR_EXTENSION => 'Upload dihentikan oleh ekstensi PHP',
|
||||
];
|
||||
$msg = $err_map[$_FILES['foto']['error']] ?? 'Error upload: kode ' . $_FILES['foto']['error'];
|
||||
sendJson(['status' => 'error', 'msg' => $msg]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_FILES['foto']['size'] <= 0) {
|
||||
sendJson(['status' => 'error', 'msg' => 'File kosong (ukuran 0 byte)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Maksimal 5MB
|
||||
if ($_FILES['foto']['size'] > 5000000) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Ukuran file maksimal 5MB']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validasi benar-benar gambar
|
||||
$check = @getimagesize($_FILES['foto']['tmp_name']);
|
||||
if ($check === false) {
|
||||
sendJson(['status' => 'error', 'msg' => 'File bukan gambar yang valid']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ekstensi yang diizinkan
|
||||
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
|
||||
if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Format tidak didukung. Gunakan JPG, PNG, GIF, atau WEBP']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$clean_name = preg_replace('/[^a-zA-Z0-9._-]/', '_', basename($_FILES['foto']['name']));
|
||||
$file_name = time() . '_' . $clean_name;
|
||||
$target_file = $target_dir . $file_name;
|
||||
$foto_url = $web_path . $file_name; // simpan path relatif ke DB
|
||||
|
||||
if (move_uploaded_file($_FILES['foto']['tmp_name'], $target_file)) {
|
||||
sendJson(['status' => 'ok', 'foto_url' => $foto_url]);
|
||||
} else {
|
||||
// Cek permission folder untuk bantu debug
|
||||
$perm = substr(sprintf('%o', fileperms($target_dir)), -4);
|
||||
sendJson([
|
||||
'status' => 'error',
|
||||
'msg' => 'Gagal menyimpan file. Permission folder uploads: ' . $perm . '. Pastikan folder bisa ditulis (chmod 777).',
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// ==================== GET DATA ====================
|
||||
|
||||
if ($action == 'get_masjid') {
|
||||
$data = [];
|
||||
$query = mysqli_query($conn, "SELECT id, nama_rumah_ibadah as nama, alamat, lat, lng FROM rumah_ibadah WHERE jenis_rumah_ibadah = 'masjid' OR jenis_rumah_ibadah IS NULL OR jenis_rumah_ibadah = ''");
|
||||
while ($row = mysqli_fetch_assoc($query)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
sendJson($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'get_gereja') {
|
||||
$data = [];
|
||||
$query = mysqli_query($conn, "SELECT id, nama_rumah_ibadah as nama, alamat, lat, lng FROM rumah_ibadah WHERE jenis_rumah_ibadah = 'gereja'");
|
||||
while ($row = mysqli_fetch_assoc($query)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
sendJson($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'get_poverty') {
|
||||
$data = [];
|
||||
$query = mysqli_query($conn, "SELECT * FROM penduduk_miskin ORDER BY id DESC");
|
||||
while ($row = mysqli_fetch_assoc($query)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
sendJson($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'get_bantuan') {
|
||||
$data = [];
|
||||
$query = mysqli_query($conn, "SELECT b.*, p.nama as nama_penduduk FROM bantuan b LEFT JOIN penduduk_miskin p ON b.penduduk_id = p.id ORDER BY b.tanggal_bantuan DESC LIMIT 50");
|
||||
while ($row = mysqli_fetch_assoc($query)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
sendJson($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'get_stats_bantuan') {
|
||||
$data = [];
|
||||
$query = mysqli_query($conn, "SELECT DATE_FORMAT(tanggal_bantuan, '%b') as bulan, COUNT(*) as jumlah FROM bantuan GROUP BY MONTH(tanggal_bantuan) ORDER BY MONTH(tanggal_bantuan)");
|
||||
while ($row = mysqli_fetch_assoc($query)) {
|
||||
$data[] = $row;
|
||||
}
|
||||
sendJson($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ==================== CREATE (TAMBAH DATA) ====================
|
||||
|
||||
if ($action == 'add_masjid') {
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$lat = isset($input['lat']) ? floatval($input['lat']) : 0;
|
||||
$lng = isset($input['lng']) ? floatval($input['lng']) : 0;
|
||||
|
||||
if (empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Nama wajib diisi']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
|
||||
$sql = "INSERT INTO rumah_ibadah (nama_rumah_ibadah, alamat, lat, lng, jenis_rumah_ibadah) VALUES ('$nama', '$alamat', $lat, $lng, 'masjid')";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok', 'id' => mysqli_insert_id($conn)]);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'add_gereja') {
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$lat = isset($input['lat']) ? floatval($input['lat']) : 0;
|
||||
$lng = isset($input['lng']) ? floatval($input['lng']) : 0;
|
||||
|
||||
if (empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Nama wajib diisi']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
|
||||
$sql = "INSERT INTO rumah_ibadah (nama_rumah_ibadah, alamat, lat, lng, jenis_rumah_ibadah) VALUES ('$nama', '$alamat', $lat, $lng, 'gereja')";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok', 'id' => mysqli_insert_id($conn)]);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'add_poverty') {
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$nik = isset($input['nik']) ? trim($input['nik']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$pekerjaan = isset($input['pekerjaan']) ? trim($input['pekerjaan']) : '';
|
||||
$penghasilan = isset($input['penghasilan']) ? intval($input['penghasilan']) : 0;
|
||||
$anggota = isset($input['anggota']) ? intval($input['anggota']) : 1;
|
||||
$tanggungan = isset($input['tanggungan']) ? intval($input['tanggungan']) : 0;
|
||||
$kategori = isset($input['kategori']) ? trim($input['kategori']) : 'Miskin';
|
||||
$status_bantuan = isset($input['status_bantuan']) ? trim($input['status_bantuan']) : 'Belum';
|
||||
$keterangan = isset($input['keterangan']) ? trim($input['keterangan']) : '';
|
||||
$lat = isset($input['lat']) ? floatval($input['lat']) : 0;
|
||||
$lng = isset($input['lng']) ? floatval($input['lng']) : 0;
|
||||
$foto = isset($input['foto']) ? trim($input['foto']) : '';
|
||||
|
||||
if (empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Nama wajib diisi']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$nik = mysqli_real_escape_string($conn, $nik);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
$pekerjaan = mysqli_real_escape_string($conn, $pekerjaan);
|
||||
$kategori = mysqli_real_escape_string($conn, $kategori);
|
||||
$status_bantuan = mysqli_real_escape_string($conn, $status_bantuan);
|
||||
$keterangan = mysqli_real_escape_string($conn, $keterangan);
|
||||
$foto = mysqli_real_escape_string($conn, $foto);
|
||||
|
||||
$sql = "INSERT INTO penduduk_miskin (nama, nik, alamat, pekerjaan, penghasilan, jumlah_anggota_keluarga, jumlah_tanggungan, kategori_kemiskinan, status_bantuan, keterangan, foto, lat, lng)
|
||||
VALUES ('$nama', '$nik', '$alamat', '$pekerjaan', $penghasilan, $anggota, $tanggungan, '$kategori', '$status_bantuan', '$keterangan', '$foto', $lat, $lng)";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok', 'id' => mysqli_insert_id($conn)]);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'add_bantuan') {
|
||||
$jenis = isset($input['jenis_bantuan']) ? trim($input['jenis_bantuan']) : '';
|
||||
$jumlah = isset($input['jumlah']) ? trim($input['jumlah']) : '';
|
||||
$tanggal = isset($input['tanggal']) ? trim($input['tanggal']) : date('Y-m-d');
|
||||
$keterangan = isset($input['keterangan']) ? trim($input['keterangan']) : '';
|
||||
$penduduk_id = isset($input['id_penduduk']) ? intval($input['id_penduduk']) : 0;
|
||||
|
||||
$jenis = mysqli_real_escape_string($conn, $jenis);
|
||||
$jumlah = mysqli_real_escape_string($conn, $jumlah);
|
||||
$tanggal = mysqli_real_escape_string($conn, $tanggal);
|
||||
$keterangan = mysqli_real_escape_string($conn, $keterangan);
|
||||
|
||||
$sql = "INSERT INTO bantuan (penduduk_id, jenis_bantuan, jumlah_bantuan, tanggal_bantuan, keterangan)
|
||||
VALUES ($penduduk_id, '$jenis', '$jumlah', '$tanggal', '$keterangan')";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// ==================== UPDATE (EDIT DATA) ====================
|
||||
|
||||
if ($action == 'update_masjid') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$lat = isset($input['lat']) ? floatval($input['lat']) : 0;
|
||||
$lng = isset($input['lng']) ? floatval($input['lng']) : 0;
|
||||
|
||||
if ($id == 0 || empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Data tidak lengkap']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
|
||||
$sql = "UPDATE rumah_ibadah SET nama_rumah_ibadah = '$nama', alamat = '$alamat', lat = $lat, lng = $lng WHERE id = $id AND (jenis_rumah_ibadah = 'masjid' OR jenis_rumah_ibadah IS NULL)";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'update_gereja') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$lat = isset($input['lat']) ? floatval($input['lat']) : 0;
|
||||
$lng = isset($input['lng']) ? floatval($input['lng']) : 0;
|
||||
|
||||
if ($id == 0 || empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Data tidak lengkap']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
|
||||
$sql = "UPDATE rumah_ibadah SET nama_rumah_ibadah = '$nama', alamat = '$alamat', lat = $lat, lng = $lng WHERE id = $id AND jenis_rumah_ibadah = 'gereja'";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'update_poverty') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
if ($id == 0) {
|
||||
sendJson(['status' => 'error', 'msg' => 'ID tidak valid']);
|
||||
}
|
||||
|
||||
if (isset($input['status_bantuan']) && !isset($input['nama'])) {
|
||||
$status_bantuan = mysqli_real_escape_string($conn, trim($input['status_bantuan']));
|
||||
$sql = "UPDATE penduduk_miskin SET status_bantuan = '$status_bantuan' WHERE id = $id";
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
$nama = isset($input['nama']) ? trim($input['nama']) : '';
|
||||
$nik = isset($input['nik']) ? trim($input['nik']) : '';
|
||||
$alamat = isset($input['alamat']) ? trim($input['alamat']) : '';
|
||||
$pekerjaan = isset($input['pekerjaan']) ? trim($input['pekerjaan']) : '';
|
||||
$penghasilan = isset($input['penghasilan']) ? intval($input['penghasilan']) : 0;
|
||||
$anggota = isset($input['anggota']) ? intval($input['anggota']) : 1;
|
||||
$tanggungan = isset($input['tanggungan']) ? intval($input['tanggungan']) : 0;
|
||||
$kategori = isset($input['kategori']) ? trim($input['kategori']) : 'Miskin';
|
||||
$status_bantuan = isset($input['status_bantuan']) ? trim($input['status_bantuan']) : 'Belum';
|
||||
$keterangan = isset($input['keterangan']) ? trim($input['keterangan']) : '';
|
||||
$foto = isset($input['foto']) ? trim($input['foto']) : '';
|
||||
|
||||
if (empty($nama)) {
|
||||
sendJson(['status' => 'error', 'msg' => 'Nama wajib diisi']);
|
||||
}
|
||||
|
||||
$nama = mysqli_real_escape_string($conn, $nama);
|
||||
$nik = mysqli_real_escape_string($conn, $nik);
|
||||
$alamat = mysqli_real_escape_string($conn, $alamat);
|
||||
$pekerjaan = mysqli_real_escape_string($conn, $pekerjaan);
|
||||
$kategori = mysqli_real_escape_string($conn, $kategori);
|
||||
$status_bantuan = mysqli_real_escape_string($conn, $status_bantuan);
|
||||
$keterangan = mysqli_real_escape_string($conn, $keterangan);
|
||||
$foto = mysqli_real_escape_string($conn, $foto);
|
||||
|
||||
$sql = "UPDATE penduduk_miskin SET
|
||||
nama = '$nama',
|
||||
nik = '$nik',
|
||||
alamat = '$alamat',
|
||||
pekerjaan = '$pekerjaan',
|
||||
penghasilan = $penghasilan,
|
||||
jumlah_anggota_keluarga = $anggota,
|
||||
jumlah_tanggungan = $tanggungan,
|
||||
kategori_kemiskinan = '$kategori',
|
||||
status_bantuan = '$status_bantuan',
|
||||
keterangan = '$keterangan',
|
||||
foto = '$foto'
|
||||
WHERE id = $id";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// ==================== DELETE (HAPUS DATA) ====================
|
||||
|
||||
if ($action == 'delete_masjid') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
if ($id == 0) {
|
||||
sendJson(['status' => 'error', 'msg' => 'ID tidak valid']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM rumah_ibadah WHERE id = $id AND (jenis_rumah_ibadah = 'masjid' OR jenis_rumah_ibadah IS NULL)";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'delete_gereja') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
if ($id == 0) {
|
||||
sendJson(['status' => 'error', 'msg' => 'ID tidak valid']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM rumah_ibadah WHERE id = $id AND jenis_rumah_ibadah = 'gereja'";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action == 'delete_poverty') {
|
||||
$id = isset($input['id']) ? intval($input['id']) : 0;
|
||||
if ($id == 0) {
|
||||
sendJson(['status' => 'error', 'msg' => 'ID tidak valid']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$query = mysqli_query($conn, "SELECT foto FROM penduduk_miskin WHERE id = $id");
|
||||
if ($row = mysqli_fetch_assoc($query)) {
|
||||
if (!empty($row['foto']) && file_exists($row['foto'])) {
|
||||
unlink($row['foto']);
|
||||
}
|
||||
}
|
||||
|
||||
mysqli_query($conn, "UPDATE bantuan SET penduduk_id = NULL WHERE penduduk_id = $id");
|
||||
|
||||
$sql = "DELETE FROM penduduk_miskin WHERE id = $id";
|
||||
|
||||
if (mysqli_query($conn, $sql)) {
|
||||
sendJson(['status' => 'ok']);
|
||||
} else {
|
||||
sendJson(['status' => 'error', 'msg' => mysqli_error($conn)]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
sendJson(['status' => 'error', 'msg' => 'Aksi tidak dikenal: ' . $action]);
|
||||
+861
@@ -0,0 +1,861 @@
|
||||
<!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>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
$host = 'localhost';
|
||||
$user = 'root';
|
||||
$password = '';
|
||||
$database = 'webgis_kemiskinan';
|
||||
|
||||
$conn = new mysqli($host, $user, $password, $database);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
die(json_encode([
|
||||
'status' => 'error',
|
||||
'msg' => 'Koneksi database gagal: ' . $conn->connect_error
|
||||
]));
|
||||
}
|
||||
|
||||
$conn->set_charset("utf8");
|
||||
Reference in New Issue
Block a user