query("SELECT *, TIMESTAMPDIFF(YEAR,tanggal_lahir,CURDATE()) AS umur FROM anggota_keluarga WHERE id_penduduk=$pid ORDER BY id"); $anggota = []; while ($a = $ak->fetch_assoc()) { // Pendidikan terakhir $pend = $conn->query("SELECT jenjang,nama_institusi,tahun_lulus,status_pendidikan FROM riwayat_pendidikan WHERE id_anggota={$a['id']} ORDER BY tahun_masuk DESC LIMIT 1")->fetch_assoc(); $a['pendidikan_terakhir'] = $pend; $anggota[] = $a; } $row['anggota'] = $anggota; // Histori bantuan $bq = $conn->query("SELECT b.*,kb.nama AS jenis_bantuan,ri.nama AS nama_ibadah,rim.nama AS nama_mitra FROM bantuan b JOIN kategori_bantuan kb ON b.id_kategori_bantuan=kb.id LEFT JOIN rumah_ibadah ri ON b.id_rumah_ibadah=ri.id LEFT JOIN rumah_ibadah rim ON b.id_rumah_ibadah_mitra=rim.id WHERE b.id_penduduk=$pid ORDER BY b.tanggal_bantuan DESC"); $bantuan = []; while ($b = $bq->fetch_assoc()) $bantuan[] = $b; $row['histori_bantuan'] = $bantuan; $row['jumlah_bantuan'] = count($bantuan); return [ 'type' => 'Feature', 'geometry' => ['type'=>'Point','coordinates'=>[(float)$row['longitude'],(float)$row['latitude']]], 'properties' => $row ]; } // ── GET ─────────────────────────────────────────────────── if ($method === 'GET') { if ($action === 'geojson') { $where = "WHERE 1=1"; if (isset($_GET['status_ekonomi']) && $_GET['status_ekonomi'] !== 'all') $where .= " AND p.status_ekonomi='".esc($conn,$_GET['status_ekonomi'])."'"; if (isset($_GET['id_ibadah']) && $_GET['id_ibadah']) $where .= " AND p.id_rumah_ibadah=".(int)$_GET['id_ibadah']; if (isset($_GET['kecamatan']) && $_GET['kecamatan']) $where .= " AND p.kecamatan='".esc($conn,$_GET['kecamatan'])."'"; $res = $conn->query("SELECT p.*,ri.nama AS nama_ibadah,ri.jenis AS jenis_ibadah FROM penduduk p LEFT JOIN rumah_ibadah ri ON p.id_rumah_ibadah=ri.id $where ORDER BY p.id DESC"); $features = []; while ($row = $res->fetch_assoc()) $features[] = buildFeature($row, $conn); jsonResponse(['type'=>'FeatureCollection','features'=>$features]); } elseif ($action === 'get' && isset($_GET['id'])) { $id = (int)$_GET['id']; $row = $conn->query("SELECT p.*,ri.nama AS nama_ibadah FROM penduduk p LEFT JOIN rumah_ibadah ri ON p.id_rumah_ibadah=ri.id WHERE p.id=$id")->fetch_assoc(); jsonResponse($row ? buildFeature($row,$conn) : ['error'=>'Tidak ditemukan']); } elseif ($action === 'dashboard') { $where = 'WHERE 1=1'; $ibadahFilter = ''; $laporanFilter = ''; if (!empty($_SESSION['role']) && $_SESSION['role'] === 'pengurus_ibadah') { $iid = (int)($_SESSION['id_rumah_ibadah'] ?? 0); $where .= " AND p.id_rumah_ibadah=$iid"; $ibadahFilter = " WHERE id=$iid"; $laporanFilter = " WHERE id_rumah_ibadah=$iid"; } $total = $conn->query("SELECT COUNT(*) c FROM penduduk $where")->fetch_assoc()['c']; $jiwa = $conn->query("SELECT COALESCE(SUM(jumlah_anggota),0) c FROM penduduk $where")->fetch_assoc()['c']; $ibadah = $conn->query("SELECT COUNT(*) c FROM rumah_ibadah$ibadahFilter")->fetch_assoc()['c']; $bantuan = $conn->query("SELECT COUNT(*) c FROM bantuan" . ($laporanFilter ? " WHERE id_rumah_ibadah=$iid" : ''))->fetch_assoc()['c']; $pending = $conn->query("SELECT COUNT(*) c FROM laporan_status" . ($laporanFilter ? " WHERE status_verifikasi='pending' AND id_rumah_ibadah=$iid" : " WHERE status_verifikasi='pending'") )->fetch_assoc()['c']; $sm = $conn->query("SELECT COUNT(*) c FROM penduduk $where AND status_ekonomi='sangat_miskin'")->fetch_assoc()['c']; $miskin = $conn->query("SELECT COUNT(*) c FROM penduduk $where AND status_ekonomi='miskin'")->fetch_assoc()['c']; $rentan = $conn->query("SELECT COUNT(*) c FROM penduduk $where AND status_ekonomi='rentan'")->fetch_assoc()['c']; // Per kecamatan $kecRes = $conn->query("SELECT kecamatan,COUNT(*) AS jumlah_kk,SUM(jumlah_anggota) AS jiwa FROM penduduk $where GROUP BY kecamatan ORDER BY jumlah_kk DESC"); $perkec = []; while ($r = $kecRes->fetch_assoc()) $perkec[] = $r; jsonResponse([ 'total_kk' => (int)$total, 'total_jiwa' => (int)$jiwa, 'total_ibadah' => (int)$ibadah, 'total_bantuan' => (int)$bantuan, 'pending_laporan'=> (int)$pending, 'sangat_miskin' => (int)$sm, 'miskin' => (int)$miskin, 'rentan' => (int)$rentan, 'per_kecamatan' => $perkec, ]); } } // ── POST: tambah penduduk ───────────────────────────────── if ($method === 'POST') { requireLogin(['admin','pengurus_ibadah','masyarakat']); $nama = esc($conn,$_POST['nama_kepala_keluarga']??''); $no_kk = esc($conn,$_POST['no_kk']??''); $nik = esc($conn,$_POST['nik_kepala']??''); $lat = (float)($_POST['latitude']??0); $lon = (float)($_POST['longitude']??0); $alamat = esc($conn,$_POST['alamat']??''); $rt = esc($conn,$_POST['rt']??''); $rw = esc($conn,$_POST['rw']??''); $kel = esc($conn,$_POST['kelurahan']??''); $kec = esc($conn,$_POST['kecamatan']??''); $jml = (int)($_POST['jumlah_anggota']??1); $sekon = esc($conn,$_POST['status_ekonomi']??'miskin'); $shun = esc($conn,$_POST['status_hunian']??'milik_sendiri'); $nearest = findNearestIbadah($conn,$lat,$lon); $id_ibadah = $nearest?$nearest['id']:'NULL'; $jarak = $nearest?$nearest['jarak']:0; $sql = "INSERT INTO penduduk (no_kk,nama_kepala_keluarga,nik_kepala,latitude,longitude, alamat,rt,rw,kelurahan,kecamatan,jumlah_anggota,id_rumah_ibadah,jarak_ke_ibadah, status_ekonomi,status_hunian) VALUES ('$no_kk','$nama','$nik',$lat,$lon,'$alamat','$rt','$rw','$kel','$kec', $jml,$id_ibadah,$jarak,'$sekon','$shun')"; if ($conn->query($sql)) { $pid = $conn->insert_id; // Simpan anggota keluarga $anggota = json_decode($_POST['anggota']??'[]', true); foreach ($anggota as $a) { $anm = esc($conn,$a['nama']??''); $hub = esc($conn,$a['hubungan']??'Anak'); $jk = esc($conn,$a['jenis_kelamin']??'L'); $tgl = esc($conn,$a['tanggal_lahir']??'2000-01-01'); $tmp = esc($conn,$a['tempat_lahir']??''); $agm = esc($conn,$a['agama']??'Islam'); $pkj = esc($conn,$a['pekerjaan']??''); $nik2 = esc($conn,$a['nik']??''); $conn->query("INSERT INTO anggota_keluarga (id_penduduk,nik,nama,hubungan,jenis_kelamin,tanggal_lahir,tempat_lahir,agama,pekerjaan) VALUES ($pid,'$nik2','$anm','$hub','$jk','$tgl','$tmp','$agm','$pkj')"); $aid = $conn->insert_id; // Riwayat pendidikan per anggota $pendList = json_decode($a['pendidikan']??'[]', true); foreach ($pendList as $pd) { $jj = esc($conn,$pd['jenjang']??''); $ni = esc($conn,$pd['nama_institusi']??''); $tm = (int)($pd['tahun_masuk']??0)?:'NULL'; $tl = (int)($pd['tahun_lulus']??0)?:'NULL'; $sp = esc($conn,$pd['status_pendidikan']??'lulus'); $conn->query("INSERT INTO riwayat_pendidikan (id_anggota,jenjang,nama_institusi,tahun_masuk,tahun_lulus,status_pendidikan) VALUES ($aid,'$jj','$ni',$tm,$tl,'$sp')"); } } // Upload foto/dokumen $foto = uploadFile('foto','penduduk'); logAktivitas($conn,'tambah_penduduk','penduduk',$pid,"Tambah KK: $nama"); jsonResponse(['success'=>true,'id'=>$pid,'message'=>'Data berhasil disimpan','nearest_ibadah'=>$nearest]); } else { jsonResponse(['success'=>false,'error'=>$conn->error],500); } } // ── PUT: update penduduk ────────────────────────────────── if ($method === 'PUT') { requireLogin(['admin','pengurus_ibadah']); $d = json_decode(file_get_contents('php://input'), true); $id = (int)$d['id']; $nama = esc($conn,$d['nama_kepala_keluarga']??''); $lat = (float)($d['latitude']??0); $lon = (float)($d['longitude']??0); $alam = esc($conn,$d['alamat']??''); $jml = (int)($d['jumlah_anggota']??1); $se = esc($conn,$d['status_ekonomi']??'miskin'); $nearest = findNearestIbadah($conn,$lat,$lon); $id_ibadah = $nearest?$nearest['id']:'NULL'; $jarak = $nearest?$nearest['jarak']:0; $sql = "UPDATE penduduk SET nama_kepala_keluarga='$nama',latitude=$lat,longitude=$lon, alamat='$alam',jumlah_anggota=$jml,status_ekonomi='$se', id_rumah_ibadah=$id_ibadah,jarak_ke_ibadah=$jarak WHERE id=$id"; if ($conn->query($sql)) { logAktivitas($conn,'edit_penduduk','penduduk',$id,"Edit KK: $nama"); jsonResponse(['success'=>true,'message'=>'Data diperbarui']); } else { jsonResponse(['success'=>false,'error'=>$conn->error],500); } } // ── DELETE ──────────────────────────────────────────────── if ($method === 'DELETE') { requireLogin(['admin']); $id = (int)($_GET['id']??0); if ($conn->query("DELETE FROM penduduk WHERE id=$id")) { logAktivitas($conn,'hapus_penduduk','penduduk',$id,''); jsonResponse(['success'=>true,'message'=>'Data dihapus']); } else { jsonResponse(['success'=>false,'error'=>$conn->error],500); } } ?>