329 lines
19 KiB
HTML
329 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>SIG Bansos - Tempat Ibadah</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">
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: 'Segoe UI', sans-serif; background: #f0f2f5; }
|
|
#map { height: 70vh; width: 100%; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
|
|
.sidebar { background: white; border-radius: 10px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); height: 70vh; overflow-y: auto; }
|
|
.form-group { margin-bottom: 12px; }
|
|
.form-group label { font-weight: 600; margin-bottom: 3px; display: block; color: #495057; font-size: 13px; }
|
|
.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 8px 10px; border: 1px solid #ced4da; border-radius: 6px; font-size: 13px; }
|
|
.btn { padding: 8px 16px; font-size: 13px; border-radius: 6px; margin-right: 5px; }
|
|
.data-list { max-height: 300px; overflow-y: auto; margin-top: 15px; }
|
|
.data-item { background: #f8f9fa; padding: 10px; margin-bottom: 8px; border-radius: 8px; cursor: pointer; }
|
|
.data-item:hover { background: #e9ecef; }
|
|
.data-item strong { display: block; font-size: 14px; }
|
|
.data-item small { color: #6c757d; font-size: 11px; display: block; }
|
|
.draw-controls { margin-top: 10px; padding: 10px; background: white; border-radius: 8px; display: flex; flex-wrap: wrap; gap: 5px; }
|
|
.draw-status { background: #e8f5e9; padding: 10px; border-radius: 6px; margin-top: 10px; font-size: 13px; border-left: 4px solid #28a745; display: none; }
|
|
.toast-notification { position: fixed; top: 20px; right: 20px; z-index: 10000; min-width: 280px; }
|
|
.leaflet-popup-content-wrapper { border-radius: 12px; padding: 0; overflow: hidden; }
|
|
.leaflet-popup-content { margin: 0 !important; width: 260px; }
|
|
.popup-header { padding: 10px; color: white; font-weight: 600; font-size: 14px; }
|
|
.popup-body { padding: 10px 12px; font-size: 12px; }
|
|
.popup-row { display: flex; justify-content: space-between; margin-bottom: 3px; }
|
|
.popup-label { color: #888; }
|
|
.popup-value { font-weight: 500; }
|
|
.popup-footer { display: flex; border-top: 1px solid #eee; }
|
|
.popup-btn { flex: 1; padding: 8px; border: none; font-size: 11px; cursor: pointer; }
|
|
.popup-btn-edit { background: #fff3cd; color: #856404; }
|
|
.popup-btn-delete { background: #f8d7da; color: #842029; }
|
|
.search-box { margin-bottom: 10px; }
|
|
.border-masjid { border-left: 4px solid #28a745; }
|
|
.border-gereja { border-left: 4px solid #dc3545; }
|
|
.border-klenteng { border-left: 4px solid #ff6f00; }
|
|
.border-vihara { border-left: 4px solid #ff9800; }
|
|
.border-pura { border-left: 4px solid #9c27b0; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<script>
|
|
const user = JSON.parse(sessionStorage.getItem('user'));
|
|
if (!user || user.role !== 'admin') {
|
|
window.location.href = '/login.html';
|
|
}
|
|
</script>
|
|
|
|
<div class="container-fluid p-4">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h4><i class="fas fa-map-marked-alt"></i> SIG Bansos - Tempat Ibadah</h4>
|
|
<button class="btn btn-danger btn-sm" onclick="logout()"><i class="fas fa-sign-out-alt"></i> Logout</button>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<div id="map"></div>
|
|
<div class="draw-controls">
|
|
<button class="btn btn-success btn-sm" onclick="startDrawing('masjid')"><i class="fas fa-mosque"></i> Masjid</button>
|
|
<button class="btn btn-danger btn-sm" onclick="startDrawing('gereja')"><i class="fas fa-church"></i> Gereja</button>
|
|
<button class="btn btn-warning btn-sm" onclick="startDrawing('klenteng')"><i class="fas fa-torii-gate"></i> Klenteng</button>
|
|
<button class="btn btn-warning btn-sm" onclick="startDrawing('vihara')"><i class="fas fa-om"></i> Vihara</button>
|
|
<button class="btn btn-sm" onclick="startDrawing('pura')" style="background:#9c27b0;color:white;"><i class="fas fa-gopuram"></i> Pura</button>
|
|
<button class="btn btn-secondary btn-sm" onclick="cancelDrawing()"><i class="fas fa-times"></i> Batal</button>
|
|
</div>
|
|
<div id="drawStatus" class="draw-status"></div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="sidebar">
|
|
<h5><i class="fas fa-place-of-worship"></i> Form Tempat Ibadah</h5>
|
|
<form id="ibadahForm">
|
|
<input type="hidden" id="ibadahId">
|
|
<div class="form-group"><label>Jenis Ibadah</label><select id="jenisIbadah" class="form-control"><option value="masjid">🕌 Masjid</option><option value="gereja">⛪ Gereja</option><option value="klenteng">🏮 Klenteng</option><option value="vihara">🛕 Vihara</option><option value="pura">🕉️ Pura</option></select></div>
|
|
<div class="form-group"><label>Nama</label><input type="text" id="namaIbadah" class="form-control" placeholder="Nama tempat ibadah" required></div>
|
|
<div class="form-group"><label>Alamat</label><input type="text" id="alamatIbadah" class="form-control" placeholder="Alamat"></div>
|
|
<div class="form-group"><label>No HP</label><input type="text" id="noHpIbadah" class="form-control" placeholder="No HP"></div>
|
|
<div class="form-group"><label>Koordinat</label><input type="text" id="koordinatIbadah" class="form-control" readonly placeholder="Klik pada peta"></div>
|
|
<div class="form-group"><label>Keterangan</label><textarea id="keteranganIbadah" class="form-control" rows="2" placeholder="Keterangan tambahan..."></textarea></div>
|
|
<button type="submit" class="btn btn-primary"><i class="fas fa-save"></i> Simpan</button>
|
|
<button type="button" class="btn btn-danger" onclick="resetForm()"><i class="fas fa-times"></i> Batal</button>
|
|
</form>
|
|
<hr>
|
|
<h6>Daftar Tempat Ibadah</h6>
|
|
<div class="search-box"><input type="text" id="searchIbadah" class="form-control form-control-sm" placeholder="Cari nama..."></div>
|
|
<div style="margin-bottom:8px;">
|
|
<button class="btn btn-outline-success btn-sm" onclick="filterData('masjid')">🕌</button>
|
|
<button class="btn btn-outline-danger btn-sm" onclick="filterData('gereja')">⛪</button>
|
|
<button class="btn btn-outline-warning btn-sm" onclick="filterData('klenteng')">🏮</button>
|
|
<button class="btn btn-outline-warning btn-sm" onclick="filterData('vihara')">🛕</button>
|
|
<button class="btn btn-outline-secondary btn-sm" onclick="filterData('pura')">🕉️</button>
|
|
<button class="btn btn-outline-dark btn-sm" onclick="filterData('semua')">Semua</button>
|
|
</div>
|
|
<div id="ibadahList" class="data-list"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="toast-notification" id="toastNotification"></div>
|
|
|
|
<script>
|
|
function logout() {
|
|
sessionStorage.removeItem('user');
|
|
window.location.href = '/login.html';
|
|
}
|
|
|
|
const API_URL = '/sig-jalan/api_ibadah.php';
|
|
const warna = { masjid: '#28a745', gereja: '#dc3545', klenteng: '#ff6f00', vihara: '#ff9800', pura: '#9c27b0' };
|
|
const ikon = { masjid: 'fa-mosque', gereja: 'fa-church', klenteng: 'fa-torii-gate', vihara: 'fa-om', pura: 'fa-gopuram' };
|
|
|
|
var map = L.map('map').setView([-0.026330, 109.342519], 13);
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19 }).addTo(map);
|
|
|
|
let ibadahData = [];
|
|
let layersIbadah = {};
|
|
let drawingMode = false;
|
|
let currentJenis = 'masjid';
|
|
let currentMarker = null;
|
|
let currentCircle = null;
|
|
let pendingCoord = null;
|
|
let currentFilter = 'semua';
|
|
|
|
function showMsg(msg, type='success') {
|
|
const bg = type==='success'?'bg-success':'bg-danger';
|
|
const icon = type==='success'?'fa-check-circle':'fa-exclamation-circle';
|
|
const el = document.getElementById('toastNotification');
|
|
el.innerHTML = `<div class="alert ${bg} text-white alert-dismissible fade show mb-0"><i class="fas ${icon}"></i> ${msg}<button class="btn-close" data-bs-dismiss="alert"></button></div>`;
|
|
setTimeout(()=>el.innerHTML='',3000);
|
|
}
|
|
|
|
async function apiCall(url, method='GET', data=null) {
|
|
const opt = { method };
|
|
if(data && (method==='POST'||method==='PUT')) {
|
|
opt.headers = {'Content-Type':'application/json'};
|
|
opt.body = JSON.stringify(data);
|
|
}
|
|
const res = await fetch(url, opt);
|
|
return await res.json();
|
|
}
|
|
|
|
async function loadData() {
|
|
const jenisList = ['masjid','gereja','klenteng','vihara','pura'];
|
|
ibadahData = [];
|
|
for(const j of jenisList) {
|
|
const result = await apiCall(API_URL+'?type='+j+'&action=getAll');
|
|
if(result && result.success) {
|
|
result.data.forEach(d => d._jenis = j);
|
|
ibadahData = ibadahData.concat(result.data);
|
|
}
|
|
}
|
|
renderMarkers();
|
|
}
|
|
|
|
function renderMarkers() {
|
|
Object.values(layersIbadah).forEach(l => {
|
|
if(l.marker) map.removeLayer(l.marker);
|
|
if(l.circle) map.removeLayer(l.circle);
|
|
});
|
|
layersIbadah = {};
|
|
|
|
const filtered = currentFilter==='semua' ? ibadahData : ibadahData.filter(d => d._jenis===currentFilter);
|
|
|
|
filtered.forEach(d => {
|
|
const color = warna[d._jenis];
|
|
const icon = L.divIcon({
|
|
html: `<i class="fas ${ikon[d._jenis]}" style="font-size:28px;color:${color}"></i>`,
|
|
className: 'custom-marker', iconSize: [28,28], iconAnchor: [14,28], popupAnchor: [0,-28]
|
|
});
|
|
|
|
const marker = L.marker([parseFloat(d.latitude), parseFloat(d.longitude)], {icon}).addTo(map);
|
|
const circle = L.circle([parseFloat(d.latitude), parseFloat(d.longitude)], {
|
|
radius: d.radius||500, color: color, weight: 2, dashArray: '5,5', fillOpacity: 0.1
|
|
}).addTo(map);
|
|
|
|
marker.bindPopup(`
|
|
<div>
|
|
<div class="popup-header" style="background:${color}"><i class="fas ${ikon[d._jenis]}"></i> ${d.nama}</div>
|
|
<div class="popup-body">
|
|
<div class="popup-row"><span class="popup-label">Jenis</span><span class="popup-value">${d._jenis}</span></div>
|
|
<div class="popup-row"><span class="popup-label">Alamat</span><span class="popup-value">${d.alamat||'-'}</span></div>
|
|
<div class="popup-row"><span class="popup-label">Keterangan</span><span class="popup-value">${d.keterangan||'-'}</span></div>
|
|
</div>
|
|
<div class="popup-footer">
|
|
<button class="popup-btn popup-btn-edit" onclick="editData(${d.id},'${d._jenis}')"><i class="fas fa-edit"></i></button>
|
|
<button class="popup-btn popup-btn-delete" onclick="deleteData(${d.id},'${d._jenis}')"><i class="fas fa-trash"></i></button>
|
|
</div>
|
|
</div>
|
|
`);
|
|
|
|
layersIbadah[d._jenis+'_'+d.id] = {marker, circle};
|
|
});
|
|
displayList();
|
|
}
|
|
|
|
function displayList(data=null) {
|
|
const list = data || (currentFilter==='semua' ? ibadahData : ibadahData.filter(d => d._jenis===currentFilter));
|
|
document.getElementById('ibadahList').innerHTML = list.length ? list.map(d => `
|
|
<div class="data-item border-${d._jenis}" onclick="zoomTo(${d.id},'${d._jenis}')">
|
|
<strong style="color:${warna[d._jenis]}"><i class="fas ${ikon[d._jenis]}"></i> ${d.nama}</strong>
|
|
<small>${d._jenis} | ${d.alamat||'-'}</small>
|
|
</div>
|
|
`).join('') : '<p class="text-muted text-center">Tidak ada data</p>';
|
|
}
|
|
|
|
function startDrawing(jenis) {
|
|
cancelDrawing();
|
|
currentJenis = jenis;
|
|
drawingMode = true;
|
|
document.getElementById('jenisIbadah').value = jenis;
|
|
document.getElementById('drawStatus').style.display = 'block';
|
|
document.getElementById('drawStatus').style.borderLeftColor = warna[jenis];
|
|
document.getElementById('drawStatus').innerHTML = '<i class="fas '+ikon[jenis]+'"></i> Klik peta untuk tentukan lokasi '+jenis;
|
|
map.on('click', onMapClick);
|
|
}
|
|
|
|
function onMapClick(e) {
|
|
if(!drawingMode) return;
|
|
if(currentMarker) map.removeLayer(currentMarker);
|
|
if(currentCircle) map.removeLayer(currentCircle);
|
|
|
|
const lat = e.latlng.lat;
|
|
const lng = e.latlng.lng;
|
|
const color = warna[currentJenis];
|
|
|
|
currentMarker = L.marker([lat,lng], {
|
|
icon: L.divIcon({html:'<i class="fas '+ikon[currentJenis]+'" style="font-size:28px;color:'+color+'"></i>',className:'custom-marker',iconSize:[28,28],iconAnchor:[14,28]}),
|
|
draggable: true
|
|
}).addTo(map);
|
|
|
|
currentCircle = L.circle([lat,lng], {radius:500, color:color, weight:2, dashArray:'5,5', fillOpacity:0.1}).addTo(map);
|
|
|
|
pendingCoord = {lat, lng};
|
|
document.getElementById('koordinatIbadah').value = lat.toFixed(6)+', '+lng.toFixed(6);
|
|
|
|
currentMarker.on('dragend', function() {
|
|
const p = currentMarker.getLatLng();
|
|
pendingCoord = {lat: p.lat, lng: p.lng};
|
|
document.getElementById('koordinatIbadah').value = p.lat.toFixed(6)+', '+p.lng.toFixed(6);
|
|
currentCircle.setLatLng([p.lat, p.lng]);
|
|
});
|
|
}
|
|
|
|
function cancelDrawing() {
|
|
drawingMode = false;
|
|
map.off('click', onMapClick);
|
|
document.getElementById('drawStatus').style.display = 'none';
|
|
if(currentMarker) { map.removeLayer(currentMarker); currentMarker = null; }
|
|
if(currentCircle) { map.removeLayer(currentCircle); currentCircle = null; }
|
|
}
|
|
|
|
function resetForm() {
|
|
document.getElementById('ibadahForm').reset();
|
|
document.getElementById('ibadahId').value = '';
|
|
document.getElementById('koordinatIbadah').value = '';
|
|
pendingCoord = null;
|
|
cancelDrawing();
|
|
}
|
|
|
|
async function saveData(data) {
|
|
const action = data.id ? 'update&id='+data.id : 'create';
|
|
const result = await apiCall(API_URL+'?type='+data._jenis+'&action='+action, data.id?'PUT':'POST', data);
|
|
if(result && result.success) { showMsg('Data berhasil disimpan'); resetForm(); loadData(); }
|
|
else { showMsg(result?.message||'Gagal menyimpan','error'); }
|
|
}
|
|
|
|
async function editData(id, jenis) {
|
|
const d = ibadahData.find(item => item.id===id && item._jenis===jenis);
|
|
if(!d) return;
|
|
document.getElementById('ibadahId').value = d.id;
|
|
document.getElementById('jenisIbadah').value = jenis;
|
|
document.getElementById('namaIbadah').value = d.nama;
|
|
document.getElementById('alamatIbadah').value = d.alamat||'';
|
|
document.getElementById('noHpIbadah').value = d.no_hp||'';
|
|
document.getElementById('koordinatIbadah').value = d.latitude+', '+d.longitude;
|
|
document.getElementById('keteranganIbadah').value = d.keterangan||'';
|
|
pendingCoord = {lat: parseFloat(d.latitude), lng: parseFloat(d.longitude)};
|
|
currentJenis = jenis;
|
|
map.setView([d.latitude, d.longitude], 17);
|
|
}
|
|
|
|
async function deleteData(id, jenis) {
|
|
if(!confirm('Hapus data ini?')) return;
|
|
const result = await apiCall(API_URL+'?type='+jenis+'&action=delete&id='+id, 'DELETE');
|
|
if(result && result.success) { showMsg('Data dihapus'); loadData(); }
|
|
else { showMsg('Gagal menghapus','error'); }
|
|
}
|
|
|
|
function zoomTo(id, jenis) {
|
|
const d = ibadahData.find(item => item.id===id && item._jenis===jenis);
|
|
if(d) map.flyTo([d.latitude, d.longitude], 17);
|
|
}
|
|
|
|
function filterData(jenis) {
|
|
currentFilter = jenis;
|
|
renderMarkers();
|
|
}
|
|
|
|
document.getElementById('searchIbadah').addEventListener('input', function() {
|
|
const kw = this.value.toLowerCase();
|
|
const base = currentFilter==='semua' ? ibadahData : ibadahData.filter(d => d._jenis===currentFilter);
|
|
displayList(base.filter(d => d.nama.toLowerCase().includes(kw)));
|
|
});
|
|
|
|
document.getElementById('ibadahForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
if(!pendingCoord && !document.getElementById('ibadahId').value) {
|
|
showMsg('Klik pada peta dulu!','error'); return;
|
|
}
|
|
saveData({
|
|
id: document.getElementById('ibadahId').value || null,
|
|
_jenis: document.getElementById('jenisIbadah').value,
|
|
nama: document.getElementById('namaIbadah').value,
|
|
alamat: document.getElementById('alamatIbadah').value,
|
|
no_hp: document.getElementById('noHpIbadah').value,
|
|
keterangan: document.getElementById('keteranganIbadah').value,
|
|
latitude: pendingCoord?.lat,
|
|
longitude: pendingCoord?.lng
|
|
});
|
|
});
|
|
|
|
loadData();
|
|
</script>
|
|
</body>
|
|
</html> |