Initial commit: Upload project WebGIS pemetaan sosial
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
$stmt = $conn->prepare("DELETE FROM area_polygon WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
|
||||
// Hapus data dari tabel jalan_polyline berdasarkan ID
|
||||
$stmt = $conn->prepare("DELETE FROM jalan_polyline WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Garis jalan berhasil dihapus"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal menghapus data: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
|
||||
$stmt = $conn->prepare("DELETE FROM spbu_point WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Data berhasil dihapus"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal menghapus data: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sistem Pemetaan</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css" />
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="sidebar">
|
||||
<h3>Menu Peta</h3>
|
||||
|
||||
<div class="mode-selector">
|
||||
<strong>Pilih Mode Pemetaan:</strong><br><br>
|
||||
<div class="mode-buttons">
|
||||
<button class="mode-btn active" data-mode="point" onclick="ubahMode('point')">
|
||||
<i class="fa-solid fa-gas-pump"></i> SPBU
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="polyline" onclick="ubahMode('polyline')">
|
||||
<i class="fa-solid fa-road"></i> Jalan
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="polygon" onclick="ubahMode('polygon')">
|
||||
<i class="fa-solid fa-draw-polygon"></i> Kavling
|
||||
</button>
|
||||
</div><br>
|
||||
<div class="mode-buttons">
|
||||
<button class="mode-btn" data-mode="edit_jalan" onclick="ubahMode('edit_jalan')" style="background-color: #fcf3cf; border-color: #f1c40f; color: #d35400;">
|
||||
<i class="fa-solid fa-pen-ruler"></i> Edit Jalan
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="edit_kavling" onclick="ubahMode('edit_kavling')" style="background-color: #d4efdf; border-color: #27ae60; color: #1e8449;">
|
||||
<i class="fa-solid fa-pen-ruler"></i> Edit Kavling
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="polyline-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-road"></i> Gambar Jalan Baru</strong>
|
||||
<p style="font-size: 11px; color: #666;">Klik di peta untuk menggambar garis.</p>
|
||||
<label>Nama Jalan:</label>
|
||||
<input type="text" id="input_nama_jalan" placeholder="Masukkan nama...">
|
||||
<label>Status Jalan:</label>
|
||||
<select id="input_status_jalan">
|
||||
<option value="Nasional">Nasional (Merah)</option>
|
||||
<option value="Provinsi">Provinsi (Kuning)</option>
|
||||
<option value="Kabupaten">Kabupaten (Hijau)</option>
|
||||
</select>
|
||||
<button onclick="simpanPolyline()" class="btn-success">Simpan Jalan</button>
|
||||
<button onclick="batalPolyline()" class="btn-danger">Batal</button>
|
||||
</div>
|
||||
|
||||
<div id="polygon-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-draw-polygon"></i> Gambar Kavling</strong>
|
||||
<p style="font-size: 11px; color: #666;">Klik min. 3 titik untuk area.</p>
|
||||
<label>Nama Pemilik/Kavling:</label>
|
||||
<input type="text" id="input_nama_kavling" placeholder="Masukkan nama...">
|
||||
<label>Status Tanah:</label>
|
||||
<select id="input_status_tanah">
|
||||
<option value="SHM">SHM (Merah)</option>
|
||||
<option value="HGB">HGB (Biru)</option>
|
||||
<option value="HGU">HGU (Hijau)</option>
|
||||
<option value="HP">HP (Kuning)</option>
|
||||
</select>
|
||||
<button onclick="simpanPolygon()" class="btn-success">Simpan Area</button>
|
||||
<button onclick="batalPolygon()" class="btn-danger">Batal</button>
|
||||
</div>
|
||||
|
||||
<div id="edit-jalan-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-pen-ruler"></i> Mode Edit Jalan Aktif</strong>
|
||||
<p style="font-size: 11px; color: #666;">Pilih salah satu jalan di peta yang ingin diubah bentuknya.</p>
|
||||
<div id="info-edit-jalan" style="display:none; margin-bottom:10px; padding:10px; background:#f9f9f9; border:1px solid #ccc; border-radius:4px;">
|
||||
<b id="nama-jalan-edit">Nama Jalan</b><br>
|
||||
<span style="font-size:12px; color:gray;">Geser titik-titik (kotak putih) pada jalan di peta untuk mengubah bentuknya.</span>
|
||||
</div>
|
||||
<button id="btn-simpan-edit-jalan" onclick="simpanEditPolyline()" class="btn-success" style="display:none;">Simpan Perubahan Jalan</button>
|
||||
</div>
|
||||
|
||||
<div id="edit-kavling-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-pen-ruler"></i> Mode Edit Kavling Aktif</strong>
|
||||
<p style="font-size: 11px; color: #666;">Pilih salah satu kavling di peta yang ingin diubah bentuknya.</p>
|
||||
<div id="info-edit-kavling" style="display:none; margin-bottom:10px; padding:10px; background:#f9f9f9; border:1px solid #ccc; border-radius:4px;">
|
||||
<b id="nama-kavling-edit">Nama Kavling</b><br>
|
||||
<span style="font-size:12px; color:gray;">Geser titik-titik (kotak putih) pada area di peta untuk mengubah bentuknya.</span>
|
||||
</div>
|
||||
<button id="btn-simpan-edit-kavling" onclick="simpanEditPolygon()" class="btn-success" style="display:none;">Simpan Perubahan Kavling</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="map-container">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.min.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
$sql = "SELECT * FROM area_polygon";
|
||||
$result = $conn->query($sql);
|
||||
$data_area = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
// Mengubah string geojson dari database kembali menjadi Object JSON
|
||||
// Ini wajib agar Leaflet.geoJSON() di Javascript bisa merendernya
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$data_area[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($data_area);
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$sql = "SELECT * FROM jalan_polyline";
|
||||
$result = $conn->query($sql);
|
||||
$data_jalan = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
// Parse string geojson menjadi object agar mudah dibaca Javascript
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$data_jalan[] = $row;
|
||||
}
|
||||
}
|
||||
echo json_encode($data_jalan);
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ambil semua data dari tabel spbu_point
|
||||
$sql = "SELECT * FROM spbu_point";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$data_spbu = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$data_spbu[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
// Kirim data sebagai JSON
|
||||
echo json_encode($data_spbu);
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
+405
@@ -0,0 +1,405 @@
|
||||
// --- INISIALISASI PETA (Koordinat Pontianak) ---
|
||||
const map = L.map('map').setView([-0.055348, 109.349512], 13);
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap' }).addTo(map);
|
||||
|
||||
const popup = L.popup();
|
||||
const daftarMarker = {}, daftarPolyline = {}, daftarPolygon = {};
|
||||
|
||||
let currentMode = 'point';
|
||||
let tempLatLngs = [], tempPolyline = null;
|
||||
let tempPolygonLatLngs = [], tempPolygon = null;
|
||||
let targetEditJalanId = null; // Menyimpan ID jalan yang sedang diedit
|
||||
let targetEditKavlingId = null; // Menyimpan ID kavling yang sedang diedit
|
||||
|
||||
// Konfigurasi SweetAlert2 (Toast Pojok Kanan Atas)
|
||||
const Toast = Swal.mixin({
|
||||
toast: true, position: 'top-end', showConfirmButton: false, timer: 3000, timerProgressBar: true
|
||||
});
|
||||
|
||||
// Definisi Ikon Kustom
|
||||
const ikonHijau = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
const ikonMerah = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
|
||||
// --- MANAJEMEN MODE UI ---
|
||||
function ubahMode(mode) {
|
||||
currentMode = mode;
|
||||
|
||||
// Matikan mode edit Geoman global jika sedang aktif
|
||||
map.pm.disableGlobalEditMode();
|
||||
|
||||
// Reset state edit
|
||||
if (targetEditJalanId) batalkanEditJalan();
|
||||
if (targetEditKavlingId) batalkanEditKavling();
|
||||
|
||||
// Atur tampilan tombol aktif
|
||||
document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
|
||||
document.querySelector(`.mode-btn[data-mode="${mode}"]`).classList.add('active');
|
||||
|
||||
// Munculkan menu yang sesuai di sidebar
|
||||
document.getElementById('polyline-actions').style.display = (mode === 'polyline') ? 'block' : 'none';
|
||||
document.getElementById('polygon-actions').style.display = (mode === 'polygon') ? 'block' : 'none';
|
||||
document.getElementById('edit-jalan-actions').style.display = (mode === 'edit_jalan') ? 'block' : 'none';
|
||||
document.getElementById('edit-kavling-actions').style.display = (mode === 'edit_kavling') ? 'block' : 'none';
|
||||
|
||||
map.closePopup();
|
||||
if (mode !== 'polyline') batalPolyline();
|
||||
if (mode !== 'polygon') batalPolygon();
|
||||
}
|
||||
|
||||
// --- FUNGSI BANTUAN ---
|
||||
function hitungPanjangJalan(latlngs) { let t=0; for (let i=0; i<latlngs.length-1; i++) t += map.distance(latlngs[i], latlngs[i + 1]); return t; }
|
||||
function warnaJalan(s) { return (s === 'Nasional') ? 'red' : (s === 'Provinsi') ? 'yellow' : (s === 'Kabupaten') ? 'green' : 'blue'; }
|
||||
function hitungLuasArea(latlngs) {
|
||||
let area = 0, p = Array.isArray(latlngs[0]) ? latlngs[0] : latlngs;
|
||||
area = L.GeometryUtil ? L.GeometryUtil.geodesicArea(p) : 0;
|
||||
if (area === 0) {
|
||||
const R = 6378137, rad = Math.PI / 180;
|
||||
for (let i = 0; i < p.length; i++) {
|
||||
let p1 = p[i], p2 = p[(i + 1) % p.length];
|
||||
area += (p2.lng - p1.lng) * rad * (2 + Math.sin(p1.lat * rad) + Math.sin(p2.lat * rad));
|
||||
}
|
||||
area = Math.abs(area * R * R / 2);
|
||||
} return area;
|
||||
}
|
||||
function warnaPolygon(s) { return (s === 'SHM') ? 'red' : (s === 'HGB') ? 'blue' : (s === 'HGU') ? 'green' : (s === 'HP') ? 'yellow' : 'gray'; }
|
||||
|
||||
// --- LOAD DATA DARI DATABASE ---
|
||||
function loadDB() {
|
||||
fetch('load_spbu.php').then(res => res.json()).then(data => {
|
||||
data.forEach(spbu => {
|
||||
let marker = L.marker([spbu.lat, spbu.lng], { icon: (spbu.buka_24jam == '1') ? ikonHijau : ikonMerah, draggable: true }).addTo(map);
|
||||
marker.bindPopup(`<b>${spbu.nama_spbu}</b><br>WA: ${spbu.no_wa}<br>24 Jam: ${spbu.buka_24jam == '1' ? 'Ya' : 'Tidak'}<hr><button onclick="hapusSPBU(${spbu.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
marker.on('dragend', function(e) { updateLokasiSPBU(spbu.id, e.target.getLatLng().lat, e.target.getLatLng().lng); });
|
||||
daftarMarker[spbu.id] = marker;
|
||||
});
|
||||
});
|
||||
|
||||
fetch('load_jalan.php').then(res => res.json()).then(data => {
|
||||
data.forEach(jalan => {
|
||||
let geojsonGroup = L.geoJSON(jalan.geojson, { style: { color: warnaJalan(jalan.status), weight: 4 } }).addTo(map);
|
||||
let polylineLayer = geojsonGroup.getLayers()[0]; // Ambil layer aslinya
|
||||
|
||||
polylineLayer.bindPopup(`<b>Jalan: ${jalan.nama_jalan}</b><br>Status: ${jalan.status}<br>Panjang: ${parseFloat(jalan.panjang_m).toFixed(2)} m<hr><button onclick="hapusPolyline(${jalan.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
|
||||
// Tambahkan event click khusus untuk mode edit
|
||||
polylineLayer.on('click', function(e) {
|
||||
if (currentMode === 'edit_jalan') {
|
||||
aktifkanEditJalan(jalan.id, jalan.nama_jalan);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolyline[jalan.id] = polylineLayer;
|
||||
});
|
||||
});
|
||||
|
||||
fetch('load_area.php').then(res => res.json()).then(data => {
|
||||
data.forEach(area => {
|
||||
let geojsonGroup = L.geoJSON(area.geojson, { style: { color: warnaPolygon(area.status_kepemilikan), fillOpacity: 0.4 } }).addTo(map);
|
||||
let polygonLayer = geojsonGroup.getLayers()[0]; // Ambil layer aslinya
|
||||
|
||||
polygonLayer.bindPopup(`<b>Kavling: ${area.nama_kavling}</b><br>Status: ${area.status_kepemilikan}<br>Luas: ${parseFloat(area.luas_m2).toFixed(2)} m²<hr><button onclick="hapusPolygon(${area.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
|
||||
// Tambahkan event click khusus untuk mode edit
|
||||
polygonLayer.on('click', function(e) {
|
||||
if (currentMode === 'edit_kavling') {
|
||||
aktifkanEditKavling(area.id, area.nama_kavling);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolygon[area.id] = polygonLayer;
|
||||
});
|
||||
});
|
||||
}
|
||||
loadDB();
|
||||
|
||||
// --- EVENT KLIK PETA ---
|
||||
function onMapClick(e) {
|
||||
if (currentMode === 'point') {
|
||||
let formHtml = `
|
||||
<div style="width: 200px;">
|
||||
<h4 style="margin-top:0; border-bottom:1px solid #ddd; padding-bottom:5px;"><i class="fa-solid fa-gas-pump"></i> SPBU Baru</h4>
|
||||
<form onsubmit="simpanSPBU(event, ${e.latlng.lat}, ${e.latlng.lng})">
|
||||
<input type="text" id="nama_spbu" placeholder="Nama SPBU" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<input type="tel" id="no_wa" placeholder="No WhatsApp" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<label style="font-size:12px; font-weight:bold;">Buka 24 Jam?</label><br>
|
||||
<label><input type="radio" name="buka_24jam" value="1" required> Ya</label>
|
||||
<label><input type="radio" name="buka_24jam" value="0"> Tidak</label><br><br>
|
||||
<button type="submit" style="width: 100%; padding: 8px; background:#2ecc71; color:#fff; border:none; border-radius:4px; font-weight:bold; cursor:pointer;"><i class="fa-solid fa-save"></i> Simpan Data</button>
|
||||
</form>
|
||||
</div>`;
|
||||
popup.setLatLng(e.latlng).setContent(formHtml).openOn(map);
|
||||
} else if (currentMode === 'polyline') {
|
||||
tempLatLngs.push(e.latlng);
|
||||
if (!tempPolyline) tempPolyline = L.polyline(tempLatLngs, {color: '#3498db', weight: 4}).addTo(map);
|
||||
else tempPolyline.setLatLngs(tempLatLngs);
|
||||
} else if (currentMode === 'polygon') {
|
||||
tempPolygonLatLngs.push(e.latlng);
|
||||
if (!tempPolygon) tempPolygon = L.polygon(tempPolygonLatLngs, {color: '#2ecc71', fillColor: '#2ecc71', fillOpacity: 0.4}).addTo(map);
|
||||
else tempPolygon.setLatLngs(tempPolygonLatLngs);
|
||||
}
|
||||
}
|
||||
map.on('click', onMapClick);
|
||||
|
||||
// --- LOGIKA SPBU ---
|
||||
function simpanSPBU(event, lat, lng) {
|
||||
event.preventDefault();
|
||||
let dataKirim = { lat: lat, lng: lng, nama_spbu: document.getElementById('nama_spbu').value, no_wa: document.getElementById('no_wa').value, buka_24jam: document.querySelector('input[name="buka_24jam"]:checked').value };
|
||||
|
||||
fetch('simpan_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'SPBU Berhasil Disimpan!' });
|
||||
map.closePopup();
|
||||
let markerBaru = L.marker([lat, lng], { icon: (dataKirim.buka_24jam === '1') ? ikonHijau : ikonMerah, draggable: true }).addTo(map);
|
||||
markerBaru.bindPopup(`<b>${dataKirim.nama_spbu}</b><br>WA: ${dataKirim.no_wa}<br>24 Jam: ${dataKirim.buka_24jam == '1' ? 'Ya' : 'Tidak'}<hr><button onclick="hapusSPBU(${data.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
markerBaru.on('dragend', function(e) { updateLokasiSPBU(data.id, e.target.getLatLng().lat, e.target.getLatLng().lng); });
|
||||
daftarMarker[data.id] = markerBaru;
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan SPBU!' });
|
||||
});
|
||||
}
|
||||
function updateLokasiSPBU(id, latBaru, lngBaru) {
|
||||
fetch('update_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id, lat: latBaru, lng: lngBaru }) })
|
||||
.then(res => res.json()).then(data => { if (data.status === 'success') Toast.fire({ icon: 'info', title: 'Posisi Diperbarui' }); });
|
||||
}
|
||||
function hapusSPBU(id) {
|
||||
Swal.fire({ title: 'Hapus Titik SPBU?', text: "Data tidak dapat dikembalikan!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!', cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Titik SPBU Dihapus!' }); if (daftarMarker[id]) { map.removeLayer(daftarMarker[id]); delete daftarMarker[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- LOGIKA JALAN ---
|
||||
function batalPolyline() { if (tempPolyline) { map.removeLayer(tempPolyline); tempPolyline = null; } tempLatLngs = []; }
|
||||
function simpanPolyline() {
|
||||
if (tempLatLngs.length < 2) return Toast.fire({ icon: 'warning', title: 'Klik minimal 2 titik di peta!' });
|
||||
let nama = document.getElementById('input_nama_jalan').value, status = document.getElementById('input_status_jalan').value;
|
||||
if (!nama) return Toast.fire({ icon: 'warning', title: 'Nama Jalan harus diisi!' });
|
||||
|
||||
let panjang = hitungPanjangJalan(tempLatLngs);
|
||||
let dataKirim = { nama_jalan: nama, status: status, panjang_m: panjang, geojson: tempPolyline.toGeoJSON() };
|
||||
|
||||
fetch('simpan_jalan.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Jalan Disimpan (${panjang.toFixed(0)}m)` });
|
||||
tempPolyline.setStyle({color: warnaJalan(status)});
|
||||
tempPolyline.bindPopup(`<b>Jalan: ${nama}</b><br>Status: ${status}<br>Panjang: ${panjang.toFixed(2)} m<hr><button onclick="hapusPolyline(${data.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`).openPopup();
|
||||
|
||||
daftarPolyline[data.id] = tempPolyline;
|
||||
document.getElementById('input_nama_jalan').value = '';
|
||||
|
||||
// PERBAIKAN BUG: Hanya kosongkan variabel penampung sementara, jangan removeLayer dari map.
|
||||
tempPolyline = null;
|
||||
tempLatLngs = [];
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan!' });
|
||||
});
|
||||
}
|
||||
function hapusPolyline(id) {
|
||||
Swal.fire({ title: 'Hapus Jalan?', text: "Data permanen dihapus!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_jalan.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Jalan Dihapus!' }); if (daftarPolyline[id]) { map.removeLayer(daftarPolyline[id]); delete daftarPolyline[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- LOGIKA KAVLING ---
|
||||
function batalPolygon() { if (tempPolygon) { map.removeLayer(tempPolygon); tempPolygon = null; } tempPolygonLatLngs = []; }
|
||||
function simpanPolygon() {
|
||||
if (tempPolygonLatLngs.length < 3) return Toast.fire({ icon: 'warning', title: 'Minimal 3 titik untuk area!' });
|
||||
let nama = document.getElementById('input_nama_kavling').value, status = document.getElementById('input_status_tanah').value;
|
||||
if (!nama) return Toast.fire({ icon: 'warning', title: 'Nama kavling harus diisi!' });
|
||||
|
||||
let luas = hitungLuasArea(tempPolygonLatLngs);
|
||||
let dataKirim = { nama_kavling: nama, status: status, luas_m2: luas, geojson: tempPolygon.toGeoJSON() };
|
||||
|
||||
fetch('simpan_area.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Area Disimpan (${luas.toFixed(0)}m²)` });
|
||||
tempPolygon.setStyle({color: warnaPolygon(status), fillOpacity: 0.5});
|
||||
tempPolygon.bindPopup(`<b>Kavling: ${nama}</b><br>Status: ${status}<br>Luas: ${luas.toFixed(2)} m²<hr><button onclick="hapusPolygon(${data.id})" style="color:red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`).openPopup();
|
||||
|
||||
daftarPolygon[data.id] = tempPolygon;
|
||||
document.getElementById('input_nama_kavling').value = '';
|
||||
|
||||
// PERBAIKAN BUG: Sama seperti Polyline
|
||||
tempPolygon = null;
|
||||
tempPolygonLatLngs = [];
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan!' });
|
||||
});
|
||||
}
|
||||
function hapusPolygon(id) {
|
||||
Swal.fire({ title: 'Hapus Kavling?', text: "Area ini akan dihapus permanen!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_area.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Kavling Dihapus!' }); if (daftarPolygon[id]) { map.removeLayer(daftarPolygon[id]); delete daftarPolygon[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// --- LOGIKA MODE EDIT POLYLINE (JALAN) ---
|
||||
// ==========================================
|
||||
|
||||
function aktifkanEditJalan(id, namaJalan) {
|
||||
let layer = daftarPolyline[id];
|
||||
if (!layer) return;
|
||||
|
||||
// Jika sedang edit jalan lain, batalkan dulu
|
||||
if (targetEditJalanId && targetEditJalanId !== id) {
|
||||
batalkanEditJalan();
|
||||
}
|
||||
|
||||
targetEditJalanId = id;
|
||||
map.closePopup(); // Tutup popup info
|
||||
|
||||
// Tampilkan panel info dan tombol simpan di sidebar
|
||||
document.getElementById('info-edit-jalan').style.display = 'block';
|
||||
document.getElementById('nama-jalan-edit').innerText = "Edit: " + namaJalan;
|
||||
document.getElementById('btn-simpan-edit-jalan').style.display = 'block';
|
||||
|
||||
// Aktifkan Leaflet.Geoman khusus pada layer ini
|
||||
layer.pm.enable({
|
||||
allowSelfIntersection: false,
|
||||
});
|
||||
}
|
||||
|
||||
function batalkanEditJalan() {
|
||||
if (targetEditJalanId && daftarPolyline[targetEditJalanId]) {
|
||||
daftarPolyline[targetEditJalanId].pm.disable();
|
||||
}
|
||||
targetEditJalanId = null;
|
||||
document.getElementById('info-edit-jalan').style.display = 'none';
|
||||
document.getElementById('btn-simpan-edit-jalan').style.display = 'none';
|
||||
}
|
||||
|
||||
function simpanEditPolyline() {
|
||||
if (!targetEditJalanId) return;
|
||||
|
||||
let layer = daftarPolyline[targetEditJalanId];
|
||||
if (!layer) return;
|
||||
|
||||
// 1. Matikan mode edit
|
||||
layer.pm.disable();
|
||||
|
||||
// 2. Kalkulasi ulang panjang
|
||||
let latlngsBaru = layer.getLatLngs();
|
||||
let panjangBaru = hitungPanjangJalan(latlngsBaru);
|
||||
|
||||
// 3. Konversi ke GeoJSON
|
||||
let geojsonBaru = layer.toGeoJSON();
|
||||
|
||||
let dataKirim = {
|
||||
id: targetEditJalanId,
|
||||
panjang_m: panjangBaru,
|
||||
geojson: geojsonBaru
|
||||
};
|
||||
|
||||
fetch('update_jalan.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(dataKirim)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Bentuk Jalan Diperbarui!\nPanjang: ${panjangBaru.toFixed(0)}m` });
|
||||
batalkanEditJalan();
|
||||
|
||||
// Reload halaman secara otomatis setelah 1.5 detik agar data popup ikut ter-refresh
|
||||
setTimeout(() => { window.location.reload(); }, 1500);
|
||||
} else {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal memperbarui jalan: ' + data.message });
|
||||
batalkanEditJalan();
|
||||
}
|
||||
}).catch(error => console.error('Error:', error));
|
||||
}
|
||||
|
||||
|
||||
// ===========================================
|
||||
// --- LOGIKA MODE EDIT POLYGON (KAVLING) ---
|
||||
// ===========================================
|
||||
|
||||
function aktifkanEditKavling(id, namaKavling) {
|
||||
let layer = daftarPolygon[id];
|
||||
if (!layer) return;
|
||||
|
||||
// Jika sedang edit kavling lain, batalkan dulu
|
||||
if (targetEditKavlingId && targetEditKavlingId !== id) {
|
||||
batalkanEditKavling();
|
||||
}
|
||||
|
||||
targetEditKavlingId = id;
|
||||
map.closePopup();
|
||||
|
||||
// Tampilkan panel info dan tombol simpan di sidebar
|
||||
document.getElementById('info-edit-kavling').style.display = 'block';
|
||||
document.getElementById('nama-kavling-edit').innerText = "Edit: " + namaKavling;
|
||||
document.getElementById('btn-simpan-edit-kavling').style.display = 'block';
|
||||
|
||||
// Aktifkan Leaflet.Geoman khusus pada layer ini
|
||||
layer.pm.enable({
|
||||
allowSelfIntersection: false,
|
||||
});
|
||||
}
|
||||
|
||||
function batalkanEditKavling() {
|
||||
if (targetEditKavlingId && daftarPolygon[targetEditKavlingId]) {
|
||||
daftarPolygon[targetEditKavlingId].pm.disable();
|
||||
}
|
||||
targetEditKavlingId = null;
|
||||
document.getElementById('info-edit-kavling').style.display = 'none';
|
||||
document.getElementById('btn-simpan-edit-kavling').style.display = 'none';
|
||||
}
|
||||
|
||||
function simpanEditPolygon() {
|
||||
if (!targetEditKavlingId) return;
|
||||
|
||||
let layer = daftarPolygon[targetEditKavlingId];
|
||||
if (!layer) return;
|
||||
|
||||
layer.pm.disable();
|
||||
|
||||
let latlngsBaru = layer.getLatLngs();
|
||||
let luasBaru = hitungLuasArea(latlngsBaru);
|
||||
let geojsonBaru = layer.toGeoJSON();
|
||||
|
||||
let dataKirim = {
|
||||
id: targetEditKavlingId,
|
||||
luas_m2: luasBaru,
|
||||
geojson: geojsonBaru
|
||||
};
|
||||
|
||||
fetch('update_area.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(dataKirim)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Bentuk Kavling Diperbarui!\nLuas: ${luasBaru.toFixed(0)}m²` });
|
||||
batalkanEditKavling();
|
||||
|
||||
setTimeout(() => { window.location.reload(); }, 1500);
|
||||
} else {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal memperbarui kavling: ' + data.message });
|
||||
batalkanEditKavling();
|
||||
}
|
||||
}).catch(error => console.error('Error:', error));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
// Pastikan data yang dikirim dari JS sesuai dengan variabel baru
|
||||
if ($data && isset($data['nama_kavling']) && isset($data['geojson'])) {
|
||||
$nama_kavling = $data['nama_kavling'];
|
||||
$status = $data['status'];
|
||||
$luas_m2 = $data['luas_m2'];
|
||||
|
||||
// Ubah object GeoJSON menjadi string agar bisa disimpan di MySQL
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
// Sesuaikan query INSERT dengan nama kolom di tabel database yang baru
|
||||
$stmt = $conn->prepare("INSERT INTO area_polygon (nama_kavling, status_kepemilikan, luas_m2, geojson) VALUES (?, ?, ?, ?)");
|
||||
|
||||
// Parameter: "ssds" berarti String, String, Double (Desimal), String
|
||||
$stmt->bind_param("ssds", $nama_kavling, $status, $luas_m2, $geojson_string);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "id" => $stmt->insert_id]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
// Tambahkan pesan error jika data tidak lengkap
|
||||
echo json_encode(["status" => "error", "message" => "Data area tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['nama_jalan']) && isset($data['geojson'])) {
|
||||
$nama_jalan = $data['nama_jalan'];
|
||||
$status = $data['status'];
|
||||
$panjang_m = $data['panjang_m'];
|
||||
$geojson_string = json_encode($data['geojson']); // Jadikan string untuk disimpan
|
||||
|
||||
$stmt = $conn->prepare("INSERT INTO jalan_polyline (nama_jalan, status, panjang_m, geojson) VALUES (?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssds", $nama_jalan, $status, $panjang_m, $geojson_string);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "id" => $stmt->insert_id]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
// simpan_spbu.php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI!
|
||||
|
||||
// Koneksi ke database
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ambil data JSON yang dikirim oleh Fetch API
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data) {
|
||||
$lat = $data['lat'];
|
||||
$lng = $data['lng'];
|
||||
$nama_spbu = $data['nama_spbu'];
|
||||
$no_wa = $data['no_wa'];
|
||||
$buka_24jam = $data['buka_24jam'];
|
||||
|
||||
// Gunakan Prepared Statement untuk keamanan (mencegah SQL Injection)
|
||||
$stmt = $conn->prepare("INSERT INTO spbu_point (lat, lng, nama_spbu, no_wa, buka_24jam) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("ddssi", $lat, $lng, $nama_spbu, $no_wa, $buka_24jam);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
// AMBIL ID TERAKHIR YANG BARU SAJA DISIMPAN
|
||||
$new_id = $stmt->insert_id;
|
||||
|
||||
// Kirim kembali ID tersebut ke JavaScript
|
||||
echo json_encode([
|
||||
"status" => "success",
|
||||
"message" => "Data berhasil disimpan",
|
||||
"id" => $new_id
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal mengeksekusi query: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Tidak ada data yang diterima"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,52 @@
|
||||
html, body {
|
||||
height: 100vh; width: 100vw; margin: 0; padding: 0;
|
||||
display: flex; font-family: Arial, sans-serif; overflow: hidden;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 280px; background-color: #f8f9fa; padding: 20px;
|
||||
box-shadow: 2px 0 5px rgba(0,0,0,0.2); z-index: 1000; overflow-y: auto;
|
||||
}
|
||||
|
||||
#sidebar h3 { margin-top: 0; border-bottom: 2px solid #ddd; padding-bottom: 10px; }
|
||||
|
||||
/* Styling Ikon Mode */
|
||||
.mode-selector { margin-bottom: 20px; }
|
||||
.mode-buttons { display: flex; gap: 10px; justify-content: space-between; }
|
||||
.mode-btn {
|
||||
flex: 1; padding: 15px 5px; background: #fff; border: 2px solid #ccc;
|
||||
border-radius: 8px; cursor: pointer; text-align: center;
|
||||
transition: all 0.3s ease; color: #555; font-size: 12px; font-weight: bold;
|
||||
}
|
||||
.mode-btn i { font-size: 24px; margin-bottom: 8px; display: block; }
|
||||
.mode-btn:hover { background: #e9ecef; }
|
||||
|
||||
/* Warna saat tombol mode aktif */
|
||||
.mode-btn.active[data-mode="point"] { border-color: #e74c3c; color: #e74c3c; background: #fadbd8; }
|
||||
.mode-btn.active[data-mode="polyline"] { border-color: #3498db; color: #3498db; background: #d6eaf8; }
|
||||
.mode-btn.active[data-mode="polygon"] { border-color: #2ecc71; color: #2ecc71; background: #d5f5e3; }
|
||||
/* Styling tombol edit aktif */
|
||||
.mode-btn.active[data-mode="edit_jalan"] { background-color: #f1c40f !important; color: white !important; }
|
||||
.mode-btn.active[data-mode="edit_kavling"] { background-color: #27ae60 !important; color: white !important; }
|
||||
|
||||
/* Styling Input & Action Buttons */
|
||||
.action-buttons {
|
||||
display: none; background: #fff; padding: 15px;
|
||||
border-radius: 8px; border: 1px solid #ddd; margin-top: 10px;
|
||||
}
|
||||
|
||||
.action-buttons input, .action-buttons select {
|
||||
width: 100%; margin-bottom: 15px; padding: 8px; box-sizing: border-box;
|
||||
border: 1px solid #ccc; border-radius: 4px;
|
||||
}
|
||||
|
||||
.action-buttons button {
|
||||
width: 100%; padding: 10px; margin-bottom: 8px; cursor: pointer;
|
||||
border-radius: 5px; font-weight: bold;
|
||||
}
|
||||
|
||||
.btn-success { background-color: #2ecc71; color: white; border: none; }
|
||||
.btn-danger { background-color: #e74c3c; color: white; border: none; }
|
||||
|
||||
#map-container { flex: 1; position: relative; }
|
||||
#map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
// Sesuaikan dengan konfigurasi database Anda
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['geojson'])) {
|
||||
$id = $data['id'];
|
||||
$luas_m2 = $data['luas_m2'];
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
$stmt = $conn->prepare("UPDATE area_polygon SET luas_m2 = ?, geojson = ? WHERE id = ?");
|
||||
$stmt->bind_param("dsi", $luas_m2, $geojson_string, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
// Sesuaikan dengan konfigurasi database Anda
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['geojson'])) {
|
||||
$id = $data['id'];
|
||||
$panjang_m = $data['panjang_m'];
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
$stmt = $conn->prepare("UPDATE jalan_polyline SET panjang_m = ?, geojson = ? WHERE id = ?");
|
||||
$stmt->bind_param("dsi", $panjang_m, $geojson_string, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['lat']) && isset($data['lng'])) {
|
||||
$id = $data['id'];
|
||||
$lat = $data['lat'];
|
||||
$lng = $data['lng'];
|
||||
|
||||
// Update lat dan lng berdasarkan ID
|
||||
$stmt = $conn->prepare("UPDATE spbu_point SET lat = ?, lng = ? WHERE id = ?");
|
||||
$stmt->bind_param("ddi", $lat, $lng, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Lokasi berhasil diperbarui"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal update lokasi: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
$stmt = $conn->prepare("DELETE FROM area_polygon WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
|
||||
// Hapus data dari tabel jalan_polyline berdasarkan ID
|
||||
$stmt = $conn->prepare("DELETE FROM jalan_polyline WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Garis jalan berhasil dihapus"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal menghapus data: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
|
||||
$stmt = $conn->prepare("DELETE FROM spbu_point WHERE id = ?");
|
||||
$stmt->bind_param("i", $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Data berhasil dihapus"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal menghapus data: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sistem Pemetaan</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css" />
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="sidebar">
|
||||
<h3>Menu Peta</h3>
|
||||
|
||||
<div class="mode-selector">
|
||||
<strong>Pilih Mode Pemetaan:</strong><br><br>
|
||||
<div class="mode-buttons">
|
||||
<button class="mode-btn active" data-mode="point" onclick="ubahMode('point')">
|
||||
<i class="fa-solid fa-gas-pump"></i> SPBU
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="polyline" onclick="ubahMode('polyline')">
|
||||
<i class="fa-solid fa-road"></i> Jalan
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="polygon" onclick="ubahMode('polygon')">
|
||||
<i class="fa-solid fa-draw-polygon"></i> Kavling
|
||||
</button>
|
||||
</div><br>
|
||||
<div class="mode-buttons">
|
||||
<button class="mode-btn" data-mode="edit_jalan" onclick="ubahMode('edit_jalan')" style="background-color: #fcf3cf; border-color: #f1c40f; color: #d35400;">
|
||||
<i class="fa-solid fa-pen-ruler"></i> Edit Jalan
|
||||
</button>
|
||||
<button class="mode-btn" data-mode="edit_kavling" onclick="ubahMode('edit_kavling')" style="background-color: #d4efdf; border-color: #27ae60; color: #1e8449;">
|
||||
<i class="fa-solid fa-pen-ruler"></i> Edit Kavling
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="polyline-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-road"></i> Gambar Jalan Baru</strong>
|
||||
<p style="font-size: 11px; color: #666;">Klik di peta untuk menggambar garis.</p>
|
||||
<label>Nama Jalan:</label>
|
||||
<input type="text" id="input_nama_jalan" placeholder="Masukkan nama...">
|
||||
<label>Status Jalan:</label>
|
||||
<select id="input_status_jalan">
|
||||
<option value="Nasional">Nasional (Merah)</option>
|
||||
<option value="Provinsi">Provinsi (Kuning)</option>
|
||||
<option value="Kabupaten">Kabupaten (Hijau)</option>
|
||||
</select>
|
||||
<button onclick="simpanPolyline()" class="btn-success">Simpan Jalan</button>
|
||||
<button onclick="batalPolyline()" class="btn-danger">Batal</button>
|
||||
</div>
|
||||
|
||||
<div id="polygon-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-draw-polygon"></i> Gambar Kavling</strong>
|
||||
<p style="font-size: 11px; color: #666;">Klik min. 3 titik untuk area.</p>
|
||||
<label>Nama Pemilik/Kavling:</label>
|
||||
<input type="text" id="input_nama_kavling" placeholder="Masukkan nama...">
|
||||
<label>Status Tanah:</label>
|
||||
<select id="input_status_tanah">
|
||||
<option value="SHM">SHM (Merah)</option>
|
||||
<option value="HGB">HGB (Biru)</option>
|
||||
<option value="HGU">HGU (Hijau)</option>
|
||||
<option value="HP">HP (Kuning)</option>
|
||||
</select>
|
||||
<button onclick="simpanPolygon()" class="btn-success">Simpan Area</button>
|
||||
<button onclick="batalPolygon()" class="btn-danger">Batal</button>
|
||||
</div>
|
||||
|
||||
<div id="edit-jalan-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-pen-ruler"></i> Mode Edit Jalan Aktif</strong>
|
||||
<p style="font-size: 11px; color: #666;">Pilih salah satu jalan di peta yang ingin diubah bentuknya.</p>
|
||||
<div id="info-edit-jalan" style="display:none; margin-bottom:10px; padding:10px; background:#f9f9f9; border:1px solid #ccc; border-radius:4px;">
|
||||
<b id="nama-jalan-edit">Nama Jalan</b><br>
|
||||
<span style="font-size:12px; color:gray;">Geser titik-titik (kotak putih) pada jalan di peta untuk mengubah bentuknya.</span>
|
||||
</div>
|
||||
<button id="btn-simpan-edit-jalan" onclick="simpanEditPolyline()" class="btn-success" style="display:none;">Simpan Perubahan Jalan</button>
|
||||
</div>
|
||||
|
||||
<div id="edit-kavling-actions" class="action-buttons">
|
||||
<strong><i class="fa-solid fa-pen-ruler"></i> Mode Edit Kavling Aktif</strong>
|
||||
<p style="font-size: 11px; color: #666;">Pilih salah satu kavling di peta yang ingin diubah bentuknya.</p>
|
||||
<div id="info-edit-kavling" style="display:none; margin-bottom:10px; padding:10px; background:#f9f9f9; border:1px solid #ccc; border-radius:4px;">
|
||||
<b id="nama-kavling-edit">Nama Kavling</b><br>
|
||||
<span style="font-size:12px; color:gray;">Geser titik-titik (kotak putih) pada area di peta untuk mengubah bentuknya.</span>
|
||||
</div>
|
||||
<button id="btn-simpan-edit-kavling" onclick="simpanEditPolygon()" class="btn-success" style="display:none;">Simpan Perubahan Kavling</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="map-container">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.min.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
$sql = "SELECT * FROM area_polygon";
|
||||
$result = $conn->query($sql);
|
||||
$data_area = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
// Mengubah string geojson dari database kembali menjadi Object JSON
|
||||
// Ini wajib agar Leaflet.geoJSON() di Javascript bisa merendernya
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$data_area[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($data_area);
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$sql = "SELECT * FROM jalan_polyline";
|
||||
$result = $conn->query($sql);
|
||||
$data_jalan = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
// Parse string geojson menjadi object agar mudah dibaca Javascript
|
||||
$row['geojson'] = json_decode($row['geojson']);
|
||||
$data_jalan[] = $row;
|
||||
}
|
||||
}
|
||||
echo json_encode($data_jalan);
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ambil semua data dari tabel spbu_point
|
||||
$sql = "SELECT * FROM spbu_point";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$data_spbu = array();
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$data_spbu[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
// Kirim data sebagai JSON
|
||||
echo json_encode($data_spbu);
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
+462
@@ -0,0 +1,462 @@
|
||||
// --- INISIALISASI PETA (Koordinat Pontianak) ---
|
||||
const map = L.map('map').setView([-0.055348, 109.349512], 13);
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap' }).addTo(map);
|
||||
|
||||
const popup = L.popup();
|
||||
const daftarMarker = {}, daftarPolyline = {}, daftarPolygon = {};
|
||||
|
||||
// 1. BUAT KERTAS TRANSPARAN (LAYER GROUPS)
|
||||
const layerSPBU24 = L.layerGroup().addTo(map); // SPBU 24 Jam
|
||||
const layerSPBUNon24 = L.layerGroup().addTo(map); // SPBU Tidak 24 Jam
|
||||
const layerJalan = L.layerGroup().addTo(map); // Jaringan Jalan
|
||||
const layerKavling = L.layerGroup().addTo(map); // Area Kavling Tanah
|
||||
|
||||
// 2. DAFTARKAN LAYER-LAYER TERSEBUT KE DALAM CONTROL PANEL
|
||||
const overlays = {
|
||||
"<i class='fa-solid fa-gas-pump' style='color:green'></i> SPBU (Buka 24 Jam)": layerSPBU24,
|
||||
"<i class='fa-solid fa-gas-pump' style='color:red'></i> SPBU (Tidak 24 Jam)": layerSPBUNon24,
|
||||
"<i class='fa-solid fa-road' style='color:blue'></i> Jaringan Jalan": layerJalan,
|
||||
"<i class='fa-solid fa-draw-polygon' style='color:darkgreen'></i> Kavling Tanah": layerKavling
|
||||
};
|
||||
|
||||
// 3. MUNCULKAN KONTROL DI POJOK KANAN ATAS PETA
|
||||
L.control.layers(null, overlays, { collapsed: false }).addTo(map);
|
||||
|
||||
let currentMode = 'point';
|
||||
let tempLatLngs = [], tempPolyline = null;
|
||||
let tempPolygonLatLngs = [], tempPolygon = null;
|
||||
let targetEditJalanId = null; // Menyimpan ID jalan yang sedang diedit
|
||||
let targetEditKavlingId = null; // Menyimpan ID kavling yang sedang diedit
|
||||
|
||||
// Konfigurasi SweetAlert2 (Toast Pojok Kanan Atas)
|
||||
const Toast = Swal.mixin({
|
||||
toast: true, position: 'top-end', showConfirmButton: false, timer: 3000, timerProgressBar: true
|
||||
});
|
||||
|
||||
// Definisi Ikon Kustom
|
||||
const ikonHijau = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
const ikonMerah = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
|
||||
// --- MANAJEMEN MODE UI ---
|
||||
function ubahMode(mode) {
|
||||
currentMode = mode;
|
||||
|
||||
// Matikan mode edit Geoman global jika sedang aktif
|
||||
map.pm.disableGlobalEditMode();
|
||||
|
||||
// Reset state edit
|
||||
if (targetEditJalanId) batalkanEditJalan();
|
||||
if (targetEditKavlingId) batalkanEditKavling();
|
||||
|
||||
// Atur tampilan tombol aktif
|
||||
document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
|
||||
document.querySelector(`.mode-btn[data-mode="${mode}"]`).classList.add('active');
|
||||
|
||||
// Munculkan menu yang sesuai di sidebar
|
||||
document.getElementById('polyline-actions').style.display = (mode === 'polyline') ? 'block' : 'none';
|
||||
document.getElementById('polygon-actions').style.display = (mode === 'polygon') ? 'block' : 'none';
|
||||
document.getElementById('edit-jalan-actions').style.display = (mode === 'edit_jalan') ? 'block' : 'none';
|
||||
document.getElementById('edit-kavling-actions').style.display = (mode === 'edit_kavling') ? 'block' : 'none';
|
||||
|
||||
map.closePopup();
|
||||
if (mode !== 'polyline') batalPolyline();
|
||||
if (mode !== 'polygon') batalPolygon();
|
||||
}
|
||||
|
||||
// --- FUNGSI BANTUAN ---
|
||||
function hitungPanjangJalan(latlngs) { let t=0; for (let i=0; i<latlngs.length-1; i++) t += map.distance(latlngs[i], latlngs[i + 1]); return t; }
|
||||
function warnaJalan(s) { return (s === 'Nasional') ? 'red' : (s === 'Provinsi') ? 'yellow' : (s === 'Kabupaten') ? 'green' : 'blue'; }
|
||||
function hitungLuasArea(latlngs) {
|
||||
let area = 0, p = Array.isArray(latlngs[0]) ? latlngs[0] : latlngs;
|
||||
area = L.GeometryUtil ? L.GeometryUtil.geodesicArea(p) : 0;
|
||||
if (area === 0) {
|
||||
const R = 6378137, rad = Math.PI / 180;
|
||||
for (let i = 0; i < p.length; i++) {
|
||||
let p1 = p[i], p2 = p[(i + 1) % p.length];
|
||||
area += (p2.lng - p1.lng) * rad * (2 + Math.sin(p1.lat * rad) + Math.sin(p2.lat * rad));
|
||||
}
|
||||
area = Math.abs(area * R * R / 2);
|
||||
} return area;
|
||||
}
|
||||
function warnaPolygon(s) { return (s === 'SHM') ? 'red' : (s === 'HGB') ? 'blue' : (s === 'HGU') ? 'green' : (s === 'HP') ? 'yellow' : 'gray'; }
|
||||
|
||||
// --- LOAD DATA DARI DATABASE ---
|
||||
function loadDB() {
|
||||
fetch('load_spbu.php').then(res => res.json()).then(data => {
|
||||
data.forEach(spbu => {
|
||||
let targetLayer = (spbu.buka_24jam == '1') ? layerSPBU24 : layerSPBUNon24;
|
||||
let marker = L.marker([spbu.lat, spbu.lng], { icon: (spbu.buka_24jam == '1') ? ikonHijau : ikonMerah, draggable: true }).addTo(targetLayer);
|
||||
marker.bindPopup(`<b>${spbu.nama_spbu}</b><br>WA: ${spbu.no_wa}<br>24 Jam: ${spbu.buka_24jam == '1' ? 'Ya' : 'Tidak'}<hr><button onclick="hapusSPBU(${spbu.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
marker.on('dragend', function(e) { updateLokasiSPBU(spbu.id, e.target.getLatLng().lat, e.target.getLatLng().lng); });
|
||||
daftarMarker[spbu.id] = marker;
|
||||
});
|
||||
});
|
||||
|
||||
fetch('load_jalan.php').then(res => res.json()).then(data => {
|
||||
data.forEach(jalan => {
|
||||
let geojsonGroup = L.geoJSON(jalan.geojson, { style: { color: warnaJalan(jalan.status), weight: 4 } }).addTo(layerJalan);
|
||||
let polylineLayer = geojsonGroup.getLayers()[0]; // Ambil layer aslinya
|
||||
|
||||
polylineLayer.bindPopup(`<b>Jalan: ${jalan.nama_jalan}</b><br>Status: ${jalan.status}<br>Panjang: ${parseFloat(jalan.panjang_m).toFixed(2)} m<hr><button onclick="hapusPolyline(${jalan.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
|
||||
// Tambahkan event click khusus untuk mode edit
|
||||
polylineLayer.on('click', function(e) {
|
||||
if (currentMode === 'edit_jalan') {
|
||||
aktifkanEditJalan(jalan.id, jalan.nama_jalan);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolyline[jalan.id] = polylineLayer;
|
||||
});
|
||||
});
|
||||
|
||||
fetch('load_area.php').then(res => res.json()).then(data => {
|
||||
data.forEach(area => {
|
||||
let geojsonGroup = L.geoJSON(area.geojson, { style: { color: warnaPolygon(area.status_kepemilikan), fillOpacity: 0.4 } }).addTo(layerKavling);
|
||||
let polygonLayer = geojsonGroup.getLayers()[0]; // Ambil layer aslinya
|
||||
|
||||
polygonLayer.bindPopup(`<b>Kavling: ${area.nama_kavling}</b><br>Status: ${area.status_kepemilikan}<br>Luas: ${parseFloat(area.luas_m2).toFixed(2)} m²<hr><button onclick="hapusPolygon(${area.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
|
||||
// Tambahkan event click khusus untuk mode edit
|
||||
polygonLayer.on('click', function(e) {
|
||||
if (currentMode === 'edit_kavling') {
|
||||
aktifkanEditKavling(area.id, area.nama_kavling);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolygon[area.id] = polygonLayer;
|
||||
});
|
||||
});
|
||||
}
|
||||
loadDB();
|
||||
|
||||
// --- FUNGSI UNTUK ME-REFRESH PETA SECARA OTOMATIS (SOFT REFRESH) ---
|
||||
function refreshPeta() {
|
||||
// 1. Bersihkan semua layer dari peta
|
||||
layerSPBU24.clearLayers();
|
||||
layerSPBUNon24.clearLayers();
|
||||
layerJalan.clearLayers();
|
||||
layerKavling.clearLayers();
|
||||
|
||||
// 2. Bersihkan memori agar ID tidak menumpuk/ganda
|
||||
for (let id in daftarMarker) delete daftarMarker[id];
|
||||
for (let id in daftarPolyline) delete daftarPolyline[id];
|
||||
for (let id in daftarPolygon) delete daftarPolygon[id];
|
||||
|
||||
// 3. Panggil ulang data terbaru dari database
|
||||
loadDB();
|
||||
}
|
||||
|
||||
// --- EVENT KLIK PETA ---
|
||||
function onMapClick(e) {
|
||||
if (currentMode === 'point') {
|
||||
let formHtml = `
|
||||
<div style="width: 200px;">
|
||||
<h4 style="margin-top:0; border-bottom:1px solid #ddd; padding-bottom:5px;"><i class="fa-solid fa-gas-pump"></i> SPBU Baru</h4>
|
||||
<form onsubmit="simpanSPBU(event, ${e.latlng.lat}, ${e.latlng.lng})">
|
||||
<input type="text" id="nama_spbu" placeholder="Nama SPBU" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<input type="tel" id="no_wa" placeholder="No WhatsApp" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<label style="font-size:12px; font-weight:bold;">Buka 24 Jam?</label><br>
|
||||
<label><input type="radio" name="buka_24jam" value="1" required> Ya</label>
|
||||
<label><input type="radio" name="buka_24jam" value="0"> Tidak</label><br><br>
|
||||
<button type="submit" style="width: 100%; padding: 8px; background:#2ecc71; color:#fff; border:none; border-radius:4px; font-weight:bold; cursor:pointer;"><i class="fa-solid fa-save"></i> Simpan Data</button>
|
||||
</form>
|
||||
</div>`;
|
||||
popup.setLatLng(e.latlng).setContent(formHtml).openOn(map);
|
||||
} else if (currentMode === 'polyline') {
|
||||
tempLatLngs.push(e.latlng);
|
||||
if (!tempPolyline) tempPolyline = L.polyline(tempLatLngs, {color: '#3498db', weight: 4}).addTo(map);
|
||||
else tempPolyline.setLatLngs(tempLatLngs);
|
||||
} else if (currentMode === 'polygon') {
|
||||
tempPolygonLatLngs.push(e.latlng);
|
||||
if (!tempPolygon) tempPolygon = L.polygon(tempPolygonLatLngs, {color: '#2ecc71', fillColor: '#2ecc71', fillOpacity: 0.4}).addTo(map);
|
||||
else tempPolygon.setLatLngs(tempPolygonLatLngs);
|
||||
}
|
||||
}
|
||||
map.on('click', onMapClick);
|
||||
|
||||
// --- LOGIKA SPBU ---
|
||||
function simpanSPBU(event, lat, lng) {
|
||||
event.preventDefault();
|
||||
let dataKirim = { lat: lat, lng: lng, nama_spbu: document.getElementById('nama_spbu').value, no_wa: document.getElementById('no_wa').value, buka_24jam: document.querySelector('input[name="buka_24jam"]:checked').value };
|
||||
|
||||
fetch('simpan_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'SPBU Berhasil Disimpan!' });
|
||||
map.closePopup();
|
||||
refreshPeta();
|
||||
let targetLayerBaru = (dataKirim.buka_24jam === '1') ? layerSPBU24 : layerSPBUNon24;
|
||||
let markerBaru = L.marker([lat, lng], { icon: (dataKirim.buka_24jam === '1') ? ikonHijau : ikonMerah, draggable: true }).addTo(targetLayerBaru);
|
||||
markerBaru.bindPopup(`<b>${dataKirim.nama_spbu}</b><br>WA: ${dataKirim.no_wa}<br>24 Jam: ${dataKirim.buka_24jam == '1' ? 'Ya' : 'Tidak'}<hr><button onclick="hapusSPBU(${data.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
markerBaru.on('dragend', function(e) { updateLokasiSPBU(data.id, e.target.getLatLng().lat, e.target.getLatLng().lng); });
|
||||
daftarMarker[data.id] = markerBaru;
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan SPBU!' });
|
||||
});
|
||||
}
|
||||
function updateLokasiSPBU(id, latBaru, lngBaru) {
|
||||
fetch('update_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id, lat: latBaru, lng: lngBaru }) })
|
||||
.then(res => res.json()).then(data => { if (data.status === 'success') Toast.fire({ icon: 'info', title: 'Posisi Diperbarui' }); });
|
||||
}
|
||||
function hapusSPBU(id) {
|
||||
Swal.fire({ title: 'Hapus Titik SPBU?', text: "Data tidak dapat dikembalikan!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!', cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_spbu.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Titik SPBU Dihapus!' }); if (daftarMarker[id]) { map.removeLayer(daftarMarker[id]); delete daftarMarker[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- LOGIKA JALAN ---
|
||||
function batalPolyline() { if (tempPolyline) { map.removeLayer(tempPolyline); tempPolyline = null; } tempLatLngs = []; }
|
||||
function simpanPolyline() {
|
||||
if (tempLatLngs.length < 2) return Toast.fire({ icon: 'warning', title: 'Klik minimal 2 titik di peta!' });
|
||||
let nama = document.getElementById('input_nama_jalan').value, status = document.getElementById('input_status_jalan').value;
|
||||
if (!nama) return Toast.fire({ icon: 'warning', title: 'Nama Jalan harus diisi!' });
|
||||
|
||||
let panjang = hitungPanjangJalan(tempLatLngs);
|
||||
let dataKirim = { nama_jalan: nama, status: status, panjang_m: panjang, geojson: tempPolyline.toGeoJSON() };
|
||||
|
||||
fetch('simpan_jalan.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Jalan Disimpan (${panjang.toFixed(0)}m)` });
|
||||
tempPolyline.setStyle({color: warnaJalan(status)});
|
||||
tempPolyline.bindPopup(`<b>Jalan: ${nama}</b><br>Status: ${status}<br>Panjang: ${panjang.toFixed(2)} m<hr><button onclick="hapusPolyline(${data.id})" style="color: red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`).openPopup();
|
||||
|
||||
layerJalan.addLayer(tempPolyline);
|
||||
map.removeLayer(tempPolyline);
|
||||
|
||||
tempPolyline.on('click', function(e) {
|
||||
if (currentMode === 'edit_jalan') {
|
||||
aktifkanEditJalan(data.id, nama);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolyline[data.id] = tempPolyline;
|
||||
document.getElementById('input_nama_jalan').value = '';
|
||||
refreshPeta();
|
||||
|
||||
// PERBAIKAN BUG: Hanya kosongkan variabel penampung sementara, jangan removeLayer dari map.
|
||||
tempPolyline = null;
|
||||
tempLatLngs = [];
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan!' });
|
||||
});
|
||||
}
|
||||
function hapusPolyline(id) {
|
||||
Swal.fire({ title: 'Hapus Jalan?', text: "Data permanen dihapus!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_jalan.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Jalan Dihapus!' }); if (daftarPolyline[id]) { map.removeLayer(daftarPolyline[id]); delete daftarPolyline[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- LOGIKA KAVLING ---
|
||||
function batalPolygon() { if (tempPolygon) { map.removeLayer(tempPolygon); tempPolygon = null; } tempPolygonLatLngs = []; }
|
||||
function simpanPolygon() {
|
||||
if (tempPolygonLatLngs.length < 3) return Toast.fire({ icon: 'warning', title: 'Minimal 3 titik untuk area!' });
|
||||
let nama = document.getElementById('input_nama_kavling').value, status = document.getElementById('input_status_tanah').value;
|
||||
if (!nama) return Toast.fire({ icon: 'warning', title: 'Nama kavling harus diisi!' });
|
||||
|
||||
let luas = hitungLuasArea(tempPolygonLatLngs);
|
||||
let dataKirim = { nama_kavling: nama, status: status, luas_m2: luas, geojson: tempPolygon.toGeoJSON() };
|
||||
|
||||
fetch('simpan_area.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Area Disimpan (${luas.toFixed(0)}m²)` });
|
||||
tempPolygon.setStyle({color: warnaPolygon(status), fillOpacity: 0.5});
|
||||
tempPolygon.bindPopup(`<b>Kavling: ${nama}</b><br>Status: ${status}<br>Luas: ${luas.toFixed(2)} m²<hr><button onclick="hapusPolygon(${data.id})" style="color:red; width: 100%; cursor:pointer;"><i class="fa-solid fa-trash"></i> Hapus</button>`).openPopup();
|
||||
|
||||
layerKavling.addLayer(tempPolygon);
|
||||
map.removeLayer(tempPolygon);
|
||||
|
||||
tempPolygon.on('click', function(e) {
|
||||
if (currentMode === 'edit_kavling') {
|
||||
aktifkanEditKavling(data.id, nama);
|
||||
}
|
||||
});
|
||||
|
||||
daftarPolygon[data.id] = tempPolygon;
|
||||
document.getElementById('input_nama_kavling').value = '';
|
||||
refreshPeta();
|
||||
|
||||
// PERBAIKAN BUG: Sama seperti Polyline
|
||||
tempPolygon = null;
|
||||
tempPolygonLatLngs = [];
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan!' });
|
||||
});
|
||||
}
|
||||
function hapusPolygon(id) {
|
||||
Swal.fire({ title: 'Hapus Kavling?', text: "Area ini akan dihapus permanen!", icon: 'warning', showCancelButton: true, confirmButtonColor: '#d33', cancelButtonColor: '#3085d6', confirmButtonText: 'Ya, Hapus!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('hapus_area.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') { Toast.fire({ icon: 'success', title: 'Kavling Dihapus!' }); if (daftarPolygon[id]) { map.removeLayer(daftarPolygon[id]); delete daftarPolygon[id]; } }
|
||||
else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// --- LOGIKA MODE EDIT POLYLINE (JALAN) ---
|
||||
// ==========================================
|
||||
|
||||
function aktifkanEditJalan(id, namaJalan) {
|
||||
let layer = daftarPolyline[id];
|
||||
if (!layer) return;
|
||||
|
||||
// Jika sedang edit jalan lain, batalkan dulu
|
||||
if (targetEditJalanId && targetEditJalanId !== id) {
|
||||
batalkanEditJalan();
|
||||
}
|
||||
|
||||
targetEditJalanId = id;
|
||||
map.closePopup(); // Tutup popup info
|
||||
|
||||
// Tampilkan panel info dan tombol simpan di sidebar
|
||||
document.getElementById('info-edit-jalan').style.display = 'block';
|
||||
document.getElementById('nama-jalan-edit').innerText = "Edit: " + namaJalan;
|
||||
document.getElementById('btn-simpan-edit-jalan').style.display = 'block';
|
||||
|
||||
// Aktifkan Leaflet.Geoman khusus pada layer ini
|
||||
layer.pm.enable({
|
||||
allowSelfIntersection: false,
|
||||
});
|
||||
}
|
||||
|
||||
function batalkanEditJalan() {
|
||||
if (targetEditJalanId && daftarPolyline[targetEditJalanId]) {
|
||||
daftarPolyline[targetEditJalanId].pm.disable();
|
||||
}
|
||||
targetEditJalanId = null;
|
||||
document.getElementById('info-edit-jalan').style.display = 'none';
|
||||
document.getElementById('btn-simpan-edit-jalan').style.display = 'none';
|
||||
}
|
||||
|
||||
function simpanEditPolyline() {
|
||||
if (!targetEditJalanId) return;
|
||||
|
||||
let layer = daftarPolyline[targetEditJalanId];
|
||||
if (!layer) return;
|
||||
|
||||
// 1. Matikan mode edit
|
||||
layer.pm.disable();
|
||||
|
||||
// 2. Kalkulasi ulang panjang
|
||||
let latlngsBaru = layer.getLatLngs();
|
||||
let panjangBaru = hitungPanjangJalan(latlngsBaru);
|
||||
|
||||
// 3. Konversi ke GeoJSON
|
||||
let geojsonBaru = layer.toGeoJSON();
|
||||
|
||||
let dataKirim = {
|
||||
id: targetEditJalanId,
|
||||
panjang_m: panjangBaru,
|
||||
geojson: geojsonBaru
|
||||
};
|
||||
|
||||
fetch('update_jalan.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(dataKirim)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Bentuk Jalan Diperbarui!\nPanjang: ${panjangBaru.toFixed(0)}m` });
|
||||
batalkanEditJalan();
|
||||
|
||||
// Reload halaman secara otomatis setelah 1.5 detik agar data popup ikut ter-refresh
|
||||
setTimeout(() => { window.location.reload(); }, 1500);
|
||||
} else {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal memperbarui jalan: ' + data.message });
|
||||
batalkanEditJalan();
|
||||
}
|
||||
}).catch(error => console.error('Error:', error));
|
||||
}
|
||||
|
||||
|
||||
// ===========================================
|
||||
// --- LOGIKA MODE EDIT POLYGON (KAVLING) ---
|
||||
// ===========================================
|
||||
|
||||
function aktifkanEditKavling(id, namaKavling) {
|
||||
let layer = daftarPolygon[id];
|
||||
if (!layer) return;
|
||||
|
||||
// Jika sedang edit kavling lain, batalkan dulu
|
||||
if (targetEditKavlingId && targetEditKavlingId !== id) {
|
||||
batalkanEditKavling();
|
||||
}
|
||||
|
||||
targetEditKavlingId = id;
|
||||
map.closePopup();
|
||||
|
||||
// Tampilkan panel info dan tombol simpan di sidebar
|
||||
document.getElementById('info-edit-kavling').style.display = 'block';
|
||||
document.getElementById('nama-kavling-edit').innerText = "Edit: " + namaKavling;
|
||||
document.getElementById('btn-simpan-edit-kavling').style.display = 'block';
|
||||
|
||||
// Aktifkan Leaflet.Geoman khusus pada layer ini
|
||||
layer.pm.enable({
|
||||
allowSelfIntersection: false,
|
||||
});
|
||||
}
|
||||
|
||||
function batalkanEditKavling() {
|
||||
if (targetEditKavlingId && daftarPolygon[targetEditKavlingId]) {
|
||||
daftarPolygon[targetEditKavlingId].pm.disable();
|
||||
}
|
||||
targetEditKavlingId = null;
|
||||
document.getElementById('info-edit-kavling').style.display = 'none';
|
||||
document.getElementById('btn-simpan-edit-kavling').style.display = 'none';
|
||||
}
|
||||
|
||||
function simpanEditPolygon() {
|
||||
if (!targetEditKavlingId) return;
|
||||
|
||||
let layer = daftarPolygon[targetEditKavlingId];
|
||||
if (!layer) return;
|
||||
|
||||
layer.pm.disable();
|
||||
|
||||
let latlngsBaru = layer.getLatLngs();
|
||||
let luasBaru = hitungLuasArea(latlngsBaru);
|
||||
let geojsonBaru = layer.toGeoJSON();
|
||||
|
||||
let dataKirim = {
|
||||
id: targetEditKavlingId,
|
||||
luas_m2: luasBaru,
|
||||
geojson: geojsonBaru
|
||||
};
|
||||
|
||||
fetch('update_area.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(dataKirim)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: `Bentuk Kavling Diperbarui!\nLuas: ${luasBaru.toFixed(0)}m²` });
|
||||
batalkanEditKavling();
|
||||
|
||||
setTimeout(() => { window.location.reload(); }, 1500);
|
||||
} else {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal memperbarui kavling: ' + data.message });
|
||||
batalkanEditKavling();
|
||||
}
|
||||
}).catch(error => console.error('Error:', error));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
// Pastikan data yang dikirim dari JS sesuai dengan variabel baru
|
||||
if ($data && isset($data['nama_kavling']) && isset($data['geojson'])) {
|
||||
$nama_kavling = $data['nama_kavling'];
|
||||
$status = $data['status'];
|
||||
$luas_m2 = $data['luas_m2'];
|
||||
|
||||
// Ubah object GeoJSON menjadi string agar bisa disimpan di MySQL
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
// Sesuaikan query INSERT dengan nama kolom di tabel database yang baru
|
||||
$stmt = $conn->prepare("INSERT INTO area_polygon (nama_kavling, status_kepemilikan, luas_m2, geojson) VALUES (?, ?, ?, ?)");
|
||||
|
||||
// Parameter: "ssds" berarti String, String, Double (Desimal), String
|
||||
$stmt->bind_param("ssds", $nama_kavling, $status, $luas_m2, $geojson_string);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "id" => $stmt->insert_id]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
// Tambahkan pesan error jika data tidak lengkap
|
||||
echo json_encode(["status" => "error", "message" => "Data area tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis"); // UBAH DB
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['nama_jalan']) && isset($data['geojson'])) {
|
||||
$nama_jalan = $data['nama_jalan'];
|
||||
$status = $data['status'];
|
||||
$panjang_m = $data['panjang_m'];
|
||||
$geojson_string = json_encode($data['geojson']); // Jadikan string untuk disimpan
|
||||
|
||||
$stmt = $conn->prepare("INSERT INTO jalan_polyline (nama_jalan, status, panjang_m, geojson) VALUES (?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssds", $nama_jalan, $status, $panjang_m, $geojson_string);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "id" => $stmt->insert_id]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
// simpan_spbu.php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI!
|
||||
|
||||
// Koneksi ke database
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Ambil data JSON yang dikirim oleh Fetch API
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data) {
|
||||
$lat = $data['lat'];
|
||||
$lng = $data['lng'];
|
||||
$nama_spbu = $data['nama_spbu'];
|
||||
$no_wa = $data['no_wa'];
|
||||
$buka_24jam = $data['buka_24jam'];
|
||||
|
||||
// Gunakan Prepared Statement untuk keamanan (mencegah SQL Injection)
|
||||
$stmt = $conn->prepare("INSERT INTO spbu_point (lat, lng, nama_spbu, no_wa, buka_24jam) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("ddssi", $lat, $lng, $nama_spbu, $no_wa, $buka_24jam);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
// AMBIL ID TERAKHIR YANG BARU SAJA DISIMPAN
|
||||
$new_id = $stmt->insert_id;
|
||||
|
||||
// Kirim kembali ID tersebut ke JavaScript
|
||||
echo json_encode([
|
||||
"status" => "success",
|
||||
"message" => "Data berhasil disimpan",
|
||||
"id" => $new_id
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal mengeksekusi query: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Tidak ada data yang diterima"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,52 @@
|
||||
html, body {
|
||||
height: 100vh; width: 100vw; margin: 0; padding: 0;
|
||||
display: flex; font-family: Arial, sans-serif; overflow: hidden;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 280px; background-color: #f8f9fa; padding: 20px;
|
||||
box-shadow: 2px 0 5px rgba(0,0,0,0.2); z-index: 1000; overflow-y: auto;
|
||||
}
|
||||
|
||||
#sidebar h3 { margin-top: 0; border-bottom: 2px solid #ddd; padding-bottom: 10px; }
|
||||
|
||||
/* Styling Ikon Mode */
|
||||
.mode-selector { margin-bottom: 20px; }
|
||||
.mode-buttons { display: flex; gap: 10px; justify-content: space-between; }
|
||||
.mode-btn {
|
||||
flex: 1; padding: 15px 5px; background: #fff; border: 2px solid #ccc;
|
||||
border-radius: 8px; cursor: pointer; text-align: center;
|
||||
transition: all 0.3s ease; color: #555; font-size: 12px; font-weight: bold;
|
||||
}
|
||||
.mode-btn i { font-size: 24px; margin-bottom: 8px; display: block; }
|
||||
.mode-btn:hover { background: #e9ecef; }
|
||||
|
||||
/* Warna saat tombol mode aktif */
|
||||
.mode-btn.active[data-mode="point"] { border-color: #e74c3c; color: #e74c3c; background: #fadbd8; }
|
||||
.mode-btn.active[data-mode="polyline"] { border-color: #3498db; color: #3498db; background: #d6eaf8; }
|
||||
.mode-btn.active[data-mode="polygon"] { border-color: #2ecc71; color: #2ecc71; background: #d5f5e3; }
|
||||
/* Styling tombol edit aktif */
|
||||
.mode-btn.active[data-mode="edit_jalan"] { background-color: #f1c40f !important; color: white !important; }
|
||||
.mode-btn.active[data-mode="edit_kavling"] { background-color: #27ae60 !important; color: white !important; }
|
||||
|
||||
/* Styling Input & Action Buttons */
|
||||
.action-buttons {
|
||||
display: none; background: #fff; padding: 15px;
|
||||
border-radius: 8px; border: 1px solid #ddd; margin-top: 10px;
|
||||
}
|
||||
|
||||
.action-buttons input, .action-buttons select {
|
||||
width: 100%; margin-bottom: 15px; padding: 8px; box-sizing: border-box;
|
||||
border: 1px solid #ccc; border-radius: 4px;
|
||||
}
|
||||
|
||||
.action-buttons button {
|
||||
width: 100%; padding: 10px; margin-bottom: 8px; cursor: pointer;
|
||||
border-radius: 5px; font-weight: bold;
|
||||
}
|
||||
|
||||
.btn-success { background-color: #2ecc71; color: white; border: none; }
|
||||
.btn-danger { background-color: #e74c3c; color: white; border: none; }
|
||||
|
||||
#map-container { flex: 1; position: relative; }
|
||||
#map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
// Sesuaikan dengan konfigurasi database Anda
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['geojson'])) {
|
||||
$id = $data['id'];
|
||||
$luas_m2 = $data['luas_m2'];
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
$stmt = $conn->prepare("UPDATE area_polygon SET luas_m2 = ?, geojson = ? WHERE id = ?");
|
||||
$stmt->bind_param("dsi", $luas_m2, $geojson_string, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
// Sesuaikan dengan konfigurasi database Anda
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['geojson'])) {
|
||||
$id = $data['id'];
|
||||
$panjang_m = $data['panjang_m'];
|
||||
$geojson_string = json_encode($data['geojson']);
|
||||
|
||||
$stmt = $conn->prepare("UPDATE jalan_polyline SET panjang_m = ?, geojson = ? WHERE id = ?");
|
||||
$stmt->bind_param("dsi", $panjang_m, $geojson_string, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Konfigurasi Database (Sesuaikan dengan milik Anda)
|
||||
$host = "localhost";
|
||||
$user = "root";
|
||||
$pass = "";
|
||||
$db = "webgis"; // UBAH INI
|
||||
|
||||
$conn = new mysqli($host, $user, $pass, $db);
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id']) && isset($data['lat']) && isset($data['lng'])) {
|
||||
$id = $data['id'];
|
||||
$lat = $data['lat'];
|
||||
$lng = $data['lng'];
|
||||
|
||||
// Update lat dan lng berdasarkan ID
|
||||
$stmt = $conn->prepare("UPDATE spbu_point SET lat = ?, lng = ? WHERE id = ?");
|
||||
$stmt->bind_param("ddi", $lat, $lng, $id);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "message" => "Lokasi berhasil diperbarui"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Gagal update lokasi: " . $stmt->error]);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
// Pastikan nama database sudah benar
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
if ($conn->connect_error) {
|
||||
echo json_encode(["status" => "error", "message" => "Koneksi database gagal"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Menangkap data JSON yang dikirim dari fetch() JavaScript
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
|
||||
// Sesuaikan nama tabel dengan screenshot phpMyAdmin Anda: rumah_prasejahtera
|
||||
$stmt = $conn->prepare("DELETE FROM rumah_prasejahtera WHERE id = ?");
|
||||
$stmt->bind_param("i", $id); // "i" berarti integer
|
||||
|
||||
if ($stmt->execute()) {
|
||||
// Cek apakah benar-benar ada baris yang terhapus di database
|
||||
if ($stmt->affected_rows > 0) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
// Jika ID tidak ditemukan di tabel
|
||||
echo json_encode(["status" => "error", "message" => "Data dengan ID $id tidak ditemukan di database."]);
|
||||
}
|
||||
} else {
|
||||
// Jika query MySQL gagal/error
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
// Jika JavaScript gagal mengirimkan ID
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak diterima oleh server PHP."]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$result = $conn->query("SELECT * FROM rumah_prasejahtera");
|
||||
$data = [];
|
||||
while ($row = $result->fetch_assoc()) $data[] = $row;
|
||||
echo json_encode($data);
|
||||
?>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli("localhost", "root", "", "webgis");
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
if ($data && isset($data['lat']) && isset($data['lng'])) {
|
||||
// Tangkap data
|
||||
$nama_kk = $data['nama_kk'];
|
||||
$penghasilan = $data['penghasilan'];
|
||||
$jumlah_anak = $data['jumlah_anak'];
|
||||
$umur_anak = $data['umur_anak'];
|
||||
$status_ortu = $data['status_ortu'];
|
||||
$ada_pensiun = $data['ada_pensiun'];
|
||||
$nominal_pensiun = $data['nominal_pensiun'];
|
||||
$ada_terusan = $data['ada_terusan'];
|
||||
$nominal_terusan = $data['nominal_terusan'];
|
||||
$keterangan = $data['keterangan'];
|
||||
$lat = $data['lat'];
|
||||
$lng = $data['lng'];
|
||||
|
||||
// Update Query (12 Parameter)
|
||||
$stmt = $conn->prepare("INSERT INTO rumah_prasejahtera
|
||||
(nama_kepala_keluarga, penghasilan, jumlah_anak, umur_anak, status_ortu, ada_pensiun, nominal_pensiun, ada_terusan, nominal_terusan, keterangan, lat, lng)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
// PERBAIKAN DI SINI: Jumlah huruf (12) sekarang sudah pas dengan jumlah variabelnya (12)
|
||||
$stmt->bind_param("sdisssdsdsdd", $nama_kk, $penghasilan, $jumlah_anak, $umur_anak, $status_ortu, $ada_pensiun, $nominal_pensiun, $ada_terusan, $nominal_terusan, $keterangan, $lat, $lng);
|
||||
|
||||
if ($stmt->execute()) {
|
||||
echo json_encode(["status" => "success", "id" => $stmt->insert_id]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $stmt->error]);
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
}
|
||||
$conn->close();
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$stmt = $conn->prepare("UPDATE rumah_prasejahtera SET lat=?, lng=? WHERE id=?");
|
||||
$stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']);
|
||||
echo $stmt->execute()
|
||||
? json_encode(['status' => 'success'])
|
||||
: json_encode(['status' => 'error']);
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$stmt = $conn->prepare("DELETE FROM rumah_ibadah WHERE id = ?");
|
||||
$stmt->bind_param("i", $data['id']);
|
||||
echo $stmt->execute()
|
||||
? json_encode(['status' => 'success'])
|
||||
: json_encode(['status' => 'error']);
|
||||
?>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$result = $conn->query("SELECT * FROM rumah_ibadah");
|
||||
$data = [];
|
||||
while ($row = $result->fetch_assoc()) $data[] = $row;
|
||||
echo json_encode($data);
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$stmt = $conn->prepare("INSERT INTO rumah_ibadah (nama_ibadah, jenis, radius_m, lat, lng) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssidd", $data['nama_ibadah'], $data['jenis'], $data['radius_m'], $data['lat'], $data['lng']);
|
||||
echo $stmt->execute()
|
||||
? json_encode(['status' => 'success', 'id' => $conn->insert_id])
|
||||
: json_encode(['status' => 'error']);
|
||||
?>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
$conn = new mysqli('localhost', 'root', '', 'webgis');
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$stmt = $conn->prepare("UPDATE rumah_ibadah SET lat=?, lng=? WHERE id=?");
|
||||
$stmt->bind_param("ddi", $data['lat'], $data['lng'], $data['id']);
|
||||
echo $stmt->execute()
|
||||
? json_encode(['status' => 'success'])
|
||||
: json_encode(['status' => 'error']);
|
||||
?>
|
||||
@@ -0,0 +1,54 @@
|
||||
html, body {
|
||||
height: 100vh; width: 100vw; margin: 0; padding: 0;
|
||||
display: flex; font-family: Arial, sans-serif; overflow: hidden;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
width: 280px; background-color: #f8f9fa; padding: 20px;
|
||||
box-shadow: 2px 0 5px rgba(0,0,0,0.2); z-index: 1000; overflow-y: auto;
|
||||
}
|
||||
|
||||
#sidebar h3 { margin-top: 0; border-bottom: 2px solid #ddd; padding-bottom: 10px; }
|
||||
|
||||
/* Styling Ikon Mode */
|
||||
.mode-selector { margin-bottom: 20px; }
|
||||
.mode-buttons { display: flex; gap: 10px; justify-content: space-between; }
|
||||
.mode-btn {
|
||||
flex: 1; padding: 15px 5px; background: #fff; border: 2px solid #ccc;
|
||||
border-radius: 8px; cursor: pointer; text-align: center;
|
||||
transition: all 0.3s ease; color: #555; font-size: 12px; font-weight: bold;
|
||||
}
|
||||
.mode-btn i { font-size: 24px; margin-bottom: 8px; display: block; }
|
||||
.mode-btn:hover { background: #e9ecef; }
|
||||
|
||||
/* Warna saat tombol mode aktif */
|
||||
.mode-btn.active[data-mode="point"] { border-color: #e74c3c; color: #e74c3c; background: #fadbd8; }
|
||||
.mode-btn.active[data-mode="polyline"] { border-color: #3498db; color: #3498db; background: #d6eaf8; }
|
||||
.mode-btn.active[data-mode="polygon"] { border-color: #2ecc71; color: #2ecc71; background: #d5f5e3; }
|
||||
.mode-btn.active[data-mode="prasejahtera"] { border-color: #c0392b; color: #ffffff; background: #e74c3c; }
|
||||
.mode-btn.active[data-mode="ibadah"] { border-color: #6c3483; color: #ffffff; background: #8e44ad; }
|
||||
/* Styling tombol edit aktif */
|
||||
.mode-btn.active[data-mode="edit_jalan"] { background-color: #f1c40f !important; color: white !important; }
|
||||
.mode-btn.active[data-mode="edit_kavling"] { background-color: #27ae60 !important; color: white !important; }
|
||||
|
||||
/* Styling Input & Action Buttons */
|
||||
.action-buttons {
|
||||
display: none; background: #fff; padding: 15px;
|
||||
border-radius: 8px; border: 1px solid #ddd; margin-top: 10px; margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.action-buttons input, .action-buttons select {
|
||||
width: 100%; margin-bottom: 15px; padding: 8px; box-sizing: border-box;
|
||||
border: 1px solid #ccc; border-radius: 4px;
|
||||
}
|
||||
|
||||
.action-buttons button {
|
||||
width: 100%; padding: 10px; margin-bottom: 8px; cursor: pointer;
|
||||
border-radius: 5px; font-weight: bold;
|
||||
}
|
||||
|
||||
.btn-success { background-color: #2ecc71; color: white; border: none; }
|
||||
.btn-danger { background-color: #e74c3c; color: white; border: none; }
|
||||
|
||||
#map-container { flex: 1; position: relative; }
|
||||
#map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
|
||||
@@ -0,0 +1,519 @@
|
||||
// --- INISIALISASI PETA (Koordinat Pontianak) ---
|
||||
const map = L.map('map').setView([-0.055348, 109.349512], 13);
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap' }).addTo(map);
|
||||
|
||||
const popup = L.popup();
|
||||
const daftarMarker = {}, daftarPolyline = {}, daftarPolygon = {};
|
||||
|
||||
// 1. BUAT KERTAS TRANSPARAN (LAYER GROUPS)
|
||||
const layerPrasejahtera = L.layerGroup().addTo(map);
|
||||
const layerIbadah = L.layerGroup().addTo(map);
|
||||
|
||||
// 2. DAFTARKAN LAYER-LAYER TERSEBUT KE DALAM CONTROL PANEL
|
||||
const overlays = {
|
||||
"<i class='fa-solid fa-house-chimney-crack' style='color:red'></i> Rumah Prasejahtera": layerPrasejahtera,
|
||||
"<i class='fa-solid fa-place-of-worship' style='color:purple'></i> Rumah Ibadah": layerIbadah,
|
||||
};
|
||||
|
||||
// 3. MUNCULKAN KONTROL DI POJOK KANAN ATAS PETA
|
||||
L.control.layers(null, overlays, { collapsed: false }).addTo(map);
|
||||
|
||||
let currentMode = 'none';
|
||||
let tempLatLngs = [], tempPolyline = null;
|
||||
let tempPolygonLatLngs = [], tempPolygon = null;
|
||||
let targetEditJalanId = null; // Menyimpan ID jalan yang sedang diedit
|
||||
let targetEditKavlingId = null; // Menyimpan ID kavling yang sedang diedit
|
||||
|
||||
// Konfigurasi SweetAlert2 (Toast Pojok Kanan Atas)
|
||||
const Toast = Swal.mixin({
|
||||
toast: true, position: 'top-end', showConfirmButton: false, timer: 3000, timerProgressBar: true
|
||||
});
|
||||
|
||||
// Definisi Ikon Kustom
|
||||
const ikonHijau = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
const ikonMerah = new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] });
|
||||
|
||||
// ikon rumah prasejahtera
|
||||
const ikonPrasejahtera = L.divIcon({
|
||||
html: `<div style="
|
||||
background-color: #e74c3c;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50% 50% 50% 0;
|
||||
transform: rotate(-45deg);
|
||||
border: 2px solid #c0392b;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
">
|
||||
<i class="fa-solid fa-house-chimney-crack" style="
|
||||
transform: rotate(45deg);
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
"></i>
|
||||
</div>`,
|
||||
iconSize: [32, 32],
|
||||
iconAnchor: [16, 32],
|
||||
popupAnchor: [0, -34],
|
||||
className: ''
|
||||
});
|
||||
|
||||
const ikonPrasejahteraTercakup = L.divIcon({
|
||||
html: `<div style="
|
||||
background-color: #27ae60;
|
||||
width: 32px; height: 32px;
|
||||
border-radius: 50% 50% 50% 0;
|
||||
transform: rotate(-45deg);
|
||||
border: 2px solid #1e8449;
|
||||
display: flex; align-items: center; justify-content: center;">
|
||||
<i class="fa-solid fa-house-chimney-crack" style="transform:rotate(45deg); color:white; font-size:14px;"></i>
|
||||
</div>`,
|
||||
iconSize: [32, 32], iconAnchor: [16, 32], popupAnchor: [0, -34], className: ''
|
||||
});
|
||||
|
||||
function buatIkonIbadah(jenis) {
|
||||
const config = {
|
||||
'Masjid': { icon: 'fa-mosque', color: '#1abc9c' },
|
||||
'Gereja': { icon: 'fa-church', color: '#3498db' },
|
||||
'Vihara': { icon: 'fa-torii-gate', color: '#e67e22' },
|
||||
'Pura': { icon: 'fa-om', color: '#9b59b6' },
|
||||
'Klenteng': { icon: 'fa-yin-yang', color: '#e74c3c' },
|
||||
};
|
||||
const c = config[jenis] || { icon: 'fa-place-of-worship', color: '#7f8c8d' };
|
||||
return L.divIcon({
|
||||
html: `<div style="
|
||||
background-color: ${c.color};
|
||||
width: 32px; height: 32px;
|
||||
border-radius: 50% 50% 50% 0;
|
||||
transform: rotate(-45deg);
|
||||
border: 2px solid rgba(0,0,0,0.3);
|
||||
display: flex; align-items: center; justify-content: center;">
|
||||
<i class="fa-solid ${c.icon}" style="transform:rotate(45deg); color:white; font-size:14px;"></i>
|
||||
</div>`,
|
||||
iconSize: [32, 32], iconAnchor: [16, 32], popupAnchor: [0, -34], className: ''
|
||||
});
|
||||
}
|
||||
|
||||
// Simpan data ibadah dan prasejahtera dalam memori untuk kalkulasi
|
||||
const dataPrasejahtera = {}; // { id: {lat, lng, marker} }
|
||||
const dataIbadah = {}; // { id: {lat, lng, radius_m, lingkaran} }
|
||||
|
||||
function perbaruiWarnaPrasejahtera() {
|
||||
for (let pid in dataPrasejahtera) {
|
||||
let p = dataPrasejahtera[pid];
|
||||
let tercakup = false;
|
||||
|
||||
for (let iid in dataIbadah) {
|
||||
let ib = dataIbadah[iid];
|
||||
let jarak = map.distance([p.lat, p.lng], [ib.lat, ib.lng]);
|
||||
if (jarak <= ib.radius_m) { tercakup = true; break; }
|
||||
}
|
||||
|
||||
// Ganti ikon sesuai status
|
||||
let ikonBaru = tercakup ? ikonPrasejahteraTercakup : ikonPrasejahtera;
|
||||
p.marker.setIcon(ikonBaru);
|
||||
}
|
||||
}
|
||||
|
||||
// --- MANAJEMEN MODE UI ---
|
||||
function ubahMode(mode) {
|
||||
console.log('Mode diklik:', mode, '| Mode saat ini:', currentMode); // ← tambah ini
|
||||
|
||||
if (currentMode === mode) {
|
||||
// Jika mode yang diklik sama dengan yang aktif, matikan semua
|
||||
currentMode = 'none'; // Mode netral
|
||||
|
||||
map.pm.disableGlobalEditMode();
|
||||
if (targetEditJalanId) batalkanEditJalan();
|
||||
if (targetEditKavlingId) batalkanEditKavling();
|
||||
|
||||
// Matikan semua highlight tombol aktif
|
||||
document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
|
||||
|
||||
// Sembunyikan semua panel sidebar
|
||||
document.getElementById('polyline-actions').style.display = 'none';
|
||||
document.getElementById('polygon-actions').style.display = 'none';
|
||||
document.getElementById('edit-jalan-actions').style.display = 'none';
|
||||
document.getElementById('edit-kavling-actions').style.display = 'none';
|
||||
|
||||
map.closePopup();
|
||||
batalPolyline();
|
||||
batalPolygon();
|
||||
return; // Hentikan eksekusi, tidak perlu lanjut ke bawah
|
||||
}
|
||||
currentMode = mode;
|
||||
|
||||
// Matikan mode edit Geoman global jika sedang aktif
|
||||
map.pm.disableGlobalEditMode();
|
||||
|
||||
// Reset state edit
|
||||
if (targetEditJalanId) batalkanEditJalan();
|
||||
if (targetEditKavlingId) batalkanEditKavling();
|
||||
|
||||
// Atur tampilan tombol aktif
|
||||
document.querySelectorAll('.mode-btn').forEach(btn => btn.classList.remove('active'));
|
||||
document.querySelector(`.mode-btn[data-mode="${mode}"]`).classList.add('active');
|
||||
|
||||
// Munculkan menu yang sesuai di sidebar
|
||||
document.getElementById('polyline-actions').style.display = (mode === 'polyline') ? 'block' : 'none';
|
||||
document.getElementById('polygon-actions').style.display = (mode === 'polygon') ? 'block' : 'none';
|
||||
document.getElementById('edit-jalan-actions').style.display = (mode === 'edit_jalan') ? 'block' : 'none';
|
||||
document.getElementById('edit-kavling-actions').style.display = (mode === 'edit_kavling') ? 'block' : 'none';
|
||||
|
||||
map.closePopup();
|
||||
if (mode !== 'polyline') batalPolyline();
|
||||
if (mode !== 'polygon') batalPolygon();
|
||||
}
|
||||
|
||||
// --- LOAD DATA DARI DATABASE ---
|
||||
function loadIbadah() {
|
||||
fetch('api/rumahibadah/load_ibadah.php').then(res => res.json()).then(data => {
|
||||
data.forEach(ib => {
|
||||
let marker = L.marker([ib.lat, ib.lng], { icon: buatIkonIbadah(ib.jenis), draggable: true })
|
||||
.addTo(layerIbadah);
|
||||
|
||||
// Lingkaran radius
|
||||
let lingkaran = L.circle([ib.lat, ib.lng], {
|
||||
radius: ib.radius_m, color: '#8e44ad',
|
||||
fillColor: '#8e44ad', fillOpacity: 0.1, weight: 1, dashArray: '5,5'
|
||||
}).addTo(layerIbadah);
|
||||
|
||||
marker.bindPopup(`<b>${ib.nama_ibadah}</b><br>Jenis Rumah Ibadah: ${ib.jenis}<br>Jangkauan Bantuan: ${ib.radius_m} m<hr>
|
||||
<button onclick="hapusIbadah(${ib.id})" style="color:red; width:100%; cursor:pointer;">
|
||||
<i class="fa-solid fa-trash"></i> Hapus</button>`);
|
||||
|
||||
marker.on('dragend', function(e) {
|
||||
let pos = e.target.getLatLng();
|
||||
lingkaran.setLatLng(pos);
|
||||
dataIbadah[ib.id] = { lat: pos.lat, lng: pos.lng, radius_m: ib.radius_m, lingkaran };
|
||||
updateLokasiIbadah(ib.id, pos.lat, pos.lng);
|
||||
perbaruiWarnaPrasejahtera();
|
||||
});
|
||||
|
||||
dataIbadah[ib.id] = { lat: ib.lat, lng: ib.lng, radius_m: ib.radius_m, lingkaran };
|
||||
daftarMarker['ib_' + ib.id] = marker;
|
||||
});
|
||||
|
||||
// Setelah semua ibadah dimuat, perbarui warna prasejahtera
|
||||
perbaruiWarnaPrasejahtera();
|
||||
});
|
||||
}
|
||||
|
||||
function formatRupiah(angka) {
|
||||
return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR' }).format(angka);
|
||||
}
|
||||
|
||||
function loadDB() {
|
||||
fetch('api/prasejahtera/load_prasejahtera.php').then(res => res.json()).then(data => {
|
||||
data.forEach(rumah => {
|
||||
// PERBAIKAN: Gunakan 'rumah.', bukan 'data.'
|
||||
let penghasilanTeks = formatRupiah(rumah.penghasilan);
|
||||
let statusOrtuTeks = `<b>Status Ortu:</b> ${rumah.status_ortu}<br>`;
|
||||
|
||||
if (rumah.status_ortu === 'Bekerja') {
|
||||
statusOrtuTeks += `<b>Penghasilan:</b> ${formatRupiah(rumah.penghasilan)}<br>`;
|
||||
} else if (rumah.status_ortu === 'Pensiun') {
|
||||
statusOrtuTeks += `<b>Uang Pensiun:</b> ${rumah.ada_pensiun === 'Ya' ? formatRupiah(rumah.nominal_pensiun) : 'Tidak Ada'}<br>`;
|
||||
} else if (rumah.status_ortu === 'Meninggal') {
|
||||
statusOrtuTeks += `<b>Uang Terusan:</b> ${rumah.ada_terusan === 'Ya' ? formatRupiah(rumah.nominal_terusan) : 'Tidak Ada'}<br>`;
|
||||
}
|
||||
|
||||
let isiPopup = `
|
||||
<div style="font-size:13px;">
|
||||
<b style="font-size:15px;"><i class="fa-solid fa-users"></i> ${rumah.nama_kepala_keluarga}</b><hr style="margin:5px 0;">
|
||||
<b>Anak:</b> ${rumah.jumlah_anak} orang (Umur: ${rumah.umur_anak || '-'})<br>
|
||||
${statusOrtuTeks}
|
||||
<b>Keterangan:</b> ${rumah.keterangan || '-'}<br>
|
||||
<hr style="margin: 5px 0;">
|
||||
<button onclick="hapusPrasejahtera(${rumah.id})" style="color: red; width: 100%; cursor:pointer; border:none; background:none;">
|
||||
<i class="fa-solid fa-trash"></i> Hapus Data
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
let marker = L.marker([rumah.lat, rumah.lng], { icon: ikonPrasejahtera, draggable: true })
|
||||
.addTo(layerPrasejahtera);
|
||||
marker.bindPopup(isiPopup);
|
||||
marker.on('dragend', function(e) {
|
||||
let pos = e.target.getLatLng();
|
||||
dataPrasejahtera[rumah.id].lat = pos.lat;
|
||||
dataPrasejahtera[rumah.id].lng = pos.lng;
|
||||
updateLokasiPrasejahtera(rumah.id, pos.lat, pos.lng);
|
||||
perbaruiWarnaPrasejahtera();
|
||||
});
|
||||
dataPrasejahtera[rumah.id] = { lat: rumah.lat, lng: rumah.lng, marker };
|
||||
daftarMarker['p_' + rumah.id] = marker;
|
||||
});
|
||||
|
||||
// Muat ibadah SETELAH prasejahtera selesai
|
||||
loadIbadah();
|
||||
});
|
||||
}
|
||||
loadDB();
|
||||
|
||||
// --- FUNGSI UNTUK ME-REFRESH PETA SECARA OTOMATIS (SOFT REFRESH) ---
|
||||
function refreshPeta() {
|
||||
layerPrasejahtera.clearLayers();
|
||||
layerIbadah.clearLayers();
|
||||
|
||||
// 2. Bersihkan memori agar ID tidak menumpuk/ganda
|
||||
for (let id in dataIbadah) delete dataIbadah[id];
|
||||
for (let id in dataPrasejahtera) delete dataPrasejahtera[id];
|
||||
|
||||
// 3. Panggil ulang data terbaru dari database
|
||||
loadDB();
|
||||
}
|
||||
|
||||
// --- EVENT KLIK PETA ---
|
||||
function onMapClick(e) {
|
||||
if (currentMode === 'point') {
|
||||
let formHtml = `
|
||||
<div style="width: 200px;">
|
||||
<h4 style="margin-top:0; border-bottom:1px solid #ddd; padding-bottom:5px;"><i class="fa-solid fa-gas-pump"></i> SPBU Baru</h4>
|
||||
<form onsubmit="simpanSPBU(event, ${e.latlng.lat}, ${e.latlng.lng})">
|
||||
<input type="text" id="nama_spbu" placeholder="Nama SPBU" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<input type="tel" id="no_wa" placeholder="No WhatsApp" required style="width: 100%; margin-bottom: 8px; padding:6px; box-sizing:border-box;">
|
||||
<label style="font-size:12px; font-weight:bold;">Buka 24 Jam?</label><br>
|
||||
<label><input type="radio" name="buka_24jam" value="1" required> Ya</label>
|
||||
<label><input type="radio" name="buka_24jam" value="0"> Tidak</label><br><br>
|
||||
<button type="submit" style="width: 100%; padding: 8px; background:#2ecc71; color:#fff; border:none; border-radius:4px; font-weight:bold; cursor:pointer;"><i class="fa-solid fa-save"></i> Simpan Data</button>
|
||||
</form>
|
||||
</div>`;
|
||||
popup.setLatLng(e.latlng).setContent(formHtml).openOn(map);
|
||||
} else if (currentMode === 'polyline') {
|
||||
tempLatLngs.push(e.latlng);
|
||||
if (!tempPolyline) tempPolyline = L.polyline(tempLatLngs, {color: '#3498db', weight: 4}).addTo(map);
|
||||
else tempPolyline.setLatLngs(tempLatLngs);
|
||||
} else if (currentMode === 'polygon') {
|
||||
tempPolygonLatLngs.push(e.latlng);
|
||||
if (!tempPolygon) tempPolygon = L.polygon(tempPolygonLatLngs, {color: '#2ecc71', fillColor: '#2ecc71', fillOpacity: 0.4}).addTo(map);
|
||||
else tempPolygon.setLatLngs(tempPolygonLatLngs);
|
||||
} else if (currentMode === 'prasejahtera') {
|
||||
let formHtml = `
|
||||
<div style="width: 250px;">
|
||||
<h4 style="margin-top:0; border-bottom:1px solid #ddd; padding-bottom:5px;"><i class="fa-solid fa-home"></i> Data Prasejahtera</h4>
|
||||
|
||||
<label style="font-size:12px; font-weight:bold;">Nama Kepala Keluarga:</label>
|
||||
<input type="text" id="nama_kk" style="width: 100%; margin-bottom: 8px; padding:4px;">
|
||||
|
||||
<label style="font-size:12px; font-weight:bold;">Jumlah Anak:</label>
|
||||
<input type="number" id="jumlah_anak" value="0" style="width: 100%; margin-bottom: 8px; padding:4px;">
|
||||
|
||||
<label style="font-size:12px; font-weight:bold;">Umur Anak (Pisahkan dgn koma):</label>
|
||||
<input type="text" id="umur_anak" placeholder="Contoh: 15, 12, 8" style="width: 100%; margin-bottom: 8px; padding:4px;">
|
||||
|
||||
<label style="font-size:12px; font-weight:bold;">Status Orang Tua:</label>
|
||||
<select id="status_ortu" onchange="toggleStatusOrtu()" style="width: 100%; margin-bottom: 8px; padding:4px;">
|
||||
<option value="Bekerja">Bekerja</option>
|
||||
<option value="Pensiun">Pensiun</option>
|
||||
<option value="Meninggal">Meninggal Dunia</option>
|
||||
</select>
|
||||
|
||||
<div id="grup_bekerja" style="display:block; background:#e8f8f5; padding:5px; border-radius:4px; margin-bottom:8px;">
|
||||
<label style="font-size:12px; font-weight:bold;">Penghasilan/Bulan (Rp):</label>
|
||||
<input type="number" id="penghasilan" value="0" style="width: 100%; padding:4px;">
|
||||
</div>
|
||||
|
||||
<div id="grup_pensiun" style="display:none; background:#fef9e7; padding:5px; border-radius:4px; margin-bottom:8px;">
|
||||
<label style="font-size:12px; font-weight:bold;">Ada Uang Pensiun?</label>
|
||||
<select id="ada_pensiun" onchange="togglePensiun()" style="width: 100%; margin-bottom: 5px; padding:4px;">
|
||||
<option value="Tidak">Tidak Ada</option>
|
||||
<option value="Ya">Ya, Ada</option>
|
||||
</select>
|
||||
<div id="grup_nominal_pensiun" style="display:none;">
|
||||
<label style="font-size:12px; font-weight:bold;">Nominal Pensiun (Rp):</label>
|
||||
<input type="number" id="nominal_pensiun" value="0" style="width: 100%; padding:4px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="grup_meninggal" style="display:none; background:#fdedec; padding:5px; border-radius:4px; margin-bottom:8px;">
|
||||
<label style="font-size:12px; font-weight:bold;">Ada Uang Terusan?</label>
|
||||
<select id="ada_terusan" onchange="toggleTerusan()" style="width: 100%; margin-bottom: 5px; padding:4px;">
|
||||
<option value="Tidak">Tidak Ada</option>
|
||||
<option value="Ya">Ya, Ada</option>
|
||||
</select>
|
||||
<div id="grup_nominal_terusan" style="display:none;">
|
||||
<label style="font-size:12px; font-weight:bold;">Nominal Terusan (Rp):</label>
|
||||
<input type="number" id="nominal_terusan" value="0" style="width: 100%; padding:4px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label style="font-size:12px; font-weight:bold;">Keterangan Tambahan:</label>
|
||||
<textarea id="keterangan" style="width: 100%; margin-bottom: 10px; padding:4px;"></textarea>
|
||||
|
||||
<button type="button" onclick="simpanPrasejahtera(${e.latlng.lat}, ${e.latlng.lng})" style="width: 100%; padding: 8px; background:#2ecc71; color:#fff; border:none; border-radius:4px; font-weight:bold; cursor:pointer;">
|
||||
<i class="fa-solid fa-save"></i> Simpan Data
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
popup.setLatLng(e.latlng).setContent(formHtml).openOn(map);
|
||||
} else if (currentMode === 'ibadah') {
|
||||
let formHtml = `
|
||||
<div style="width: 220px;">
|
||||
<h4 style="margin-top:0; border-bottom:1px solid #ddd; padding-bottom:5px;">
|
||||
<i class="fa-solid fa-place-of-worship"></i> Rumah Ibadah
|
||||
</h4>
|
||||
<form onsubmit="simpanIbadah(event, ${e.latlng.lat}, ${e.latlng.lng})">
|
||||
<label style="font-size:12px; font-weight:bold;">Jenis:</label>
|
||||
<select id="jenis_ibadah" style="width:100%; margin-bottom:8px; padding:6px; box-sizing:border-box;">
|
||||
<option value="Masjid">🕌 Masjid</option>
|
||||
<option value="Gereja">⛪ Gereja</option>
|
||||
<option value="Vihara">🛕 Vihara</option>
|
||||
<option value="Pura">🪔 Pura</option>
|
||||
<option value="Klenteng">🏮 Klenteng</option>
|
||||
</select>
|
||||
<input type="text" id="nama_ibadah" placeholder="Nama Rumah Ibadah" required
|
||||
style="width:100%; margin-bottom:8px; padding:6px; box-sizing:border-box;">
|
||||
<label style="font-size:12px; font-weight:bold;">Radius Bantuan (meter):</label>
|
||||
<input type="number" id="radius_ibadah" value="500" min="50" max="5000" required
|
||||
style="width:100%; margin-bottom:8px; padding:6px; box-sizing:border-box;">
|
||||
<button type="submit" style="width:100%; padding:8px; background:#8e44ad; color:#fff; border:none; border-radius:4px; font-weight:bold; cursor:pointer;">
|
||||
<i class="fa-solid fa-save"></i> Simpan
|
||||
</button>
|
||||
</form>
|
||||
</div>`;
|
||||
popup.setLatLng(e.latlng).setContent(formHtml).openOn(map);
|
||||
}
|
||||
}
|
||||
map.on('click', onMapClick);
|
||||
|
||||
function simpanPrasejahtera(lat, lng) {
|
||||
// 1. Validasi Manual
|
||||
let nama_kk = document.getElementById('nama_kk').value.trim();
|
||||
if (!nama_kk || nama_kk === "") {
|
||||
Toast.fire({ icon: 'warning', title: 'Nama Kepala Keluarga wajib diisi!' });
|
||||
return; // Hentikan proses eksekusi jika kosong
|
||||
}
|
||||
|
||||
// 2. Susun Data
|
||||
let dataKirim = {
|
||||
lat: lat, lng: lng,
|
||||
nama_kk: nama_kk,
|
||||
penghasilan: parseInt(document.getElementById('penghasilan').value) || 0,
|
||||
jumlah_anak: parseInt(document.getElementById('jumlah_anak').value) || 0,
|
||||
umur_anak: document.getElementById('umur_anak').value,
|
||||
status_ortu: document.getElementById('status_ortu').value,
|
||||
ada_pensiun: document.getElementById('ada_pensiun').value,
|
||||
nominal_pensiun: parseInt(document.getElementById('nominal_pensiun').value) || 0,
|
||||
ada_terusan: document.getElementById('ada_terusan').value,
|
||||
nominal_terusan: parseInt(document.getElementById('nominal_terusan').value) || 0,
|
||||
keterangan: document.getElementById('keterangan').value
|
||||
};
|
||||
|
||||
// 3. Kirim ke Database
|
||||
fetch('api/prasejahtera/simpan_prasejahtera.php', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(dataKirim)
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'Data Berhasil Disimpan!' });
|
||||
map.closePopup();
|
||||
refreshPeta(); // Sinkronisasi seketika
|
||||
} else {
|
||||
Toast.fire({ icon: 'error', title: 'Gagal Menyimpan: ' + (data.message || 'Error Database') });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Terjadi masalah:", error);
|
||||
Toast.fire({ icon: 'error', title: 'Koneksi ke Server Gagal!' });
|
||||
});
|
||||
}
|
||||
|
||||
function hapusPrasejahtera(id) {
|
||||
Swal.fire({ title: 'Hapus data ini?', icon: 'warning', showCancelButton: true,
|
||||
confirmButtonColor: '#d33', cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus!', cancelButtonText: 'Batal'
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('api/prasejahtera/hapus_prasejahtera.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ id: id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'Data Dihapus!' });
|
||||
|
||||
// Cukup panggil fungsi ini, Leaflet akan menyapu bersih peta
|
||||
// dan memanggil ulang data terbaru dari database secara otomatis!
|
||||
refreshPeta();
|
||||
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateLokasiPrasejahtera(id, lat, lng) {
|
||||
fetch('api/prasejahtera/update_prasejahtera.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ id, lat, lng }) })
|
||||
.then(res => res.json()).then(data => { if (data.status === 'success') Toast.fire({ icon: 'info', title: 'Posisi Diperbarui' }); });
|
||||
}
|
||||
|
||||
function simpanIbadah(event, lat, lng) {
|
||||
event.preventDefault();
|
||||
let dataKirim = {
|
||||
lat, lng,
|
||||
nama_ibadah: document.getElementById('nama_ibadah').value,
|
||||
jenis: document.getElementById('jenis_ibadah').value,
|
||||
radius_m: parseInt(document.getElementById('radius_ibadah').value)
|
||||
};
|
||||
fetch('api/rumahibadah/simpan_ibadah.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(dataKirim) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'Rumah Ibadah Disimpan!' });
|
||||
map.closePopup();
|
||||
refreshPeta();
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menyimpan!' });
|
||||
});
|
||||
}
|
||||
|
||||
function hapusIbadah(id) {
|
||||
Swal.fire({ title: 'Hapus Rumah Ibadah?', icon: 'warning', showCancelButton: true,
|
||||
confirmButtonColor: '#d33', cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ya, Hapus!', cancelButtonText: 'Batal'
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fetch('api/rumahibadah/hapus_ibadah.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ id }) })
|
||||
.then(res => res.json()).then(data => {
|
||||
if (data.status === 'success') {
|
||||
Toast.fire({ icon: 'success', title: 'Data Dihapus!' });
|
||||
|
||||
// Gunakan refreshPeta agar sinkron dengan database 100%
|
||||
refreshPeta();
|
||||
|
||||
} else Toast.fire({ icon: 'error', title: 'Gagal Menghapus!' });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateLokasiIbadah(id, lat, lng) {
|
||||
fetch('api/rumahibadah/update_ibadah.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ id, lat, lng }) })
|
||||
.then(res => res.json()).then(data => { if (data.status === 'success') Toast.fire({ icon: 'info', title: 'Posisi Diperbarui' }); });
|
||||
}
|
||||
|
||||
// --- FUNGSI TOGGLE FORM PRASEJAHTERA ---
|
||||
function toggleStatusOrtu() {
|
||||
let status = document.getElementById('status_ortu').value;
|
||||
|
||||
// Atur visibilitas grup
|
||||
document.getElementById('grup_bekerja').style.display = (status === 'Bekerja') ? 'block' : 'none';
|
||||
document.getElementById('grup_pensiun').style.display = (status === 'Pensiun') ? 'block' : 'none';
|
||||
document.getElementById('grup_meninggal').style.display = (status === 'Meninggal') ? 'block' : 'none';
|
||||
|
||||
// Reset nilai yang tersembunyi agar tidak ikut tersimpan salah
|
||||
if(status !== 'Bekerja') document.getElementById('penghasilan').value = 0;
|
||||
if(status !== 'Pensiun') { document.getElementById('ada_pensiun').value = 'Tidak'; togglePensiun(); }
|
||||
if(status !== 'Meninggal') { document.getElementById('ada_terusan').value = 'Tidak'; toggleTerusan(); }
|
||||
}
|
||||
|
||||
function togglePensiun() {
|
||||
let ada = document.getElementById('ada_pensiun').value;
|
||||
document.getElementById('grup_nominal_pensiun').style.display = (ada === 'Ya') ? 'block' : 'none';
|
||||
if(ada === 'Tidak') document.getElementById('nominal_pensiun').value = 0;
|
||||
}
|
||||
|
||||
function toggleTerusan() {
|
||||
let ada = document.getElementById('ada_terusan').value;
|
||||
document.getElementById('grup_nominal_terusan').style.display = (ada === 'Ya') ? 'block' : 'none';
|
||||
if(ada === 'Tidak') document.getElementById('nominal_terusan').value = 0;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sistem Pemetaan</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css" />
|
||||
|
||||
<link rel="stylesheet" href="assets/css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="sidebar">
|
||||
<h3>Menu Pemetaan</h3>
|
||||
|
||||
<button class="mode-btn" data-mode="prasejahtera" onclick="ubahMode('prasejahtera')">
|
||||
<i class="fa-solid fa-house-chimney-crack"></i> Prasejahtera
|
||||
</button>
|
||||
<button class="mode-btn mode-ibadah" data-mode="ibadah" onclick="ubahMode('ibadah')">
|
||||
<i class="fa-solid fa-place-of-worship"></i> Rumah Ibadah
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="map-container">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.min.js"></script>
|
||||
<script src="assets/js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user