fix: update final code deployment

This commit is contained in:
muthianura
2026-06-15 21:53:17 +07:00
parent 62a5a26fe0
commit 9cc6fcf52d
42 changed files with 177 additions and 23 deletions
+283
View File
@@ -0,0 +1,283 @@
<?php
if (isset($_GET['action'])) { include 'api.php'; exit; }
include 'db.php';
require_once 'includes/stats.php';
$stats = spbu_stats($conn);
$activePage = 'index';
$saved = isset($_GET['saved']);
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sistem Informasi Geografis SPBU — Pontianak</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
<link rel="stylesheet" href="assets/spbu.css?v=1.2"/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
</head>
<body>
<?php include 'includes/sidebar.php'; ?>
<div class="sb-body">
<div class="sb-search"><input type="text" id="search-input" placeholder="Cari nama atau nomor SPBU..."></div>
<div class="sb-filter">
<button class="active" data-filter="semua">Semua (<?= $stats['total'] ?>)</button>
<button data-filter="24 Jam">24 Jam (<?= $stats['jam24'] ?>)</button>
<button data-filter="Tidak 24 Jam">Lainnya (<?= $stats['tidak24'] ?>)</button>
</div>
<div class="sb-list-head">
<span>Daftar SPBU</span>
<span id="list-count"><?= $stats['total'] ?> lokasi</span>
</div>
<div class="sb-list" id="spbu-list"></div>
</div>
<div class="sb-foot" style="flex-direction:column; gap:10px">
<div style="display:flex; justify-content:space-between; width:100%">
<span>Operasional 24 jam: <b><?= $stats['pct24'] ?>%</b></span>
<span><?= date('d M Y') ?></span>
</div>
<a href="../index.php" class="btn-portal" style="display:flex; align-items:center; justify-content:center; gap:6px; padding:10px; background:#eff6ff; color:#1d4ed8; border:1px solid #bfdbfe; border-radius:8px; font-weight:600; text-decoration:none; font-size:12px; transition:all 0.15s; width:100%">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink:0"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
Kembali ke Portal
</a>
</div>
</aside>
<div id="map-area">
<!-- Topbar -->
<div id="topbar" style="position:relative; z-index:1000; height:56px; background:#fff; border-bottom:1px solid #e2e8f0; display:flex; align-items:center; justify-content:space-between; padding:0 16px; flex-shrink:0">
<div style="display:flex; align-items:center; gap:8px">
<button type="button" onclick="document.getElementById('sidebar').style.display=document.getElementById('sidebar').style.display==='none'?'flex':'none';setTimeout(function(){map.invalidateSize()},300)" style="background:none;border:none;cursor:pointer;color:#64748b;padding:4px;display:flex;align-items:center"><svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg></button>
<div style="font-size:15px; font-weight:700; color:#1e293b">Peta GIS <span style="font-size:13px; font-weight:500; color:#64748b; margin-left:4px">Kanalisasi SPBU</span></div>
</div>
<div style="display:flex; gap:8px">
<a href="tambah.php" style="display:flex; align-items:center; gap:6px; padding:8px 14px; background:#1d4ed8; color:#fff; border-radius:8px; font-size:12px; font-weight:600; text-decoration:none; box-shadow:0 2px 4px rgba(29,78,216,0.15)">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink:0"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
Tambah Baru
</a>
</div>
</div>
<div id="map"></div>
<?php include 'includes/map-controls.php'; ?>
</div>
<div id="edit-modal">
<div id="edit-box">
<h3>Edit Data SPBU</h3>
<input type="hidden" id="edit-id">
<label>Nama SPBU</label>
<input type="text" id="edit-nama">
<label>Nomor Depot</label>
<input type="text" id="edit-nomor">
<label>Jam Operasional</label>
<select id="edit-status">
<option value="24 Jam">24 Jam</option>
<option value="Tidak 24 Jam">Tidak 24 Jam</option>
</select>
<div class="edit-btns">
<button class="btn-cancel" type="button" onclick="closeModal()">Batal</button>
<button class="btn-save" type="button" onclick="submitEdit()">Simpan</button>
</div>
</div>
</div>
<div id="toast"></div>
<?php include 'includes/confirm-modal.php'; ?>
<script src="assets/map-base.js"></script>
<script>
var map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13);
L.control.zoom({ position: 'bottomright' }).addTo(map);
initBaseLayers(map);
<?php if ($saved): ?>showToast('Data SPBU berhasil disimpan.');<?php endif ?>
var spbuData = [];
var layer24Jam = L.layerGroup().addTo(map);
var layerTidak24 = L.layerGroup().addTo(map);
document.getElementById('ly-24').addEventListener('change', function() {
this.checked ? map.addLayer(layer24Jam) : map.removeLayer(layer24Jam);
});
document.getElementById('ly-tdk').addEventListener('change', function() {
this.checked ? map.addLayer(layerTidak24) : map.removeLayer(layerTidak24);
});
async function deleteData(id) {
var ok = await showConfirm({
title: 'Hapus Data SPBU',
message: 'Data ini akan dihapus permanen dari database.',
confirmText: 'Ya, Hapus', danger: true
});
if (ok) window.location.href = 'index.php?action=delete&id=' + id;
}
function openEdit(id, nama, nomor, status) {
document.getElementById('edit-id').value = id;
document.getElementById('edit-nama').value = nama;
document.getElementById('edit-nomor').value = nomor;
document.getElementById('edit-status').value = status;
document.getElementById('edit-modal').classList.add('active');
}
function closeModal() { document.getElementById('edit-modal').classList.remove('active'); }
function submitEdit() {
var id = document.getElementById('edit-id').value;
var nama = document.getElementById('edit-nama').value.trim();
var nomor = document.getElementById('edit-nomor').value.trim();
var status = document.getElementById('edit-status').value;
if (!nama || !nomor) { showToast('Nama dan nomor wajib diisi.'); return; }
window.location.href = 'index.php?action=edit&id=' + id
+ '&nama=' + encodeURIComponent(nama)
+ '&nomor=' + encodeURIComponent(nomor)
+ '&status=' + encodeURIComponent(status);
}
document.getElementById('edit-modal').addEventListener('click', function(e) {
if (e.target === this) closeModal();
});
function flyToSpbu(id) {
var s = spbuData.find(function(x) { return x.id === id; });
if (!s) return;
document.querySelectorAll('.spbu-item').forEach(function(el) { el.classList.remove('active'); });
var el = document.querySelector('.spbu-item[data-id="' + id + '"]');
if (el) el.classList.add('active');
map.flyTo([s.lat, s.lng], 17, { duration: 1 });
setTimeout(function() { s.marker.openPopup(); }, 1100);
}
<?php
$data = $conn->query("SELECT * FROM tempat ORDER BY nama_tempat ASC");
while ($row = $data->fetch_assoc()):
$id = $row['id']; $lat = $row['latitude']; $lng = $row['longitude'];
$nama = addslashes($row['nama_tempat']); $nomor = addslashes($row['nomor_tempat']);
$status = addslashes($row['status']);
$color = ($row['status'] === '24 Jam') ? '#22c55e' : '#ef4444';
$badge = ($row['status'] === '24 Jam') ? 'badge-green' : 'badge-red';
$layerVar = ($row['status'] === '24 Jam') ? 'layer24Jam' : 'layerTidak24';
$latFmt = number_format($lat, 5); $lngFmt = number_format($lng, 5);
?>
(function() {
var savedLat = <?= $lat ?>, savedLng = <?= $lng ?>, markerId = <?= $id ?>, color = '<?= $color ?>';
var marker = L.marker([savedLat, savedLng], { icon: makeSpbuIcon(color), draggable: true }).addTo(<?= $layerVar ?>);
spbuData.push({ id: markerId, lat: savedLat, lng: savedLng, nama: '<?= $nama ?>', nomor: '<?= $nomor ?>', status: '<?= $status ?>', color: color, badge: '<?= $badge ?>', marker: marker });
function showInfoPopup() {
marker.unbindPopup();
marker.bindPopup(
'<div class="popup-wrap"><div class="popup-title"><?= $nama ?></div>' +
'<div class="popup-row">Depot No. <?= $nomor ?></div>' +
'<div class="popup-coord"><?= $latFmt ?>, <?= $lngFmt ?></div>' +
'<span class="popup-badge <?= $badge ?>"><?= $status ?></span>' +
'<div class="popup-actions">' +
'<button class="btn-edit" onclick="openEdit(<?= $id ?>,\'<?= $nama ?>\',\'<?= $nomor ?>\',\'<?= $status ?>\')">Edit</button>' +
'<button class="btn-delete" onclick="deleteData(<?= $id ?>)">Hapus</button></div></div>'
);
}
showInfoPopup();
var dragStartLat, dragStartLng;
marker.on('dragstart', function() {
dragStartLat = marker.getLatLng().lat; dragStartLng = marker.getLatLng().lng;
marker.closePopup(); marker.unbindPopup();
});
marker.on('dragend', function() {
var np = marker.getLatLng();
var msgBase = '<div style="text-align:left;line-height:1.6">' +
'<b>' + '<?= $nama ?>' + '</b><br>' +
'<span style="color:var(--text3);font-size:12px">Koordinat: ' + np.lat.toFixed(6) + ', ' + np.lng.toFixed(6) + '</span><br>';
fetch('https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat='+np.lat+'&lon='+np.lng+'&accept-language=id&zoom=18')
.then(r => r.json())
.then(d => {
var alamat = d.display_name || 'Alamat tidak ditemukan';
showConfirm({
title: 'Simpan posisi baru?',
message: msgBase + '<span style="font-size:13px;color:var(--text2)"><b>Alamat Baru:</b> ' + alamat + '</span></div>',
confirmText: 'Ya, Simpan',
icon: 'move',
position: 'top'
}).then(function(ok) {
if (ok) {
fetch('index.php?action=update_pos&id=' + markerId + '&lat=' + np.lat + '&lng=' + np.lng)
.then(function(r) { return r.text(); }).then(function(t) {
if (t.trim() === 'ok') {
savedLat = np.lat; savedLng = np.lng;
var s = spbuData.find(function(x) { return x.id === markerId; });
if (s) { s.lat = savedLat; s.lng = savedLng; }
showToast('Posisi diperbarui.');
} else {
showToast('Gagal menyimpan.');
marker.setLatLng([dragStartLat, dragStartLng]);
}
showInfoPopup();
});
} else {
marker.setLatLng([dragStartLat, dragStartLng]);
showInfoPopup();
}
});
})
.catch(() => {
showConfirm({
title: 'Simpan posisi baru?',
message: msgBase + '<span style="font-size:13px;color:var(--text2)"><b>Alamat Baru:</b> Gagal memuat alamat</span></div>',
confirmText: 'Ya, Simpan',
icon: 'move',
position: 'top'
}).then(function(ok) {
if (ok) {
fetch('index.php?action=update_pos&id=' + markerId + '&lat=' + np.lat + '&lng=' + np.lng)
.then(function(r) { return r.text(); }).then(function(t) {
if (t.trim() === 'ok') {
savedLat = np.lat; savedLng = np.lng;
var s = spbuData.find(function(x) { return x.id === markerId; });
if (s) { s.lat = savedLat; s.lng = savedLng; }
showToast('Posisi diperbarui.');
} else {
showToast('Gagal menyimpan.');
marker.setLatLng([dragStartLat, dragStartLng]);
}
showInfoPopup();
});
} else {
marker.setLatLng([dragStartLat, dragStartLng]);
showInfoPopup();
}
});
});
});
marker.on('click', function() {
document.querySelectorAll('.spbu-item').forEach(function(el) { el.classList.remove('active'); });
var el = document.querySelector('.spbu-item[data-id="' + markerId + '"]');
if (el) { el.classList.add('active'); el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }
});
})();
<?php endwhile; ?>
var currentFilter = 'semua', currentSearch = '';
function renderList() {
var list = document.getElementById('spbu-list');
var kw = currentSearch.toLowerCase();
var filtered = spbuData.filter(function(s) {
var f = (currentFilter === 'semua') || (s.status === currentFilter);
var q = s.nama.toLowerCase().indexOf(kw) !== -1 || s.nomor.toLowerCase().indexOf(kw) !== -1;
return f && q;
});
document.getElementById('list-count').textContent = filtered.length + ' lokasi';
if (!filtered.length) { list.innerHTML = '<div class="no-result">Tidak ada SPBU ditemukan</div>'; return; }
list.innerHTML = filtered.map(function(s) {
return '<div class="spbu-item" data-id="' + s.id + '" onclick="flyToSpbu(' + s.id + ')">' +
'<div class="spbu-dot" style="background:' + s.color + '"></div>' +
'<div><div class="spbu-nama">' + s.nama + '</div>' +
'<div class="spbu-meta">No. ' + s.nomor + ' · ' + s.lat.toFixed(5) + ', ' + s.lng.toFixed(5) + '</div></div>' +
'<span class="spbu-badge ' + s.badge + '">' + (s.status === '24 Jam' ? '24 Jam' : 'Tdk 24 Jam') + '</span></div>';
}).join('');
}
document.getElementById('search-input').addEventListener('input', function() { currentSearch = this.value; renderList(); });
document.querySelectorAll('.sb-filter button').forEach(function(btn) {
btn.addEventListener('click', function() {
document.querySelectorAll('.sb-filter button').forEach(function(b) { b.classList.remove('active'); });
this.classList.add('active'); currentFilter = this.dataset.filter; renderList();
});
});
renderList();
</script>
</body>
</html>