109 lines
6.8 KiB
PHP
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'; ?>
|