Files
2026-06-13 11:24:58 +07:00

109 lines
6.8 KiB
PHP

<?php
require_once __DIR__ . '/../config/db.php';
require_once __DIR__ . '/../config/auth_check.php';
requireAnyRole(['pimpinan']);
$pdo = Database::getConnection();
$user = currentUser();
// KPI
$total = (int)$pdo->query("SELECT COUNT(*) FROM warga_miskin")->fetchColumn();
$dibantu = (int)$pdo->query("SELECT COUNT(DISTINCT warga_id) FROM bantuan_sosial WHERE is_aktif=1")->fetchColumn();
$terverif = (int)$pdo->query("SELECT COUNT(*) FROM warga_miskin WHERE status_verifikasi='terverifikasi'")->fetchColumn();
$cakupan = $total > 0 ? round($dibantu / $total * 100, 1) : 0;
// Zona prioritas (skor sama dgn api/zona_prioritas)
$zrows = $pdo->query("
SELECT w.nama, w.jumlah_penduduk,
COUNT(DISTINCT wm.id) AS miskin,
COUNT(DISTINCT CASE WHEN bs.id IS NOT NULL THEN wm.id END) AS dibantu
FROM wilayah w
LEFT JOIN warga_miskin wm ON ST_Contains(w.geom, wm.geom)
LEFT JOIN bantuan_sosial bs ON bs.warga_id=wm.id AND bs.is_aktif=1
GROUP BY w.id
")->fetchAll();
$zona = [];
foreach ($zrows as $r) {
$m = (int)$r['miskin']; $p = (int)$r['jumlah_penduduk'];
$persen = $p > 0 ? round($m/$p*100,2) : 0;
$cak = $m > 0 ? round($r['dibantu']/$m*100,1) : 0;
$gap = $m > 0 ? (100-$cak) : 0;
$skor = round($persen*2 + $gap*0.2 + $m*1, 1);
$level = $skor > 35 ? 'Tinggi' : ($skor > 20 ? 'Sedang' : 'Rendah');
$zona[] = ['nama'=>$r['nama'],'skor'=>$skor,'level'=>$level,'persen'=>$persen,'cakupan'=>$cak];
}
usort($zona, fn($a,$b)=>$b['skor']<=>$a['skor']);
$zonaTinggi = count(array_filter($zona, fn($z)=>$z['level']==='Tinggi'));
$pageTitle = 'Dashboard Eksekutif';
$activeNav = 'dashboard';
$extraHead = '';
require_once __DIR__ . '/partials/header.php';
?>
<div class="page-header" style="margin-bottom:18px;">
<h1 style="font-size:1.4rem;">👋 Selamat datang, <?= htmlspecialchars($user['nama_lengkap'] ?: $user['username']) ?></h1>
<p>Ringkasan eksekutif kondisi kemiskinan & penyaluran bantuan sosial kota.</p>
</div>
<div class="stats-grid">
<div class="stat-card primary"><div class="stat-icon"><i class="fas fa-house-user"></i></div>
<div class="stat-body"><div class="stat-label">Total RT Miskin</div><div class="stat-value"><?= $total ?></div><div class="stat-change"><?= count($zona) ?> kelurahan</div></div></div>
<div class="stat-card info"><div class="stat-icon"><i class="fas fa-hand-holding-heart"></i></div>
<div class="stat-body"><div class="stat-label">Cakupan Bantuan</div><div class="stat-value"><?= $cakupan ?>%</div><div class="stat-change"><?= $dibantu ?> RT dibantu</div></div></div>
<div class="stat-card success"><div class="stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="stat-body"><div class="stat-label">Terverifikasi</div><div class="stat-value"><?= $terverif ?></div><div class="stat-change">dari <?= $total ?> data</div></div></div>
<div class="stat-card danger"><div class="stat-icon"><i class="fas fa-triangle-exclamation"></i></div>
<div class="stat-body"><div class="stat-label">Zona Prioritas Tinggi</div><div class="stat-value"><?= $zonaTinggi ?></div><div class="stat-change">kelurahan</div></div></div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px;">
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Cakupan Bantuan</h3><canvas id="cPie" height="200"></canvas></div>
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Penerima per Jenis Bantuan</h3><canvas id="cBar" height="200"></canvas></div>
</div>
<div style="display:grid;grid-template-columns:1.4fr 1fr;gap:18px;margin-bottom:18px;">
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Tren 12 Bulan</h3><canvas id="cTren" height="150"></canvas></div>
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Komparatif Kelurahan (radar)</h3><canvas id="cRadar" height="150"></canvas></div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:18px;">
<div class="card">
<h3 style="font-size:0.95rem;margin-bottom:10px;">🏆 Zona Prioritas Teratas</h3>
<?php foreach (array_slice($zona,0,4) as $i=>$z): $c=['Tinggi'=>'#EF4444','Sedang'=>'#FB923C','Rendah'=>'#10B981'][$z['level']]; ?>
<div style="display:flex;justify-content:space-between;align-items:center;padding:9px 0;border-bottom:1px solid #F3F4F6;">
<div><strong>#<?= $i+1 ?> <?= htmlspecialchars($z['nama']) ?></strong>
<div style="font-size:0.74rem;color:#9CA3AF;">% miskin <?= $z['persen'] ?>% · cakupan <?= $z['cakupan'] ?>%</div></div>
<span class="badge" style="background:<?= $c ?>22;color:<?= $c ?>;">Skor <?= $z['skor'] ?> · <?= $z['level'] ?></span>
</div>
<?php endforeach; ?>
</div>
<div class="card" style="display:flex;flex-direction:column;justify-content:center;gap:10px;">
<h3 style="font-size:0.95rem;">Tindak Lanjut</h3>
<a href="<?= app_url('pimpinan/analisis.php') ?>" class="btn btn-primary"><i class="fas fa-chart-line"></i> Buka Analisis Spasial</a>
<a href="<?= app_url('pimpinan/pelaporan.php') ?>" class="btn btn-success"><i class="fas fa-file-pdf"></i> Laporan & Cetak</a>
<a href="<?= app_url('pimpinan/peta.php') ?>" class="btn btn-ghost"><i class="fas fa-map"></i> Peta Interaktif</a>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script>
const DAPI = APP_BASE + '/api';
(async ()=>{
const cak = (await (await fetch(`${DAPI}/cakupan_bantuan.php`)).json()).data;
new Chart(cPie,{type:'doughnut',data:{labels:['Dibantu','Belum'],datasets:[{data:[cak.dibantu,cak.belum_dibantu],backgroundColor:['#10B981','#E5E7EB']}]},options:{plugins:{legend:{position:'bottom'}}}});
new Chart(cBar,{type:'bar',data:{labels:cak.per_jenis.map(j=>j.kode),datasets:[{label:'Penerima',data:cak.per_jenis.map(j=>j.penerima),backgroundColor:'#2563EB'}]},options:{plugins:{legend:{display:false}},scales:{y:{beginAtZero:true,ticks:{precision:0}}}}});
const tr = (await (await fetch(`${DAPI}/tren.php`)).json()).data;
new Chart(cTren,{type:'line',data:{labels:tr.labels,datasets:[
{label:'Kumulatif Warga',data:tr.kumulatif,borderColor:'#2563EB',backgroundColor:'#2563EB22',fill:true,tension:.3},
{label:'Bantuan Baru',data:tr.bantuan_baru,borderColor:'#10B981',tension:.3}
]},options:{scales:{y:{beginAtZero:true,ticks:{precision:0}}}}});
const km = (await (await fetch(`${DAPI}/komparatif.php`)).json()).data;
new Chart(cRadar,{type:'radar',data:{labels:km.labels,datasets:[
{label:'% Miskin',data:km.persentase_miskin,borderColor:'#EF4444',backgroundColor:'#EF444422'},
{label:'Cakupan %',data:km.cakupan_bantuan,borderColor:'#10B981',backgroundColor:'#10B98122'}
]},options:{scales:{r:{beginAtZero:true}}}});
})();
</script>
<?php require_once __DIR__ . '/partials/footer.php'; ?>