UAS SIG Proyek WebGis

This commit is contained in:
L4zyL4mb
2026-06-10 21:46:56 +07:00
commit df18a7a99a
35 changed files with 8977 additions and 0 deletions
+293
View File
@@ -0,0 +1,293 @@
<?php
require_once 'db_connect.php';
$message = "";
$edit_data = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'insert') {
$stmt = $pdo->prepare("INSERT INTO spbu (nama, no, status, latitude, longitude) VALUES (:nama,:no,:status,:lat,:lng)");
$stmt->execute([':nama'=>trim($_POST['nama']),':no'=>trim($_POST['no']),':status'=>isset($_POST['status'])?1:0,':lat'=>floatval($_POST['latitude']),':lng'=>floatval($_POST['longitude'])]);
$message = ['type'=>'success','text'=>'Data SPBU berhasil ditambahkan!'];
}
if ($_POST['action'] === 'update') {
$stmt = $pdo->prepare("UPDATE spbu SET nama=:nama,no=:no,status=:status,latitude=:lat,longitude=:lng WHERE id=:id");
$stmt->execute([':nama'=>trim($_POST['nama']),':no'=>trim($_POST['no']),':status'=>isset($_POST['status'])?1:0,':lat'=>floatval($_POST['latitude']),':lng'=>floatval($_POST['longitude']),':id'=>intval($_POST['id'])]);
$message = ['type'=>'success','text'=>'Data berhasil diperbarui!'];
}
if ($_POST['action'] === 'delete') {
$pdo->prepare("DELETE FROM spbu WHERE id=:id")->execute([':id'=>intval($_POST['id'])]);
$message = ['type'=>'danger','text'=>'Data berhasil dihapus.'];
}
}
if (isset($_GET['edit'])) {
$stmt = $pdo->prepare("SELECT * FROM spbu WHERE id=:id");
$stmt->execute([':id'=>intval($_GET['edit'])]);
$edit_data = $stmt->fetch(PDO::FETCH_ASSOC);
}
$all = $pdo->query("SELECT * FROM spbu ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Input SPBU — WebGIS Pontianak</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--bg:#f5f4f0;--card:#fff;--border:#e8e5df;--border2:#d4d0c8;
--text:#1a1915;--muted:#7c7a72;--hint:#b0ada5;
--accent:#e85a1a;--accent-bg:#fdf0eb;--accent-dk:#c44a12;
--green:#1a7a45;--green-bg:#ebf7f0;
--red:#c0392b;--red-bg:#fdf0ef;
--r:10px;--r-sm:7px;
--shadow:0 1px 2px rgba(0,0,0,.05),0 3px 12px rgba(0,0,0,.04);
}
body{font-family:'Plus Jakarta Sans',sans-serif;background:var(--bg);color:var(--text);font-size:14px;line-height:1.5}
/* TOP NAV */
.topnav{background:var(--card);border-bottom:1px solid var(--border);height:54px;padding:0 24px;display:flex;align-items:center;gap:6px;position:sticky;top:0;z-index:9999}
.brand{display:flex;align-items:center;gap:9px;font-weight:700;font-size:14px;color:var(--text);text-decoration:none;margin-right:auto}
.brand-mark{width:30px;height:30px;background:var(--accent);border-radius:8px;display:grid;place-items:center;color:#fff;font-size:14px;font-weight:800;letter-spacing:-.5px}
.nav-a{padding:5px 13px;border-radius:var(--r-sm);font-size:13px;font-weight:500;color:var(--muted);text-decoration:none;transition:.12s}
.nav-a:hover{background:var(--bg);color:var(--text)}
.nav-a.on{background:var(--accent-bg);color:var(--accent);font-weight:600}
/* PAGE */
.page{max-width:1140px;margin:0 auto;padding:24px 20px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media(max-width:840px){.grid2{grid-template-columns:1fr}}
/* CARD */
.card{background:var(--card);border:1px solid var(--border);border-radius:var(--r);box-shadow:var(--shadow)}
.ch{padding:16px 18px 13px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px}
.ch-icon{width:30px;height:30px;border-radius:var(--r-sm);background:var(--bg);display:grid;place-items:center;font-size:14px;flex-shrink:0}
.ch h2{font-size:13px;font-weight:600;color:var(--text)}
.cb{padding:18px}
/* ALERT */
.alert{display:flex;align-items:center;gap:8px;padding:10px 14px;border-radius:var(--r-sm);margin-bottom:18px;font-size:13px;font-weight:500}
.alert.success{background:var(--green-bg);color:var(--green)}
.alert.danger{background:var(--red-bg);color:var(--red)}
/* MAP */
#map{height:310px;border-radius:var(--r-sm);border:1px solid var(--border);overflow:hidden}
.map-tip{margin-top:8px;font-size:12px;color:var(--hint);display:flex;align-items:center;gap:4px}
.coord-tag{display:none;margin-top:10px;background:var(--accent-bg);border:1px solid #f0c5ae;border-radius:20px;padding:4px 12px;font-size:12px;font-weight:500;color:var(--accent);width:fit-content}
/* FORM */
.fg{margin-bottom:13px}
.fg label{display:block;font-size:11px;font-weight:600;color:var(--hint);text-transform:uppercase;letter-spacing:.5px;margin-bottom:5px}
.fg input[type=text],.fg input[type=number]{width:100%;padding:8px 11px;border:1px solid var(--border2);border-radius:var(--r-sm);font-family:inherit;font-size:13px;color:var(--text);background:#fff;transition:.12s}
.fg input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(232,90,26,.09)}
.cols2{display:grid;grid-template-columns:1fr 1fr;gap:9px}
/* TOGGLE */
.trow{display:flex;align-items:center;gap:9px;padding:8px 0}
.sw{position:relative;width:36px;height:19px;flex-shrink:0}
.sw input{opacity:0;position:absolute;width:0;height:0}
.sw-t{position:absolute;inset:0;background:var(--border2);border-radius:20px;cursor:pointer;transition:.18s}
.sw-t::after{content:'';position:absolute;width:13px;height:13px;background:#fff;border-radius:50%;top:3px;left:3px;transition:.18s}
.sw input:checked~.sw-t{background:var(--green)}
.sw input:checked~.sw-t::after{transform:translateX(17px)}
.trow span{font-size:13px;font-weight:500}
/* BUTTONS */
.btn{display:inline-flex;align-items:center;gap:5px;padding:8px 16px;border-radius:var(--r-sm);font-family:inherit;font-size:13px;font-weight:600;border:none;cursor:pointer;transition:.12s;text-decoration:none}
.btn-p{background:var(--accent);color:#fff}
.btn-p:hover{background:var(--accent-dk)}
.btn-g{background:transparent;color:var(--muted);border:1px solid var(--border2)}
.btn-g:hover{background:var(--bg);color:var(--text)}
.btn-xs{padding:4px 10px;font-size:11px;border-radius:6px}
.btn-edit{background:transparent;color:var(--accent);border:1px solid #f0c5ae}
.btn-edit:hover{background:var(--accent-bg)}
.btn-del{background:transparent;color:var(--red);border:1px solid #f0c4bf}
.btn-del:hover{background:var(--red-bg)}
.btn-row{display:flex;gap:8px;margin-top:16px}
/* TABLE */
.tw{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
th{padding:9px 14px;text-align:left;font-size:11px;font-weight:600;color:var(--hint);text-transform:uppercase;letter-spacing:.5px;border-bottom:1px solid var(--border);white-space:nowrap}
td{padding:10px 14px;border-bottom:1px solid var(--bg);vertical-align:middle}
tr:last-child td{border-bottom:none}
tr:hover td{background:#fafaf8}
.badge{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:600}
.b-open{background:var(--green-bg);color:var(--green)}
.b-closed{background:var(--bg);color:var(--hint);border:1px solid var(--border)}
.acts{display:flex;gap:5px}
.mono{font-family:'Courier New',monospace;font-size:12px;color:var(--muted)}
.empty{text-align:center;padding:40px;color:var(--hint)}
.pill{background:var(--bg);border:1px solid var(--border);border-radius:20px;padding:1px 8px;font-size:11px;color:var(--hint);margin-left:6px}
</style>
</head>
<body>
<nav class="topnav">
<a href="index.php" class="brand">
<div class="brand-mark">S</div>
WebGIS SPBU Pontianak
</a>
<a href="insert.php" class="nav-a on">Input Data</a>
<a href="index.php" class="nav-a">Lihat Peta</a>
</nav>
<div class="page">
<?php if($message): ?>
<div class="alert <?= $message['type'] ?>">
<?= $message['type']==='success' ? '✓' : '✕' ?> <?= $message['text'] ?>
</div>
<?php endif; ?>
<div class="grid2">
<div class="card">
<div class="ch"><div class="ch-icon">📍</div><h2>Klik Peta — Tentukan Lokasi</h2></div>
<div class="cb">
<div id="map"></div>
<div class="map-tip">Klik titik mana saja untuk mengisi koordinat otomatis</div>
<div class="coord-tag" id="coord-tag"></div>
</div>
</div>
<div class="card">
<div class="ch">
<div class="ch-icon"><?= $edit_data ? '✏️' : '' ?></div>
<h2><?= $edit_data ? 'Edit Data SPBU' : 'Tambah SPBU Baru' ?></h2>
</div>
<div class="cb">
<form method="POST">
<input type="hidden" name="action" value="<?= $edit_data ? 'update' : 'insert' ?>">
<?php if($edit_data): ?>
<input type="hidden" name="id" value="<?= $edit_data['id'] ?>">
<?php endif; ?>
<div class="fg">
<label>Nama SPBU</label>
<input type="text" name="nama" placeholder="cth: SPBU Jl. Ahmad Yani"
value="<?= htmlspecialchars($edit_data['nama'] ?? '') ?>" required>
</div>
<div class="fg">
<label>Nomor SPBU</label>
<input type="text" name="no" placeholder="cth: 64.751.01"
value="<?= htmlspecialchars($edit_data['no'] ?? '') ?>" required>
</div>
<div class="fg">
<label>Status Operasional</label>
<div class="trow">
<label class="sw">
<input type="checkbox" name="status" id="chk" <?= ($edit_data['status'] ?? 0) ? 'checked' : '' ?>>
<span class="sw-t"></span>
</label>
<span>Buka 24 Jam</span>
</div>
</div>
<div class="fg">
<label>Koordinat</label>
<div class="cols2">
<input type="number" name="latitude" id="inp-lat" step="any" placeholder="Latitude"
value="<?= $edit_data['latitude'] ?? '' ?>" required>
<input type="number" name="longitude" id="inp-lng" step="any" placeholder="Longitude"
value="<?= $edit_data['longitude'] ?? '' ?>" required>
</div>
</div>
<div class="btn-row">
<button type="submit" class="btn btn-p"><?= $edit_data ? '💾 Simpan' : '📍 Simpan SPBU' ?></button>
<?php if($edit_data): ?><a href="insert.php" class="btn btn-g">Batal</a><?php endif; ?>
</div>
</form>
</div>
</div>
</div>
<!-- TABEL -->
<div class="card" style="margin-top:18px">
<div class="ch">
<div class="ch-icon">📋</div>
<h2>Daftar SPBU <span class="pill"><?= count($all) ?> data</span></h2>
</div>
<div class="tw">
<?php if(!count($all)): ?>
<div class="empty">Belum ada data. Tambahkan SPBU lewat form di atas.</div>
<?php else: ?>
<table>
<thead><tr><th>#</th><th>Nama</th><th>No</th><th>Status</th><th>Latitude</th><th>Longitude</th><th>Aksi</th></tr></thead>
<tbody>
<?php foreach($all as $i=>$r): ?>
<tr>
<td style="color:var(--hint)"><?= $i+1 ?></td>
<td style="font-weight:600"><?= htmlspecialchars($r['nama']) ?></td>
<td style="color:var(--muted)"><?= htmlspecialchars($r['no']) ?></td>
<td><span class="badge <?= $r['status']?'b-open':'b-closed' ?>"><?= $r['status']?'● 24 Jam':'○ Terbatas' ?></span></td>
<td class="mono"><?= number_format($r['latitude'],6) ?></td>
<td class="mono"><?= number_format($r['longitude'],6) ?></td>
<td>
<div class="acts">
<a href="?edit=<?= $r['id'] ?>" class="btn btn-xs btn-edit">Edit</a>
<form method="POST" style="display:inline" onsubmit="return confirm('Hapus SPBU ini?')">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?= $r['id'] ?>">
<button type="submit" class="btn btn-xs btn-del">Hapus</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const map=L.map('map').setView([-0.0263,109.3425],13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{attribution:'© OSM',maxZoom:19}).addTo(map);
function mkIcon(color,big){
const s=big?32:26;
return L.divIcon({className:'',
html:`<div style="width:${s}px;height:${s}px;border-radius:50%;background:${color};border:2px solid #fff;box-shadow:0 2px 8px rgba(0,0,0,.2);display:grid;place-items:center;font-size:${big?15:12}px;">⛽</div>`,
iconSize:[s,s],iconAnchor:[s/2,s/2],popupAnchor:[0,-s/2]});
}
let marker=null;
<?php if($edit_data): ?>
marker=L.marker([<?= $edit_data['latitude'] ?>,<?= $edit_data['longitude'] ?>],{icon:mkIcon('#e85a1a',true),draggable:true}).addTo(map);
map.setView([<?= $edit_data['latitude'] ?>,<?= $edit_data['longitude'] ?>],16);
marker.on('dragend',e=>{const p=e.target.getLatLng();setCoord(p.lat.toFixed(6),p.lng.toFixed(6));});
setCoord(<?= $edit_data['latitude'] ?>,<?= $edit_data['longitude'] ?>);
<?php endif; ?>
<?= json_encode($all) ?>.forEach(s=>{
L.marker([s.latitude,s.longitude],{icon:mkIcon(s.status==1?'#1a7a45':'#b0ada5',false)})
.addTo(map).bindPopup(`<b>${s.nama}</b><br>${s.no}<br>${s.status==1?'24 Jam':'Terbatas'}`);
});
map.on('click',e=>{
const lat=e.latlng.lat.toFixed(6),lng=e.latlng.lng.toFixed(6);
if(marker) map.removeLayer(marker);
marker=L.marker([lat,lng],{icon:mkIcon('#e85a1a',true),draggable:true}).addTo(map);
marker.on('dragend',ev=>{const p=ev.target.getLatLng();setCoord(p.lat.toFixed(6),p.lng.toFixed(6));});
setCoord(lat,lng);
});
function setCoord(lat,lng){
document.getElementById('inp-lat').value=lat;
document.getElementById('inp-lng').value=lng;
const t=document.getElementById('coord-tag');
t.textContent=`📍 ${lat}, ${lng}`;
t.style.display='block';
}
</script>
</body>
</html>