533 lines
23 KiB
JavaScript
533 lines
23 KiB
JavaScript
// ===== Panel Management =====
|
|
// Mengelola Left Sidebar Toggle + Right Panel + Layer Control
|
|
|
|
(function () {
|
|
// ---- Konstanta Jenis Ibadah ----
|
|
const IBADAH_EMOJI = {
|
|
'Masjid': '🕌',
|
|
'Gereja': '⛪',
|
|
'Pura': '🛕',
|
|
'Vihara': '🪷',
|
|
'Kelenteng': '🏮',
|
|
};
|
|
window.IBADAH_EMOJI = IBADAH_EMOJI;
|
|
|
|
// ---- State ----
|
|
let activePanel = null;
|
|
|
|
// ---- Elements ----
|
|
// removed
|
|
// removed
|
|
const leftSidebar = document.getElementById('leftSidebar');
|
|
const rightPanel = document.getElementById('rightPanel');
|
|
const rightPanelTitle = document.getElementById('rightPanelTitle');
|
|
const rightPanelActions = document.getElementById('rightPanelActions');
|
|
const rightPanelBody = document.getElementById('rightPanelBody');
|
|
const rightPanelClose = document.getElementById('rightPanelClose');
|
|
|
|
// Sidebar collapse handled in map.js
|
|
|
|
// ---- Sidebar Buttons ----
|
|
document.querySelectorAll('.sidebar-btn').forEach(btn => {
|
|
btn.addEventListener('click', function () {
|
|
const panel = this.dataset.panel;
|
|
if (activePanel === panel) {
|
|
closePanel();
|
|
} else {
|
|
openPanel(panel);
|
|
}
|
|
});
|
|
});
|
|
|
|
rightPanelClose.addEventListener('click', closePanel);
|
|
|
|
// ---- Open / Close Panel ----
|
|
function openPanel(panel) {
|
|
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
|
|
activePanel = panel;
|
|
rightPanel.classList.add('open');
|
|
document.body.classList.add('right-panel-open');
|
|
document.querySelectorAll('.sidebar-btn').forEach(b => b.classList.remove('active'));
|
|
const activeBtn = document.querySelector(`.sidebar-btn[data-panel="${panel}"]`);
|
|
if (activeBtn) activeBtn.classList.add('active');
|
|
renderPanel(panel);
|
|
}
|
|
|
|
function closePanel() {
|
|
if (typeof window.deactivateAddMode === 'function') window.deactivateAddMode();
|
|
activePanel = null;
|
|
rightPanel.classList.remove('open');
|
|
document.body.classList.remove('right-panel-open');
|
|
document.querySelectorAll('.sidebar-btn').forEach(b => b.classList.remove('active'));
|
|
}
|
|
|
|
window.refreshActivePanel = function () {
|
|
if (activePanel && activePanel !== 'layer') renderPanel(activePanel);
|
|
};
|
|
|
|
// ---- Render Panel by Type ----
|
|
function renderPanel(type) {
|
|
rightPanelBody.innerHTML = '<div class="panel-empty">Memuat data...</div>';
|
|
rightPanelActions.innerHTML = '';
|
|
|
|
switch (type) {
|
|
case 'ibadah': renderIbadahPanel(); break;
|
|
case 'miskin': renderMiskinPanel(); break;
|
|
case 'log_bantuan': renderLogBantuanPanel(); break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ==========================
|
|
// ===== Ibadah Panel =======
|
|
// ==========================
|
|
function renderIbadahPanel() {
|
|
rightPanelTitle.textContent = '🕌 Rumah Ibadah';
|
|
const isAdmin = !!(window.currentUser && window.currentUser.role === 'admin');
|
|
if (isAdmin) {
|
|
rightPanelActions.innerHTML = `
|
|
<button class="btn-panel-add" id="btnPanelAddIbadah">
|
|
<i class="fas fa-plus"></i> Tambah Ibadah
|
|
</button>`;
|
|
document.getElementById('btnPanelAddIbadah').addEventListener('click', () => {
|
|
window.activateAddMode('rumah_ibadah');
|
|
});
|
|
} else {
|
|
rightPanelActions.innerHTML = '';
|
|
}
|
|
|
|
const items = [];
|
|
rumahIbadahLayer.eachLayer(l => {
|
|
if (l.ibadahData && l instanceof L.Marker) items.push(l.ibadahData);
|
|
});
|
|
|
|
if (!items.length) {
|
|
rightPanelBody.innerHTML = '<div class="panel-empty">Belum ada data rumah ibadah</div>';
|
|
return;
|
|
}
|
|
|
|
rightPanelBody.innerHTML = '';
|
|
items.forEach(d => {
|
|
const emoji = IBADAH_EMOJI[d.jenis] || '🕌';
|
|
const card = document.createElement('div');
|
|
card.className = 'data-card';
|
|
let actionButtons = '';
|
|
if (isAdmin) {
|
|
actionButtons = `
|
|
<div class="data-card-actions">
|
|
<button class="btn-card-action btn-card-edit" title="Edit"><i class="fas fa-pen"></i></button>
|
|
<button class="btn-card-action btn-card-delete" title="Hapus"><i class="fas fa-trash"></i></button>
|
|
</div>
|
|
`;
|
|
}
|
|
card.innerHTML = `
|
|
<div class="data-card-main">
|
|
<div class="data-card-icon card-icon-ibadah">${emoji}</div>
|
|
<div class="data-card-info">
|
|
<div class="data-card-name">${escHtml(d.nama)}</div>
|
|
<div class="data-card-sub">${escHtml(d.jenis || 'Masjid')} • 📡 ${d.radius} m</div>
|
|
</div>
|
|
${actionButtons}
|
|
</div>`;
|
|
if (isAdmin) {
|
|
card.querySelector('.btn-card-edit').addEventListener('click', (e) => { e.stopPropagation(); openEditIbadahModal(d.id); });
|
|
card.querySelector('.btn-card-delete').addEventListener('click', (e) => { e.stopPropagation(); deleteIbadah(d.id); });
|
|
}
|
|
card.addEventListener('click', () => flyToIbadah(d.id));
|
|
rightPanelBody.appendChild(card);
|
|
});
|
|
}
|
|
|
|
function flyToIbadah(id) {
|
|
rumahIbadahLayer.eachLayer(l => {
|
|
if (l.ibadahData && l.ibadahData.id == id && l instanceof L.Marker) {
|
|
map.setView(l.getLatLng(), 17); l.openPopup();
|
|
}
|
|
});
|
|
}
|
|
|
|
// ==========================
|
|
// ===== Miskin Panel =======
|
|
// ==========================
|
|
function renderMiskinPanel() {
|
|
rightPanelTitle.textContent = '🏠 Penduduk Miskin';
|
|
const canManage = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola'));
|
|
if (canManage) {
|
|
const isPengelola = window.currentUser.role === 'pengelola';
|
|
const addLabel = isPengelola
|
|
? '<i class="fas fa-plus"></i> Tambah <span style="font-size:10px;opacity:0.8;">(dalam radius)</span>'
|
|
: '<i class="fas fa-plus"></i> Tambah';
|
|
rightPanelActions.innerHTML = `
|
|
<button class="btn-panel-add" id="btnPanelTambahMiskin">
|
|
${addLabel}
|
|
</button>
|
|
<button class="btn-panel-import" id="btnPanelImportMiskin">
|
|
<i class="fas fa-file-import"></i> Impor
|
|
</button>`;
|
|
|
|
document.getElementById('btnPanelTambahMiskin').addEventListener('click', () => {
|
|
window.currentAddMode = 'miskin_click';
|
|
document.getElementById('map').style.cursor = 'crosshair';
|
|
if (window.cursorTooltip) {
|
|
const tipText = isPengelola
|
|
? 'Klik di dalam radius ibadah Anda untuk tambah penduduk'
|
|
: 'Klik di peta untuk tentukan lokasi penduduk miskin';
|
|
window.cursorTooltip.textContent = tipText;
|
|
}
|
|
});
|
|
|
|
document.getElementById('btnPanelImportMiskin').addEventListener('click', () => {
|
|
if (typeof window.openImportMiskinModal === 'function') {
|
|
window.openImportMiskinModal();
|
|
} else {
|
|
alert('Fitur impor belum siap.');
|
|
}
|
|
});
|
|
} else {
|
|
rightPanelActions.innerHTML = '';
|
|
}
|
|
|
|
const all = [];
|
|
pendudukMiskinLayer.eachLayer(l => { if (l.miskinData) all.push(l.miskinData); });
|
|
|
|
if (!all.length) {
|
|
rightPanelBody.innerHTML = '<div class="panel-empty">Belum ada data penduduk miskin</div>';
|
|
return;
|
|
}
|
|
|
|
const inRadius = (d) => {
|
|
if (typeof ibadahDataList === 'undefined') return false;
|
|
for (const ib of ibadahDataList) {
|
|
const dist = L.latLng(d.lat, d.lng).distanceTo(L.latLng(ib.lat, ib.lng));
|
|
if (dist <= ib.radius) return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
rightPanelBody.innerHTML = '';
|
|
|
|
const terurusItems = all.filter(d => inRadius(d));
|
|
const tidakItems = all.filter(d => !inRadius(d));
|
|
|
|
if (terurusItems.length) {
|
|
const h1 = document.createElement('div');
|
|
h1.className = 'panel-section-title';
|
|
h1.innerHTML = `✅ Terurus <span style="font-weight:400;text-transform:none;font-size:10px;">(${terurusItems.length})</span>`;
|
|
rightPanelBody.appendChild(h1);
|
|
terurusItems.forEach(d => rightPanelBody.appendChild(buildMiskinCard(d, true)));
|
|
}
|
|
|
|
if (tidakItems.length) {
|
|
const h2 = document.createElement('div');
|
|
h2.className = 'panel-section-title';
|
|
h2.innerHTML = `⚠️ Tidak Terurus <span style="font-weight:400;text-transform:none;font-size:10px;">(${tidakItems.length})</span>`;
|
|
rightPanelBody.appendChild(h2);
|
|
tidakItems.forEach(d => rightPanelBody.appendChild(buildMiskinCard(d, false)));
|
|
}
|
|
}
|
|
|
|
|
|
// ==========================
|
|
// ===== Log Bantuan Panel ==
|
|
// ==========================
|
|
function renderLogBantuanPanel() {
|
|
rightPanelTitle.textContent = '📋 Log Bantuan';
|
|
rightPanelActions.innerHTML = '';
|
|
const all = [];
|
|
if (typeof pendudukMiskinLayer !== 'undefined') {
|
|
pendudukMiskinLayer.eachLayer(l => { if (l.miskinData) all.push(l.miskinData); });
|
|
}
|
|
if (!all.length) {
|
|
rightPanelBody.innerHTML = '<div class="panel-empty">Belum ada data penduduk miskin</div>';
|
|
return;
|
|
}
|
|
rightPanelBody.innerHTML = '';
|
|
const canLog = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola'));
|
|
|
|
// Hint strip
|
|
const hint = document.createElement('div');
|
|
hint.className = 'panel-hint';
|
|
hint.innerHTML = `<i class="fas fa-info-circle"></i> ${canLog ? 'Klik penduduk untuk lihat atau tambah log bantuan.' : 'Klik penduduk untuk melihat riwayat log bantuan.'}`;
|
|
rightPanelBody.appendChild(hint);
|
|
|
|
// Summary badge
|
|
const summary = document.createElement('div');
|
|
summary.className = 'panel-section-title';
|
|
summary.textContent = `${all.length} Kepala Keluarga`;
|
|
rightPanelBody.appendChild(summary);
|
|
|
|
all.forEach(d => {
|
|
const isMakan = d.kategori_bantuan === 'Makan';
|
|
const card = document.createElement('div');
|
|
card.className = 'log-person-card';
|
|
const badgeHtml = isMakan
|
|
? '<span class="data-card-badge badge-orange">Bantuan Makan</span>'
|
|
: '<span class="data-card-badge badge-blue">Pemberdayaan</span>';
|
|
const avatarCls = isMakan ? 'avatar-makan' : 'avatar-pmbr';
|
|
card.innerHTML = `
|
|
<div class="log-person-avatar ${avatarCls}">🏠</div>
|
|
<div class="log-person-info">
|
|
<div class="log-person-name">${escHtml(d.nama)}</div>
|
|
<div class="log-person-meta">
|
|
<span>👨👩👧 ${d.jumlah_jiwa || '-'} jiwa</span>
|
|
${badgeHtml}
|
|
</div>
|
|
</div>
|
|
<i class="fas fa-chevron-right log-person-arrow"></i>`;
|
|
card.addEventListener('click', () => window.openLogBantuan(d.id, d.nama));
|
|
rightPanelBody.appendChild(card);
|
|
});
|
|
}
|
|
|
|
function buildMiskinCard(d, terurus) {
|
|
// Pengelola hanya boleh edit/hapus penduduk yang dalam radius ibadahnya
|
|
const isPengelolaOrAdmin = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola'));
|
|
const canManage = isPengelolaOrAdmin && (typeof window.isInMyIbadahRadius === 'function'
|
|
? window.isInMyIbadahRadius(d.lat, d.lng)
|
|
: true);
|
|
const iconCls = terurus ? 'card-icon-miskin-in' : 'card-icon-miskin-out';
|
|
const badge = d.kategori_bantuan === 'Makan'
|
|
? '<span class="data-card-badge badge-orange">Bantuan Makan</span>'
|
|
: '<span class="data-card-badge badge-blue">Pemberdayaan</span>';
|
|
|
|
const card = document.createElement('div');
|
|
card.className = 'data-card';
|
|
card.dataset.miskinId = d.id;
|
|
|
|
let actionButtons = '';
|
|
if (canManage) {
|
|
actionButtons = `
|
|
<div class="data-card-actions">
|
|
<button class="btn-card-action btn-card-edit" title="Edit"><i class="fas fa-pen"></i></button>
|
|
<button class="btn-card-action btn-card-delete" title="Hapus"><i class="fas fa-trash"></i></button>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
let fotoHtml = '';
|
|
if (d.foto_rumah || d.foto_kk) {
|
|
fotoHtml += `<div class="expand-row-photos" style="display:flex; gap:10px; margin-top:8px; justify-content: space-around;">`;
|
|
if (d.foto_rumah) {
|
|
fotoHtml += `
|
|
<div style="text-align:center;">
|
|
<span style="font-size:10px; display:block; font-weight:500; color:#555;">Foto Rumah</span>
|
|
<a href="uploads/${d.foto_rumah}" target="_blank">
|
|
<img src="uploads/${d.foto_rumah}" style="width:80px; height:60px; object-fit:cover; border-radius:4px; border:1px solid #ddd; margin-top:3px;" />
|
|
</a>
|
|
</div>`;
|
|
}
|
|
if (d.foto_kk) {
|
|
fotoHtml += `
|
|
<div style="text-align:center;">
|
|
<span style="font-size:10px; display:block; font-weight:500; color:#555;">Foto KK</span>
|
|
<a href="uploads/${d.foto_kk}" target="_blank">
|
|
<img src="uploads/${d.foto_kk}" style="width:80px; height:60px; object-fit:cover; border-radius:4px; border:1px solid #ddd; margin-top:3px;" />
|
|
</a>
|
|
</div>`;
|
|
}
|
|
fotoHtml += `</div>`;
|
|
}
|
|
|
|
card.innerHTML = `
|
|
<div class="data-card-main">
|
|
<div class="data-card-icon ${iconCls}">🏠</div>
|
|
<div class="data-card-info">
|
|
<div class="data-card-name">${escHtml(d.nama)}</div>
|
|
<div class="data-card-sub">👨👩👧 ${d.jumlah_jiwa || '-'} jiwa</div>
|
|
${badge}
|
|
</div>
|
|
${actionButtons}
|
|
</div>
|
|
<div class="data-card-expand">
|
|
<div class="expand-row"><span>Kepala Keluarga</span><span>${escHtml(d.nama)}</span></div>
|
|
<div class="expand-row"><span>Kategori Bantuan</span><span>${escHtml(d.kategori_bantuan)}</span></div>
|
|
<div class="expand-row"><span>Jumlah Jiwa</span><span>${d.jumlah_jiwa || '-'}</span></div>
|
|
<div class="expand-row"><span>Status</span><span>${terurus ? 'Terurus ✅' : 'Tidak Terurus ⚠️'}</span></div>
|
|
${fotoHtml}
|
|
<button class="btn-log-bantuan" data-id="${d.id}" data-nama="${escHtml(d.nama)}">
|
|
<i class="fas fa-history"></i> Lihat Log Bantuan
|
|
</button>
|
|
</div>`;
|
|
|
|
if (canManage) {
|
|
card.querySelector('.btn-card-edit').addEventListener('click', (e) => { e.stopPropagation(); openEditMiskinModal(d.id); });
|
|
card.querySelector('.btn-card-delete').addEventListener('click', (e) => { e.stopPropagation(); deleteMiskin(d.id); });
|
|
}
|
|
card.querySelector('.btn-log-bantuan').addEventListener('click', (e) => { e.stopPropagation(); openLogBantuan(d.id, d.nama); });
|
|
|
|
card.querySelector('.data-card-main').addEventListener('click', () => {
|
|
card.classList.toggle('expanded');
|
|
flyToMiskin(d.id);
|
|
});
|
|
|
|
return card;
|
|
}
|
|
|
|
function flyToMiskin(id) {
|
|
pendudukMiskinLayer.eachLayer(l => {
|
|
if (l.miskinData && l.miskinData.id == id) {
|
|
map.setView(l.getLatLng(), 17); l.openPopup();
|
|
}
|
|
});
|
|
}
|
|
|
|
// ---- Hook: klik peta saat mode miskin_click ----
|
|
// Ditangkap oleh kemiskinan.js via contextmenu — mode ini pakai klik kiri
|
|
map.on('click', function(e) {
|
|
if (window.currentAddMode === 'miskin_click') {
|
|
window.currentAddMode = null;
|
|
document.getElementById('map').style.cursor = '';
|
|
if (window.cursorTooltip) window.cursorTooltip.style.display = 'none';
|
|
// Buka form tambah miskin
|
|
if (typeof window.formAddMiskin === 'function') {
|
|
window.formAddMiskin(e.latlng.lat, e.latlng.lng);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ==========================================
|
|
// ===== Log Bantuan Modal ==================
|
|
// ==========================================
|
|
|
|
window.openLogBantuan = function (miskinId, nama) {
|
|
const modal = document.getElementById('logBantuanModal');
|
|
document.getElementById('logBantuanTitle').textContent = '📋 Log Bantuan — ' + nama;
|
|
document.getElementById('logBantuanMiskinId').value = miskinId;
|
|
modal.classList.add('show');
|
|
loadLogBantuan(miskinId);
|
|
|
|
// Tampilkan form tambah hanya untuk admin/pengelola
|
|
const canLog = !!(window.currentUser && (window.currentUser.role === 'admin' || window.currentUser.role === 'pengelola'));
|
|
document.getElementById('logBantuanFormSection').style.display = canLog ? 'block' : 'none';
|
|
|
|
// Isi dropdown ibadah jika pengelola (auto-select ibadahnya)
|
|
if (canLog) populateLogIbadahSelect();
|
|
};
|
|
|
|
window.closeLogBantuanModal = function () {
|
|
document.getElementById('logBantuanModal').classList.remove('show');
|
|
};
|
|
|
|
function loadLogBantuan(miskinId) {
|
|
const listEl = document.getElementById('logBantuanList');
|
|
listEl.innerHTML = '<div class="panel-empty">Memuat log...</div>';
|
|
fetch('api/log_bantuan/read.php?miskin_id=' + miskinId)
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.status !== 'success' || !res.data.length) {
|
|
listEl.innerHTML = '<div class="panel-empty">Belum ada log bantuan tercatat.</div>';
|
|
return;
|
|
}
|
|
listEl.innerHTML = '';
|
|
res.data.forEach(log => {
|
|
const item = document.createElement('div');
|
|
item.className = 'log-item';
|
|
const tgl = new Date(log.tanggal).toLocaleDateString('id-ID', { day: '2-digit', month: 'short', year: 'numeric' });
|
|
item.innerHTML = `
|
|
<div class="log-item-header">
|
|
<span class="log-tipe-badge"><i class="fas fa-hand-holding-heart" style="margin-right:4px;font-size:10px;"></i>${escHtml(log.tipe_bantuan)}</span>
|
|
<span class="log-tgl"><i class="fas fa-calendar-alt"></i>${tgl}</span>
|
|
</div>
|
|
<div class="log-ibadah"><span>🕌</span> ${escHtml(log.nama_ibadah)} <span class="log-jenis">${escHtml(log.jenis_ibadah)}</span></div>
|
|
${log.keterangan ? `<div class="log-ket"><i class="fas fa-quote-left" style="margin-right:4px;font-size:9px;opacity:0.5;"></i>${escHtml(log.keterangan)}</div>` : ''}
|
|
`;
|
|
listEl.appendChild(item);
|
|
});
|
|
})
|
|
.catch(() => {
|
|
listEl.innerHTML = '<div class="panel-empty" style="color:var(--danger);">Gagal memuat data log.</div>';
|
|
});
|
|
}
|
|
|
|
function populateLogIbadahSelect() {
|
|
const sel = document.getElementById('logIbadahId');
|
|
sel.innerHTML = '<option value="">-- Pilih Rumah Ibadah --</option>';
|
|
if (window.currentUser && window.currentUser.role === 'pengelola' && window.currentUser.ibadah_id) {
|
|
// Pengelola hanya bisa pilih ibadah miliknya — fetch dari layer
|
|
const id = window.currentUser.ibadah_id;
|
|
let found = false;
|
|
if (typeof rumahIbadahLayer !== 'undefined') {
|
|
rumahIbadahLayer.eachLayer(l => {
|
|
if (l.ibadahData) {
|
|
const opt = document.createElement('option');
|
|
opt.value = l.ibadahData.id;
|
|
opt.textContent = l.ibadahData.nama;
|
|
if (l.ibadahData.id == id) { opt.selected = true; found = true; }
|
|
sel.appendChild(opt);
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
// Admin bisa pilih semua
|
|
if (typeof rumahIbadahLayer !== 'undefined') {
|
|
rumahIbadahLayer.eachLayer(l => {
|
|
if (l.ibadahData) {
|
|
const opt = document.createElement('option');
|
|
opt.value = l.ibadahData.id;
|
|
opt.textContent = l.ibadahData.nama;
|
|
sel.appendChild(opt);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
document.getElementById('btnSaveLog').addEventListener('click', function () {
|
|
const miskinId = parseInt(document.getElementById('logBantuanMiskinId').value);
|
|
const ibadahId = parseInt(document.getElementById('logIbadahId').value);
|
|
const tipe = document.getElementById('logTipeBantuan').value.trim();
|
|
const tanggal = document.getElementById('logTanggal').value;
|
|
const keterangan = document.getElementById('logKeterangan').value.trim();
|
|
|
|
if (!ibadahId || !tipe || !tanggal) {
|
|
window.showToast('Lengkapi semua field wajib', 'error');
|
|
return;
|
|
}
|
|
|
|
const btn = this;
|
|
btn.disabled = true;
|
|
btn.textContent = 'Menyimpan...';
|
|
|
|
fetch('api/log_bantuan/create.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ miskin_id: miskinId, ibadah_id: ibadahId, tipe_bantuan: tipe, tanggal, keterangan })
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Simpan Log';
|
|
if (res.status === 'success') {
|
|
window.showToast('Log bantuan berhasil disimpan', 'success');
|
|
document.getElementById('logTipeBantuan').value = '';
|
|
document.getElementById('logTanggal').value = '';
|
|
document.getElementById('logKeterangan').value = '';
|
|
loadLogBantuan(miskinId);
|
|
} else {
|
|
window.showToast(res.message || 'Gagal menyimpan log', 'error');
|
|
}
|
|
})
|
|
.catch(() => {
|
|
btn.disabled = false;
|
|
btn.textContent = 'Simpan Log';
|
|
window.showToast('Terjadi kesalahan koneksi', 'error');
|
|
});
|
|
});
|
|
|
|
// Close on overlay click
|
|
document.getElementById('logBantuanModal').addEventListener('click', function(e) {
|
|
if (e.target === this) window.closeLogBantuanModal();
|
|
});
|
|
|
|
// ---- Utility ----
|
|
function escHtml(str) {
|
|
if (!str) return '';
|
|
return String(str).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
}
|
|
|
|
// ---- Expose ----
|
|
window.openRightPanel = openPanel;
|
|
|
|
})();
|