285 lines
13 KiB
HTML
285 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Sistem GIS SPBU - Mandiri</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<style>
|
|
/* Mengatur tinggi peta agar serasi dengan sidebar */
|
|
#map { height: 650px; width: 100%; border-radius: 12px; border: 2px solid #dee2e6; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
|
|
/* Sidebar diperpanjang ke bawah */
|
|
.sidebar-panel {
|
|
background: white; padding: 20px; border-radius: 12px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
height: 730px; /* Tinggi total sidebar ditambah */
|
|
display: flex; flex-direction: column;
|
|
}
|
|
|
|
/* Kolom Daftar SPBU diperpanjang maksimal */
|
|
.data-list {
|
|
flex-grow: 1;
|
|
overflow-y: auto;
|
|
margin-top: 10px;
|
|
padding-right: 8px;
|
|
border-top: 1px solid #eee;
|
|
padding-top: 10px;
|
|
}
|
|
|
|
/* Desain item daftar lebih elegan */
|
|
.data-item {
|
|
background: #ffffff; padding: 15px; margin-bottom: 12px; border-radius: 10px;
|
|
cursor: pointer; border: 1px solid #e9ecef; border-left: 6px solid #0d6efd;
|
|
transition: all 0.2s ease;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.02);
|
|
}
|
|
.data-item:hover { background: #f1f4f9; transform: translateX(5px); border-color: #0d6efd; }
|
|
.data-item strong { color: #333; display: block; margin-bottom: 3px; }
|
|
.data-item small { color: #6c757d; font-size: 0.85rem; display: block; line-height: 1.3; }
|
|
|
|
.is-editing { border-left-color: #ffc107 !important; background: #fffdf5 !important; border-color: #ffc107; }
|
|
.custom-pin { filter: drop-shadow(0 3px 3px rgba(0,0,0,0.4)); }
|
|
|
|
/* Scrollbar kustom agar terlihat modern */
|
|
.data-list::-webkit-scrollbar { width: 6px; }
|
|
.data-list::-webkit-scrollbar-track { background: #f1f1f1; }
|
|
.data-list::-webkit-scrollbar-thumb { background: #ccc; border-radius: 10px; }
|
|
</style>
|
|
</head>
|
|
<body class="bg-light">
|
|
|
|
<div class="container-fluid py-4">
|
|
<div class="row g-4">
|
|
<div class="col-md-8">
|
|
<div id="map" class="mb-3"></div>
|
|
<div class="bg-white p-3 rounded shadow-sm d-flex justify-content-between align-items-center">
|
|
<button class="btn btn-success px-4 py-2 fw-bold shadow-sm" onclick="startAdding()">
|
|
<i class="fas fa-plus-circle me-2"></i> TAMBAH SPBU BARU
|
|
</button>
|
|
<div class="text-muted small">
|
|
<i class="fas fa-info-circle text-primary me-1"></i>
|
|
<b>Navigasi:</b> Klik item di daftar untuk Edit. Geser pin di peta untuk pindah lokasi.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<div class="sidebar-panel">
|
|
<div id="formSection">
|
|
<h5 id="formTitle" class="fw-bold mb-3 text-primary d-flex justify-content-between">
|
|
<span><i class="fas fa-edit me-2"></i>Form SPBU</span>
|
|
<button class="btn btn-sm btn-link p-0 text-decoration-none" onclick="resetForm()">Reset</button>
|
|
</h5>
|
|
<form id="spbuForm">
|
|
<input type="hidden" id="spbuId">
|
|
<div class="mb-2">
|
|
<label class="small fw-bold text-secondary">Nama SPBU</label>
|
|
<input type="text" id="namaSpbu" class="form-control form-control-sm border-2" placeholder="Contoh: SPBU 64.001" required>
|
|
</div>
|
|
<div class="row mb-2 g-2">
|
|
<div class="col-7">
|
|
<label class="small fw-bold text-secondary">No. Register</label>
|
|
<input type="text" id="noSpbu" class="form-control form-control-sm" placeholder="ID SPBU" required>
|
|
</div>
|
|
<div class="col-5">
|
|
<label class="small fw-bold text-secondary">Tipe</label>
|
|
<select id="tipeSpbu" class="form-select form-select-sm">
|
|
<option value="24jam">24 Jam</option>
|
|
<option value="tidak">Biasa</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="small fw-bold text-secondary">Alamat (Geocode Otomatis)</label>
|
|
<textarea id="alamatSpbu" class="form-control form-control-sm" rows="2" placeholder="Klik lokasi di peta..."></textarea>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="small fw-bold text-secondary">Koordinat (Lat, Lng)</label>
|
|
<input type="text" id="koordinatSpbu" class="form-control form-control-sm bg-light text-muted" readonly>
|
|
</div>
|
|
<button type="submit" id="btnSubmit" class="btn btn-primary w-100 fw-bold shadow-sm py-2">SIMPAN DATA</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="mt-4 d-flex justify-content-between align-items-center">
|
|
<h6 class="fw-bold mb-0"><i class="fas fa-list-ul me-2"></i>Daftar SPBU Terdaftar</h6>
|
|
<span id="countBadges" class="badge bg-secondary rounded-pill">0</span>
|
|
</div>
|
|
|
|
<div id="spbuList" class="data-list">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<script>
|
|
var map = L.map('map').setView([-0.026330, 109.342519], 13);
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
|
|
|
|
var spbuGroup = L.layerGroup().addTo(map);
|
|
var tempMarker = null;
|
|
var isAddingMode = false;
|
|
|
|
function getIcon(tipe) {
|
|
const color = tipe === '24jam' ? '#198754' : '#dc3545';
|
|
return L.divIcon({
|
|
html: `<i class="fas fa-map-marker-alt fa-2x custom-pin" style="color: ${color};"></i>`,
|
|
className: 'custom-div-icon',
|
|
iconSize: [30, 30],
|
|
iconAnchor: [15, 30],
|
|
popupAnchor: [0, -30]
|
|
});
|
|
}
|
|
|
|
async function reverseGeocode(lat, lng) {
|
|
const target = document.getElementById('alamatSpbu');
|
|
target.value = "Sedang melacak alamat...";
|
|
try {
|
|
const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}`);
|
|
const data = await response.json();
|
|
target.value = data.display_name || "Alamat tidak ditemukan di sistem";
|
|
} catch (e) {
|
|
target.value = "Koneksi ke layanan alamat terputus";
|
|
}
|
|
}
|
|
|
|
async function loadData() {
|
|
const res = await fetch('api_spbu.php?action=getAll');
|
|
const json = await res.json();
|
|
spbuGroup.clearLayers();
|
|
const listContainer = document.getElementById('spbuList');
|
|
listContainer.innerHTML = '';
|
|
document.getElementById('countBadges').innerText = json.data.length;
|
|
|
|
json.data.forEach(spbu => {
|
|
const marker = L.marker([spbu.latitude, spbu.longitude], {
|
|
icon: getIcon(spbu.tipe),
|
|
draggable: true
|
|
}).addTo(spbuGroup);
|
|
|
|
marker.on('dragend', async function(e) {
|
|
const pos = e.target.getLatLng();
|
|
if(document.getElementById('spbuId').value == spbu.id) {
|
|
document.getElementById('koordinatSpbu').value = `${pos.lat.toFixed(6)}, ${pos.lng.toFixed(6)}`;
|
|
reverseGeocode(pos.lat, pos.lng);
|
|
}
|
|
await saveUpdate(spbu.id, spbu.nama, spbu.no_spbu, spbu.alamat, spbu.tipe, pos.lat, pos.lng);
|
|
});
|
|
|
|
marker.bindPopup(`<b>${spbu.nama}</b><br><button class="btn btn-danger btn-sm mt-2 w-100" onclick="deleteData(${spbu.id})">Hapus</button>`);
|
|
|
|
const item = document.createElement('div');
|
|
item.className = 'data-item';
|
|
item.id = `item-${spbu.id}`;
|
|
item.innerHTML = `
|
|
<strong>${spbu.nama}</strong>
|
|
<small><i class="fas fa-tag me-1"></i> No: ${spbu.no_spbu}</small>
|
|
<small><i class="fas fa-map-marked-alt me-1"></i> ${spbu.alamat ? spbu.alamat.substring(0, 60) + '...' : 'Alamat belum diatur'}</small>
|
|
`;
|
|
item.onclick = () => prepareEdit(spbu, marker);
|
|
listContainer.appendChild(item);
|
|
});
|
|
}
|
|
|
|
function startAdding() {
|
|
resetForm();
|
|
isAddingMode = true;
|
|
document.getElementById('map').style.cursor = 'crosshair';
|
|
}
|
|
|
|
map.on('click', function(e) {
|
|
if (!isAddingMode) return;
|
|
const {lat, lng} = e.latlng;
|
|
document.getElementById('koordinatSpbu').value = `${lat.toFixed(6)}, ${lng.toFixed(6)}`;
|
|
reverseGeocode(lat, lng);
|
|
|
|
if (tempMarker) map.removeLayer(tempMarker);
|
|
tempMarker = L.marker([lat, lng], { draggable: true }).addTo(map);
|
|
|
|
tempMarker.on('dragend', function(ev) {
|
|
const p = ev.target.getLatLng();
|
|
document.getElementById('koordinatSpbu').value = `${p.lat.toFixed(6)}, ${p.lng.toFixed(6)}`;
|
|
reverseGeocode(p.lat, p.lng);
|
|
});
|
|
|
|
isAddingMode = false;
|
|
document.getElementById('map').style.cursor = '';
|
|
});
|
|
|
|
function prepareEdit(spbu, marker) {
|
|
document.querySelectorAll('.data-item').forEach(i => i.classList.remove('is-editing'));
|
|
document.getElementById(`item-${spbu.id}`).classList.add('is-editing');
|
|
|
|
document.getElementById('formTitle').innerHTML = '<span><i class="fas fa-edit me-2"></i>Edit SPBU</span><button class="btn btn-sm btn-link p-0 text-decoration-none" onclick="resetForm()">Batal</button>';
|
|
document.getElementById('spbuId').value = spbu.id;
|
|
document.getElementById('namaSpbu').value = spbu.nama;
|
|
document.getElementById('noSpbu').value = spbu.no_spbu;
|
|
document.getElementById('alamatSpbu').value = spbu.alamat || '';
|
|
document.getElementById('tipeSpbu').value = spbu.tipe;
|
|
document.getElementById('koordinatSpbu').value = `${spbu.latitude}, ${spbu.longitude}`;
|
|
|
|
document.getElementById('btnSubmit').innerText = "UPDATE DATA SPBU";
|
|
document.getElementById('btnSubmit').className = "btn btn-warning w-100 fw-bold py-2";
|
|
|
|
map.flyTo([spbu.latitude, spbu.longitude], 17);
|
|
marker.openPopup();
|
|
}
|
|
|
|
document.getElementById('spbuForm').onsubmit = async (e) => {
|
|
e.preventDefault();
|
|
const id = document.getElementById('spbuId').value;
|
|
const coords = document.getElementById('koordinatSpbu').value.split(', ');
|
|
|
|
if(!coords[0]) return alert("Tentukan lokasi di peta terlebih dahulu!");
|
|
|
|
const data = {
|
|
nama: document.getElementById('namaSpbu').value,
|
|
no_spbu: document.getElementById('noSpbu').value,
|
|
alamat: document.getElementById('alamatSpbu').value,
|
|
tipe: document.getElementById('tipeSpbu').value,
|
|
latitude: coords[0],
|
|
longitude: coords[1]
|
|
};
|
|
|
|
const url = id ? `api_spbu.php?action=update&id=${id}` : `api_spbu.php?action=create`;
|
|
await fetch(url, { method: id ? 'PUT' : 'POST', body: JSON.stringify(data) });
|
|
|
|
resetForm();
|
|
loadData();
|
|
};
|
|
|
|
async function saveUpdate(id, nama, no, alamat, tipe, lat, lng) {
|
|
await fetch(`api_spbu.php?action=update&id=${id}`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify({ nama, no_spbu: no, alamat, tipe, latitude: lat, longitude: lng })
|
|
});
|
|
}
|
|
|
|
async function deleteData(id) {
|
|
if (confirm('Apakah Anda yakin ingin menghapus data SPBU ini dari sistem?')) {
|
|
await fetch(`api_spbu.php?action=delete&id=${id}`, { method: 'DELETE' });
|
|
loadData();
|
|
resetForm();
|
|
}
|
|
}
|
|
|
|
function resetForm() {
|
|
document.getElementById('spbuForm').reset();
|
|
document.getElementById('spbuId').value = '';
|
|
document.getElementById('formTitle').innerHTML = '<span><i class="fas fa-edit me-2"></i>Form SPBU</span>';
|
|
document.getElementById('btnSubmit').innerText = "SIMPAN DATA";
|
|
document.getElementById('btnSubmit').className = "btn btn-primary w-100 fw-bold py-2";
|
|
document.querySelectorAll('.data-item').forEach(i => i.classList.remove('is-editing'));
|
|
if (tempMarker) map.removeLayer(tempMarker);
|
|
isAddingMode = false;
|
|
document.getElementById('map').style.cursor = '';
|
|
}
|
|
|
|
loadData();
|
|
</script>
|
|
</body>
|
|
</html> |