Files
2026-06-13 10:54:54 +07:00

612 lines
15 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_top">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Map SPBU</title>
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<style>
html, body {
height: 100%;
margin: 0;
}
#map {
height: 100%;
}
.popup-card {
font-family: Arial, sans-serif;
width: 200px;
}
.popup-title {
font-weight: bold;
font-size: 16px;
margin-bottom: 6px;
}
.popup-item {
font-size: 13px;
margin: 2px 0;
}
.badge {
display: inline-block;
padding: 2px 6px;
border-radius: 6px;
font-size: 11px;
color: white;
}
.green { background: #28a745; }
.red { background: #dc3545; }
.popup-btn {
margin-top: 8px;
padding: 5px;
width: 100%;
border: none;
border-radius: 6px;
background: #007bff;
color: white;
cursor: pointer;
}
.popup-btn:hover {
background: #0056b3;
}
.form-card {
font-family: Arial, sans-serif;
width: 220px;
}
.form-title {
font-weight: bold;
font-size: 15px;
margin-bottom: 6px;
}
.form-group {
margin-bottom: 6px;
}
.form-group label {
font-size: 12px;
}
.form-group input,
.form-group select {
width: 100%;
padding: 4px;
border-radius: 5px;
border: 1px solid #ccc;
font-size: 12px;
}
.form-btn {
width: 100%;
padding: 6px;
border: none;
border-radius: 6px;
color: white;
cursor: pointer;
}
.btn-save { background: #28a745; }
.btn-update { background: #007bff; }
</style>
</head>
<body>
<div style="position:absolute; z-index:1000; background:white; padding:10px;">
<button onclick="startLine()">✏️ Line</button>
<button onclick="startPolygons()">🔺 Polygon</button>
<button onclick="finishShape()">✅ Selesai</button>
<button onclick="resetShape()">❌ Reset</button>
</div>
<div id="map"></div>
<script>
const map = L.map('map').setView([-0.055326, 109.349500], 13);
let layer24 = L.layerGroup();
let layerNon24 = L.layerGroup();
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
const marker = L.marker([-0.055326, 109.349500]).addTo(map)
.bindPopup('<b>Hello world!</b><br />I am a popup.').openPopup();
const circle = L.circle([-0.055326, 109.349500], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 200
}).addTo(map).bindPopup('I am a circle.');
const polygon = L.polygon([
[-0.054817, 109.349522],
[-0.055520, 109.349915],
[-0.055349, 109.348959]
]).addTo(map).bindPopup('I am a polygon.');
let mode = null;
let points = [];
let tempLayer = null;
let shapes = [];
map.on('click', function(e) {
if (mode) {
points.push([e.latlng.lat, e.latlng.lng]);
if (tempLayer) {
map.removeLayer(tempLayer);
}
if (mode === 'line') {
tempLayer = L.polyline(points, { color: 'blue' }).addTo(map);
}
if (mode === 'polygons') {
tempLayer = L.polygon(points, { color: 'green' }).addTo(map);
}
} else {
tampilForm('tambah', e.latlng.lat, e.latlng.lng);
}
});
// LOAD DATA
function loadData() {
fetch('get.php')
.then(res => res.json())
.then(data => {
data.forEach(d => {
let marker = L.marker([d.lat, d.lng]);
if (d.buka_24jam === 'Ya') {
marker.addTo(layer24);
} else {
marker.addTo(layerNon24);
}
marker.bindPopup(`
<div class="popup-card">
<div class="popup-title">⛽ ${d.nama}</div>
<div class="popup-item">📞 ${d.no_hp}</div>
<div class="popup-item">
🕒 24 Jam:
<span class="badge ${d.buka_24jam === 'Ya' ? 'green' : 'red'}">
${d.buka_24jam}
</span>
</div>
<div class="popup-item">
🔥 Ramai:
<span class="badge ${d.ramai === 'Ya' ? 'green' : 'red'}">
${d.ramai}
</span>
</div>
<div style="display:flex; gap:5px; margin-top:8px;">
<button class="popup-btn" style="background:#ffc107;"
onclick="editData(${d.id}, '${d.nama}', '${d.no_hp}', '${d.buka_24jam}', '${d.ramai}', ${d.lat}, ${d.lng})">
✏️ Edit
</button>
<button class="popup-btn" style="background:#dc3545;"
onclick="hapus(${d.id})">
🗑️ Hapus
</button>
</div>
</div>
`);
});
});
}
// CLICK MAP → INPUT
function tampilForm(mode, lat, lng, data = null) {
let isEdit = mode === 'edit';
let form = `
<div class="form-card">
<div class="form-title">
${isEdit ? '✏️ Edit SPBU' : ' Tambah SPBU'}
</div>
<div class="form-group">
<label>Nama</label>
<input id="nama" value="${data ? data.nama : ''}">
</div>
<div class="form-group">
<label>No HP</label>
<input id="no_hp" value="${data ? data.no_hp : ''}">
</div>
<div class="form-group">
<label>24 Jam</label>
<select id="buka">
<option ${data?.buka_24jam === 'Ya' ? 'selected' : ''}>Ya</option>
<option ${data?.buka_24jam === 'Tidak' ? 'selected' : ''}>Tidak</option>
</select>
</div>
<div class="form-group">
<label>Ramai</label>
<select id="ramai">
<option ${data?.ramai === 'Ya' ? 'selected' : ''}>Ya</option>
<option ${data?.ramai === 'Tidak' ? 'selected' : ''}>Tidak</option>
</select>
</div>
<button class="form-btn ${isEdit ? 'btn-update' : 'btn-save'}"
onclick="${isEdit
? `updateData(${data.id})`
: `simpan(${lat}, ${lng})`}">
${isEdit ? 'Update' : 'Simpan'}
</button>
</div>
`;
L.popup()
.setLatLng([lat, lng])
.setContent(form)
.openOn(map);
}
// SIMPAN
function simpan(lat, lng) {
let data = {
nama: document.getElementById('nama').value,
no_hp: document.getElementById('no_hp').value,
buka_24jam: document.getElementById('buka').value,
ramai: document.getElementById('ramai').value,
lat: lat,
lng: lng
};
fetch('tambah.php', {
method: 'POST',
body: JSON.stringify(data)
})
.then(() => location.reload());
}
// DELETE
function hapus(id) {
fetch('delete.php?id=' + id)
.then(() => location.reload());
}
function editData(id, nama, no_hp, buka, ramai, lat, lng) {
let data = {
id: id,
nama: nama,
no_hp: no_hp,
buka_24jam: buka,
ramai: ramai
};
tampilForm('edit', lat, lng, data);
}
function updateData(id) {
let data = {
id: id,
nama: document.getElementById('nama').value,
no_hp: document.getElementById('no_hp').value,
buka_24jam: document.getElementById('buka').value,
ramai: document.getElementById('ramai').value
};
fetch('update.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(res => res.text())
.then(res => {
alert("Data berhasil diupdate!");
location.reload();
});
}
function startLine() {
mode = 'line';
points = [];
alert("Mode LINE aktif");
}
function startPolygons() {
mode = 'polygons';
points = [];
alert("Mode POLYGON aktif");
}
function resetShape() {
points = [];
if (tempLayer) {
map.removeLayer(tempLayer);
tempLayer = null;
}
}
function finishShape() {
if (points.length < 2) {
alert("Titik belum cukup!");
return;
}
let shape;
let currentType = mode; // 🔥 SIMPAN DULU
if (mode === 'line') {
shape = L.polyline(points, { color: 'blue', weight: 4 }).addTo(map);
}
if (mode === 'polygons') {
shape = L.polygon(points, { color: 'green', fillOpacity: 0.4 }).addTo(map);
}
fetch(currentType === 'line' ? 'simpan_line.php' : 'simpan_polygons.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
coordinates: points
})
})
.then(res => res.json())
.then(res => {
let id = res.id;
if (currentType === 'line') {
let panjang = hitungPanjang(points);
shape.bindPopup(`
<b>Atur Jalan</b><br>
<select id="status_${id}">
<option value="Nasional">Nasional</option>
<option value="Provinsi">Provinsi</option>
<option value="Kabupaten">Kabupaten</option>
</select>
<br><br>
Panjang: ${panjang} meter<br><br>
<button onclick="updateLine(${id})">✅ OK</button>
<button onclick="hapusShape(${id}, 'line')">🗑️ Hapus</button>
`);
} else {
shape.bindPopup(`
<b>Atur Kavling</b><br>
<select id="status_poly_${id}">
<option value="SHM">SHM</option>
<option value="HGB">HGB</option>
<option value="HGU">HGU</option>
<option value="HP">HP</option>
</select>
<br><br>
<button onclick="updatePolygon(${id})">✅ OK</button>
<button onclick="hapusShape(${id}, 'polygons')">🗑️ Hapus</button>
`);
}
});
// reset
mode = null;
points = [];
if (tempLayer) {
map.removeLayer(tempLayer);
tempLayer = null;
}
alert("Shape selesai!");
}
function hapusShape(id, type) {
fetch(type === 'line' ? 'delete_line.php' : 'delete_polygons.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ id: id })
})
.then(() => location.reload());
}
function loadLines() {
fetch('get_line.php')
.then(res => res.json())
.then(data => {
data.forEach(d => {
let coords = JSON.parse(d.coordinates);
let color = getColor(d.status) || 'blue';
let line = L.polyline(coords, { color: color }).addTo(map);
let panjang = hitungPanjang(coords);
line.bindPopup(`
<b>Atur Jalan</b><br>
<select id="status_${d.id}">
<option value="Nasional" ${d.status === 'Nasional' ? 'selected' : ''}>Nasional</option>
<option value="Provinsi" ${d.status === 'Provinsi' ? 'selected' : ''}>Provinsi</option>
<option value="Kabupaten" ${d.status === 'Kabupaten' ? 'selected' : ''}>Kabupaten</option>
</select>
<br><br>
Panjang: ${panjang} meter<br><br>
<button onclick="updateLine(${d.id})">✅ OK</button>
<button onclick="hapusShape(${d.id}, 'line')">🗑️ Hapus</button>
`);
});
});
}
function loadPolygons() {
fetch('get_polygons.php')
.then(res => res.json())
.then(data => {
data.forEach(d => {
let coords = JSON.parse(d.coordinates);
let color = getColorPolygon(d.status) || 'green';
let polygon = L.polygon(coords, {
color: color,
fillOpacity: 0.4
}).addTo(map);
polygon.bindPopup(`
<b>Atur Kavling</b><br>
<select id="status_poly_${d.id}">
<option value="SHM" ${d.status === 'SHM' ? 'selected' : ''}>SHM</option>
<option value="HGB" ${d.status === 'HGB' ? 'selected' : ''}>HGB</option>
<option value="HGU" ${d.status === 'HGU' ? 'selected' : ''}>HGU</option>
<option value="HP" ${d.status === 'HP' ? 'selected' : ''}>HP</option>
</select>
<br><br>
<button onclick="updatePolygon(${d.id})">✅ OK</button>
<button onclick="hapusShape(${d.id}, 'polygons')">🗑️ Hapus</button>
`);
});
});
}
loadData();
loadLines();
loadPolygons();
layer24.addTo(map);
layerNon24.addTo(map);
L.control.layers(null, {
"SPBU 24 Jam": layer24,
"SPBU Tidak 24 Jam": layerNon24
}).addTo(map);
function getColor(status) {
if (status === 'Nasional') return 'red';
if (status === 'Provinsi') return 'blue';
if (status === 'Kabupaten') return 'green';
}
function getColorPolygon(status) {
if (status === 'SHM') return 'green';
if (status === 'HGB') return 'blue';
if (status === 'HGU') return 'orange';
if (status === 'HP') return 'purple';
}
function hitungPanjang(points) {
let total = 0;
for (let i = 0; i < points.length - 1; i++) {
let p1 = L.latLng(points[i]);
let p2 = L.latLng(points[i + 1]);
total += p1.distanceTo(p2);
}
return total.toFixed(2);
}
function updateLine(id) {
let status = document.getElementById('status_' + id).value;
fetch('get_line.php')
.then(res => res.json())
.then(data => {
let d = data.find(item => item.id == id);
let coords = JSON.parse(d.coordinates);
let panjang = hitungPanjang(coords);
fetch('update_line.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: id,
status: status,
panjang: panjang
})
})
.then(() => {
alert("Data jalan berhasil diupdate!");
location.reload();
});
});
}
function updatePolygon(id) {
let status = document.getElementById('status_poly_' + id).value;
fetch('update_polygons.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: id,
status: status
})
})
.then(() => {
alert("Status kavling berhasil diupdate!");
location.reload();
});
}
</script>
</body>
</html>