Refactor database interactions and schema updates

- Updated column names in insert_data.php and update_data.php to match the database schema.
- Added new tables for 'jalan', 'parsil', and 'jalan_rusak' in spbu_db.sql to enhance data structure.
- Changed admin password hash in spbu_db.sql for security improvements.
This commit is contained in:
2026-06-12 11:02:31 +07:00
parent 6cc14e087e
commit 6901d07126
5 changed files with 698 additions and 726 deletions
+19 -8
View File
@@ -1,16 +1,27 @@
CREATE DATABASE db_spbu;
USE db_spbu;
CREATE DATABASE IF NOT EXISTS spbu_db;
USE spbu_db;
CREATE TABLE spbu (
CREATE TABLE IF NOT EXISTS admin (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_spbu VARCHAR(100),
no_spbu VARCHAR(50),
status ENUM('Buka 24 Jam', 'Tidak 24 Jam'),
latitude DOUBLE,
longitude DOUBLE,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO admin (username, password) VALUES
('admin', '$2y$10$A9m/u6sAxEwgIO4dlmIvNO2WJioIya4TwMvSe06hgFrDsq1xg7x16');
CREATE TABLE IF NOT EXISTS spbu (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(200) NOT NULL,
no_spbu VARCHAR(50) NOT NULL,
status ENUM('24jam', 'terbatas') NOT NULL DEFAULT '24jam',
latitude DECIMAL(10, 7) NOT NULL,
longitude DECIMAL(10, 7) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(100),
+105 -169
View File
@@ -11,6 +11,7 @@ while ($row = mysqli_fetch_assoc($result)) {
<!DOCTYPE html>
<html>
<head>
<title>WebGIS SPBU - Modern</title>
<meta charset="UTF-8">
@@ -41,7 +42,6 @@ while ($row = mysqli_fetch_assoc($result)) {
transition: all 0.3s ease;
}
/* SIDEBAR */
.sidebar {
position: absolute;
top: 0;
@@ -64,7 +64,6 @@ while ($row = mysqli_fetch_assoc($result)) {
transform: translateX(-100%);
}
/* Tombol toggle sidebar (hamburger) */
.toggle-sidebar-btn {
position: absolute;
top: 18px;
@@ -84,23 +83,28 @@ while ($row = mysqli_fetch_assoc($result)) {
transition: all 0.2s;
color: #1f2937;
}
body.sidebar-open .toggle-sidebar-btn {
display: none;
}
/* Atur posisi zoom control Leaflet agar tidak tertutup hamburger */
.leaflet-control-zoom {
transition: margin-left 0.3s ease;
margin-left: 60px;
}
body.sidebar-open .leaflet-control-zoom {
margin-left: 340px;
}
@media (max-width: 640px) {
body.sidebar-open .leaflet-control-zoom {
margin-left: 280px;
}
.sidebar { width: 280px; }
.sidebar {
width: 280px;
}
}
.sidebar-header {
@@ -110,6 +114,7 @@ while ($row = mysqli_fetch_assoc($result)) {
justify-content: space-between;
align-items: center;
}
.sidebar-header h2 {
font-size: 1.35rem;
font-weight: 600;
@@ -118,6 +123,7 @@ while ($row = mysqli_fetch_assoc($result)) {
background-clip: text;
color: transparent;
}
.close-sidebar {
background: none;
border: none;
@@ -131,6 +137,7 @@ while ($row = mysqli_fetch_assoc($result)) {
align-items: center;
justify-content: center;
}
.close-sidebar:hover {
background: #f1f5f9;
color: #0f172a;
@@ -141,6 +148,7 @@ while ($row = mysqli_fetch_assoc($result)) {
background: #ffffff;
border-bottom: 1px solid #edf2f7;
}
.search-box input {
width: 100%;
padding: 10px 16px;
@@ -150,16 +158,19 @@ while ($row = mysqli_fetch_assoc($result)) {
outline: none;
transition: 0.2s;
}
.search-box input:focus {
border-color: #6366f1;
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
}
.filter-buttons {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 12px;
}
.filter-chip {
background: #f1f5f9;
border: none;
@@ -171,6 +182,7 @@ while ($row = mysqli_fetch_assoc($result)) {
transition: 0.2s;
color: #334155;
}
.filter-chip.active {
background: #6366f1;
color: white;
@@ -181,6 +193,7 @@ while ($row = mysqli_fetch_assoc($result)) {
overflow-y: auto;
padding: 12px 16px;
}
.result-card {
background: #ffffff;
border-radius: 16px;
@@ -191,11 +204,13 @@ while ($row = mysqli_fetch_assoc($result)) {
border: 1px solid #ecf3fa;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
}
.result-card:hover {
background: #fafcff;
transform: translateX(4px);
border-color: #cbdff2;
}
.result-title {
font-weight: 600;
color: #0f172a;
@@ -203,6 +218,7 @@ while ($row = mysqli_fetch_assoc($result)) {
align-items: center;
gap: 6px;
}
.result-sub {
font-size: 0.7rem;
color: #5b6e8c;
@@ -222,8 +238,8 @@ while ($row = mysqli_fetch_assoc($result)) {
display: flex;
gap: 12px;
border: 1px solid rgba(255, 255, 255, 0.5);
transition: all 0.3s ease;
}
.mode-icon {
background: #f1f5f9;
border: none;
@@ -238,22 +254,27 @@ while ($row = mysqli_fetch_assoc($result)) {
transition: 0.2s;
color: #1e293b;
}
.mode-icon.active {
background: #6366f1;
color: white;
}
.mode-icon.edit-mode {
background: #1e293b;
color: white;
}
.mode-icon.edit-mode.active {
background: #10b981;
}
.draw-actions {
display: flex;
gap: 12px;
transition: all 0.3s ease;
}
body.view-mode .draw-actions {
display: none;
}
@@ -271,6 +292,7 @@ while ($row = mysqli_fetch_assoc($result)) {
z-index: 10;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
}
.custom-draw-toolbar button {
background: #334155;
border: none;
@@ -279,6 +301,7 @@ while ($row = mysqli_fetch_assoc($result)) {
border-radius: 40px;
cursor: pointer;
}
.custom-draw-toolbar button:hover {
background: #6366f1;
}
@@ -286,7 +309,10 @@ while ($row = mysqli_fetch_assoc($result)) {
.edit-popup {
min-width: 220px;
}
.edit-popup input, .edit-popup select, .edit-popup textarea {
.edit-popup input,
.edit-popup select,
.edit-popup textarea {
width: 100%;
padding: 8px 12px;
margin: 8px 0;
@@ -294,6 +320,7 @@ while ($row = mysqli_fetch_assoc($result)) {
border-radius: 30px;
font-size: 0.85rem;
}
.edit-popup button {
padding: 6px 14px;
border-radius: 30px;
@@ -302,10 +329,26 @@ while ($row = mysqli_fetch_assoc($result)) {
cursor: pointer;
font-weight: 500;
}
.btn-save { background: #10b981; color: white; }
.btn-cancel { background: #94a3b8; color: white; }
.btn-edit { background: #f59e0b; color: white; }
.btn-delete { background: #ef4444; color: white; }
.btn-save {
background: #10b981;
color: white;
}
.btn-cancel {
background: #94a3b8;
color: white;
}
.btn-edit {
background: #f59e0b;
color: white;
}
.btn-delete {
background: #ef4444;
color: white;
}
.toast {
position: fixed;
@@ -320,22 +363,27 @@ while ($row = mysqli_fetch_assoc($result)) {
transition: 0.2s;
pointer-events: none;
}
.toast.show { opacity: 1; }
.toast.show {
opacity: 1;
}
.drawing-cursor {
cursor: crosshair !important;
}
body.view-mode #map {
cursor: grab;
}
body.view-mode #map:active {
cursor: grabbing;
}
/* Kursor saat drag marker */
.leaflet-marker-dragging {
cursor: grabbing !important;
}
/* thumbail foto di popup */
.popup-img {
max-width: 200px;
max-height: 150px;
@@ -345,6 +393,7 @@ while ($row = mysqli_fetch_assoc($result)) {
}
</style>
</head>
<body>
<button class="toggle-sidebar-btn" id="openSidebarBtn">☰</button>
@@ -356,7 +405,8 @@ while ($row = mysqli_fetch_assoc($result)) {
</div>
<div class="search-area">
<div class="search-box">
<input type="text" id="searchInput" placeholder="Cari nama, jalan, pemilik, jalan rusak..." autocomplete="off">
<input type="text" id="searchInput" placeholder="Cari nama, jalan, pemilik, jalan rusak..."
autocomplete="off">
</div>
<div class="filter-buttons">
<button class="filter-chip active" data-filter="all">Semua</button>
@@ -404,8 +454,8 @@ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
}).addTo(map);
// ================= GLOBAL STATE =================
let globalEditMode = true; // true = edit, false = view
let activeMode = null; // null = tidak ada mode aktif, 'marker_add', 'polyline', 'polygon', 'road_damage'
let globalEditMode = true;
let activeMode = null;
let customDrawingActive = false;
let customDrawingType = null;
let customPoints = [];
@@ -415,7 +465,7 @@ let customPreviewLine = null;
let markers = {};
let polylines = {};
let polygons = {};
let roadDamageMarkers = {}; // simpan marker jalan rusak
let roadDamageMarkers = {};
let dataSpbu = <?php echo json_encode($data); ?>;
let jalanData = [];
let parsilData = [];
@@ -425,7 +475,6 @@ let dataLoaded = { jalan: false, parsil: false, roadDamage: false };
const greenIcon = L.icon({ iconUrl: 'https://maps.google.com/mapfiles/ms/icons/green-dot.png', iconSize: [32, 32] });
const yellowIcon = L.icon({ iconUrl: 'https://maps.google.com/mapfiles/ms/icons/yellow-dot.png', iconSize: [32, 32] });
const blueIcon = L.icon({ iconUrl: 'https://maps.google.com/mapfiles/ms/icons/blue-dot.png', iconSize: [32, 32] });
// Icon khusus jalan rusak (merah)
const damageIcon = L.icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png',
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
@@ -438,7 +487,6 @@ const damageIcon = L.icon({
function postForm(url, data) {
const params = new URLSearchParams();
Object.entries(data).forEach(([key, value]) => params.append(key, value));
return fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
@@ -446,7 +494,6 @@ function postForm(url, data) {
}).then(res => res.text()).then(res => res.trim());
}
// Fungsi upload file dengan FormData
function uploadForm(url, formData) {
return fetch(url, {
method: 'POST',
@@ -478,14 +525,8 @@ function updateSidebarState() {
setTimeout(() => map.invalidateSize(), 250);
}
openBtn.addEventListener('click', () => {
sidebar.classList.remove('closed');
updateSidebarState();
});
closeBtn.addEventListener('click', () => {
sidebar.classList.add('closed');
updateSidebarState();
});
openBtn.addEventListener('click', () => { sidebar.classList.remove('closed'); updateSidebarState(); });
closeBtn.addEventListener('click', () => { sidebar.classList.add('closed'); updateSidebarState(); });
updateSidebarState();
// ================= EDIT / VIEW MODE =================
@@ -495,7 +536,6 @@ function setGlobalMode(modeType) {
document.body.classList.remove('view-mode');
document.getElementById('btn-edit-mode').classList.add('active');
document.getElementById('btn-view-mode').classList.remove('active');
// Aktifkan drag marker untuk SPBU dan Jalan Rusak
for (let id in markers) if (markers[id].dragging) markers[id].dragging.enable();
for (let id in roadDamageMarkers) if (roadDamageMarkers[id].dragging) roadDamageMarkers[id].dragging.enable();
toast("Mode Edit aktif");
@@ -503,9 +543,7 @@ function setGlobalMode(modeType) {
document.body.classList.add('view-mode');
document.getElementById('btn-view-mode').classList.add('active');
document.getElementById('btn-edit-mode').classList.remove('active');
// Batalkan drawing jika sedang aktif
if (customDrawingActive) cancelCustomDrawing();
// Nonaktifkan mode marker_add dan road_damage
if (activeMode === 'marker_add' || activeMode === 'road_damage') setActiveMode(null);
for (let id in markers) if (markers[id].dragging) markers[id].dragging.disable();
for (let id in roadDamageMarkers) if (roadDamageMarkers[id].dragging) roadDamageMarkers[id].dragging.disable();
@@ -518,19 +556,13 @@ function setGlobalMode(modeType) {
document.getElementById('btn-edit-mode').addEventListener('click', () => setGlobalMode('edit'));
document.getElementById('btn-view-mode').addEventListener('click', () => setGlobalMode('view'));
// ================= FUNGSI MENGATUR MODE AKTIF (SPBU, Jalan, Tanah, Jalan Rusak) =================
function setActiveMode(mode) {
// Jika mode yang sama dan sedang aktif, nonaktifkan
if (activeMode === mode && mode !== null) {
mode = null;
}
if (activeMode === mode && mode !== null) { mode = null; }
activeMode = mode;
// Update tampilan tombol
document.querySelectorAll('.mode-icon[data-mode]').forEach(btn => btn.classList.remove('active'));
if (activeMode === 'marker_add') {
document.getElementById('btn-marker').classList.add('active');
map.getContainer().style.cursor = 'crosshair';
// Jika sedang drawing, batalkan
if (customDrawingActive) cancelCustomDrawing();
} else if (activeMode === 'polyline') {
document.getElementById('btn-polyline').classList.add('active');
@@ -543,52 +575,26 @@ function setActiveMode(mode) {
map.getContainer().style.cursor = 'crosshair';
if (customDrawingActive) cancelCustomDrawing();
} else {
// Tidak ada mode aktif
map.getContainer().style.cursor = '';
if (customDrawingActive) cancelCustomDrawing();
}
}
// Tombol SPBU: toggle mode marker_add
document.getElementById('btn-marker').addEventListener('click', () => {
if (!globalEditMode) return;
if (activeMode === 'marker_add') {
setActiveMode(null);
} else {
setActiveMode('marker_add');
}
if (activeMode === 'marker_add') { setActiveMode(null); } else { setActiveMode('marker_add'); }
});
// Tombol Jalan: jika sedang drawing polyline, batalkan; jika tidak, mulai drawing polyline
document.getElementById('btn-polyline').addEventListener('click', () => {
if (!globalEditMode) return;
if (customDrawingActive && customDrawingType === 'polyline') {
cancelCustomDrawing();
setActiveMode(null);
} else {
setActiveMode('polyline');
}
if (customDrawingActive && customDrawingType === 'polyline') { cancelCustomDrawing(); setActiveMode(null); } else { setActiveMode('polyline'); }
});
// Tombol Tanah: jika sedang drawing polygon, batalkan; jika tidak, mulai drawing polygon
document.getElementById('btn-polygon').addEventListener('click', () => {
if (!globalEditMode) return;
if (customDrawingActive && customDrawingType === 'polygon') {
cancelCustomDrawing();
setActiveMode(null);
} else {
setActiveMode('polygon');
}
if (customDrawingActive && customDrawingType === 'polygon') { cancelCustomDrawing(); setActiveMode(null); } else { setActiveMode('polygon'); }
});
// Tombol Jalan Rusak: toggle mode road_damage
document.getElementById('btn-road-damage').addEventListener('click', () => {
if (!globalEditMode) return;
if (activeMode === 'road_damage') {
setActiveMode(null);
} else {
setActiveMode('road_damage');
}
if (activeMode === 'road_damage') { setActiveMode(null); } else { setActiveMode('road_damage'); }
});
// ================= CUSTOM DRAWING =================
@@ -686,84 +692,34 @@ function finishCustomDrawing() {
}
}
// Fungsi untuk menyimpan jalan dari custom drawing dengan validasi lengkap
window.simpanJalanCustom = function () {
const namaInput = document.getElementById('nama_jalan');
const statusSelect = document.getElementById('status_jalan');
if (!namaInput || !statusSelect) {
toast("Error: Form tidak ditemukan, coba ulangi drawing.");
return;
}
if (!namaInput || !statusSelect) { toast("Error: Form tidak ditemukan"); return; }
const nama = namaInput.value.trim();
const status = statusSelect.value;
if (nama === "") {
alert("❌ Nama jalan harus diisi!");
return;
}
if (status === "") {
alert("❌ Silakan pilih status jalan!");
return;
}
if (nama === "") { alert("❌ Nama jalan harus diisi!"); return; }
if (status === "") { alert("❌ Silakan pilih status jalan!"); return; }
const geo = JSON.stringify(customPoints.map(p => [p.lat, p.lng]));
const panjang = hitungPanjang(customPoints);
postForm('insert_jalan.php', {
nama,
status,
panjang,
geojson: geo
}).then(res => {
if (res === "success") {
toast("Jalan tersimpan");
location.reload();
} else {
alert("Gagal menyimpan: " + res);
}
}).catch(err => alert("Error: " + err));
postForm('insert_jalan.php', { nama, status, panjang, geojson: geo })
.then(res => { if (res === "success") { toast("Jalan tersimpan"); location.reload(); } else { alert("Gagal menyimpan: " + res); } })
.catch(err => alert("Error: " + err));
};
// Fungsi untuk menyimpan persil dari custom drawing dengan validasi lengkap
window.simpanParsilCustom = function () {
const pemilikInput = document.getElementById('pemilik');
const statusSelect = document.getElementById('status_tanah');
if (!pemilikInput || !statusSelect) {
toast("Error: Form tidak ditemukan, coba ulangi drawing.");
return;
}
if (!pemilikInput || !statusSelect) { toast("Error: Form tidak ditemukan"); return; }
const pemilik = pemilikInput.value.trim();
const status = statusSelect.value;
if (pemilik === "") {
alert("❌ Nama pemilik harus diisi!");
return;
}
if (status === "") {
alert("❌ Silakan pilih status tanah!");
return;
}
if (pemilik === "") { alert("❌ Nama pemilik harus diisi!"); return; }
if (status === "") { alert("❌ Silakan pilih status tanah!"); return; }
const geo = JSON.stringify([customPoints.map(p => [p.lat, p.lng])]);
const luas = hitungLuas([customPoints]);
postForm('insert_parsil.php', {
pemilik,
status,
luas,
geojson: geo
}).then(res => {
if (res === "success") {
toast("Persil tersimpan");
location.reload();
} else {
alert("Gagal menyimpan: " + res);
}
}).catch(err => alert("Error: " + err));
postForm('insert_parsil.php', { pemilik, status, luas, geojson: geo })
.then(res => { if (res === "success") { toast("Persil tersimpan"); location.reload(); } else { alert("Gagal menyimpan: " + res); } })
.catch(err => alert("Error: " + err));
};
function cancelCustomDrawing() {
@@ -776,10 +732,7 @@ function cancelCustomDrawing() {
customDrawingActive = false;
customPoints = [];
document.getElementById('customDrawToolbar').style.display = 'none';
// Jangan reset activeMode, biar tombol tetap menunjukkan status
if (activeMode === 'polyline' || activeMode === 'polygon') {
setActiveMode(null);
}
if (activeMode === 'polyline' || activeMode === 'polygon') { setActiveMode(null); }
toast("Drawing dibatalkan");
}
window.batalCustomDrawing = cancelCustomDrawing;
@@ -793,18 +746,13 @@ function hitungLuas(latlngs) {
return L.GeometryUtil.geodesicArea(latlngs[0]);
}
// ================= LOAD DATA JALAN & PARSIL & JALAN RUSAK =================
// ================= LOAD DATA =================
function loadJalan() {
fetch('get_jalan.php').then(res => res.json()).then(data => {
jalanData = data;
data.forEach(j => {
let coords = JSON.parse(j.geojson);
let colorMap = {
"Nasional": "#ef4444", // merah
"Provinsi": "#f97316", // oranye
"Kabupaten": "#3b82f6", // biru
"Kota": "#10b981" // hijau
};
let colorMap = { "Nasional": "#ef4444", "Provinsi": "#f97316", "Kabupaten": "#3b82f6", "Kota": "#10b981" };
let color = colorMap[j.status] || "#6b7280";
let polyline = L.polyline(coords, { color: color, weight: 4, opacity: 0.8 }).addTo(map);
polyline.on('click', () => polyline.bindPopup(getPopupJalan(j)).openPopup());
@@ -841,7 +789,6 @@ function loadRoadDamage() {
m.on('dragend', function () {
if (!globalEditMode) return;
let pos = m.getLatLng();
// Update posisi via AJAX
postForm('update_jalan_rusak.php', { id: rd.id, lat: pos.lat, lng: pos.lng, deskripsi: rd.deskripsi, foto_lama: rd.foto })
.then(res => { if (res !== "success") alert("Gagal update posisi: " + res); else toast("Posisi jalan rusak diperbarui"); })
.catch(err => alert("Error: " + err));
@@ -858,24 +805,18 @@ function loadRoadDamage() {
// Load marker SPBU
dataSpbu.forEach(d => {
let icon = d.status === "Buka 24 Jam" ? greenIcon : yellowIcon;
let icon = d.status === '24jam' ? greenIcon : yellowIcon;
let m = L.marker([d.latitude, d.longitude], { icon: icon, draggable: globalEditMode }).addTo(map);
markers[d.id] = m;
m.bindPopup(getPopupMarker(d));
m.on('dragstart', () => {
map.getContainer().style.cursor = 'grabbing';
});
m.on('dragstart', () => { map.getContainer().style.cursor = 'grabbing'; });
m.on('dragend', () => {
map.getContainer().style.cursor = '';
if (!globalEditMode) return;
let pos = m.getLatLng();
postForm('update.php', {
id: d.id,
lat: pos.lat,
lng: pos.lng
}).then(res => {
if (res !== "OK") alert("Gagal memperbarui posisi SPBU: " + res);
}).catch(err => alert("Error: " + err));
postForm('update.php', { id: d.id, lat: pos.lat, lng: pos.lng })
.then(res => { if (res !== "OK") alert("Gagal memperbarui posisi SPBU: " + res); })
.catch(err => alert("Error: " + err));
d.latitude = pos.lat; d.longitude = pos.lng;
toast("Posisi SPBU diperbarui");
});
@@ -889,12 +830,12 @@ loadRoadDamage();
function getPopupMarker(d) {
if (globalEditMode) {
return `<div class="edit-popup">
<b>📍 ${d.nama_spbu}</b><br>${d.no_spbu}<br>${d.status}<br>
<b>📍 ${d.nama}</b><br>${d.no_spbu}<br>${d.status === '24jam' ? '24 Jam' : 'Terbatas'}<br>
<button class="btn-edit" onclick="editMarker(${d.id})">Edit</button>
<button class="btn-delete" onclick="deleteMarker(${d.id})">Hapus</button>
</div>`;
} else {
return `<div><b>${d.nama_spbu}</b><br>${d.no_spbu}<br>${d.status}</div>`;
return `<div><b>${d.nama}</b><br>${d.no_spbu}<br>${d.status === '24jam' ? '24 Jam' : 'Terbatas'}</div>`;
}
}
function getPopupJalan(j) {
@@ -950,8 +891,8 @@ function filterSidebar() {
if (activeFilter === 'all' || activeFilter === 'marker') {
dataSpbu.forEach(d => {
if (d.nama_spbu.toLowerCase().includes(searchText))
results.push({ type: 'marker', id: d.id, name: d.nama_spbu, desc: d.status, latlng: [d.latitude, d.longitude] });
if (d.nama.toLowerCase().includes(searchText))
results.push({ type: 'marker', id: d.id, name: d.nama, desc: d.status === '24jam' ? '24 Jam' : 'Terbatas', latlng: [d.latitude, d.longitude] });
});
}
if (activeFilter === 'all' || activeFilter === 'polyline') {
@@ -1001,12 +942,12 @@ document.querySelectorAll('.filter-chip').forEach(chip => {
});
document.getElementById('searchInput').addEventListener('input', filterSidebar);
// ================= CRUD FUNCTIONS (SPBU, Jalan, Tanah) =================
// ================= CRUD FUNCTIONS =================
window.editMarker = function (id) {
let d = dataSpbu.find(x => x.id == id);
let form = `<div class="edit-popup">
<input id="nama" value="${d.nama_spbu}"><input id="no" value="${d.no_spbu}">
<select id="status"><option ${d.status=="Buka 24 Jam"?"selected":""}>Buka 24 Jam</option><option ${d.status=="Tidak 24 Jam"?"selected":""}>Tidak 24 Jam</option></select>
<input id="nama" value="${d.nama}"><input id="no" value="${d.no_spbu}">
<select id="status"><option ${d.status == "24jam" ? "selected" : ""} value="24jam">24 Jam</option><option ${d.status == "terbatas" ? "selected" : ""} value="terbatas">Terbatas</option></select>
<button class="btn-save" onclick="saveEditMarker(${id})">Simpan</button>
<button class="btn-cancel" onclick="refreshAllPopups()">Batal</button>
</div>`;
@@ -1065,13 +1006,9 @@ window.deleteParsil = function(id){
.catch(err => alert("Error: " + err));
};
// ================= CRUD JALAN RUSAK =================
// Variabel untuk marker sementara saat mode road_damage
// ================= JALAN RUSAK =================
let tempRoadMarker = null;
// Hapus event click lama dan ganti dengan yang baru (mencakup road_damage)
map.off('click');
let tempMarker = null;
map.on('click', function (e) {
@@ -1082,7 +1019,7 @@ map.on('click', function(e) {
tempMarker = L.marker(e.latlng, { icon: blueIcon }).addTo(map);
let form = `<div class="edit-popup">
<input id="nama_baru" placeholder="Nama SPBU" autocomplete="off"><input id="no_baru" placeholder="No SPBU" autocomplete="off">
<select id="status_baru"><option>Buka 24 Jam</option><option>Tidak 24 Jam</option></select>
<select id="status_baru"><option value="24jam">24 Jam</option><option value="terbatas">Terbatas</option></select>
<button class="btn-save" onclick="simpanMarkerBaru(${e.latlng.lat}, ${e.latlng.lng})">Simpan</button>
<button class="btn-cancel" onclick="batalMarkerBaru()">Batal</button>
</div>`;
@@ -1129,7 +1066,6 @@ window.simpanRoadDamageBaru = function(lat, lng) {
.catch(err => alert("Error: " + err));
};
// Edit & Delete jalan rusak
window.saveEditRoadDamage = function (id) {
let rd = roadDamageData.find(r => r.id == id);
let deskripsiBaru = document.getElementById('deskripsi_edit').value.trim();
@@ -1157,9 +1093,9 @@ window.deleteRoadDamage = function(id) {
document.getElementById('undoPointBtn').addEventListener('click', undoLastPoint);
document.getElementById('finishDrawBtn').addEventListener('click', finishCustomDrawing);
document.getElementById('cancelDrawBtn').addEventListener('click', cancelCustomDrawing);
// Tidak ada mode aktif saat awal
setActiveMode(null);
setGlobalMode('edit'); // default mode edit
setGlobalMode('edit');
</script>
</body>
</html>
+1 -3
View File
@@ -7,14 +7,12 @@ $status = $_POST['status'] ?? '';
$lat = $_POST['lat'] ?? '';
$lng = $_POST['lng'] ?? '';
// VALIDASI
if($nama == "" || $no == "" || $status == "" || $lat == "" || $lng == ""){
echo "DATA TIDAK LENGKAP";
exit;
}
// PREPARED STATEMENT
$stmt = $conn->prepare("INSERT INTO spbu (nama_spbu, no_spbu, status, latitude, longitude) VALUES (?, ?, ?, ?, ?)");
$stmt = $conn->prepare("INSERT INTO spbu (nama, no_spbu, status, latitude, longitude) VALUES (?, ?, ?, ?, ?)");
$stmt->bind_param("sssdd", $nama, $no, $status, $lat, $lng);
if($stmt->execute()){
+1 -1
View File
@@ -11,7 +11,7 @@ if($id == "" || $nama == "" || $no == "" || $status == ""){
exit;
}
$stmt = $conn->prepare("UPDATE spbu SET nama_spbu=?, no_spbu=?, status=? WHERE id=?");
$stmt = $conn->prepare("UPDATE spbu SET nama=?, no_spbu=?, status=? WHERE id=?");
$stmt->bind_param("sssi", $nama, $no, $status, $id);
if($stmt->execute()){
+28 -1
View File
@@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS admin (
);
INSERT INTO admin (username, password) VALUES
('admin', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi');
('admin', '$2y$10$A9m/u6sAxEwgIO4dlmIvNO2WJioIya4TwMvSe06hgFrDsq1xg7x16');
CREATE TABLE IF NOT EXISTS spbu (
id INT AUTO_INCREMENT PRIMARY KEY,
@@ -21,3 +21,30 @@ CREATE TABLE IF NOT EXISTS spbu (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(100),
status ENUM('Nasional','Provinsi','Kabupaten'),
panjang DOUBLE,
geojson TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE parsil (
id INT AUTO_INCREMENT PRIMARY KEY,
pemilik VARCHAR(100),
status ENUM('SHM','HGB','HGU','HP'),
luas DOUBLE,
geojson TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS `jalan_rusak` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`deskripsi` TEXT NOT NULL,
`foto` VARCHAR(255) NOT NULL,
`latitude` DOUBLE NOT NULL,
`longitude` DOUBLE NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;