up
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM spbu WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM jalan WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
|
||||
if ($id <= 0) {
|
||||
echo json_encode(["status" => "error", "message" => "ID tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM parsil WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$sql = "SELECT * FROM spbu";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
if (!$result) {
|
||||
echo json_encode([
|
||||
"status" => "error",
|
||||
"message" => "Gagal membaca tabel spbu",
|
||||
"detail" => $conn->error
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
while($row = $result->fetch_assoc()){
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
echo json_encode($data);
|
||||
?>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$sql = "SELECT * FROM jalan";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
if (!$result) {
|
||||
echo json_encode([
|
||||
"status" => "error",
|
||||
"message" => "Gagal membaca tabel jalan",
|
||||
"detail" => $conn->error
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
while($row = $result->fetch_assoc()){
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
echo json_encode($data);
|
||||
?>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$sql = "SELECT * FROM parsil";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
if (!$result) {
|
||||
echo json_encode([
|
||||
"status" => "error",
|
||||
"message" => "Gagal membaca tabel parsil",
|
||||
"detail" => $conn->error
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
while($row = $result->fetch_assoc()){
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
echo json_encode($data);
|
||||
?>
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
ob_start();
|
||||
|
||||
include "db_config.php";
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$raw = file_get_contents("php://input");
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
$nama = $data['nama'] ?? '';
|
||||
$no = $data['no'] ?? '';
|
||||
$status = $data['status'] ?? 'Tidak';
|
||||
$lat = floatval($data['lat'] ?? 0);
|
||||
$lng = floatval($data['lng'] ?? 0);
|
||||
|
||||
if(!$nama || !$no) {
|
||||
ob_clean();
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak lengkap"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $conn->prepare("INSERT INTO spbu (nama,no,status,lat,lng) VALUES (?,?,?,?,?)");
|
||||
if(!$stmt) {
|
||||
$err = $conn->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " SPBU PREPARE ERR: $err\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"prepare","message"=>$err]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("sssdd", $nama, $no, $status, $lat, $lng);
|
||||
|
||||
if($stmt->execute()){
|
||||
$id = $stmt->insert_id;
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"success","id"=>$id]);
|
||||
} else {
|
||||
$err = $stmt->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " SPBU EXEC ERR: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"execute","message"=>$err]);
|
||||
}
|
||||
$stmt->close();
|
||||
} catch (Exception $e) {
|
||||
$err = $e->getMessage();
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " SPBU EXCEPTION: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"exception","message"=>$err]);
|
||||
}
|
||||
?>
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
ob_start();
|
||||
|
||||
include "db_config.php";
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$raw = file_get_contents("php://input");
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
$nama = $data['nama'] ?? '';
|
||||
$status = $data['status'] ?? 'Kabupaten';
|
||||
$panjang = floatval($data['panjang'] ?? 0);
|
||||
$koordinatInput = $data['koordinat'] ?? [];
|
||||
|
||||
if (is_string($koordinatInput)) {
|
||||
$decoded = json_decode($koordinatInput, true);
|
||||
$koordinat = (json_last_error() === JSON_ERROR_NONE) ? json_encode($decoded) : '[]';
|
||||
} else {
|
||||
$koordinat = json_encode($koordinatInput);
|
||||
}
|
||||
|
||||
if(!$nama) {
|
||||
ob_clean();
|
||||
echo json_encode(["status" => "error", "message" => "Nama tidak boleh kosong"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $conn->prepare("INSERT INTO jalan (nama,status,panjang,koordinat) VALUES (?,?,?,?)");
|
||||
if(!$stmt) {
|
||||
$err = $conn->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " JALAN PREPARE ERR: $err\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"prepare","message"=>$err]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("ssds", $nama, $status, $panjang, $koordinat);
|
||||
|
||||
if($stmt->execute()){
|
||||
$id = $stmt->insert_id;
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"success","id"=>$id]);
|
||||
} else {
|
||||
$err = $stmt->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " JALAN EXEC ERR: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"execute","message"=>$err]);
|
||||
}
|
||||
$stmt->close();
|
||||
} catch (Exception $e) {
|
||||
$err = $e->getMessage();
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " JALAN EXCEPTION: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"exception","message"=>$err]);
|
||||
}
|
||||
?>
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
ob_start();
|
||||
|
||||
include "db_config.php";
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$raw = file_get_contents("php://input");
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
$nama = $data['nama'] ?? '';
|
||||
$pemilik = $data['pemilik'] ?? '';
|
||||
$status = $data['status'] ?? 'SHM';
|
||||
$luas = floatval($data['luas'] ?? 0);
|
||||
$koordinatInput = $data['koordinat'] ?? [];
|
||||
|
||||
if (is_string($koordinatInput)) {
|
||||
$decoded = json_decode($koordinatInput, true);
|
||||
$koordinat = (json_last_error() === JSON_ERROR_NONE) ? json_encode($decoded) : '[]';
|
||||
} else {
|
||||
$koordinat = json_encode($koordinatInput);
|
||||
}
|
||||
|
||||
if(!$nama) {
|
||||
ob_clean();
|
||||
echo json_encode(["status" => "error", "message" => "Nama tidak boleh kosong"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $conn->prepare("INSERT INTO parsil (nama, pemilik, status, luas, koordinat) VALUES (?,?,?,?,?)");
|
||||
if(!$stmt) {
|
||||
$err = $conn->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " PARSIL PREPARE ERR: $err\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"prepare","message"=>$err]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt->bind_param("sssds", $nama, $pemilik, $status, $luas, $koordinat);
|
||||
|
||||
if($stmt->execute()){
|
||||
$id = $stmt->insert_id;
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"success","id"=>$id]);
|
||||
} else {
|
||||
$err = $stmt->error;
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " PARSIL EXEC ERR: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"execute","message"=>$err]);
|
||||
}
|
||||
$stmt->close();
|
||||
} catch (Exception $e) {
|
||||
$err = $e->getMessage();
|
||||
file_put_contents('error_log.txt', date('[Y-m-d H:i:s]') . " PARSIL EXCEPTION: $err | Payload: $raw\n", FILE_APPEND);
|
||||
ob_clean();
|
||||
echo json_encode(["status"=>"error","step"=>"exception","message"=>$err]);
|
||||
}
|
||||
?>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
$nama = $conn->real_escape_string($data['nama'] ?? '');
|
||||
$no = $conn->real_escape_string($data['no'] ?? '');
|
||||
$status = $conn->real_escape_string($data['status'] ?? 'Tidak');
|
||||
$lat = isset($data['lat']) ? floatval($data['lat']) : 0;
|
||||
$lng = isset($data['lng']) ? floatval($data['lng']) : 0;
|
||||
|
||||
if ($id <= 0 || $nama === '' || $no === '') {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "UPDATE spbu SET nama='$nama', no='$no', status='$status', lat='$lat', lng='$lng' WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
$nama = $conn->real_escape_string($data['nama'] ?? '');
|
||||
$status = $conn->real_escape_string($data['status'] ?? 'Kabupaten');
|
||||
$panjang = isset($data['panjang']) ? floatval($data['panjang']) : 0;
|
||||
$koordinatInput = $data['koordinat'] ?? [];
|
||||
|
||||
if ($id <= 0 || $nama === '') {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_string($koordinatInput)) {
|
||||
$decoded = json_decode($koordinatInput, true);
|
||||
$koordinat = (json_last_error() === JSON_ERROR_NONE) ? json_encode($decoded) : '[]';
|
||||
} else {
|
||||
$koordinat = json_encode($koordinatInput);
|
||||
}
|
||||
|
||||
$koordinat = $conn->real_escape_string($koordinat);
|
||||
|
||||
$sql = "UPDATE jalan SET nama='$nama', status='$status', panjang='$panjang', koordinat='$koordinat' WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
include "db_config.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents("php://input"), true);
|
||||
|
||||
$id = isset($data['id']) ? intval($data['id']) : 0;
|
||||
$nama = $conn->real_escape_string($data['nama'] ?? '');
|
||||
$pemilik = $conn->real_escape_string($data['pemilik'] ?? '');
|
||||
$status = $conn->real_escape_string($data['status'] ?? 'SHM');
|
||||
$luas = isset($data['luas']) ? floatval($data['luas']) : 0;
|
||||
$koordinatInput = $data['koordinat'] ?? [];
|
||||
|
||||
if ($id <= 0 || $nama === '') {
|
||||
echo json_encode(["status" => "error", "message" => "Data tidak valid"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_string($koordinatInput)) {
|
||||
$decoded = json_decode($koordinatInput, true);
|
||||
$koordinat = (json_last_error() === JSON_ERROR_NONE) ? json_encode($decoded) : '[]';
|
||||
} else {
|
||||
$koordinat = json_encode($koordinatInput);
|
||||
}
|
||||
|
||||
$koordinat = $conn->real_escape_string($koordinat);
|
||||
|
||||
$sql = "UPDATE parsil SET nama='$nama', pemilik='$pemilik', status='$status', luas='$luas', koordinat='$koordinat' WHERE id=$id";
|
||||
|
||||
if ($conn->query($sql)) {
|
||||
echo json_encode(["status" => "success"]);
|
||||
} else {
|
||||
echo json_encode(["status" => "error", "message" => $conn->error]);
|
||||
}
|
||||
?>
|
||||
+28
-734
@@ -2950,10 +2950,7 @@
|
||||
}
|
||||
.pf h4 i { font-size: 15px !important; opacity: .9; }
|
||||
/* Color the h4 based on icon color */
|
||||
.pf h4:has(.fa-gas-pump) { background: linear-gradient(135deg,#064e3b,#059669); }
|
||||
.pf h4:has(.fa-road) { background: linear-gradient(135deg,#1e3a8a,#2563eb); }
|
||||
.pf h4:has(.fa-vector-square){ background: linear-gradient(135deg,#78350f,#d97706); }
|
||||
|
||||
|
||||
.pf label {
|
||||
display: block;
|
||||
font-size: 10px !important;
|
||||
@@ -3284,10 +3281,7 @@
|
||||
</div>
|
||||
<div id="list-masjid" style="display:none;"><span id="cnt-masjid">0</span></div>
|
||||
<div id="list-kemiskinan" style="display:none;"><span id="cnt-kemiskinan">0</span></div>
|
||||
<div id="list-spbu" style="display:none;"><span id="cnt-spbu">0</span></div>
|
||||
<div id="list-jalan" style="display:none;"><span id="cnt-jalan">0</span></div>
|
||||
<div id="list-parsil" style="display:none;"><span id="cnt-parsil">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="leg-sec">
|
||||
<div class="sec-lbl" style="margin-bottom:10px">Legenda Peta</div>
|
||||
@@ -3341,20 +3335,7 @@
|
||||
<span>Rumah Ibadah <small>Tambah lokasi ibadah</small></span>
|
||||
</div>
|
||||
<div style="height:1px;background:#e2e8f0;margin:4px 4px"></div>
|
||||
<div style="padding:6px 10px 2px;font-size:10px;font-weight:800;color:#94a3b8;text-transform:uppercase;letter-spacing:.6px">Opsional</div>
|
||||
<div class="add-item" onclick="setMode('spbu');closeAddMenu()">
|
||||
<span class="ai-icon" style="background:#dcfce7;color:#16a34a"><i class="fas fa-gas-pump"></i></span>
|
||||
<span>SPBU <small>Tambah titik SPBU</small></span>
|
||||
</div>
|
||||
<div class="add-item" onclick="setMode('jalan');closeAddMenu()">
|
||||
<span class="ai-icon" style="background:#dbeafe;color:#2563eb"><i class="fas fa-road"></i></span>
|
||||
<span>Jalan <small>Gambar ruas jalan</small></span>
|
||||
</div>
|
||||
<div class="add-item" onclick="setMode('parsil');closeAddMenu()">
|
||||
<span class="ai-icon" style="background:#fef3c7;color:#d97706"><i class="fas fa-vector-square"></i></span>
|
||||
<span>Parsil / Lahan <small>Gambar area persil</small></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Icon buttons -->
|
||||
@@ -3523,10 +3504,10 @@
|
||||
|
||||
/* STATE */
|
||||
const state = {
|
||||
mode: null, spbu: [], jalan: [], parsil: [], kemiskinan: [], masjid: [],
|
||||
featureRefs: { spbu: {}, jalan: {}, parsil: {}, kemiskinan: {}, masjid: {} },
|
||||
mode: null, kemiskinan: [], masjid: [],
|
||||
featureRefs: { kemiskinan: {}, masjid: {} },
|
||||
kkLayerRefs: {}, blankRefs: {}, useSatellite: false, geometryEdit: null, activeCard: null,
|
||||
spbuFilterVis: { open24: true, non24: true }, drawingLine: false, drawingPoly: false,
|
||||
drawingLine: false, drawingPoly: false,
|
||||
tempPoints: [], tempMarkers: [], tempPolyline: null, tempPolygon: null
|
||||
};
|
||||
|
||||
@@ -3542,22 +3523,12 @@
|
||||
const layers = {
|
||||
kemiskinan: L.layerGroup().addTo(map),
|
||||
masjid: L.layerGroup().addTo(map),
|
||||
blankspot: L.layerGroup().addTo(map),
|
||||
// Layer opsional — OFF by default (tidak .addTo(map))
|
||||
spbu24: L.layerGroup(),
|
||||
spbuNon24: L.layerGroup(),
|
||||
jalan: L.layerGroup(),
|
||||
parsil: L.layerGroup()
|
||||
};
|
||||
blankspot: L.layerGroup().addTo(map),};
|
||||
const layersControl = L.control.layers(null, {
|
||||
'<span class="lc-item"><span class="lc-dot lc-dot-kemiskinan"></span><span class="lc-text"><strong>Kemiskinan</strong><small>Data KK miskin</small></span></span>': layers.kemiskinan,
|
||||
'<span class="lc-item"><span class="lc-dot lc-dot-masjid"></span><span class="lc-text"><strong>Rumah Ibadah</strong><small>Fasilitas ibadah</small></span></span>': layers.masjid,
|
||||
'<span class="lc-item"><span class="lc-dot" style="background:#64748b"></span><span class="lc-text"><strong>Blank Spot</strong><small>Di luar radius rumah ibadah</small></span></span>': layers.blankspot,
|
||||
'<span class="lc-item"><span class="lc-dot" style="background:#16a34a"></span><span class="lc-text"><strong>SPBU 24 Jam</strong><small>Buka 24 jam</small></span></span>': layers.spbu24,
|
||||
'<span class="lc-item"><span class="lc-dot" style="background:#dc2626"></span><span class="lc-text"><strong>SPBU Non-24</strong><small>Tidak 24 jam</small></span></span>': layers.spbuNon24,
|
||||
'<span class="lc-item"><span class="lc-dot" style="background:#2563eb"></span><span class="lc-text"><strong>Jalan</strong><small>Jaringan jalan</small></span></span>': layers.jalan,
|
||||
'<span class="lc-item"><span class="lc-dot" style="background:#d97706"></span><span class="lc-text"><strong>Parsil / Lahan</strong><small>Data persil tanah</small></span></span>': layers.parsil,
|
||||
}, { collapsed: false, position: 'topright' }).addTo(map);
|
||||
}, { collapsed: false, position: 'topright' }).addTo(map);
|
||||
decorateLayersControl();
|
||||
function decorateLayersControl() {
|
||||
const container = layersControl.getContainer();
|
||||
@@ -3565,7 +3536,7 @@
|
||||
const overlays = container.querySelector('.leaflet-control-layers-overlays');
|
||||
if (!overlays) return;
|
||||
const labels = Array.from(overlays.querySelectorAll('label'));
|
||||
if (labels.length < 6) return;
|
||||
if (labels.length < 3) return;
|
||||
overlays.innerHTML = '';
|
||||
const addGroup = (title, items, color) => {
|
||||
const head = document.createElement('div');
|
||||
@@ -3613,7 +3584,7 @@
|
||||
});
|
||||
};
|
||||
addGroup('Tematik Utama', [labels[0], labels[1], labels[2]]);
|
||||
addGroup('Opsional', [labels[3], labels[4], labels[5], labels[6]], '#64748b');
|
||||
|
||||
}
|
||||
|
||||
const statusStoreKey = 'gis-kemiskinan-status';
|
||||
@@ -3897,18 +3868,6 @@
|
||||
const fWarga = state.kemiskinan.find(d => (`${d.nama_kk} ${d.alamat}`).toLowerCase().includes(q));
|
||||
if (fWarga) return focusFeature('kemiskinan', fWarga.id);
|
||||
|
||||
// 3. Cari SPBU
|
||||
const fSpbu = state.spbu.find(d => (d.nama || '').toLowerCase().includes(q));
|
||||
if (fSpbu) return focusFeature('spbu', fSpbu.id);
|
||||
|
||||
// 4. Cari Jalan
|
||||
const fJalan = state.jalan.find(d => (d.nama || '').toLowerCase().includes(q));
|
||||
if (fJalan) return focusFeature('jalan', fJalan.id);
|
||||
|
||||
// 5. Cari Parsil
|
||||
const fParsil = state.parsil.find(d => (`${d.nama} ${d.pemilik}`).toLowerCase().includes(q));
|
||||
if (fParsil) return focusFeature('parsil', fParsil.id);
|
||||
|
||||
// Jika tidak ketemu
|
||||
alert('Data "' + q + '" tidak ditemukan.');
|
||||
}
|
||||
@@ -4124,7 +4083,7 @@
|
||||
function setMode(m) {
|
||||
cancelDrawing();
|
||||
state.mode = state.mode === m ? null : m;
|
||||
['kemiskinan', 'masjid', 'spbu', 'jalan', 'parsil'].forEach(x => {
|
||||
['kemiskinan', 'masjid'].forEach(x => {
|
||||
const el = document.getElementById('btn-' + x);
|
||||
if (el) el.className = 'mbtn';
|
||||
});
|
||||
@@ -4134,11 +4093,6 @@
|
||||
const msgs = {
|
||||
kemiskinan: 'Klik peta untuk menambah data Kemiskinan',
|
||||
masjid: 'Klik peta untuk menambah titik Rumah Ibadah',
|
||||
spbu: 'Klik peta untuk menambah titik SPBU',
|
||||
jalan: 'Klik untuk gambar jalan — klik ganda untuk selesai',
|
||||
parsil: 'Klik untuk gambar parsil — klik titik awal atau dbl-klik selesai',
|
||||
line: 'Klik untuk gambar jalan — klik ganda untuk selesai',
|
||||
poly: 'Klik untuk gambar parsil — klik titik awal atau dbl-klik selesai',
|
||||
};
|
||||
hint.textContent = msgs[m] || 'Klik peta';
|
||||
hint.classList.add('show');
|
||||
@@ -4157,14 +4111,9 @@
|
||||
if (!state.mode) return;
|
||||
if (state.mode === 'kemiskinan') handleKemiskinanClick(e);
|
||||
else if (state.mode === 'masjid') handleMasjidClick(e);
|
||||
else if (state.mode === 'spbu') handlePointClick(e);
|
||||
else if (state.mode === 'jalan') handleLineClick(e);
|
||||
else if (state.mode === 'parsil') handlePolyClick(e);
|
||||
});
|
||||
map.on('dblclick', function (e) {
|
||||
if ((state.mode === 'jalan' || state.mode === 'line') && state.drawingLine) finishLine(e);
|
||||
if ((state.mode === 'parsil' || state.mode === 'poly') && state.drawingPoly) finishPoly(e);
|
||||
if (['jalan','parsil','line','poly'].includes(state.mode)) L.DomEvent.stopPropagation(e);
|
||||
|
||||
});
|
||||
|
||||
/* ── MODERN MARKER ICON ── */
|
||||
@@ -4229,102 +4178,9 @@
|
||||
window._tmpM = tmpM;
|
||||
}
|
||||
|
||||
function savePoint() {
|
||||
|
||||
|
||||
const nama = document.getElementById('p-nama').value.trim();
|
||||
const no = document.getElementById('p-no').value.trim();
|
||||
const status = document.getElementById('p-status').value;
|
||||
const lat = parseFloat(document.getElementById('p-lat').value);
|
||||
const lng = parseFloat(document.getElementById('p-lng').value);
|
||||
|
||||
if (!nama || !no) {
|
||||
alert('Lengkapi nama dan nomor SPBU!');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("api/save_data.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: nama,
|
||||
no: no,
|
||||
status: status,
|
||||
lat: lat,
|
||||
lng: lng
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.status == "success") {
|
||||
|
||||
const d = {
|
||||
id: response.id || Date.now(),
|
||||
nama,
|
||||
no,
|
||||
status,
|
||||
lat,
|
||||
lng
|
||||
};
|
||||
|
||||
state.spbu.push(d);
|
||||
|
||||
renderSPBU(d);
|
||||
|
||||
updateCount('spbu', state.spbu.length);
|
||||
|
||||
addCard(
|
||||
'spbu',
|
||||
d.id,
|
||||
nama,
|
||||
'No: ' + no,
|
||||
status === 'Ya' ? 'Buka 24 Jam' : 'Tidak Buka 24 Jam',
|
||||
status === 'Ya' ? '#1a6b3c' : '#b93328'
|
||||
);
|
||||
|
||||
if (window._tmpM) {
|
||||
map.closePopup();
|
||||
map.removeLayer(window._tmpM);
|
||||
window._tmpM = null;
|
||||
}
|
||||
|
||||
setMode(null);
|
||||
ensureLayerVisible('spbu', d.id);
|
||||
focusFeature('spbu', d.id);
|
||||
|
||||
} else {
|
||||
alert("Gagal menyimpan: " + (response.message || "Periksa database"));
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert("Terjadi error jaringan");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function renderSPBU(d) {
|
||||
const color = d.status === 'Ya' ? '#10b981' : '#ef4444';
|
||||
const icon = createModernMarker(color, 'fas fa-gas-pump', d.nama);
|
||||
const m = L.marker([d.lat, d.lng], { icon, draggable: true });
|
||||
m.bindPopup(`<div class="pi">
|
||||
<h4><i class="fas fa-gas-pump" style="color:${color}"></i>${d.nama}<button class="pi-close-alt" onclick="map.closePopup()"><i class="fas fa-times"></i></button></h4>
|
||||
<div class="pi-body">
|
||||
<div class="pi-row"><span class="pi-k">No. SPBU</span><span class="pi-v">${d.no}</span></div>
|
||||
<div class="pi-row"><span class="pi-k">Status</span><span class="pi-v" style="color:${color}">${d.status === 'Ya' ? '✔ Buka 24 Jam' : '✖ Tidak Buka 24 Jam'}</span></div>
|
||||
<div class="pi-row"><span class="pi-k">Koordinat</span><span class="pi-v" style="font-size:11px;font-family:monospace">${d.lat.toFixed(5)}, ${d.lng.toFixed(5)}</span></div>
|
||||
</div>
|
||||
<div class="act-row">
|
||||
<button class="pbtn pbtn-y" onclick="openEditSpbu(${d.id})">Edit</button>
|
||||
<button class="pbtn pbtn-r" onclick="deleteFeature('spbu',${d.id})">Hapus</button>
|
||||
</div>
|
||||
</div>`, { autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] });
|
||||
m.addTo(d.status === 'Ya' ? layers.spbu24 : layers.spbuNon24);
|
||||
state.featureRefs.spbu[String(d.id)] = m;
|
||||
}
|
||||
|
||||
|
||||
/* ── JALAN ── */
|
||||
function handleLineClick(e) {
|
||||
@@ -4337,231 +4193,14 @@
|
||||
document.getElementById('hint').textContent = `📍 ${state.tempPoints.length} titik — klik ganda untuk selesai`;
|
||||
}
|
||||
|
||||
function finishLine(e) {
|
||||
if (state.tempPoints.length < 2) { alert('Minimal 2 titik!'); return; }
|
||||
const pts = [...state.tempPoints];
|
||||
const len = calcLen(pts);
|
||||
window._tempLinePts = pts;
|
||||
window._tempLineLen = len;
|
||||
clearTemp();
|
||||
L.popup({ closeOnClick: false, keepInView: true, autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] })
|
||||
.setLatLng(pts[Math.floor(pts.length / 2)])
|
||||
.setContent(`<div class="pf">
|
||||
<h4><i class="fas fa-road"></i> Tambah Jalan</h4>
|
||||
<label>Nama Jalan</label>
|
||||
<input id="j-nama" placeholder="Jl. Ahmad Yani">
|
||||
<label>Status Jalan</label>
|
||||
<select id="j-status">
|
||||
<option value="Nasional">Jalan Nasional</option>
|
||||
<option value="Provinsi">Jalan Provinsi</option>
|
||||
<option value="Kabupaten" selected>Jalan Kabupaten</option>
|
||||
</select>
|
||||
<div style="display:flex;align-items:center;gap:10px;margin:10px 16px 4px;padding:9px 12px;background:#eff6ff;border-radius:9px;border:1px solid #dbeafe">
|
||||
<i class="fas fa-ruler-horizontal" style="color:#2563eb;font-size:13px"></i>
|
||||
<span style="font-size:11px;color:#64748b;font-weight:600">Panjang terukur:</span>
|
||||
<span style="font-size:14px;font-weight:800;color:#1d4ed8;margin-left:auto">${fmtLen(len)}</span>
|
||||
</div>
|
||||
<button class="pbtn pbtn-b" onclick="saveLine()">Simpan Jalan</button>
|
||||
</div>`).addTo(map);
|
||||
}
|
||||
|
||||
|
||||
function saveLine() {
|
||||
const pts = window._tempLinePts || [];
|
||||
const len = window._tempLineLen || 0;
|
||||
|
||||
|
||||
|
||||
const nama = document.getElementById('j-nama').value.trim();
|
||||
const status = document.getElementById('j-status').value;
|
||||
|
||||
|
||||
if (!nama) {
|
||||
alert('Isi nama jalan!');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("api/save_jalan.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: nama,
|
||||
status: status,
|
||||
panjang: len,
|
||||
koordinat: pts
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.status == "success") {
|
||||
|
||||
const d = {
|
||||
id: response.id || Date.now(),
|
||||
nama,
|
||||
status,
|
||||
pts,
|
||||
len
|
||||
};
|
||||
|
||||
state.jalan.push(d);
|
||||
|
||||
renderJalan(d);
|
||||
|
||||
updateCount('jalan', state.jalan.length);
|
||||
|
||||
addCard(
|
||||
'jalan',
|
||||
d.id,
|
||||
nama,
|
||||
status + ' · ' + fmtLen(len),
|
||||
status,
|
||||
jColor[status]
|
||||
);
|
||||
|
||||
map.closePopup();
|
||||
setMode(null);
|
||||
ensureLayerVisible('jalan', d.id);
|
||||
focusFeature('jalan', d.id);
|
||||
|
||||
} else {
|
||||
|
||||
// log removed
|
||||
alert("Gagal simpan jalan");
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
// log removed
|
||||
alert("Error simpan jalan");
|
||||
});
|
||||
|
||||
}
|
||||
function renderJalan(d) {
|
||||
|
||||
const pts = normalizeLinePoints(d.pts);
|
||||
if (pts.length < 2) {
|
||||
// log removed
|
||||
return;
|
||||
}
|
||||
|
||||
const c = jColor[d.status] || '#ef4444';
|
||||
|
||||
const w =
|
||||
d.status === 'Nasional' ? 6 :
|
||||
d.status === 'Provinsi' ? 5 : 4;
|
||||
|
||||
const line = L.polyline(pts, {
|
||||
color: c,
|
||||
weight: w,
|
||||
opacity: 0.95,
|
||||
lineCap: 'round',
|
||||
lineJoin: 'round',
|
||||
className: 'path-glow'
|
||||
})
|
||||
.bindPopup(`
|
||||
<div class="pi">
|
||||
<h4><i class="fas fa-road" style="color:${c}"></i>${d.nama}<button class="pi-close-alt" onclick="map.closePopup()"><i class="fas fa-times"></i></button></h4>
|
||||
|
||||
<div class="pi-body">
|
||||
<div class="pi-row">
|
||||
<span class="pi-k">Status</span>
|
||||
<span class="pi-v">${d.status}</span>
|
||||
</div>
|
||||
<div class="pi-row">
|
||||
<span class="pi-k">Panjang</span>
|
||||
<span class="pi-v">${fmtLen(d.len)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="act-row">
|
||||
<button class="pbtn pbtn-y" onclick="openEditJalan(${d.id})">Edit</button>
|
||||
<button class="pbtn pbtn-r" onclick="deleteFeature('jalan',${d.id})">Hapus</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`, { autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] })
|
||||
.addTo(layers.jalan);
|
||||
|
||||
state.featureRefs.jalan[String(d.id)] = line;
|
||||
|
||||
}
|
||||
|
||||
function normalizeLinePoints(raw) {
|
||||
|
||||
let pts = raw;
|
||||
|
||||
if (typeof pts === 'string') {
|
||||
try {
|
||||
pts = JSON.parse(pts);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Kompatibilitas data lama: koordinat sempat tersimpan sebagai JSON string di dalam JSON string.
|
||||
if (typeof pts === 'string') {
|
||||
try {
|
||||
pts = JSON.parse(pts);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(pts) || pts.length === 0) return [];
|
||||
|
||||
if (Array.isArray(pts[0])) {
|
||||
return pts
|
||||
.map(p => [parseFloat(p[0]), parseFloat(p[1])])
|
||||
.filter(p => Number.isFinite(p[0]) && Number.isFinite(p[1]));
|
||||
}
|
||||
|
||||
if (pts[0] && typeof pts[0] === 'object' && pts[0].lat !== undefined) {
|
||||
return pts
|
||||
.map(p => [parseFloat(p.lat), parseFloat(p.lng)])
|
||||
.filter(p => Number.isFinite(p[0]) && Number.isFinite(p[1]));
|
||||
}
|
||||
|
||||
return [];
|
||||
|
||||
}
|
||||
|
||||
function normalizePolyPoints(raw) {
|
||||
|
||||
let pts = raw;
|
||||
|
||||
if (typeof pts === 'string') {
|
||||
try {
|
||||
pts = JSON.parse(pts);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof pts === 'string') {
|
||||
try {
|
||||
pts = JSON.parse(pts);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(pts) || pts.length === 0) return [];
|
||||
|
||||
if (Array.isArray(pts[0])) {
|
||||
return pts
|
||||
.map(p => [parseFloat(p[0]), parseFloat(p[1])])
|
||||
.filter(p => Number.isFinite(p[0]) && Number.isFinite(p[1]));
|
||||
}
|
||||
|
||||
if (pts[0] && typeof pts[0] === 'object' && pts[0].lat !== undefined) {
|
||||
return pts
|
||||
.map(p => [parseFloat(p.lat), parseFloat(p.lng)])
|
||||
.filter(p => Number.isFinite(p[0]) && Number.isFinite(p[1]));
|
||||
}
|
||||
|
||||
return [];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ── PARSIL ── */
|
||||
function handlePolyClick(e) {
|
||||
@@ -4585,160 +4224,11 @@
|
||||
`🗺️ ${state.tempPoints.length} titik — klik titik awal atau dbl-klik selesai`;
|
||||
}
|
||||
|
||||
function finishPoly(e) {
|
||||
if (state.tempPoints.length < 3) { alert('Minimal 3 titik!'); return; }
|
||||
const pts = [...state.tempPoints];
|
||||
const area = calcArea(pts);
|
||||
window._tempPolyPts = pts;
|
||||
window._tempPolyArea = area;
|
||||
clearTemp();
|
||||
const center = L.polygon(pts).getBounds().getCenter();
|
||||
L.popup({ closeOnClick: false, keepInView: true, autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] })
|
||||
.setLatLng(center)
|
||||
.setContent(`<div class="pf">
|
||||
<h4><i class="fas fa-vector-square"></i> Tambah Parsil / Lahan</h4>
|
||||
<label>Nama / ID Parsil</label>
|
||||
<input id="ps-nama" placeholder="Parsil A-01">
|
||||
<label>Pemilik</label>
|
||||
<input id="ps-pemilik" placeholder="Nama pemilik">
|
||||
<label>Status Sertifikat</label>
|
||||
<select id="ps-status">
|
||||
<option value="SHM">SHM — Hak Milik</option>
|
||||
<option value="HGB">HGB — Hak Guna Bangunan</option>
|
||||
<option value="Sewa">Sewa / Kontrak</option>
|
||||
<option value="Lainnya">Lainnya</option>
|
||||
</select>
|
||||
<div style="display:flex;align-items:center;gap:10px;margin:10px 16px 4px;padding:9px 12px;background:#fffbeb;border-radius:9px;border:1px solid #fde68a">
|
||||
<i class="fas fa-ruler-combined" style="color:#d97706;font-size:13px"></i>
|
||||
<span style="font-size:11px;color:#64748b;font-weight:600">Luas terukur:</span>
|
||||
<span style="font-size:14px;font-weight:800;color:#d97706;margin-left:auto">${fmtArea(area)}</span>
|
||||
</div>
|
||||
<button class="pbtn pbtn-y" onclick="saveParsil()">Simpan Parsil</button>
|
||||
</div>`).addTo(map);
|
||||
}
|
||||
|
||||
|
||||
function saveParsil() {
|
||||
const pts = window._tempPolyPts || [];
|
||||
const area = window._tempPolyArea || 0;
|
||||
|
||||
|
||||
const nama = document.getElementById('ps-nama').value.trim();
|
||||
const pemilik = document.getElementById('ps-pemilik').value.trim();
|
||||
const status = document.getElementById('ps-status').value;
|
||||
|
||||
if (!nama) {
|
||||
alert('Isi nama parsil!');
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("api/save_parsil.php", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: nama,
|
||||
pemilik: pemilik,
|
||||
status: status,
|
||||
luas: area,
|
||||
koordinat: pts
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(response => {
|
||||
|
||||
if (response.status == "success") {
|
||||
|
||||
const parsil = {
|
||||
id: response.id || Date.now(),
|
||||
nama,
|
||||
pemilik,
|
||||
status,
|
||||
pts,
|
||||
area
|
||||
};
|
||||
|
||||
state.parsil.push(parsil);
|
||||
|
||||
renderParsil(parsil);
|
||||
|
||||
updateCount('parsil', state.parsil.length);
|
||||
|
||||
addCard(
|
||||
'parsil',
|
||||
parsil.id,
|
||||
parsil.nama,
|
||||
parsil.status,
|
||||
parsil.status,
|
||||
'#1a5276'
|
||||
);
|
||||
|
||||
map.closePopup();
|
||||
setMode(null);
|
||||
ensureLayerVisible('parsil', parsil.id);
|
||||
focusFeature('parsil', parsil.id);
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
// log removed
|
||||
alert("Gagal simpan parsil");
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => {});
|
||||
}
|
||||
|
||||
function renderParsil(d) {
|
||||
|
||||
const pts = normalizePolyPoints(d.pts);
|
||||
if (pts.length < 3) {
|
||||
// log removed
|
||||
return;
|
||||
}
|
||||
|
||||
const c = pColor[d.status];
|
||||
|
||||
const poly = L.polygon(pts, {
|
||||
color: c,
|
||||
fillColor: c,
|
||||
fillOpacity: 0.25,
|
||||
weight: 3,
|
||||
dashArray: '8, 6',
|
||||
lineCap: 'round',
|
||||
lineJoin: 'round',
|
||||
className: 'parsil-glow'
|
||||
})
|
||||
.bindPopup(`
|
||||
<div class="pi">
|
||||
<h4><i class="fas fa-draw-polygon" style="color:${c}"></i>${d.nama}<button class="pi-close-alt" onclick="map.closePopup()"><i class="fas fa-times"></i></button></h4>
|
||||
|
||||
<div class="pi-body">
|
||||
<div class="pi-row">
|
||||
<span class="pi-k">Pemilik</span>
|
||||
<span class="pi-v">${d.pemilik || '-'}</span>
|
||||
</div>
|
||||
<div class="pi-row">
|
||||
<span class="pi-k">Status</span>
|
||||
<span class="pi-v">${d.status}</span>
|
||||
</div>
|
||||
<div class="pi-row">
|
||||
<span class="pi-k">Luas</span>
|
||||
<span class="pi-v">${fmtArea(d.area)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="act-row">
|
||||
<button class="pbtn pbtn-y" onclick="openEditParsil(${d.id})">Edit</button>
|
||||
<button class="pbtn pbtn-r" onclick="deleteFeature('parsil',${d.id})">Hapus</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`)
|
||||
.addTo(layers.parsil);
|
||||
|
||||
state.featureRefs.parsil[String(d.id)] = poly;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getById(type, id) {
|
||||
return state[type].find(x => String(x.id) === String(id));
|
||||
@@ -4911,11 +4401,7 @@
|
||||
}
|
||||
|
||||
function refreshType(type) {
|
||||
if (state.geometryEdit && state.geometryEdit.type === type) stopGeometryEdit();
|
||||
if (type === 'spbu') {
|
||||
layers.spbu24.clearLayers();
|
||||
layers.spbuNon24.clearLayers();
|
||||
} else {
|
||||
if (state.geometryEdit && state.geometryEdit.type === type) stopGeometryEdit(); else {
|
||||
layers[type].clearLayers();
|
||||
}
|
||||
state.featureRefs[type] = {};
|
||||
@@ -4952,31 +4438,7 @@
|
||||
renderDashboard();
|
||||
}
|
||||
|
||||
function openEditSpbu(id) {
|
||||
const d = getById('spbu', id);
|
||||
if (!d) return;
|
||||
const ref = state.featureRefs.spbu[String(id)];
|
||||
const ll = ref && ref.getLatLng ? ref.getLatLng() : { lat: d.lat, lng: d.lng };
|
||||
const html = `<div class="pf">
|
||||
<h4><i class="fas fa-edit" style="color:var(--amber)"></i> Edit SPBU</h4>
|
||||
<label>Nama SPBU</label>
|
||||
<input id="e-spbu-nama" value="${(d.nama || '').replace(/"/g, '"')}">
|
||||
<label>Nomor SPBU</label>
|
||||
<input id="e-spbu-no" value="${(d.no || '').replace(/"/g, '"')}">
|
||||
<label>Status Operasional</label>
|
||||
<select id="e-spbu-status">
|
||||
<option value="Ya" ${d.status === 'Ya' ? 'selected' : ''}>Buka 24 Jam</option>
|
||||
<option value="Tidak" ${d.status === 'Tidak' ? 'selected' : ''}>Tidak Buka 24 Jam</option>
|
||||
</select>
|
||||
<label>Latitude</label>
|
||||
<input id="e-spbu-lat" value="${Number(ll.lat).toFixed(6)}">
|
||||
<label>Longitude</label>
|
||||
<input id="e-spbu-lng" value="${Number(ll.lng).toFixed(6)}">
|
||||
<button class="pbtn pbtn-y" onclick="saveEditSpbu(${id})">Simpan Perubahan</button>
|
||||
</div>`;
|
||||
map.closePopup();
|
||||
L.popup({ maxWidth: 290, autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] }).setLatLng([ll.lat, ll.lng]).setContent(html).openOn(map);
|
||||
}
|
||||
|
||||
|
||||
function saveEditSpbu(id) {
|
||||
const nama = document.getElementById('e-spbu-nama').value.trim();
|
||||
@@ -5011,33 +4473,7 @@
|
||||
.catch(() => alert('Error update SPBU'));
|
||||
}
|
||||
|
||||
function openEditJalan(id) {
|
||||
if (state.geometryEdit && (state.geometryEdit.type !== 'jalan' || String(state.geometryEdit.id) !== String(id))) {
|
||||
stopGeometryEdit();
|
||||
}
|
||||
const d = getById('jalan', id);
|
||||
if (!d) return;
|
||||
const pts = normalizeLinePoints(d.pts);
|
||||
const ref = state.featureRefs.jalan[String(id)];
|
||||
const center = ref && ref.getBounds ? ref.getBounds().getCenter() : map.getCenter();
|
||||
const html = `<div class="pf" style="width:290px">
|
||||
<h4><i class="fas fa-edit" style="color:var(--amber)"></i> Edit Jalan</h4>
|
||||
<label>Nama Jalan</label>
|
||||
<input id="e-jalan-nama" value="${(d.nama || '').replace(/"/g, '"')}">
|
||||
<label>Status Jalan</label>
|
||||
<select id="e-jalan-status">
|
||||
<option value="Nasional" ${d.status === 'Nasional' ? 'selected' : ''}>Jalan Nasional</option>
|
||||
<option value="Provinsi" ${d.status === 'Provinsi' ? 'selected' : ''}>Jalan Provinsi</option>
|
||||
<option value="Kabupaten" ${d.status === 'Kabupaten' ? 'selected' : ''}>Jalan Kabupaten</option>
|
||||
</select>
|
||||
<label>Koordinat Lokasi (satu baris: lat,lng)</label>
|
||||
<textarea id="e-jalan-pts">${pointsToText(pts)}</textarea>
|
||||
<button class="pbtn pbtn-b" onclick="startGeometryEdit('jalan',${id})">Edit Vertex / Drag di Peta</button>
|
||||
<button class="pbtn pbtn-y" onclick="saveEditJalan(${id})">Simpan Perubahan</button>
|
||||
</div>`;
|
||||
map.closePopup();
|
||||
L.popup({ maxWidth: 330, autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] }).setLatLng(center).setContent(html).openOn(map);
|
||||
}
|
||||
|
||||
|
||||
function saveEditJalan(id) {
|
||||
if (state.geometryEdit && state.geometryEdit.type === 'jalan' && String(state.geometryEdit.id) === String(id)) {
|
||||
@@ -5075,36 +4511,7 @@
|
||||
.catch(() => alert('Error update jalan'));
|
||||
}
|
||||
|
||||
function openEditParsil(id) {
|
||||
if (state.geometryEdit && (state.geometryEdit.type !== 'parsil' || String(state.geometryEdit.id) !== String(id))) {
|
||||
stopGeometryEdit();
|
||||
}
|
||||
const d = getById('parsil', id);
|
||||
if (!d) return;
|
||||
const pts = normalizePolyPoints(d.pts);
|
||||
const ref = state.featureRefs.parsil[String(id)];
|
||||
const center = ref && ref.getBounds ? ref.getBounds().getCenter() : map.getCenter();
|
||||
const html = `<div class="pf" style="width:290px">
|
||||
<h4><i class="fas fa-edit" style="color:var(--amber)"></i> Edit Parsil</h4>
|
||||
<label>Nama / ID Parsil</label>
|
||||
<input id="e-parsil-nama" value="${(d.nama || '').replace(/"/g, '"')}">
|
||||
<label>Pemilik</label>
|
||||
<input id="e-parsil-pemilik" value="${(d.pemilik || '').replace(/"/g, '"')}">
|
||||
<label>Status Sertifikat</label>
|
||||
<select id="e-parsil-status">
|
||||
<option value="SHM" ${d.status === 'SHM' ? 'selected' : ''}>SHM – Hak Milik</option>
|
||||
<option value="HGB" ${d.status === 'HGB' ? 'selected' : ''}>HGB – Hak Guna Bangunan</option>
|
||||
<option value="HGU" ${d.status === 'HGU' ? 'selected' : ''}>HGU – Hak Guna Usaha</option>
|
||||
<option value="HP" ${d.status === 'HP' ? 'selected' : ''}>HP – Hak Pakai</option>
|
||||
</select>
|
||||
<label>Koordinat Lokasi (satu baris: lat,lng)</label>
|
||||
<textarea id="e-parsil-pts">${pointsToText(pts)}</textarea>
|
||||
<button class="pbtn pbtn-b" onclick="startGeometryEdit('parsil',${id})">Edit Vertex / Drag di Peta</button>
|
||||
<button class="pbtn pbtn-y" onclick="saveEditParsil(${id})">Simpan Perubahan</button>
|
||||
</div>`;
|
||||
map.closePopup();
|
||||
L.popup({ maxWidth: 330, autoPanPaddingTopLeft: [0, 80], autoPanPaddingBottomRight: [0, 20] }).setLatLng(center).setContent(html).openOn(map);
|
||||
}
|
||||
|
||||
|
||||
function saveEditParsil(id) {
|
||||
if (state.geometryEdit && state.geometryEdit.type === 'parsil' && String(state.geometryEdit.id) === String(id)) {
|
||||
@@ -5290,10 +4697,6 @@
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
loadSPBU();
|
||||
loadJalan();
|
||||
loadParsil();
|
||||
|
||||
// Kemiskinan butuh data Masjid untuk hitung Blank Spot (merah/hijau)
|
||||
// Jadi pastikan loadMasjid selesai dulu baru loadKemiskinan
|
||||
loadMasjid().then(() => {
|
||||
@@ -5302,120 +4705,11 @@
|
||||
|
||||
});
|
||||
|
||||
function loadSPBU() {
|
||||
|
||||
|
||||
fetch("api/read_data.php")
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
|
||||
|
||||
data.forEach(d => {
|
||||
|
||||
const spbu = {
|
||||
id: d.id,
|
||||
nama: d.nama,
|
||||
no: d.no,
|
||||
status: d.status,
|
||||
lat: parseFloat(d.lat),
|
||||
lng: parseFloat(d.lng)
|
||||
};
|
||||
|
||||
state.spbu.push(spbu);
|
||||
|
||||
renderSPBU(spbu);
|
||||
|
||||
updateCount('spbu', state.spbu.length);
|
||||
|
||||
addCard(
|
||||
'spbu',
|
||||
spbu.id,
|
||||
spbu.nama,
|
||||
'No: ' + spbu.no,
|
||||
spbu.status === 'Ya' ? 'Buka 24 Jam' : 'Tidak Buka 24 Jam',
|
||||
spbu.status === 'Ya' ? '#1a6b3c' : '#b93328'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch(err => {});
|
||||
|
||||
}
|
||||
|
||||
function loadJalan() {
|
||||
|
||||
fetch("api/read_jalan.php")
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
|
||||
data.forEach(d => {
|
||||
|
||||
const jalan = {
|
||||
id: d.id,
|
||||
nama: d.nama,
|
||||
status: d.status,
|
||||
len: parseFloat(d.panjang),
|
||||
pts: d.koordinat
|
||||
};
|
||||
|
||||
state.jalan.push(jalan);
|
||||
|
||||
renderJalan(jalan);
|
||||
|
||||
updateCount('jalan', state.jalan.length);
|
||||
|
||||
addCard(
|
||||
'jalan',
|
||||
jalan.id,
|
||||
jalan.nama,
|
||||
jalan.status,
|
||||
jalan.status,
|
||||
'#e74c3c'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch(err => {});
|
||||
|
||||
}
|
||||
|
||||
function loadParsil() {
|
||||
|
||||
fetch("api/read_parsil.php")
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
|
||||
data.forEach(d => {
|
||||
|
||||
const parsil = {
|
||||
id: d.id,
|
||||
nama: d.nama,
|
||||
pemilik: d.pemilik,
|
||||
status: d.status,
|
||||
area: parseFloat(d.luas),
|
||||
pts: d.koordinat
|
||||
};
|
||||
|
||||
state.parsil.push(parsil);
|
||||
|
||||
renderParsil(parsil);
|
||||
|
||||
updateCount('parsil', state.parsil.length);
|
||||
|
||||
addCard(
|
||||
'parsil',
|
||||
parsil.id,
|
||||
parsil.nama,
|
||||
parsil.status,
|
||||
parsil.status,
|
||||
'#1a5276'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch(err => {});
|
||||
}
|
||||
|
||||
|
||||
/* ── KEMISKINAN ── */
|
||||
function getKemiskinanDraft() {
|
||||
|
||||
+7482
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user