Files
UAS_WEBGIS_MichelleOlivia_D…/sig-kemiskinan/api/dashboard_stats.php
T
2026-06-10 21:46:56 +07:00

190 lines
9.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// api/dashboard_stats.php v2.0
// ============================================================
// API Statistik untuk Dashboard & Grafik
// ============================================================
require_once __DIR__ . '/../includes/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
if ($_SERVER['REQUEST_METHOD'] !== 'GET') jsonResponse(['success'=>false,'error'=>'Method tidak diizinkan'],405);
$db = getDB();
// ── Filter opsional ────────────────────────────────────────
$kelurahan = $_GET['kelurahan'] ?? null;
$kecamatan = $_GET['kecamatan'] ?? null;
$whereBase = "WHERE 1=1";
$params = [];
if ($kelurahan) { $whereBase .= " AND w.kelurahan = ?"; $params[] = $kelurahan; }
if ($kecamatan) { $whereBase .= " AND w.kecamatan = ?"; $params[] = $kecamatan; }
$joinW = "LEFT JOIN wilayah w ON w.id = pm.wilayah_id";
// ═══════════════════════════════════════════════════════════
// 1. RINGKASAN UTAMA (KPI Cards)
// ═══════════════════════════════════════════════════════════
$kpi = $db->prepare("
SELECT
COUNT(pm.id) AS total_kk,
SUM(pm.jumlah_anggota) AS total_jiwa,
SUM(pm.jumlah_anak_sekolah) AS total_anak_sekolah,
SUM(CASE WHEN pm.status_verifikasi='terverifikasi' THEN 1 ELSE 0 END) AS terverifikasi,
SUM(CASE WHEN pm.status_verifikasi='belum_diverifikasi' THEN 1 ELSE 0 END) AS belum_verifikasi,
SUM(CASE WHEN pm.punya_bpjs=1 THEN 1 ELSE 0 END) AS punya_bpjs,
SUM(CASE WHEN pm.kategori_kemiskinan='sangat_miskin' THEN 1 ELSE 0 END) AS sangat_miskin,
SUM(CASE WHEN pm.kategori_kemiskinan='miskin' THEN 1 ELSE 0 END) AS miskin,
SUM(CASE WHEN pm.kategori_kemiskinan='hampir_miskin' THEN 1 ELSE 0 END) AS hampir_miskin,
SUM(CASE WHEN pm.kategori_kemiskinan='mampu' THEN 1 ELSE 0 END) AS mampu,
ROUND(AVG(pm.penghasilan_bulanan),0) AS avg_penghasilan,
SUM(CASE WHEN bp_count.cnt > 0 THEN 1 ELSE 0 END) AS penerima_bantuan,
SUM(CASE WHEN bp_count.cnt = 0 THEN 1 ELSE 0 END) AS belum_bantuan
FROM penduduk_miskin pm
$joinW
LEFT JOIN (
SELECT penduduk_id, COUNT(*) AS cnt
FROM bantuan_penduduk
WHERE status='aktif'
GROUP BY penduduk_id
) bp_count ON bp_count.penduduk_id = pm.id
$whereBase
");
$kpi->execute($params);
$kpiData = $kpi->fetch();
// ═══════════════════════════════════════════════════════════
// 2. DISTRIBUSI KATEGORI KEMISKINAN (Donut Chart)
// ═══════════════════════════════════════════════════════════
$katStmt = $db->prepare("
SELECT pm.kategori_kemiskinan AS label, COUNT(*) AS value
FROM penduduk_miskin pm $joinW $whereBase
GROUP BY pm.kategori_kemiskinan
ORDER BY FIELD(pm.kategori_kemiskinan,'sangat_miskin','miskin','hampir_miskin','mampu')
");
$katStmt->execute($params);
$kategoriChart = $katStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 3. KK PER KELURAHAN (Bar Chart)
// ═══════════════════════════════════════════════════════════
$kelStmt = $db->prepare("
SELECT
COALESCE(w.kelurahan,'Tidak Diketahui') AS label,
COUNT(pm.id) AS total_kk,
SUM(pm.jumlah_anggota) AS total_jiwa,
SUM(CASE WHEN bp_c.cnt>0 THEN 1 ELSE 0 END) AS penerima
FROM penduduk_miskin pm $joinW
LEFT JOIN (
SELECT penduduk_id, COUNT(*) AS cnt FROM bantuan_penduduk WHERE status='aktif' GROUP BY penduduk_id
) bp_c ON bp_c.penduduk_id = pm.id
$whereBase
GROUP BY w.kelurahan
ORDER BY total_kk DESC
LIMIT 15
");
$kelStmt->execute($params);
$kelurahanChart = $kelStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 4. DISTRIBUSI JENIS BANTUAN (Pie Chart)
// ═══════════════════════════════════════════════════════════
$bantuanStmt = $db->prepare("
SELECT jb.kode, jb.nama AS label, jb.warna_badge AS color, COUNT(bp.id) AS value
FROM bantuan_penduduk bp
JOIN jenis_bantuan jb ON jb.id = bp.bantuan_id
JOIN penduduk_miskin pm ON pm.id = bp.penduduk_id
$joinW
" . str_replace('WHERE 1=1', 'WHERE bp.status=\'aktif\'', $whereBase) . "
GROUP BY jb.id
ORDER BY value DESC
");
$bantuanStmt->execute($params);
$bantuanChart = $bantuanStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 5. TREN PENDATAAN PER BULAN (Line Chart) 12 bulan terakhir
// ═══════════════════════════════════════════════════════════
$trenStmt = $db->prepare("
SELECT
DATE_FORMAT(pm.created_at,'%Y-%m') AS bulan,
COUNT(pm.id) AS total
FROM penduduk_miskin pm $joinW $whereBase
AND pm.created_at >= DATE_SUB(NOW(), INTERVAL 12 MONTH)
GROUP BY DATE_FORMAT(pm.created_at,'%Y-%m')
ORDER BY bulan ASC
");
$trenStmt->execute($params);
$trenChart = $trenStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 6. DISTRIBUSI PEKERJAAN (Bar horizontal)
// ═══════════════════════════════════════════════════════════
$pekerjaanStmt = $db->prepare("
SELECT pm.status_pekerjaan AS label, COUNT(*) AS value
FROM penduduk_miskin pm $joinW $whereBase
GROUP BY pm.status_pekerjaan
ORDER BY value DESC
");
$pekerjaanStmt->execute($params);
$pekerjaanChart = $pekerjaanStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 7. DATA HEATMAP (lat/lng + bobot untuk Leaflet.heat)
// ═══════════════════════════════════════════════════════════
$heatStmt = $db->prepare("
SELECT pm.lat, pm.lng,
CASE pm.kategori_kemiskinan
WHEN 'sangat_miskin' THEN 1.0
WHEN 'miskin' THEN 0.6
WHEN 'hampir_miskin' THEN 0.3
WHEN 'mampu' THEN 0.1
ELSE 0.1
END AS intensity
FROM penduduk_miskin pm $joinW $whereBase
");
$heatStmt->execute($params);
$heatmap = $heatStmt->fetchAll();
// ═══════════════════════════════════════════════════════════
// 8. TOP 10 KK BELUM MENERIMA BANTUAN APAPUN
// ═══════════════════════════════════════════════════════════
$belumBantuanStmt = $db->prepare("
SELECT pm.id, pm.nama_kk, pm.nik_kk, pm.alamat,
pm.kategori_kemiskinan, pm.jumlah_anggota,
pm.status_verifikasi,
COALESCE(w.kelurahan,'') AS kelurahan,
DATEDIFF(NOW(), pm.created_at) AS hari_terdata
FROM penduduk_miskin pm $joinW
$whereBase
AND NOT EXISTS (
SELECT 1 FROM bantuan_penduduk bp
WHERE bp.penduduk_id = pm.id AND bp.status='aktif'
)
ORDER BY pm.kategori_kemiskinan ASC, hari_terdata DESC
LIMIT 10
");
$belumBantuanStmt->execute($params);
$belumBantuan = $belumBantuanStmt->fetchAll();
// ── Statistik Rumah Ibadah (tetap dari v1.1) ──────────────
$ibadahStats = $db->query("
SELECT COUNT(*) AS total_ibadah FROM rumah_ibadah
")->fetch();
jsonResponse([
'success' => true,
'kpi' => $kpiData,
'chart_kategori' => $kategoriChart,
'chart_kelurahan' => $kelurahanChart,
'chart_bantuan' => $bantuanChart,
'chart_tren' => $trenChart,
'chart_pekerjaan' => $pekerjaanChart,
'heatmap' => $heatmap,
'belum_bantuan' => $belumBantuan,
'total_ibadah' => (int)$ibadahStats['total_ibadah'],
'generated_at' => date('Y-m-d H:i:s'),
]);