Files
2026-06-11 21:18:48 +07:00

331 lines
15 KiB
JavaScript

/* ============================================================
js/laporan.js — Sistem pelaporan warga v2.2
============================================================ */
window.labelKategoriLaporan = {
sakit:'Sakit / Butuh Bantuan Medis', kematian:'Kematian',
kelahiran:'Kelahiran Bayi Baru', pernikahan:'Pernikahan',
pindah:'Pindah Tempat', darurat_ekonomi:'Darurat Ekonomi', lainnya:'Lainnya'
};
window.labelStatusLaporan = {
menunggu:'Menunggu', diproses:'Diproses', selesai:'Selesai', ditolak:'Ditolak'
};
var _kategoriEmoji = {
sakit:'🤒', kematian:'💔', kelahiran:'👶', pernikahan:'💍',
pindah:'📦', darurat_ekonomi:'🆘', lainnya:'📣'
};
/* ─────────────────────────────────────────────────────
Floating detail box
───────────────────────────────────────────────────── */
window.openLaporanDetail = function (laporan) {
var fl = document.getElementById('laporan-detail-float');
if (!fl) return;
var status = laporan.status_laporan || 'menunggu';
var emoji = _kategoriEmoji[laporan.kategori] || '📣';
var label = window.labelKategoriLaporan[laporan.kategori] || laporan.kategori;
var statusLabel = window.labelStatusLaporan[status] || status;
/* Status bar colour */
var bar = document.getElementById('ldf-status-bar');
bar.className = 'ldf-status-bar ' + status;
/* Icon */
var icon = document.getElementById('ldf-icon');
icon.textContent = emoji;
icon.className = 'ldf-icon ' + status;
/* Title / subtitle */
document.getElementById('ldf-title').textContent = label;
document.getElementById('ldf-subtitle').textContent = '● ' + statusLabel;
document.getElementById('ldf-subtitle').style.color = {
menunggu: 'var(--amber)', diproses: 'var(--blue)',
selesai: 'var(--green)', ditolak: 'var(--text-muted)'
}[status] || 'var(--text-muted)';
/* Deskripsi */
document.getElementById('ldf-deskripsi').textContent = laporan.deskripsi || '(tidak ada deskripsi)';
/* KK terkait */
var sectionKK = document.getElementById('ldf-section-kk');
var badgeKK = document.getElementById('ldf-kk-badge');
if (laporan.nama_kepala_keluarga) {
badgeKK.innerHTML = '<i class="fa-solid fa-location-dot"></i> ' + laporan.nama_kepala_keluarga;
sectionKK.style.display = '';
} else {
sectionKK.style.display = 'none';
}
/* Info rows */
document.getElementById('ldf-pelapor').textContent = laporan.nama_pelapor || '-';
var rowWA = document.getElementById('ldf-row-wa');
if (laporan.nomor_wa) {
document.getElementById('ldf-wa').textContent = laporan.nomor_wa;
rowWA.style.display = '';
} else {
rowWA.style.display = 'none';
}
document.getElementById('ldf-waktu').textContent = laporan.created_fmt || '-';
var rowDitangani = document.getElementById('ldf-row-ditangani');
if (laporan.ditangani_oleh) {
document.getElementById('ldf-ditangani').textContent = laporan.ditangani_oleh;
rowDitangani.style.display = '';
} else {
rowDitangani.style.display = 'none';
}
/* Action buttons (pengurus only) */
var footer = document.getElementById('ldf-footer');
footer.innerHTML = '';
if (window.appAuth && window.appAuth.role === 'pengurus_masjid' && status !== 'selesai' && status !== 'ditolak') {
footer.style.display = '';
var statuses = [
{ val: 'diproses', label: '<i class="fa-solid fa-rotate"></i> Proses', cls: 'btn-proses' },
{ val: 'selesai', label: '<i class="fa-solid fa-check"></i> Selesai', cls: 'btn-selesai' },
{ val: 'ditolak', label: '<i class="fa-solid fa-xmark"></i> Tolak', cls: 'btn-tolak' }
];
statuses.forEach(function (s) {
if (s.val === status) return;
var btn = document.createElement('button');
btn.className = 'btn ' + s.cls;
btn.innerHTML = s.label;
btn.onclick = (function (lid, sv) {
return async function () {
btn.disabled = true;
try {
await window.postForm('php/update_laporan_status.php', {
id: lid, status_laporan: sv, ditangani_oleh: window.appAuth.nama
});
window.showToast('Status diperbarui ke: ' + window.labelStatusLaporan[sv], 'success');
window.closeLaporanDetail();
window.loadLaporan(document.getElementById('laporan-filter-status').value);
} catch (e) {
window.showToast('Gagal: ' + e.message, 'error');
btn.disabled = false;
}
};
})(laporan.id, s.val);
footer.appendChild(btn);
});
} else {
footer.style.display = 'none';
}
/* Close button */
document.getElementById('ldf-close').onclick = window.closeLaporanDetail;
/* Show with animation */
fl.style.display = 'flex';
};
window.closeLaporanDetail = function () {
var fl = document.getElementById('laporan-detail-float');
if (fl) fl.style.display = 'none';
};
/* ── Form laporan publik ── */
window.openLaporanPublikModal = function (kemiskinanId, namaKK) {
var modal = document.getElementById('modal-laporan-publik');
document.getElementById('laporan-kem-id').value = kemiskinanId || '';
document.getElementById('laporan-nama-pelapor').value = '';
document.getElementById('laporan-nomor-wa').value = '';
document.getElementById('laporan-kategori').value = 'lainnya';
document.getElementById('laporan-deskripsi').value = '';
document.getElementById('laporan-judul-kkname').textContent = namaKK
? 'Laporkan Kondisi: ' + namaKK
: 'Laporkan Kondisi Warga';
modal.style.display = 'flex';
document.getElementById('laporan-nama-pelapor').focus();
modal.onclick = function (e) { if (e.target === this) this.style.display = 'none'; };
};
/* ── Tombol submit laporan dipanggil dari inline HTML ── */
window._submitLaporanBtn = async function () {
var btn = document.getElementById('btn-submit-laporan');
var nama = document.getElementById('laporan-nama-pelapor').value.trim();
var desc = document.getElementById('laporan-deskripsi').value.trim();
if (!nama || !desc) { window.showToast('Nama dan deskripsi wajib diisi.', 'error'); return; }
btn.disabled = true; btn.textContent = 'Mengirim...';
var payload = {
kemiskinan_id: document.getElementById('laporan-kem-id').value,
nama_pelapor: nama,
nomor_wa: document.getElementById('laporan-nomor-wa').value.trim(),
kategori: document.getElementById('laporan-kategori').value,
deskripsi: desc
};
try {
var res = await fetch('php/create_laporan.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(payload)
});
var text = (await res.text()).trim();
if (text === 'success') {
document.getElementById('modal-laporan-publik').style.display = 'none';
if (window.Swal) {
Swal.fire({
icon: 'success',
title: 'Laporan Terkirim',
text: 'Laporan berhasil dikirim. Terima kasih atas informasi Anda!',
confirmButtonText: 'Tutup'
});
} else {
window.showToast('Laporan berhasil dikirim. Terima kasih!', 'success');
}
} else {
window.showToast('Gagal: ' + text, 'error');
}
} catch (err) { window.showToast('Gagal: ' + err.message, 'error'); }
finally { btn.disabled = false; btn.textContent = 'Kirim Laporan'; }
};
/* ── Panel manajemen (pengurus) ── */
window.openLaporanPanel = async function () {
var panel = document.getElementById('panel-laporan');
if (panel) {
var sidebar = document.getElementById('sidebar');
if (sidebar) sidebar.style.display = 'none';
var pes = document.getElementById('panel-pesan');
if (pes) pes.style.display = 'none';
panel.style.display = 'flex';
document.getElementById('laporan-filter-status').value = 'menunggu';
window.loadLaporan('menunggu');
}
};
window.closeLaporanPanel = function () {
var p = document.getElementById('panel-laporan');
if (p) p.style.display = 'none';
window.closeLaporanDetail();
// Auto-open sidebar
var sidebar = document.getElementById('sidebar');
if (sidebar) sidebar.style.display = 'flex';
};
window.loadLaporan = async function (statusFilter) {
var container = document.getElementById('laporan-list-container');
if (!container) return;
container.innerHTML = '<div class="loading">Memuat laporan...</div>';
var url = 'php/read_laporan.php' + (statusFilter ? '?status=' + statusFilter : '');
var data = await window.fetchJson(url, []);
container.innerHTML = '';
if (!data.length) {
container.innerHTML = '<div class="empty">Tidak ada laporan.</div>'; return;
}
data.forEach(function (l) {
var chipColors = { menunggu:'chip-amber', diproses:'chip-blue', selesai:'chip-green', ditolak:'chip-gray' };
var emoji = _kategoriEmoji[l.kategori] || '📣';
var card = document.createElement('div');
card.className = 'l-card ' + l.status_laporan;
card.title = 'Klik untuk detail lengkap';
var badgeCls = { menunggu:'chip-amber', diproses:'chip-blue', selesai:'chip-green', ditolak:'chip-gray' }[l.status_laporan] || 'chip-gray';
var kkHtml = l.nama_kepala_keluarga
? '<div class="l-kk"><i class="fa-solid fa-location-dot"></i> KK: ' + window.escapeHtml(l.nama_kepala_keluarga) + '</div>' : '';
card.innerHTML =
'<div class="l-head">' +
'<span class="l-cat">' + emoji + ' ' + (window.labelKategoriLaporan[l.kategori] || l.kategori) + '</span>' +
'<span class="chip ' + badgeCls + '">' + window.escapeHtml(window.labelStatusLaporan[l.status_laporan] || l.status_laporan) + '</span>' +
'</div>' +
kkHtml +
'<div class="l-desc">' + window.escapeHtml(l.deskripsi) + '</div>' +
'<div class="l-meta"><i class="fa-solid fa-user"></i> ' + window.escapeHtml(l.nama_pelapor) +
(l.nomor_wa ? ' &middot; <i class="fa-solid fa-mobile-screen"></i> ' + window.escapeHtml(l.nomor_wa) : '') +
' &middot; <i class="fa-regular fa-clock"></i> ' + l.created_fmt + '</div>' +
(l.ditangani_oleh ? '<div class="l-meta"><i class="fa-solid fa-check"></i> Ditangani: ' + window.escapeHtml(l.ditangani_oleh) + '</div>' : '');
/* Klik kartu → buka floating detail */
card.addEventListener('click', function (e) {
/* Jangan trigger jika yang diklik tombol aksi */
if (e.target.closest('button')) return;
window.openLaporanDetail(l);
});
if (window.appAuth.role === 'pengurus_masjid' && l.status_laporan !== 'selesai' && l.status_laporan !== 'ditolak') {
var acts = document.createElement('div');
acts.className = 'l-acts';
var statuses = [
{ val: 'diproses', label: 'Proses', cls: 'btn-proses' },
{ val: 'selesai', label: 'Selesai', cls: 'btn-selesai' },
{ val: 'ditolak', label: 'Tolak', cls: 'btn-tolak' }
];
statuses.forEach(function (s) {
if (s.val === l.status_laporan) return;
var btn = document.createElement('button');
btn.className = 'btn ' + s.cls; btn.textContent = s.label;
btn.onclick = (function(lid, sv){ return async function(){
try {
await window.postForm('php/update_laporan_status.php', {
id: lid, status_laporan: sv, ditangani_oleh: window.appAuth.nama
});
window.showToast('Status diperbarui.', 'success');
window.closeLaporanDetail();
window.loadLaporan(document.getElementById('laporan-filter-status').value);
} catch(e){ window.showToast('Gagal: ' + e.message, 'error'); }
}; })(l.id, s.val);
acts.appendChild(btn);
});
card.appendChild(acts);
}
container.appendChild(card);
});
};
/* Polling for Laporan Notification */
window.pollLaporanNotification = async function() {
if (!window.appAuth || window.appAuth.role !== 'pengurus_masjid') {
var np = document.getElementById('notif-panel');
if (np) np.style.display = 'none';
return;
}
try {
var res = await fetch('php/read_laporan.php');
var text = await res.text();
var data = JSON.parse(text);
if(Array.isArray(data)) {
var pendingCount = data.filter(function(l) { return l.status_laporan === 'menunggu'; }).length;
var badge = document.getElementById('nav-badge-laporan');
if(badge) {
if(pendingCount > 0) {
badge.style.display = 'inline-flex';
badge.textContent = pendingCount;
} else {
badge.style.display = 'none';
}
}
var np = document.getElementById('notif-panel');
var nb = document.getElementById('notif-body');
if (np && nb) {
if(pendingCount > 0) {
var isPanelOpen = document.getElementById('panel-laporan') && document.getElementById('panel-laporan').style.display === 'flex';
if(!isPanelOpen && (!window._notifDismissedForCount || window._notifDismissedForCount < pendingCount)) {
np.style.display = 'block';
nb.innerHTML = 'Terdapat <b>' + pendingCount + ' laporan baru</b> dari warga yang belum diproses.<br>Harap segera ditindaklanjuti!';
window._notifDismissedForCount = pendingCount;
}
} else {
np.style.display = 'none';
window._notifDismissedForCount = 0;
}
}
}
} catch(e) {}
};
// Start polling every 10 seconds
setInterval(window.pollLaporanNotification, 10000);