Initial commit: Setup Landing Page dan file pertemuan

This commit is contained in:
Romeo3
2026-06-09 13:50:00 +07:00
commit c94bc418ef
35 changed files with 8807 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
<?php
include 'koneksi.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$tabel = isset($_POST['tabel']) ? trim($_POST['tabel']) : '';
if ($id <= 0) {
http_response_code(400);
echo "ID tidak valid!";
exit;
}
$allowed_tables = ['spbu_locations'];
if (in_array($tabel, $allowed_tables)) {
$stmt = $conn->prepare("DELETE FROM $tabel WHERE id = ?");
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo "Data berhasil dihapus!";
} else {
http_response_code(500);
echo "Gagal menghapus: " . $conn->error;
}
$stmt->close();
} else {
http_response_code(400);
echo "Tabel tidak valid!";
}
$conn->close();
} else {
http_response_code(405);
echo "Metode tidak diizinkan";
}
?>
+225
View File
@@ -0,0 +1,225 @@
<?php
// Start session for standard PHP structure (if needed in future)
session_start();
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGIS Pertemuan 2 — Pemetaan Stasiun SPBU</title>
<!-- Leaflet & Leaflet.draw CDN -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" />
<!-- Premium Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- Custom CSS Styles -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- ==============================
HEADER BAR
============================== -->
<div class="webgis-header">
<div class="header-brand">
<div class="brand-icon">
<!-- Map icon SVG -->
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
</svg>
</div>
<div>
<div class="brand-name">WebGIS SPBU</div>
<div class="brand-subtitle">Pertemuan 2</div>
</div>
</div>
<div class="header-divider"></div>
<!-- SEARCH BAR -->
<div class="search-wrapper">
<div class="search-bar">
<!-- Category Dropdown -->
<div class="search-category-wrap" id="custom-select-wrap">
<span class="search-category-icon">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 10h16M4 14h8" />
</svg>
</span>
<div class="custom-select-trigger" id="custom-select-trigger">Semua Layer</div>
<input type="hidden" id="search-category" value="Semua">
<span class="category-arrow">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</span>
<div class="custom-select-options" id="custom-select-options">
<div class="custom-option selected" data-value="Semua">Semua Layer</div>
<div class="custom-option" data-value="SPBU">Stasiun SPBU</div>
</div>
</div>
<!-- Input Pencarian -->
<div class="search-input-wrap">
<span class="search-icon">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</span>
<input type="text" id="search-input" placeholder="Cari nama stasiun SPBU..."
onkeyup="jalankanPencarian()" oninput="toggleClearBtn()" autocomplete="off">
<button class="search-clear-btn" id="search-clear" onclick="clearSearch()" title="Hapus pencarian">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<!-- Dropdown Hasil Pencarian -->
<div class="search-results" id="search-results"></div>
</div>
<!-- HEADER RIGHT TOOLS -->
<div class="header-tools">
<div class="tool-badge">Peta Aktif</div>
<div class="tool-btn" title="Status Database">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
</svg>
<div class="status-dot"></div>
</div>
</div>
</div>
<!-- ==============================
SIDEBAR INPUT DATA
============================== -->
<!-- Toggle Button -->
<button class="sidebar-toggle" id="sidebar-toggle" title="Panel Input Data">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
</svg>
<span>Input Titik</span>
</button>
<!-- Sidebar Panel -->
<div class="input-sidebar" id="input-sidebar">
<div class="sidebar-header">
<div class="sidebar-title">
<div class="sidebar-title-icon">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</div>
<div>
<div class="sidebar-title-text">Panel Input Data</div>
<div class="sidebar-title-sub">Tambah penanda SPBU</div>
</div>
</div>
<button class="sidebar-close" id="sidebar-close" title="Tutup">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<!-- Tab Navigation -->
<div class="sidebar-tabs">
<div class="stab active">
<span class="stab-icon">⛽</span>
<span>SPBU (Marker)</span>
</div>
</div>
<!-- Scrollable Content -->
<div class="sidebar-body">
<!-- ===== TAB: SPBU ===== -->
<div class="stab-content active">
<div class="step-guide">
<div class="step-badge">Langkah 1</div>
<p>Klik tombol <strong>Tandai Lokasi SPBU</strong> di bawah, lalu klik di peta pada posisi SPBU yang diinginkan.</p>
</div>
<button class="btn-pick-location" id="btn-pick-spbu" onclick="activatePickMode()">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round"
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
Tandai Lokasi SPBU
</button>
<div class="coords-display" id="coords-spbu">
<span class="coords-label">Koordinat:</span>
<span class="coords-value" id="coords-spbu-val">Belum dipilih</span>
</div>
<div class="step-guide">
<div class="step-badge">Langkah 2</div>
<p>Lengkapi atribut data SPBU di bawah ini.</p>
</div>
<div class="sfield">
<label class="sfield-label">Nama SPBU <span class="required">*</span></label>
<input type="text" id="sb_nama_spbu" class="sinput" placeholder="Contoh: SPBU Ahmad Yani">
</div>
<div class="sfield">
<label class="sfield-label">Nomor Telepon</label>
<input type="text" id="sb_nohp_spbu" class="sinput" placeholder="Contoh: 0561-xxxxxx">
</div>
<div class="sfield">
<label class="sfield-label">Status Operasional</label>
<select id="sb_kategori_spbu" class="sselect">
<option value="Ya">Buka 24 Jam</option>
<option value="Tidak">Reguler (Jam Kerja)</option>
</select>
</div>
<button class="btn-save-sidebar" onclick="saveSPBUSidebar()">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
Simpan Data SPBU
</button>
</div>
</div><!-- end sidebar-body -->
</div><!-- end input-sidebar -->
<!-- Banner Info Mode Memilih Lokasi -->
<div class="pick-mode-overlay" id="pick-overlay">
<div class="pick-mode-banner">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5" />
</svg>
<span id="pick-overlay-text">Klik lokasi di peta...</span>
<button onclick="deactivatePickMode()">Batal</button>
</div>
</div>
<!-- Container Peta -->
<div id="map" style="padding-top: 60px; height: 100vh; box-sizing: border-box;"></div>
<!-- Scripts Leaflet, Leaflet.draw, Turf, dan script.js -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<script src="script.js"></script>
</body>
</html>
+33
View File
@@ -0,0 +1,33 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "webgis_db_pertemuan2";
// Connect first without DB to ensure we can create it if missing
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die("Koneksi gagal: " . $conn->connect_error);
}
// Create database if not exists
$conn->query("CREATE DATABASE IF NOT EXISTS `$db` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;");
// Select database
$conn->select_db($db);
// Auto create table spbu_locations if not exists
$sql_spbu = "CREATE TABLE IF NOT EXISTS `spbu_locations` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`nama_spbu` VARCHAR(255) NOT NULL,
`no_hp` VARCHAR(50) DEFAULT NULL,
`kategori` VARCHAR(50) NOT NULL,
`latitude` DOUBLE NOT NULL,
`longitude` DOUBLE NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
if (!$conn->query($sql_spbu)) {
die("Gagal membuat tabel spbu_locations: " . $conn->error);
}
?>
+30
View File
@@ -0,0 +1,30 @@
<?php
include 'koneksi.php';
$jenis = isset($_GET['jenis']) ? $_GET['jenis'] : 'spbu';
if ($jenis == 'spbu') {
$sql = "SELECT * FROM spbu_locations";
} else {
die(json_encode(["error" => "Jenis data tidak ditemukan"]));
}
$result = $conn->query($sql);
$data = array();
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
if (isset($row['latitude'])) {
$row['latitude'] = floatval($row['latitude']);
}
if (isset($row['longitude'])) {
$row['longitude'] = floatval($row['longitude']);
}
$data[] = $row;
}
}
header('Content-Type: application/json');
echo json_encode($data);
$conn->close();
?>
+33
View File
@@ -0,0 +1,33 @@
<?php
include 'koneksi.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$nama = isset($_POST['nama_spbu']) ? trim($_POST['nama_spbu']) : '';
$hp = isset($_POST['no_hp']) ? trim($_POST['no_hp']) : '';
$kategori = isset($_POST['kategori']) ? trim($_POST['kategori']) : '';
$lat = isset($_POST['latitude']) ? floatval($_POST['latitude']) : 0.0;
$lng = isset($_POST['longitude']) ? floatval($_POST['longitude']) : 0.0;
if (empty($nama) || $lat == 0.0 || $lng == 0.0) {
http_response_code(400);
echo "Nama SPBU dan koordinat lokasi wajib diisi!";
exit;
}
$stmt = $conn->prepare("INSERT INTO spbu_locations (nama_spbu, no_hp, kategori, latitude, longitude) VALUES (?, ?, ?, ?, ?)");
$stmt->bind_param("sssdd", $nama, $hp, $kategori, $lat, $lng);
if ($stmt->execute()) {
echo "Data SPBU berhasil disimpan!";
} else {
http_response_code(500);
echo "Gagal menyimpan data: " . $conn->error;
}
$stmt->close();
$conn->close();
} else {
http_response_code(405);
echo "Metode tidak diizinkan";
}
?>
+438
View File
@@ -0,0 +1,438 @@
// ==========================================
// 1. INISIALISASI PETA & LAYER
// ==========================================
var map = L.map('map', { zoomControl: false }).setView([-0.0227, 109.3425], 14);
// Zoom control di kanan bawah
L.control.zoom({ position: 'bottomright' }).addTo(map);
// OpenStreetMap Tile Layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Layer Groups
var spbu24JamLayer = L.layerGroup().addTo(map);
var spbuRegulerLayer = L.layerGroup().addTo(map);
var drawnItems = new L.FeatureGroup().addTo(map);
// Layer Control (Checkbox di kanan atas)
var overlayMaps = {
"⛽ SPBU Buka 24 Jam": spbu24JamLayer,
"⛽ SPBU Reguler": spbuRegulerLayer
};
L.control.layers(null, overlayMaps, { collapsed: true, position: 'bottomleft' }).addTo(map);
// Standard Leaflet Marker Icons
var greenIcon = 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]
});
var redIcon = 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]
});
// Global Variables
var databasePencarian = [];
var spbuMarkers = {};
var sidebarPickMode = false;
var sidebarTempLat = 0.0;
var sidebarTempLng = 0.0;
// ==========================================
// 2. FUNGSI LOAD DATA DARI DATABASE
// ==========================================
function loadSPBU() {
spbu24JamLayer.clearLayers();
spbuRegulerLayer.clearLayers();
spbuMarkers = {};
databasePencarian = [];
fetch('load.php?jenis=spbu')
.then(res => res.json())
.then(data => {
data.forEach(item => {
var is24Jam = item.kategori === 'Ya';
var statusBuka = is24Jam ? 'Buka 24 Jam' : 'Reguler';
var icon = is24Jam ? greenIcon : redIcon;
var statusColor = is24Jam ? '#10b981' : '#ef4444';
var viewHTML = `
<div class="popup-container" id="popup-spbu-${item.id}">
<div class="popup-header">
<h4>${item.nama_spbu}</h4>
<span class="popup-type-badge">⛽ Stasiun SPBU</span>
</div>
<div class="popup-body">
<div class="info-row">
<span class="info-label">Telepon</span>
<span class="info-value">${item.no_hp || '—'}</span>
</div>
<div class="info-row">
<span class="info-label">Status Operasional</span>
<span class="info-value" style="color:${statusColor}; font-weight:600;">● ${statusBuka}</span>
</div>
<div class="btn-group">
<button class="btn btn-edit" onclick="formEditSPBU('${item.id}', '${item.nama_spbu}', '${item.no_hp}', '${item.kategori}')">✏️ Edit</button>
<button class="btn btn-delete" onclick="deleteData('spbu_locations', '${item.id}')">🗑️ Hapus</button>
</div>
</div>
</div>`;
var marker = L.marker([item.latitude, item.longitude], { icon: icon, draggable: false });
if (is24Jam) {
marker.addTo(spbu24JamLayer);
} else {
marker.addTo(spbuRegulerLayer);
}
marker.bindPopup(viewHTML);
spbuMarkers[String(item.id)] = marker;
marker.on('click', function () {
map.flyTo(marker.getLatLng(), 16, { animate: true });
});
// Update coordinates input on marker drag end (during edit)
marker.on('dragend', function (e) {
var position = marker.getLatLng();
if (document.getElementById('edit_lat')) {
document.getElementById('edit_lat').value = position.lat.toFixed(6);
document.getElementById('edit_lng').value = position.lng.toFixed(6);
}
marker.openPopup();
});
databasePencarian.push({
namaLower: item.nama_spbu.toLowerCase(),
namaAsli: item.nama_spbu,
kategori: 'SPBU',
ikon: '⛽',
tipe: 'titik',
layer: marker
});
});
})
.catch(e => console.log('Belum ada data SPBU', e));
}
// Load data awal
loadSPBU();
// ==========================================
// 3. EDIT & UPDATE DATA
// ==========================================
function formEditSPBU(id, nama, hp, kategori) {
var markerId = String(id);
var currentMarker = spbuMarkers[markerId];
if (currentMarker) {
currentMarker.dragging.enable();
}
setTimeout(function () {
var container = document.getElementById(`popup-spbu-${id}`);
if (!container) return;
var lat = currentMarker.getLatLng().lat.toFixed(6);
var lng = currentMarker.getLatLng().lng.toFixed(6);
container.innerHTML = `
<div class="popup-header" style="border-radius: 0;">
<h4 style="margin:0;">Edit Lokasi SPBU</h4>
<span class="popup-type-badge">📍 Geser marker untuk mengubah posisi</span>
</div>
<div class="popup-body">
<form onsubmit="updateData(event, 'spbu_locations', '${id}')">
<div class="sfield" style="margin-bottom:8px;">
<span class="info-label">Nama SPBU</span>
<input type="text" id="edit_nama" value="${nama}" required style="margin-bottom:0;">
</div>
<div class="sfield" style="margin-bottom:8px;">
<span class="info-label">Telepon</span>
<input type="text" id="edit_hp" value="${hp}" style="margin-bottom:0;">
</div>
<div class="sfield" style="margin-bottom:12px;">
<span class="info-label">Status Operasional</span>
<select id="edit_kategori" style="margin-bottom:0;">
<option value="Ya" ${kategori === 'Ya' ? 'selected' : ''}>Buka 24 Jam</option>
<option value="Tidak" ${kategori === 'Tidak' ? 'selected' : ''}>Reguler</option>
</select>
</div>
<input type="hidden" id="edit_lat" value="${lat}">
<input type="hidden" id="edit_lng" value="${lng}">
<div class="btn-group">
<button type="submit" class="btn btn-save">💾 Simpan</button>
<button type="button" class="btn btn-delete" onclick="loadSPBU();">Batal</button>
</div>
</form>
</div>`;
}, 50);
}
function updateData(e, tabel, id) {
e.preventDefault();
var formData = new FormData();
formData.append('tabel', tabel);
formData.append('id', id);
formData.append('nama_spbu', document.getElementById('edit_nama').value);
formData.append('no_hp', document.getElementById('edit_hp').value);
formData.append('kategori', document.getElementById('edit_kategori').value);
// Get current dragged position
var markerPosisi = spbuMarkers[String(id)].getLatLng();
formData.append('latitude', markerPosisi.lat);
formData.append('longitude', markerPosisi.lng);
fetch('update_data.php', { method: 'POST', body: formData })
.then(r => r.text())
.then(res => {
alert(res);
map.closePopup();
loadSPBU();
})
.catch(error => console.error("Error updating data:", error));
}
// ==========================================
// 4. HAPUS DATA
// ==========================================
function deleteData(tabel, id) {
if (confirm('Apakah Anda yakin ingin menghapus data SPBU ini?')) {
var formData = new FormData();
formData.append('id', id);
formData.append('tabel', tabel);
fetch('delete_data.php', { method: 'POST', body: formData })
.then(r => r.text())
.then(res => {
alert(res);
map.closePopup();
loadSPBU();
})
.catch(error => console.error("Error deleting data:", error));
}
}
// ==========================================
// 5. SISTEM PENCARIAN & ZOOM
// ==========================================
function jalankanPencarian() {
var kataKunci = document.getElementById('search-input').value.toLowerCase();
var kategori = document.getElementById('search-category').value;
var wadahHasil = document.getElementById('search-results');
wadahHasil.innerHTML = '';
if (kataKunci.length < 2) {
wadahHasil.style.display = 'none';
return;
}
var hasil = databasePencarian.filter(function (item) {
var cocokNama = item.namaLower.includes(kataKunci);
var cocokKategori = (kategori === 'Semua') || (item.kategori === kategori);
return cocokNama && cocokKategori;
});
if (hasil.length > 0) {
wadahHasil.style.display = 'block';
wadahHasil.innerHTML = `<div class="results-header">${hasil.length} hasil ditemukan</div>`;
hasil.forEach(function (item) {
var div = document.createElement('div');
div.className = 'result-item';
div.innerHTML = `
<div class="result-item-icon" style="background: rgba(16,185,129,0.1);">
${item.ikon}
</div>
<div class="result-item-text">
<div class="result-item-name">${item.namaAsli}</div>
<div class="result-item-sub">Klik untuk zoom ke lokasi</div>
</div>
<span class="badge-kategori badge-SPBU">${item.kategori}</span>`;
div.onclick = function () {
map.flyTo(item.layer.getLatLng(), 16, { animate: true, duration: 1.5 });
item.layer.openPopup();
wadahHasil.style.display = 'none';
document.getElementById('search-input').value = item.namaAsli;
toggleClearBtn();
};
wadahHasil.appendChild(div);
});
} else {
wadahHasil.style.display = 'block';
wadahHasil.innerHTML = `
<div class="result-empty">
<div class="result-item" style="color:#ef4444; justify-content:center;">Data tidak ditemukan</div>
</div>`;
}
}
function toggleClearBtn() {
var input = document.getElementById('search-input');
var clearBtn = document.getElementById('search-clear');
clearBtn.style.display = input.value.length > 0 ? 'flex' : 'none';
}
function clearSearch() {
document.getElementById('search-input').value = '';
document.getElementById('search-results').style.display = 'none';
document.getElementById('search-clear').style.display = 'none';
}
// Tutup hasil saat klik di luar
document.addEventListener('click', function (e) {
var wrapper = document.querySelector('.search-wrapper');
if (wrapper && !wrapper.contains(e.target)) {
document.getElementById('search-results').style.display = 'none';
}
});
// Shortcut Ctrl + K untuk fokus ke pencarian
document.addEventListener('keydown', function (e) {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
document.getElementById('search-input').focus();
}
if (e.key === 'Escape') {
clearSearch();
document.getElementById('search-input').blur();
}
});
// ==========================================
// 6. LOGIKA INPUT SIDEBAR & PROGRAMMATIC PICK
// ==========================================
// Buka/Tutup Sidebar
document.getElementById('sidebar-toggle').addEventListener('click', function () {
var sidebar = document.getElementById('input-sidebar');
sidebar.classList.toggle('open');
this.classList.toggle('open');
});
document.getElementById('sidebar-close').addEventListener('click', function () {
document.getElementById('input-sidebar').classList.remove('open');
document.getElementById('sidebar-toggle').classList.remove('open');
});
// Aktifkan mode pilih titik di peta
function activatePickMode() {
sidebarPickMode = true;
document.getElementById('pick-overlay').classList.add('active');
document.getElementById('btn-pick-spbu').classList.add('active-pick');
map.getContainer().style.cursor = 'crosshair';
}
// Batalkan mode pick
function deactivatePickMode() {
sidebarPickMode = false;
document.getElementById('pick-overlay').classList.remove('active');
document.getElementById('btn-pick-spbu').classList.remove('active-pick');
map.getContainer().style.cursor = '';
}
// Tangkap klik peta untuk mendapatkan koordinat
map.on('click', function (e) {
if (!sidebarPickMode) return;
var lat = e.latlng.lat;
var lng = e.latlng.lng;
sidebarTempLat = lat;
sidebarTempLng = lng;
var el = document.getElementById('coords-spbu-val');
el.textContent = lat.toFixed(6) + ', ' + lng.toFixed(6);
el.classList.add('has-coords');
// Tempatkan penanda sementara
drawnItems.clearLayers();
L.marker([lat, lng], { icon: redIcon }).addTo(drawnItems);
deactivatePickMode();
});
// ==========================================
// 7. SIMPAN DATA DARI SIDEBAR
// ==========================================
function saveSPBUSidebar() {
if (!sidebarTempLat || !sidebarTempLng) {
alert('Silakan pilih lokasi SPBU di peta terlebih dahulu!');
return;
}
var nama = document.getElementById('sb_nama_spbu').value.trim();
if (!nama) {
alert('Nama SPBU wajib diisi!');
return;
}
var formData = new FormData();
formData.append('nama_spbu', nama);
formData.append('no_hp', document.getElementById('sb_nohp_spbu').value.trim());
formData.append('kategori', document.getElementById('sb_kategori_spbu').value);
formData.append('latitude', sidebarTempLat);
formData.append('longitude', sidebarTempLng);
fetch('save.php', { method: 'POST', body: formData })
.then(r => r.text())
.then(res => {
alert(res);
document.getElementById('sb_nama_spbu').value = '';
document.getElementById('sb_nohp_spbu').value = '';
document.getElementById('coords-spbu-val').textContent = 'Belum dipilih';
document.getElementById('coords-spbu-val').classList.remove('has-coords');
sidebarTempLat = 0.0;
sidebarTempLng = 0.0;
drawnItems.clearLayers();
loadSPBU();
})
.catch(e => console.error("Error saving SPBU:", e));
}
// ==========================================
// 8. DROPDOWN KATEGORI DI HEADER
// ==========================================
document.addEventListener('DOMContentLoaded', function () {
var wrap = document.getElementById('custom-select-wrap');
var trigger = document.getElementById('custom-select-trigger');
var options = document.getElementById('custom-select-options');
var hiddenInput = document.getElementById('search-category');
var optionItems = document.querySelectorAll('.custom-option');
// Toggle dropdown
wrap.addEventListener('click', function (e) {
e.stopPropagation();
options.classList.toggle('show');
});
// Pilihan dropdown diklik
optionItems.forEach(function (item) {
item.addEventListener('click', function (e) {
e.stopPropagation();
optionItems.forEach(opt => opt.classList.remove('selected'));
this.classList.add('selected');
trigger.textContent = this.textContent;
hiddenInput.value = this.getAttribute('data-value');
options.classList.remove('show');
jalankanPencarian();
});
});
// Tutup dropdown jika klik di luar
document.addEventListener('click', function () {
options.classList.remove('show');
});
});
+1201
View File
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
<?php
include 'koneksi.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$tabel = isset($_POST['tabel']) ? trim($_POST['tabel']) : '';
if ($id <= 0) {
http_response_code(400);
echo "ID tidak valid!";
exit;
}
if ($tabel === 'spbu_locations') {
$nama = isset($_POST['nama_spbu']) ? trim($_POST['nama_spbu']) : '';
$hp = isset($_POST['no_hp']) ? trim($_POST['no_hp']) : '';
$kategori = isset($_POST['kategori']) ? trim($_POST['kategori']) : '';
$lat = isset($_POST['latitude']) ? floatval($_POST['latitude']) : 0.0;
$lng = isset($_POST['longitude']) ? floatval($_POST['longitude']) : 0.0;
if (empty($nama) || $lat == 0.0 || $lng == 0.0) {
http_response_code(400);
echo "Nama SPBU dan lokasi koordinat wajib diisi!";
exit;
}
$stmt = $conn->prepare("UPDATE spbu_locations SET nama_spbu=?, no_hp=?, kategori=?, latitude=?, longitude=? WHERE id=?");
$stmt->bind_param("sssddi", $nama, $hp, $kategori, $lat, $lng, $id);
if ($stmt->execute()) {
echo "Data berhasil diperbarui!";
} else {
http_response_code(500);
echo "Gagal memperbarui: " . $conn->error;
}
$stmt->close();
} else {
http_response_code(400);
echo "Tabel tidak valid!";
}
$conn->close();
} else {
http_response_code(405);
echo "Metode tidak diizinkan";
}
?>