225 lines
8.5 KiB
JavaScript
225 lines
8.5 KiB
JavaScript
// ============================================================
|
||
// WebGIS Kemiskinan Pontianak — map.js (Redesign)
|
||
// ============================================================
|
||
|
||
// Inisialisasi Peta
|
||
const map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 13);
|
||
|
||
// ===== Toast Notification =====
|
||
window.showToast = function(message, type = 'success', duration = 3500) {
|
||
const icons = { success: '✅', error: '❌', info: 'ℹ️', warning: '⚠️' };
|
||
const container = document.getElementById('toastContainer');
|
||
if (!container) return;
|
||
const toast = document.createElement('div');
|
||
toast.className = `toast toast-${type}`;
|
||
toast.innerHTML = `<span class="toast-icon">${icons[type] || 'ℹ️'}</span><span>${message}</span>`;
|
||
container.appendChild(toast);
|
||
setTimeout(() => {
|
||
toast.classList.add('hiding');
|
||
toast.addEventListener('animationend', () => toast.remove());
|
||
}, duration);
|
||
};
|
||
|
||
// ===== Zoom Controls =====
|
||
document.getElementById('zoomInBtn').addEventListener('click', () => map.zoomIn());
|
||
document.getElementById('zoomOutBtn').addEventListener('click', () => map.zoomOut());
|
||
|
||
// ===== Base Map =====
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||
}).addTo(map);
|
||
|
||
// ===== Feature Groups =====
|
||
const rumahIbadahLayer = L.featureGroup().addTo(map);
|
||
const pendudukMiskinLayer = L.featureGroup().addTo(map);
|
||
const geoJsonLayer = L.featureGroup().addTo(map);
|
||
|
||
// ===== Sidebar Collapse =====
|
||
const collapseBtn = document.getElementById('sidebarCollapseBtn');
|
||
const collapseIcon = document.getElementById('collapseIcon');
|
||
|
||
if (collapseBtn) {
|
||
collapseBtn.addEventListener('click', function() {
|
||
const collapsed = document.body.classList.toggle('sidebar-collapsed');
|
||
if (collapseIcon) collapseIcon.className = collapsed ? 'fas fa-chevron-right' : 'fas fa-chevron-left';
|
||
setTimeout(() => map.invalidateSize(), 320);
|
||
});
|
||
}
|
||
|
||
// ===== Search =====
|
||
const searchInput = document.getElementById('searchInput');
|
||
const searchClear = document.getElementById('searchClear');
|
||
const searchResultsEl = document.getElementById('searchResults');
|
||
|
||
searchInput.addEventListener('focus', () => {
|
||
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
|
||
});
|
||
|
||
searchInput.addEventListener('input', function() {
|
||
const val = this.value.toLowerCase().trim();
|
||
if (val.length > 0) {
|
||
searchClear.style.visibility = 'visible';
|
||
window.showSearchResults(val);
|
||
} else {
|
||
searchClear.style.visibility = 'hidden';
|
||
searchResultsEl.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
searchClear.addEventListener('click', function() {
|
||
searchInput.value = '';
|
||
searchClear.style.visibility = 'hidden';
|
||
searchResultsEl.style.display = 'none';
|
||
searchInput.focus();
|
||
});
|
||
|
||
document.addEventListener('click', function(e) {
|
||
if (!e.target.closest('.search-bar') && !e.target.closest('#searchResults')) {
|
||
searchResultsEl.style.display = 'none';
|
||
}
|
||
});
|
||
|
||
window.showSearchResults = function(query) {
|
||
searchResultsEl.innerHTML = '';
|
||
let results = [];
|
||
|
||
if (typeof rumahIbadahLayer !== 'undefined') {
|
||
rumahIbadahLayer.eachLayer(layer => {
|
||
if (layer.ibadahData?.nama?.toLowerCase().includes(query) && layer instanceof L.Marker) {
|
||
results.push({ type: 'Rumah Ibadah', icon: '🕌', nama: layer.ibadahData.nama, layer });
|
||
}
|
||
});
|
||
}
|
||
|
||
if (results.length === 0) {
|
||
searchResultsEl.innerHTML = '<div class="search-result-item" style="color:#94a3b8;">Tidak ada hasil ditemukan</div>';
|
||
} else {
|
||
results.forEach(res => {
|
||
const item = document.createElement('div');
|
||
item.className = 'search-result-item';
|
||
item.innerHTML = `<span>${res.icon}</span><span><strong style="font-size:10px; color:#94a3b8; text-transform:uppercase;">${res.type}</strong><br>${res.nama}</span>`;
|
||
item.addEventListener('click', () => {
|
||
if (res.layer instanceof L.Marker) {
|
||
map.setView(res.layer.getLatLng(), 17);
|
||
} else if (res.layer.getBounds) {
|
||
map.fitBounds(res.layer.getBounds());
|
||
}
|
||
res.layer.openPopup();
|
||
searchResultsEl.style.display = 'none';
|
||
searchInput.value = res.nama;
|
||
searchClear.style.visibility = 'visible';
|
||
});
|
||
searchResultsEl.appendChild(item);
|
||
});
|
||
}
|
||
searchResultsEl.style.display = 'block';
|
||
};
|
||
|
||
// ===== Layer Panel Toggle =====
|
||
const layerBtn = document.getElementById('layerBtn');
|
||
const layerPanel = document.getElementById('layerPanel');
|
||
|
||
layerBtn.addEventListener('click', function() {
|
||
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
|
||
const isOpen = layerPanel.classList.toggle('show');
|
||
layerBtn.classList.toggle('active', isOpen);
|
||
});
|
||
|
||
map.on('click', function() {
|
||
layerPanel.classList.remove('show');
|
||
layerBtn.classList.remove('active');
|
||
});
|
||
|
||
// ===== Layer Visibility =====
|
||
document.getElementById('layerRumahIbadah').addEventListener('change', function(e) {
|
||
e.target.checked ? map.addLayer(rumahIbadahLayer) : map.removeLayer(rumahIbadahLayer);
|
||
});
|
||
|
||
document.getElementById('layerMiskin').addEventListener('change', function(e) {
|
||
e.target.checked ? map.addLayer(pendudukMiskinLayer) : map.removeLayer(pendudukMiskinLayer);
|
||
});
|
||
|
||
window.toggleSubLayer = function(subId, iconEl) {
|
||
const sub = document.getElementById(subId);
|
||
if (!sub) return;
|
||
const isHidden = sub.style.display === 'none';
|
||
sub.style.display = isHidden ? '' : 'none';
|
||
iconEl.classList.toggle('collapsed', !isHidden);
|
||
};
|
||
|
||
window.applySubFilter = function(type) {
|
||
if (type === 'miskin') {
|
||
const checked = [...document.querySelectorAll('.sub-miskin:checked')].map(el => el.value);
|
||
pendudukMiskinLayer.eachLayer(layer => {
|
||
if (!layer.miskinData) return;
|
||
const el = layer.getElement?.();
|
||
if (el) el.style.display = checked.includes(layer.miskinData.kategori_bantuan) ? '' : 'none';
|
||
});
|
||
}
|
||
};
|
||
|
||
// ===== Modal Logic =====
|
||
const unifiedModal = document.getElementById('unifiedModal');
|
||
|
||
window.openModal = function(title, bodyHTML, saveCallback) {
|
||
document.getElementById('modalTitle').textContent = title;
|
||
document.getElementById('modalBody').innerHTML = bodyHTML;
|
||
unifiedModal.classList.add('show');
|
||
|
||
const oldBtn = document.getElementById('modalSaveBtn');
|
||
const newBtn = oldBtn.cloneNode(true);
|
||
oldBtn.parentNode.replaceChild(newBtn, oldBtn);
|
||
newBtn.addEventListener('click', saveCallback);
|
||
};
|
||
|
||
window.closeModal = function() { unifiedModal.classList.remove('show'); };
|
||
|
||
const confirmModal = document.getElementById('confirmModal');
|
||
|
||
window.openConfirmModal = function(msg, confirmCallback) {
|
||
document.getElementById('confirmMessage').textContent = msg;
|
||
confirmModal.classList.add('show');
|
||
|
||
const oldBtn = document.getElementById('confirmYesBtn');
|
||
const newBtn = oldBtn.cloneNode(true);
|
||
oldBtn.parentNode.replaceChild(newBtn, oldBtn);
|
||
newBtn.addEventListener('click', function() {
|
||
confirmModal.classList.remove('show');
|
||
confirmCallback();
|
||
});
|
||
};
|
||
|
||
window.closeConfirmModal = function() { confirmModal.classList.remove('show'); };
|
||
|
||
// ===== Add Mode =====
|
||
window.currentAddMode = null;
|
||
|
||
window.activateAddMode = function(mode) {
|
||
if (window.currentAddMode === mode) { window.deactivateAddMode(); return; }
|
||
window.currentAddMode = mode;
|
||
const tooltips = { 'rumah_ibadah': 'Klik peta untuk tambah Rumah Ibadah' };
|
||
if (window.cursorTooltip && tooltips[mode]) window.cursorTooltip.textContent = tooltips[mode];
|
||
document.getElementById('map').style.cursor = 'crosshair';
|
||
};
|
||
|
||
window.deactivateAddMode = function() {
|
||
window.currentAddMode = null;
|
||
document.getElementById('map').style.cursor = '';
|
||
if (window.cursorTooltip) window.cursorTooltip.style.display = 'none';
|
||
};
|
||
|
||
// ===== Cursor Tooltip =====
|
||
window.cursorTooltip = document.createElement('div');
|
||
window.cursorTooltip.className = 'custom-cursor-tooltip';
|
||
document.body.appendChild(window.cursorTooltip);
|
||
|
||
document.addEventListener('mousemove', function(e) {
|
||
if (window.currentAddMode) {
|
||
window.cursorTooltip.style.display = 'block';
|
||
window.cursorTooltip.style.left = e.pageX + 15 + 'px';
|
||
window.cursorTooltip.style.top = e.pageY + 15 + 'px';
|
||
} else {
|
||
window.cursorTooltip.style.display = 'none';
|
||
}
|
||
});
|