const Penduduk = (() => { let all = [], filtered = [], editNIK = null; const DEMO = [ { nik:'6171010101010001', nama_lengkap:'Ahmad Suryana', umur:44, status_keluarga:'kepala', pekerjaan:'Buruh Harian', penghasilan:900000, status_ekonomi:'miskin', kondisi_kesehatan:'sehat', pendidikan_terakhir:'SMP', no_kk:'6171010101010001', kecamatan:'Pontianak Timur' }, { nik:'6171010101010002', nama_lengkap:'Siti Rahma', umur:39, status_keluarga:'istri', pekerjaan:'Ibu RT', penghasilan:0, status_ekonomi:'miskin', kondisi_kesehatan:'sakit_ringan',pendidikan_terakhir:'SD', no_kk:'6171010101010001', kecamatan:'Pontianak Timur' }, { nik:'6171010101010003', nama_lengkap:'Budi Suryana', umur:12, status_keluarga:'anak', pekerjaan:'Pelajar', penghasilan:0, status_ekonomi:'miskin', kondisi_kesehatan:'sehat', pendidikan_terakhir:'SMP', no_kk:'6171010101010001', kecamatan:'Pontianak Timur' }, { nik:'6171010101010004', nama_lengkap:'Samsul Bahri', umur:49, status_keluarga:'kepala', pekerjaan:'Pedagang Kaki Lima',penghasilan:1200000,status_ekonomi:'rentan', kondisi_kesehatan:'sehat', pendidikan_terakhir:'SMA_SMK', no_kk:'6171010101010002', kecamatan:'Pontianak Kota' }, { nik:'6171010101010005', nama_lengkap:'Dewi Kartika', umur:46, status_keluarga:'istri', pekerjaan:'Buruh Cuci', penghasilan:500000, status_ekonomi:'rentan', kondisi_kesehatan:'sehat', pendidikan_terakhir:'SD', no_kk:'6171010101010002', kecamatan:'Pontianak Kota' }, { nik:'6171010101010006', nama_lengkap:'Maria Magdalena', umur:54, status_keluarga:'kepala', pekerjaan:'Penjual Gorengan',penghasilan:800000, status_ekonomi:'miskin', kondisi_kesehatan:'sakit_berat', pendidikan_terakhir:'SD', no_kk:'6171010101010003', kecamatan:'Pontianak Selatan' }, { nik:'6171010101010007', nama_lengkap:'Petrus Yulius', umur:19, status_keluarga:'anak', pekerjaan:'Pelajar', penghasilan:0, status_ekonomi:'miskin', kondisi_kesehatan:'sehat', pendidikan_terakhir:'SMA_SMK', no_kk:'6171010101010003', kecamatan:'Pontianak Selatan' }, { nik:'6171010101010010', nama_lengkap:'Lim Ah Kow', umur:59, status_keluarga:'kepala', pekerjaan:'Tidak Bekerja', penghasilan:0, status_ekonomi:'miskin', kondisi_kesehatan:'sakit_berat', pendidikan_terakhir:'SD', no_kk:'6171010101010005', kecamatan:'Pontianak Kota' }, { nik:'6171010101010012', nama_lengkap:'Mulyadi', umur:45, status_keluarga:'kepala', pekerjaan:'PNS Gol. III', penghasilan:4500000, status_ekonomi:'mampu', kondisi_kesehatan:'sehat', pendidikan_terakhir:'S1', no_kk:'6171010101010006', kecamatan:'Pontianak Timur' }, { nik:'6171010101010014', nama_lengkap:'Tan Eng Huat', umur:65, status_keluarga:'kepala', pekerjaan:'Pemulung', penghasilan:600000, status_ekonomi:'miskin', kondisi_kesehatan:'disabilitas', pendidikan_terakhir:'SD', no_kk:'6171010101010008', kecamatan:'Pontianak Kota' }, ]; async function load() { try { all = await Api.get('/penduduk'); } catch { all = DEMO; } filtered = [...all]; render(filtered); ge('pf-count').textContent = `${all.length} total`; } function search(q) { applyFilter(q); } function applyFilter(qOverride) { const q = qOverride ?? gv('pf-search'); const ek = gv('pf-ekonomi'); const ke = gv('pf-kesehatan'); filtered = all.filter(p => (!q || p.nama_lengkap?.toLowerCase().includes(q.toLowerCase()) || p.nik?.includes(q)) && (!ek || p.status_ekonomi === ek) && (!ke || p.kondisi_kesehatan === ke) ); render(filtered); ge('pf-count').textContent = `${filtered.length} / ${all.length}`; } const pendidikanLabel = { tidak_sekolah:'Tdk Sekolah', SD:'SD', SMP:'SMP', SMA_SMK:'SMA/SMK', D1_D3:'D3', S1:'S1', S2_S3:'S2/S3' }; function render(data) { const tb = ge('tbody-penduduk'); if (!data.length) { tb.innerHTML = '
πŸ”

Tidak ada data

Coba ubah filter pencarian

'; return; } tb.innerHTML = data.map(p => ` ${p.nik} ${p.nama_lengkap}
${p.kecamatan||''}
${p.umur||'?'} th ${cap(p.status_keluarga)} ${p.pekerjaan||'β€”'} ${rp(p.penghasilan)} ${bdg(p.status_ekonomi,'')} ${bdg(p.kondisi_kesehatan,'')} ${pendidikanLabel[p.pendidikan_terakhir]||p.pendidikan_terakhir||'β€”'}
`).join(''); } async function showForm(nik = null) { editNIK = nik; ge('mp-title').textContent = nik ? `✏️ Edit β€” ${nik}` : 'βž• Tambah Penduduk Baru'; ge('fp-nik').readOnly = !!nik; await loadKKDropdown(); if (nik) { try { const p = await Api.get(`/penduduk/${nik}`); fillForm(p); } catch { const p = all.find(x => x.nik === nik); if (p) fillForm(p); } } else { ['fp-nik','fp-nama','fp-tempat','fp-pekerjaan','fp-ket-sehat'].forEach(id => sv(id,'')); sv('fp-penghasilan','0'); sv('fp-umur',''); ge('fp-warn').classList.add('hidden'); } App.showModal('modal-penduduk'); } function fillForm(p) { sv('fp-nik', p.nik); sv('fp-nama', p.nama_lengkap); sv('fp-jkel', p.jenis_kelamin); sv('fp-tgl', p.tanggal_lahir?.substring(0,10)); sv('fp-umur', p.umur ? `${p.umur} tahun` : ''); sv('fp-tempat', p.tempat_lahir); sv('fp-agama', p.agama); sv('fp-status-kk', p.status_keluarga); sv('fp-kawin', p.status_perkawinan); sv('fp-hidup', p.status_hidup); sv('fp-ekonomi', p.status_ekonomi); sv('fp-pekerjaan', p.pekerjaan); sv('fp-penghasilan', p.penghasilan || 0); sv('fp-pendidikan', p.pendidikan_terakhir); sv('fp-stat-pend', p.status_pendidikan); sv('fp-kesehatan', p.kondisi_kesehatan); sv('fp-ket-sehat', p.keterangan_kesehatan); if (p.id_keluarga) sv('fp-kk', p.id_keluarga); } async function loadKKDropdown() { const sel = ge('fp-kk'); try { const list = await Api.get('/keluarga'); sel.innerHTML = list.map(k => ``).join(''); } catch { sel.innerHTML = ''; } } function hitungUmur() { const tgl = gv('fp-tgl'); if (!tgl) return; const umur = Math.floor((Date.now() - new Date(tgl)) / (365.25*24*3600*1000)); sv('fp-umur', `${umur} tahun`); // Validasi const pend = gv('fp-pendidikan'), stat = gv('fp-stat-pend'); const warns = []; if (umur >= 7 && umur <= 15 && stat === 'tidak_sekolah') warns.push(`⚠️ Usia ${umur} tahun β€” seharusnya masih wajib belajar (SD/SMP)`); if (umur >= 16 && umur <= 18 && stat === 'tidak_sekolah' && ['tidak_sekolah','SD'].includes(pend)) warns.push(`⚠️ Usia ${umur} tahun β€” disarankan melanjutkan ke SMA/SMK`); const wEl = ge('fp-warn'); if (warns.length) { wEl.innerHTML = warns.join('
'); wEl.classList.remove('hidden'); } else wEl.classList.add('hidden'); } async function save() { const nik = gv('fp-nik'); if (!nik || nik.length !== 16 || !/^\d+$/.test(nik)) { App.toast('NIK harus 16 digit angka','error'); return; } if (!gv('fp-nama')) { App.toast('Nama lengkap wajib diisi','error'); return; } if (!gv('fp-tgl')) { App.toast('Tanggal lahir wajib diisi','error'); return; } const body = { nik, id_keluarga: gv('fp-kk'), nama_lengkap: gv('fp-nama'), jenis_kelamin: gv('fp-jkel'), tanggal_lahir: gv('fp-tgl'), tempat_lahir: gv('fp-tempat'), agama: gv('fp-agama'), status_keluarga: gv('fp-status-kk'), status_perkawinan: gv('fp-kawin'), status_hidup: gv('fp-hidup'), pekerjaan: gv('fp-pekerjaan'), penghasilan: +gv('fp-penghasilan')||0, status_ekonomi: gv('fp-ekonomi'), pendidikan_terakhir: gv('fp-pendidikan'), status_pendidikan: gv('fp-stat-pend'), kondisi_kesehatan: gv('fp-kesehatan'), keterangan_kesehatan: gv('fp-ket-sehat'), }; try { if (editNIK) { await Api.put(`/penduduk/${editNIK}`, body); App.toast('Data diperbarui βœ…','success'); } else { await Api.post('/penduduk', body); App.toast('Penduduk ditambahkan βœ…','success'); } App.closeModal('modal-penduduk'); await load(); App.updateHeaderStats(); } catch(e) { App.toast(e.message,'error'); } } async function hapus(nik) { if (!confirm(`Hapus data penduduk NIK ${nik}?\nTindakan ini tidak dapat dibatalkan.`)) return; try { await Api.delete(`/penduduk/${nik}`); App.toast('Data dihapus','success'); load(); App.updateHeaderStats(); } catch(e) { App.toast(e.message,'error'); } } async function showDetail(nik) { ge('dp-title').textContent = 'Memuat…'; ge('detail-panel').classList.add('open'); let p; try { p = await Api.get(`/penduduk/${nik}`); } catch { p = all.find(x => x.nik === nik); } if (!p) { App.toast('Gagal memuat detail','error'); return; } ge('dp-title').textContent = p.nama_lengkap; const histori = p.histori_bantuan || []; ge('dp-body').innerHTML = `
Identitas
${field('NIK', `${p.nik}`)} ${field('Jenis Kelamin', p.jenis_kelamin === 'L' ? 'Laki-laki' : 'Perempuan')} ${field('Umur', `${p.umur||'?'} tahun`)} ${field('Tempat Lahir', p.tempat_lahir||'β€”')} ${field('Agama', p.agama||'β€”')} ${field('Status KK', cap(p.status_keluarga))} ${field('Perkawinan', cap(p.status_perkawinan))}
Sosial Ekonomi
${field('Pekerjaan', p.pekerjaan||'β€”')} ${field('Penghasilan', rp(p.penghasilan))} ${field('Status Ekonomi', bdg(p.status_ekonomi,''))} ${field('Pendidikan', p.pendidikan_terakhir?.replace('_','/')||'β€”')} ${field('Kesehatan', bdg(p.kondisi_kesehatan,''))}
Lokasi
${field('Kelurahan', p.kelurahan||'β€”')} ${field('Kecamatan', p.kecamatan||'β€”')} ${field('Alamat', p.alamat||'β€”')} ${field('Rumah Ibadah', p.nama_ri||'β€”')}
Riwayat Bantuan (${histori.length}x)
${histori.length ? histori.map(h=>`
${h.nama_bantuan}${h.tanggal?.substring(0,10)}
${h.nama_ri||''} Β· ${h.jumlah} ${h.satuan||''}
`).join('') : '

Belum pernah menerima bantuan

'}
${App.canEdit() ? `
` : ''} `; } function field(lbl, val) { return `
${lbl}${val}
`; } function closeDetail() { ge('detail-panel').classList.remove('open'); } return { load, search, applyFilter, showForm, hitungUmur, save, hapus, showDetail, closeDetail }; })();