Initial commit: Setup Landing Page dan file pertemuan
This commit is contained in:
@@ -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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user