750 lines
20 KiB
PHP
750 lines
20 KiB
PHP
<?php
|
|
$conn = new mysqli("localhost", "root", "", "spbu");
|
|
|
|
// HANDLE INSERT
|
|
if(isset($_POST['nama'])){
|
|
$nama = $_POST['nama'];
|
|
$wa = $_POST['wa'];
|
|
$buka = $_POST['buka'];
|
|
$lat = $_POST['lat'];
|
|
$lng = $_POST['lng'];
|
|
|
|
$conn->query("INSERT INTO spbu (nama_spbu, nomor_wa, buka_24_jam, latitude, longitude)
|
|
VALUES ('$nama','$wa','$buka','$lat','$lng')");
|
|
exit("success");
|
|
}
|
|
|
|
// HANDLE DELETE
|
|
if(isset($_POST['delete_id'])){
|
|
$id = intval($_POST['delete_id']);
|
|
$conn->query("DELETE FROM spbu WHERE id = $id");
|
|
exit("deleted");
|
|
}
|
|
|
|
// HANDLE MOVE (update lat/lng)
|
|
if(isset($_POST['move_id'])){
|
|
$id = intval($_POST['move_id']);
|
|
$lat = $_POST['move_lat'];
|
|
$lng = $_POST['move_lng'];
|
|
$conn->query("UPDATE spbu SET latitude='$lat', longitude='$lng' WHERE id=$id");
|
|
exit("moved");
|
|
}
|
|
|
|
// HANDLE GET DATA
|
|
if(isset($_GET['get'])){
|
|
$result = $conn->query("SELECT * FROM spbu");
|
|
$data = [];
|
|
while($row = $result->fetch_assoc()){
|
|
$data[] = $row;
|
|
}
|
|
echo json_encode($data);
|
|
exit;
|
|
}
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>SPBU Map — Pontianak</title>
|
|
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap" rel="stylesheet">
|
|
|
|
<style>
|
|
:root {
|
|
--fuel-orange: #FF5722;
|
|
--fuel-amber: #FFA726;
|
|
--night: #0D0F14;
|
|
--panel: #13161E;
|
|
--panel-border: rgba(255,255,255,0.07);
|
|
--text: #F0F0F0;
|
|
--text-muted: #8A8FA0;
|
|
--green: #00C896;
|
|
--red: #FF4757;
|
|
--radius: 14px;
|
|
--shadow: 0 20px 60px rgba(0,0,0,0.5);
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
|
|
body {
|
|
font-family: 'DM Sans', sans-serif;
|
|
background: var(--night);
|
|
color: var(--text);
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
#map {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 0;
|
|
filter: brightness(0.9) saturate(0.85);
|
|
}
|
|
|
|
/* ── HEADER ── */
|
|
#header {
|
|
position: absolute;
|
|
top: 20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
z-index: 1000;
|
|
background: var(--panel);
|
|
border: 1px solid var(--panel-border);
|
|
border-radius: 50px;
|
|
padding: 10px 22px 10px 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
box-shadow: var(--shadow), 0 0 0 1px rgba(255,87,34,0.15);
|
|
backdrop-filter: blur(20px);
|
|
animation: slideDown 0.5s cubic-bezier(0.34,1.56,0.64,1) both;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.header-icon {
|
|
width: 34px;
|
|
height: 34px;
|
|
background: linear-gradient(135deg, var(--fuel-orange), var(--fuel-amber));
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 16px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
#header h1 {
|
|
font-family: 'Syne', sans-serif;
|
|
font-size: 15px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.02em;
|
|
color: var(--text);
|
|
}
|
|
|
|
#header p {
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
font-weight: 300;
|
|
letter-spacing: 0.03em;
|
|
}
|
|
|
|
/* ── LEGEND ── */
|
|
#legend {
|
|
position: absolute;
|
|
bottom: 30px;
|
|
left: 20px;
|
|
z-index: 1000;
|
|
background: var(--panel);
|
|
border: 1px solid var(--panel-border);
|
|
border-radius: var(--radius);
|
|
padding: 14px 18px;
|
|
box-shadow: var(--shadow);
|
|
backdrop-filter: blur(20px);
|
|
animation: slideUp 0.5s 0.1s cubic-bezier(0.34,1.56,0.64,1) both;
|
|
}
|
|
|
|
#legend h3 {
|
|
font-family: 'Syne', sans-serif;
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
color: var(--text-muted);
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.legend-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
margin-bottom: 7px;
|
|
font-size: 12.5px;
|
|
color: var(--text);
|
|
}
|
|
|
|
.legend-item:last-child { margin-bottom: 0; }
|
|
|
|
.legend-dot {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
box-shadow: 0 0 8px currentColor;
|
|
}
|
|
|
|
.dot-green { background: var(--green); color: var(--green); }
|
|
.dot-red { background: var(--red); color: var(--red); }
|
|
|
|
/* ── HINT CHIP ── */
|
|
#hint {
|
|
position: absolute;
|
|
bottom: 30px;
|
|
right: 20px;
|
|
z-index: 1000;
|
|
background: var(--panel);
|
|
border: 1px solid var(--panel-border);
|
|
border-radius: 50px;
|
|
padding: 10px 16px;
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 7px;
|
|
box-shadow: var(--shadow);
|
|
backdrop-filter: blur(20px);
|
|
animation: slideUp 0.5s 0.2s cubic-bezier(0.34,1.56,0.64,1) both;
|
|
}
|
|
|
|
.hint-pulse {
|
|
width: 8px;
|
|
height: 8px;
|
|
background: var(--fuel-orange);
|
|
border-radius: 50%;
|
|
animation: pulse 2s infinite;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ── TOAST ── */
|
|
#toast {
|
|
position: absolute;
|
|
top: 80px;
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(-10px);
|
|
z-index: 2000;
|
|
background: var(--panel);
|
|
border: 1px solid var(--panel-border);
|
|
border-radius: 50px;
|
|
padding: 10px 20px;
|
|
font-size: 13px;
|
|
color: var(--text);
|
|
box-shadow: var(--shadow);
|
|
backdrop-filter: blur(20px);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity 0.25s, transform 0.25s;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
#toast.show {
|
|
opacity: 1;
|
|
transform: translateX(-50%) translateY(0);
|
|
}
|
|
|
|
.toast-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ── LEAFLET POPUP OVERRIDE ── */
|
|
.leaflet-popup-content-wrapper {
|
|
background: var(--panel) !important;
|
|
color: var(--text) !important;
|
|
border: 1px solid var(--panel-border) !important;
|
|
border-radius: var(--radius) !important;
|
|
box-shadow: var(--shadow) !important;
|
|
padding: 0 !important;
|
|
overflow: hidden;
|
|
min-width: 240px;
|
|
}
|
|
|
|
.leaflet-popup-content {
|
|
margin: 0 !important;
|
|
width: auto !important;
|
|
}
|
|
|
|
.leaflet-popup-tip {
|
|
background: var(--panel) !important;
|
|
}
|
|
|
|
.leaflet-popup-close-button {
|
|
color: var(--text-muted) !important;
|
|
font-size: 18px !important;
|
|
top: 10px !important;
|
|
right: 12px !important;
|
|
}
|
|
|
|
.leaflet-popup-close-button:hover {
|
|
color: var(--text) !important;
|
|
}
|
|
|
|
/* ── POPUP CONTENT ── */
|
|
.popup-header {
|
|
background: linear-gradient(135deg, rgba(255,87,34,0.15), rgba(255,167,38,0.08));
|
|
padding: 16px 18px 14px;
|
|
border-bottom: 1px solid var(--panel-border);
|
|
}
|
|
|
|
.popup-header .popup-label {
|
|
font-size: 9px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--fuel-orange);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.popup-header .popup-title {
|
|
font-family: 'Syne', sans-serif;
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.popup-body {
|
|
padding: 14px 18px 16px;
|
|
}
|
|
|
|
.popup-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 9px;
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.popup-row:last-child { margin-bottom: 0; }
|
|
|
|
.popup-row svg { flex-shrink: 0; opacity: 0.7; }
|
|
|
|
.popup-row a { color: var(--fuel-amber); text-decoration: none; }
|
|
.popup-row a:hover { text-decoration: underline; }
|
|
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 3px 10px;
|
|
border-radius: 50px;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.badge-green {
|
|
background: rgba(0,200,150,0.12);
|
|
color: var(--green);
|
|
border: 1px solid rgba(0,200,150,0.2);
|
|
}
|
|
|
|
.badge-red {
|
|
background: rgba(255,71,87,0.12);
|
|
color: var(--red);
|
|
border: 1px solid rgba(255,71,87,0.2);
|
|
}
|
|
|
|
/* ── POPUP FOOTER ── */
|
|
.popup-footer {
|
|
border-top: 1px solid var(--panel-border);
|
|
padding: 10px 18px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
}
|
|
|
|
.drag-hint {
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
opacity: 0.65;
|
|
}
|
|
|
|
.btn-delete {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
background: rgba(255,71,87,0.1);
|
|
color: var(--red);
|
|
border: 1px solid rgba(255,71,87,0.2);
|
|
border-radius: 8px;
|
|
padding: 6px 12px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
font-family: 'DM Sans', sans-serif;
|
|
cursor: pointer;
|
|
transition: background 0.2s, transform 0.15s;
|
|
}
|
|
|
|
.btn-delete:hover { background: rgba(255,71,87,0.22); transform: translateY(-1px); }
|
|
.btn-delete:active { transform: translateY(0); }
|
|
|
|
/* ── FORM POPUP ── */
|
|
.form-popup-header {
|
|
background: linear-gradient(135deg, rgba(255,87,34,0.15), rgba(255,167,38,0.08));
|
|
padding: 14px 18px 12px;
|
|
border-bottom: 1px solid var(--panel-border);
|
|
}
|
|
|
|
.form-popup-header .fp-label {
|
|
font-size: 9px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
color: var(--fuel-orange);
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.form-popup-header .fp-title {
|
|
font-family: 'Syne', sans-serif;
|
|
font-size: 15px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.form-popup-body {
|
|
padding: 14px 18px 18px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.fp-field label {
|
|
display: block;
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--text-muted);
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.fp-field input,
|
|
.fp-field select {
|
|
width: 100%;
|
|
background: rgba(255,255,255,0.05);
|
|
border: 1px solid var(--panel-border);
|
|
border-radius: 8px;
|
|
padding: 9px 12px;
|
|
font-size: 13px;
|
|
font-family: 'DM Sans', sans-serif;
|
|
color: var(--text);
|
|
outline: none;
|
|
transition: border-color 0.2s, background 0.2s;
|
|
-webkit-appearance: none;
|
|
}
|
|
|
|
.fp-field input::placeholder { color: rgba(255,255,255,0.2); }
|
|
|
|
.fp-field input:focus,
|
|
.fp-field select:focus {
|
|
border-color: rgba(255,87,34,0.5);
|
|
background: rgba(255,87,34,0.05);
|
|
}
|
|
|
|
.fp-field select option { background: #1a1d26; color: var(--text); }
|
|
|
|
.fp-btn {
|
|
width: 100%;
|
|
background: linear-gradient(135deg, var(--fuel-orange), var(--fuel-amber));
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 8px;
|
|
padding: 11px;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
font-family: 'Syne', sans-serif;
|
|
letter-spacing: 0.04em;
|
|
cursor: pointer;
|
|
transition: opacity 0.2s, transform 0.15s;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.fp-btn:hover { opacity: 0.88; transform: translateY(-1px); }
|
|
.fp-btn:active { transform: translateY(0); opacity: 1; }
|
|
|
|
/* ── ANIMATIONS ── */
|
|
@keyframes slideDown {
|
|
from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
|
|
to { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; transform: scale(1); }
|
|
50% { opacity: 0.4; transform: scale(0.8); }
|
|
}
|
|
|
|
.leaflet-control-attribution {
|
|
background: rgba(13,15,20,0.7) !important;
|
|
color: #666 !important;
|
|
backdrop-filter: blur(8px);
|
|
border-radius: 6px 0 0 0 !important;
|
|
}
|
|
|
|
.leaflet-control-attribution a { color: #888 !important; }
|
|
|
|
.leaflet-control-zoom a {
|
|
background: var(--panel) !important;
|
|
color: var(--text) !important;
|
|
border-color: var(--panel-border) !important;
|
|
}
|
|
|
|
.leaflet-control-zoom a:hover {
|
|
background: rgba(255,87,34,0.15) !important;
|
|
color: var(--fuel-orange) !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="map"></div>
|
|
|
|
<div id="header">
|
|
<div class="header-icon">⛽</div>
|
|
<div>
|
|
<h1>SPBU Map</h1>
|
|
<p>Pontianak, Kalimantan Barat</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="legend">
|
|
<h3>Keterangan</h3>
|
|
<div class="legend-item"><div class="legend-dot dot-green"></div>Buka 24 Jam</div>
|
|
<div class="legend-item"><div class="legend-dot dot-red"></div>Tidak 24 Jam</div>
|
|
</div>
|
|
|
|
<div id="hint">
|
|
<div class="hint-pulse"></div>
|
|
Klik peta untuk tambah SPBU
|
|
</div>
|
|
|
|
<div id="toast">
|
|
<div class="toast-dot" id="toast-dot"></div>
|
|
<span id="toast-msg"></span>
|
|
</div>
|
|
|
|
<script>
|
|
|
|
// ── TOAST ──
|
|
function showToast(msg, color) {
|
|
const toast = document.getElementById('toast');
|
|
document.getElementById('toast-dot').style.background = color || '#00C896';
|
|
document.getElementById('toast-msg').textContent = msg;
|
|
toast.classList.add('show');
|
|
clearTimeout(toast._t);
|
|
toast._t = setTimeout(() => toast.classList.remove('show'), 2500);
|
|
}
|
|
|
|
// ── ICONS ──
|
|
const greenIcon = new L.Icon({
|
|
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-green.png',
|
|
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
|
|
iconSize: [25, 41], iconAnchor: [12, 41]
|
|
});
|
|
|
|
const redIcon = new L.Icon({
|
|
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png',
|
|
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
|
|
iconSize: [25, 41], iconAnchor: [12, 41]
|
|
});
|
|
|
|
// ── MAP ──
|
|
const map = L.map('map').setView([-0.05538, 109.34947], 16);
|
|
|
|
// ── TILE ──
|
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
maxZoom: 19
|
|
}).addTo(map);
|
|
|
|
// ── LAYER GROUPS (MUST BE HERE) ──
|
|
const layer24 = L.layerGroup();
|
|
const layerNon24 = L.layerGroup();
|
|
|
|
// ── CONTROL ──
|
|
const overlayMaps = {
|
|
"SPBU 24 Jam": layer24,
|
|
"SPBU Tidak 24 Jam": layerNon24
|
|
};
|
|
|
|
L.control.layers(null, overlayMaps, { collapsed: false }).addTo(map);
|
|
|
|
// ── DEFAULT SHOW ──
|
|
layer24.addTo(map);
|
|
layerNon24.addTo(map);
|
|
|
|
// ── BUILD POPUP HTML ──
|
|
function buildPopup(d) {
|
|
const is24 = d.buka_24_jam == 1;
|
|
return `
|
|
<div class="popup-header">
|
|
<div class="popup-label">Stasiun BBM</div>
|
|
<div class="popup-title">${d.nama_spbu}</div>
|
|
</div>
|
|
<div class="popup-body">
|
|
<div class="popup-row">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07A19.5 19.5 0 013.07 10.8a19.79 19.79 0 01-3.07-8.63A2 2 0 012 0h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L6.09 7.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 14h-1.08"/></svg>
|
|
<a href="https://wa.me/${d.nomor_wa}" target="_blank">${d.nomor_wa}</a>
|
|
</div>
|
|
<div class="popup-row">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
<span class="badge ${is24 ? 'badge-green' : 'badge-red'}">${is24 ? '✓ Buka 24 Jam' : '✗ Tidak 24 Jam'}</span>
|
|
</div>
|
|
</div>
|
|
<div class="popup-footer">
|
|
<span class="drag-hint">
|
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="5 9 2 12 5 15"/><polyline points="9 5 12 2 15 5"/><polyline points="15 19 12 22 9 19"/><polyline points="19 9 22 12 19 15"/><line x1="2" y1="12" x2="22" y2="12"/><line x1="12" y1="2" x2="12" y2="22"/></svg>
|
|
Tarik untuk pindah
|
|
</span>
|
|
<button class="btn-delete" onclick="deleteEntry(${d.id}, this)">
|
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14H6L5 6"/><path d="M10 11v6M14 11v6"/><path d="M9 6V4h6v2"/></svg>
|
|
Hapus
|
|
</button>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// ── LOAD & CREATE MARKERS ──
|
|
// Keep a map of id → marker for deletion
|
|
const markerMap = {};
|
|
|
|
function loadData() {
|
|
// CLEAR OLD MARKERS FIRST
|
|
layer24.clearLayers();
|
|
layerNon24.clearLayers();
|
|
|
|
fetch('index.php?get=1')
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
data.forEach(d => addMarker(d));
|
|
});
|
|
}
|
|
|
|
function addMarker(d) {
|
|
const is24 = d.buka_24_jam == 1;
|
|
const marker = L.marker([d.latitude, d.longitude], {
|
|
icon: is24 ? greenIcon : redIcon,
|
|
draggable: true
|
|
});
|
|
|
|
if (is24) {
|
|
marker.addTo(layer24);
|
|
} else {
|
|
marker.addTo(layerNon24);
|
|
}
|
|
|
|
marker.bindPopup(buildPopup(d));
|
|
markerMap[d.id] = marker;
|
|
|
|
// DRAG → AUTO SAVE
|
|
marker.on('dragend', function(e) {
|
|
map.closePopup();
|
|
const { lat, lng } = e.target.getLatLng();
|
|
const fd = new FormData();
|
|
fd.append('move_id', d.id);
|
|
fd.append('move_lat', lat);
|
|
fd.append('move_lng', lng);
|
|
fetch('index.php', { method: 'POST', body: fd })
|
|
.then(() => {
|
|
d.latitude = lat;
|
|
d.longitude = lng;
|
|
showToast('Posisi disimpan ✓', '#FFA726');
|
|
});
|
|
});
|
|
}
|
|
|
|
// ── LAYER GROUPS ──
|
|
loadData();
|
|
|
|
// ── DELETE ──
|
|
function deleteEntry(id) {
|
|
if (!confirm('Hapus SPBU ini?')) return;
|
|
const fd = new FormData();
|
|
fd.append('delete_id', id);
|
|
fetch('index.php', { method: 'POST', body: fd })
|
|
.then(() => {
|
|
map.closePopup();
|
|
if (markerMap[id]) {
|
|
layer24.removeLayer(markerMap[id]);
|
|
layerNon24.removeLayer(markerMap[id]);
|
|
delete markerMap[id];
|
|
}
|
|
showToast('SPBU dihapus', '#FF4757');
|
|
});
|
|
}
|
|
|
|
// ── ADD FORM ──
|
|
function createForm(lat, lng) {
|
|
return `
|
|
<div class="form-popup-header">
|
|
<div class="fp-label">Tambah Titik</div>
|
|
<div class="fp-title">SPBU Baru</div>
|
|
</div>
|
|
<div class="form-popup-body">
|
|
<div class="fp-field">
|
|
<label>Nama SPBU</label>
|
|
<input id="nama" placeholder="Contoh: Pertamina Sungai Raya">
|
|
</div>
|
|
<div class="fp-field">
|
|
<label>Nomor WhatsApp</label>
|
|
<input id="wa" placeholder="628xx...">
|
|
</div>
|
|
<div class="fp-field">
|
|
<label>Buka 24 Jam?</label>
|
|
<select id="buka">
|
|
<option value="1">✓ Iya, 24 Jam</option>
|
|
<option value="0">✗ Tidak</option>
|
|
</select>
|
|
</div>
|
|
<button class="fp-btn" onclick="submitData(${lat}, ${lng})">Simpan SPBU</button>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// ── SUBMIT ──
|
|
function submitData(lat, lng) {
|
|
const nama = document.getElementById('nama').value;
|
|
const wa = document.getElementById('wa').value;
|
|
const buka = document.getElementById('buka').value;
|
|
|
|
const fd = new FormData();
|
|
fd.append('nama', nama);
|
|
fd.append('wa', wa);
|
|
fd.append('buka', buka);
|
|
fd.append('lat', lat);
|
|
fd.append('lng', lng);
|
|
|
|
fetch('index.php', { method: 'POST', body: fd })
|
|
.then(res => res.text())
|
|
.then(() => {
|
|
// Fetch the newly inserted row (last inserted id) by re-fetching all
|
|
// and finding the one not yet in markerMap
|
|
fetch('index.php?get=1')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
data.forEach(d => {
|
|
if (!markerMap[d.id]) addMarker(d);
|
|
});
|
|
});
|
|
map.closePopup();
|
|
showToast('SPBU berhasil disimpan ✓', '#00C896');
|
|
});
|
|
}
|
|
|
|
// ── CLICK MAP → ADD FORM ──
|
|
map.on('click', function(e) {
|
|
L.popup()
|
|
.setLatLng(e.latlng)
|
|
.setContent(createForm(e.latlng.lat, e.latlng.lng))
|
|
.openOn(map);
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|