// modules/point.js — Logika Pertemuan 1: Point of Interest (POI) // Dipanggil oleh index.php saat mode = 1 (function () { // ── Layer group ────────────────────────────────── const layerGroup = L.layerGroup(); let allMarkers = {}; // { id: markerObject } let tempMarker = null; let active = false; // ── Custom Icons ───────────────────────────────── function createIcon(color = '#2ea043') { return L.divIcon({ className: '', html: ` `, iconSize: [28, 38], iconAnchor: [14, 38], popupAnchor: [0, -40] }); } const iconDefault = createIcon('#2ea043'); const iconClosed = createIcon('#f85149'); const iconTemp = createIcon('#e3b341'); // ── Render marker on map ───────────────────────── function addMarkerToMap(poi) { const isOpen = Number(poi.buka_24jam) === 1; const marker = L.marker( [poi.latitude, poi.longitude], { icon: isOpen ? iconDefault : iconClosed, draggable: window._IS_ADMIN, pane: 'pointPane' } ); marker._poiId = poi.id; marker._poiNama = poi.nama_tempat; marker._poiBuka = Number(poi.buka_24jam) === 1; allMarkers[poi.id] = marker; if (window._IS_ADMIN) { // Drag to update position marker.on('dragend', function (e) { const { lat, lng } = e.target.getLatLng(); const fd = new FormData(); fd.append('id', poi.id); fd.append('latitude', lat.toFixed(8)); fd.append('longitude', lng.toFixed(8)); fd.append('csrf_token', window._CSRF_TOKEN || ''); fetch('api/point/update_posisi.php', { method: 'POST', body: fd }) .then(r => r.json()) .then(j => { if (j.status === 'success') showToast(`Posisi "${escapeHTML(poi.nama_tempat)}" diperbarui!`); else throw new Error(j.message); }) .catch(err => showToast(err.message || 'Gagal update posisi.', 'error')); }); } // Popup info const noWa = poi.no_wa ? poi.no_wa.replace(/\D/g, '') : ''; const waBtn = noWa ? ` Chat WhatsApp ` : `
Tidak ada nomor WA
`; const buka24Badge = isOpen ? ` Buka 24 Jam` : ` Tidak 24 Jam`; const deleteBtn = window._IS_ADMIN ? `` : ''; marker.bindPopup(`
${escapeHTML(poi.nama_tempat)}
#${poi.id}
No. WhatsApp
${poi.no_wa ? escapeHTML(poi.no_wa) : '—'}
Jam Operasional
${buka24Badge}
Koordinat
${parseFloat(poi.latitude).toFixed(6)}, ${parseFloat(poi.longitude).toFixed(6)}
${waBtn} ${deleteBtn}
`, { maxWidth: 300 }); layerGroup.addLayer(marker); } // ── Load semua POI dari server ────────────────── function loadData() { layerGroup.clearLayers(); allMarkers = {}; fetch('api/point/ambil.php?_=' + Date.now(), { cache: 'no-store' }) .then(r => r.json()) .then(j => { if (j.status !== 'success') throw new Error(j.message); updateCount(j.total, 'Point'); j.data.forEach(addMarkerToMap); refreshPointList(j.data); }) .catch(err => { showToast('Gagal memuat data POI.', 'error'); console.error(err); }); } // ── Refresh panel list Lokasi Usaha ────────────────── function refreshPointList(data) { if (typeof window.dlRefreshList !== 'function') return; const items = (data || []).map(poi => ({ id: poi.id, name: poi.nama_tempat, badge: Number(poi.buka_24jam) === 1 ? '24 Jam' : 'Non-24', badgeColor: Number(poi.buka_24jam) === 1 ? '#2ea043' : '#f85149', dotColor: Number(poi.buka_24jam) === 1 ? '#2ea043' : '#f85149' })); window.dlRefreshList('Point', items); } // ── Hapus marker ──────────────────────────────────── window._pointHapus = function (id, btnEl) { showDeleteConfirm('Yakin ingin menghapus lokasi ini?').then(confirmed => { if (!confirmed) return; btnEl.disabled = true; btnEl.innerHTML = ' Menghapus...'; const fd = new FormData(); fd.append('id', id); fd.append('csrf_token', window._CSRF_TOKEN || ''); fetch('api/point/hapus.php', { method: 'POST', body: fd }) .then(r => r.json()) .then(j => { if (j.status === 'success') { map.closePopup(); if (allMarkers[id]) { layerGroup.removeLayer(allMarkers[id]); delete allMarkers[id]; } updateCount(Math.max(0, Object.keys(allMarkers).length), 'Point'); // rebuild list dari allMarkers (ambil nama dari marker) const remaining = Object.keys(allMarkers).map(k => ({ id: k, name: allMarkers[k]._poiNama || ('#' + k), badge: allMarkers[k]._poiBuka ? '24 Jam' : 'Non-24', badgeColor: allMarkers[k]._poiBuka ? '#2ea043' : '#f85149', dotColor: allMarkers[k]._poiBuka ? '#2ea043' : '#f85149' })); if (typeof window.dlRefreshList === 'function') window.dlRefreshList('Point', remaining); showToast('Lokasi berhasil dihapus.'); } else throw new Error(j.message); }) .catch(err => { showToast(err.message || 'Gagal menghapus.', 'error'); btnEl.disabled = false; btnEl.innerHTML = ' Hapus Lokasi'; if (typeof lucide !== 'undefined') lucide.createIcons(); }); }); }; // ── Klik peta = form tambah POI ────────────────── function onMapClick(e) { if (currentMode !== 1) return; const lat = e.latlng.lat.toFixed(8); const lng = e.latlng.lng.toFixed(8); if (tempMarker) map.removeLayer(tempMarker); tempMarker = L.marker([lat, lng], { icon: iconTemp, pane: 'drawPane' }).addTo(map); L.popup({ maxWidth: 320, closeOnClick: false }) .setLatLng(e.latlng) .setContent(`
Tambah Lokasi Baru
${lat}, ${lng}
`) .openOn(map); setTimeout(() => { const el = document.getElementById('f_nama'); if (el) el.focus(); }, 200); } // ── Simpan POI ──────────────────────────────────── window._pointSimpan = function () { const nama = document.getElementById('f_nama').value.trim(); const wa = document.getElementById('f_wa').value.trim(); const buka24 = document.getElementById('f_buka24').value; const lat = document.getElementById('f_lat').value; const lng = document.getElementById('f_lng').value; const status = document.getElementById('poiStatus'); const btn = document.getElementById('btnSimpanPoi'); if (!nama) { status.innerHTML = ' Nama tempat wajib diisi.'; status.className = 'form-status error'; if (typeof lucide !== 'undefined') lucide.createIcons(); document.getElementById('f_nama').focus(); return; } btn.disabled = true; btn.innerHTML = ' Menyimpan...'; const fd = new FormData(); fd.append('nama_tempat', nama); fd.append('no_wa', wa); fd.append('buka_24jam', buka24); fd.append('latitude', lat); fd.append('longitude', lng); fd.append('csrf_token', window._CSRF_TOKEN || ''); fetch('api/point/simpan.php', { method: 'POST', body: fd }) .then(r => r.json()) .then(j => { if (j.status === 'success') { map.closePopup(); if (tempMarker) { map.removeLayer(tempMarker); tempMarker = null; } addMarkerToMap(j.data); updateCount(Object.keys(allMarkers).length, 'Point'); // Tambahkan item baru ke list const allItems = Object.values(allMarkers).map(m => ({ id: m._poiId, name: m._poiNama || ('#' + m._poiId), badge: m._poiBuka ? '24 Jam' : 'Non-24', badgeColor: m._poiBuka ? '#2ea043' : '#f85149', dotColor: m._poiBuka ? '#2ea043' : '#f85149' })); if (typeof window.dlRefreshList === 'function') window.dlRefreshList('Point', allItems); showToast(`"${escapeHTML(nama)}" berhasil disimpan!`); } else throw new Error(j.message); }) .catch(err => { status.innerHTML = ' ' + escapeHTML(err.message); status.className = 'form-status error'; btn.disabled = false; btn.innerHTML = ' Simpan Lokasi'; if (typeof lucide !== 'undefined') lucide.createIcons(); }); }; // ── Init / cleanup ──────────────────────────────────── window.initPoint = function () { if (active) { /* already added to map, just refresh data if needed */ loadData(); return; } active = true; layerGroup.addTo(map); map.on('click', onMapClick); // Daftarkan fungsi focus untuk panel list window._dlFocusFns['Point'] = function(id) { const marker = allMarkers[id]; if (!marker) return; map.setView(marker.getLatLng(), Math.max(map.getZoom(), 17), { animate: true }); setTimeout(() => marker.openPopup(), 350); }; loadData(); }; // Filter Toggle window._pointToggleLayer = function(visible) { if (visible) { map.addLayer(layerGroup); } else { map.removeLayer(layerGroup); // Juga tutup popup & bersihkan titik sementara jika ada if (tempMarker) { map.removeLayer(tempMarker); tempMarker = null; } } }; })();