This commit is contained in:
envicy
2026-06-11 22:29:16 +07:00
parent 503e9421a9
commit ce26f9fac6
15 changed files with 1933 additions and 2015 deletions
+159 -92
View File
@@ -16,8 +16,8 @@
let activePanel = null;
// ---- Elements ----
const sidebarToggleBtn = document.getElementById('sidebarToggleBtn');
const sidebarToggleIcon = document.getElementById('sidebarToggleIcon');
// removed
// removed
const leftSidebar = document.getElementById('leftSidebar');
const rightPanel = document.getElementById('rightPanel');
const rightPanelTitle = document.getElementById('rightPanelTitle');
@@ -25,19 +25,7 @@
const rightPanelBody = document.getElementById('rightPanelBody');
const rightPanelClose = document.getElementById('rightPanelClose');
// ---- Sidebar Toggle ----
sidebarToggleBtn.addEventListener('click', function () {
const isOpen = leftSidebar.style.display !== 'none';
if (isOpen) {
leftSidebar.style.display = 'none';
sidebarToggleBtn.classList.remove('open');
sidebarToggleIcon.className = 'fas fa-chevron-right';
} else {
leftSidebar.style.display = 'flex';
sidebarToggleBtn.classList.add('open');
sidebarToggleIcon.className = 'fas fa-chevron-left';
}
});
// Sidebar collapse handled in map.js
// ---- Sidebar Buttons ----
document.querySelectorAll('.sidebar-btn').forEach(btn => {
@@ -83,8 +71,9 @@
rightPanelActions.innerHTML = '';
switch (type) {
case 'ibadah': renderIbadahPanel(); break;
case 'miskin': renderMiskinPanel(); break;
case 'ibadah': renderIbadahPanel(); break;
case 'miskin': renderMiskinPanel(); break;
case 'log_bantuan': renderLogBantuanPanel(); break;
}
}
@@ -238,6 +227,59 @@
}
}
// ==========================
// ===== 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'));
@@ -344,115 +386,140 @@
}
});
// ==========================
// ===== Log Bantuan Modal ==
// ==========================
const logModal = document.getElementById('logBantuanModal');
const logTitle = document.getElementById('logBantuanTitle');
const logList = document.getElementById('logBantuanList');
const logSaveBtn = document.getElementById('logSaveBtn');
const logIbadahSel = document.getElementById('logIbadahId');
let _logMiskinId = null;
// ==========================================
// ===== Log Bantuan Modal ==================
// ==========================================
window.openLogBantuan = function (miskinId, nama) {
_logMiskinId = miskinId;
logTitle.textContent = `Log Bantuan — ${nama}`;
logModal.classList.add('show');
const modal = document.getElementById('logBantuanModal');
document.getElementById('logBantuanTitle').textContent = '📋 Log Bantuan — ' + nama;
document.getElementById('logBantuanMiskinId').value = miskinId;
modal.classList.add('show');
loadLogBantuan(miskinId);
const isAuth = !!window.currentUser;
const formContainer = document.querySelector('#logBantuanModal .modal-body > div:last-child');
const modalFooter = document.querySelector('#logBantuanModal .modal-footer');
if (isAuth) {
if (formContainer) formContainer.style.display = 'block';
if (modalFooter) modalFooter.style.display = 'flex';
} else {
if (formContainer) formContainer.style.display = 'none';
if (modalFooter) modalFooter.style.display = 'none';
}
// 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
logIbadahSel.innerHTML = '<option value="">-- Pilih Rumah Ibadah --</option>';
if (typeof ibadahDataList !== 'undefined') {
ibadahDataList.forEach(ib => {
const opt = document.createElement('option');
opt.value = ib.id;
opt.textContent = `${IBADAH_EMOJI[ib.jenis] || '🕌'} ${ib.nama}`;
logIbadahSel.appendChild(opt);
});
}
if (window.currentUser && window.currentUser.role === 'pengelola') {
logIbadahSel.value = window.currentUser.ibadah_id;
logIbadahSel.disabled = true;
} else {
logIbadahSel.disabled = false;
}
// Set tanggal default hari ini
document.getElementById('logTanggal').valueAsDate = new Date();
fetchLogBantuan(miskinId);
// Isi dropdown ibadah jika pengelola (auto-select ibadahnya)
if (canLog) populateLogIbadahSelect();
};
window.closeLogBantuanModal = function () {
logModal.classList.remove('show');
_logMiskinId = null;
document.getElementById('logBantuanModal').classList.remove('show');
};
function fetchLogBantuan(miskinId) {
logList.innerHTML = '<div class="panel-empty" style="padding:15px;">Memuat...</div>';
fetch(`api/log_bantuan/read.php?miskin_id=${miskinId}`)
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(data => {
if (!data.data || !data.data.length) {
logList.innerHTML = '<div class="panel-empty" style="padding:15px;">Belum ada riwayat bantuan</div>';
.then(res => {
if (res.status !== 'success' || !res.data.length) {
listEl.innerHTML = '<div class="panel-empty">Belum ada log bantuan tercatat.</div>';
return;
}
logList.innerHTML = '';
data.data.forEach(log => {
const tgl = new Date(log.tanggal).toLocaleDateString('id-ID', { day:'2-digit', month:'short', year:'numeric' });
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-dot"></div>
<div class="log-info">
<div class="log-type">${escHtml(log.tipe_bantuan)}</div>
<div class="log-meta">${IBADAH_EMOJI[log.jenis_ibadah] || '🕌'} ${escHtml(log.nama_ibadah)}${tgl}</div>
${log.keterangan ? `<div class="log-keterangan">${escHtml(log.keterangan)}</div>` : ''}
</div>`;
logList.appendChild(item);
<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(() => {
logList.innerHTML = '<div class="panel-empty" style="padding:15px; color:#ef4444;">Gagal memuat data</div>';
listEl.innerHTML = '<div class="panel-empty" style="color:var(--danger);">Gagal memuat data log.</div>';
});
}
logSaveBtn.addEventListener('click', function () {
const ibadah_id = logIbadahSel.value;
const tipe_bantuan = document.getElementById('logTipeBantuan').value;
const tanggal = document.getElementById('logTanggal').value;
const keterangan = document.getElementById('logKeterangan').value;
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);
}
});
}
}
}
if (!ibadah_id) { alert('Pilih rumah ibadah terlebih dahulu!'); return; }
if (!tanggal) { alert('Tanggal harus diisi!'); return; }
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: _logMiskinId, ibadah_id, tipe_bantuan, tanggal, keterangan })
body: JSON.stringify({ miskin_id: miskinId, ibadah_id: ibadahId, tipe_bantuan: tipe, tanggal, keterangan })
})
.then(r => r.json())
.then(data => {
if (data.status === 'success') {
.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 = '';
fetchLogBantuan(_logMiskinId);
loadLogBantuan(miskinId);
} else {
alert(data.message || 'Gagal menyimpan');
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 '';