172 lines
7.8 KiB
PHP
172 lines
7.8 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../config/db.php';
|
|
require_once __DIR__ . '/../config/auth_check.php';
|
|
requireAnyRole(['operator']);
|
|
|
|
$pdo = Database::getConnection();
|
|
|
|
// KPI kemiskinan
|
|
$stats = $pdo->query("SELECT
|
|
(SELECT COUNT(*) FROM warga_miskin) AS total_warga,
|
|
(SELECT COUNT(*) FROM warga_miskin WHERE status_verifikasi='terverifikasi') AS terverifikasi,
|
|
(SELECT COUNT(*) FROM warga_miskin WHERE status_verifikasi='belum') AS belum,
|
|
(SELECT COUNT(*) FROM warga_miskin WHERE status_verifikasi='perlu_tinjauan') AS perlu_tinjauan,
|
|
(SELECT COUNT(*) FROM wilayah) AS total_wilayah,
|
|
(SELECT COUNT(DISTINCT warga_id) FROM bantuan_sosial WHERE is_aktif=1) AS warga_dibantu,
|
|
(SELECT COUNT(*) FROM users) AS total_users
|
|
")->fetch();
|
|
|
|
$total = (int)$stats['total_warga'];
|
|
$dibantu = (int)$stats['warga_dibantu'];
|
|
$cakupan = $total > 0 ? round($dibantu / $total * 100, 1) : 0;
|
|
$belumDibantu = $total - $dibantu;
|
|
|
|
// Zona prioritas: kelurahan dengan % miskin > 5%
|
|
$zona = $pdo->query("
|
|
SELECT COUNT(*) AS cnt FROM (
|
|
SELECT w.id, (COUNT(wm.id) / NULLIF(w.jumlah_penduduk,0) * 100) AS persen
|
|
FROM wilayah w LEFT JOIN warga_miskin wm ON ST_Contains(w.geom, wm.geom)
|
|
GROUP BY w.id HAVING persen > 5
|
|
) sub
|
|
")->fetch();
|
|
$zonaPrioritas = (int)($zona['cnt'] ?? 0);
|
|
|
|
// Data terbaru
|
|
$recentWarga = $pdo->query("
|
|
SELECT w.nama_kk, w.penghasilan, w.status_verifikasi, wl.nama AS kelurahan, w.created_at
|
|
FROM warga_miskin w LEFT JOIN wilayah wl ON wl.id=w.wilayah_id
|
|
ORDER BY w.id DESC LIMIT 6
|
|
")->fetchAll();
|
|
|
|
// Rekap per kelurahan
|
|
$rekapWilayah = $pdo->query("
|
|
SELECT w.nama, w.jumlah_penduduk, COUNT(wm.id) AS miskin
|
|
FROM wilayah w LEFT JOIN warga_miskin wm ON ST_Contains(w.geom, wm.geom)
|
|
GROUP BY w.id ORDER BY miskin DESC
|
|
")->fetchAll();
|
|
|
|
$pageTitle = 'Dashboard';
|
|
$activeNav = 'dashboard';
|
|
require_once __DIR__ . '/partials/header.php';
|
|
|
|
function vBadge($s) {
|
|
return match ($s) {
|
|
'terverifikasi' => '<span class="badge badge-success">Terverifikasi</span>',
|
|
'perlu_tinjauan' => '<span class="badge badge-warning">Perlu Tinjauan</span>',
|
|
default => '<span class="badge" style="background:#F3F4F6;color:#6B7280;">Belum</span>',
|
|
};
|
|
}
|
|
?>
|
|
|
|
<!-- Quick access -->
|
|
<div class="card" style="background:#EFF6FF; border:1px solid #BFDBFE; margin-bottom:24px;">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:16px;">
|
|
<div>
|
|
<h3 style="font-size:1.1rem; font-weight:700; margin-bottom:6px; color:#1E3A8A;">🗺️ Peta Pemetaan Kemiskinan</h3>
|
|
<p style="color:#3B82F6; font-size:0.88rem; max-width:520px;">
|
|
Visualisasikan sebaran kemiskinan (choropleth & heatmap), kelola data rumah tangga, dan analisis zona prioritas.
|
|
</p>
|
|
</div>
|
|
<a href="<?= app_url('admin/peta.php') ?>" class="btn btn-primary"><i class="fas fa-map-marked-alt"></i> Buka Peta</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- KPI -->
|
|
<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 Rumah Tangga Miskin</div>
|
|
<div class="stat-value"><?= $total ?></div>
|
|
<div class="stat-change"><?= $stats['total_wilayah'] ?> kelurahan</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"><?= $stats['terverifikasi'] ?></div>
|
|
<div class="stat-change"><?= $stats['belum'] ?> belum diverifikasi</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 ?> dari <?= $total ?> RT</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card warning">
|
|
<div class="stat-icon"><i class="fas fa-user-clock"></i></div>
|
|
<div class="stat-body">
|
|
<div class="stat-label">Belum Terima Bantuan</div>
|
|
<div class="stat-value"><?= $belumDibantu ?></div>
|
|
<div class="stat-change">kandidat prioritas</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</div>
|
|
<div class="stat-value"><?= $zonaPrioritas ?></div>
|
|
<div class="stat-change">kelurahan > 5% miskin</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card violet">
|
|
<div class="stat-icon"><i class="fas fa-clipboard-check"></i></div>
|
|
<div class="stat-body">
|
|
<div class="stat-label">Perlu Tinjauan</div>
|
|
<div class="stat-value"><?= $stats['perlu_tinjauan'] ?></div>
|
|
<div class="stat-change">data menunggu review</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content row -->
|
|
<div style="display:grid; grid-template-columns: 1fr 1fr; gap:20px; margin-bottom:24px;">
|
|
<!-- Rekap per kelurahan -->
|
|
<div class="card">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
|
|
<h3 style="font-size:0.95rem; font-weight:700;">📊 Rekap per Kelurahan</h3>
|
|
</div>
|
|
<?php foreach ($rekapWilayah as $w): $p = $w['jumlah_penduduk'] > 0 ? round($w['miskin']/$w['jumlah_penduduk']*100,1) : 0; ?>
|
|
<div style="margin-bottom:10px;">
|
|
<div style="display:flex;justify-content:space-between;font-size:0.85rem;margin-bottom:3px;">
|
|
<span><?= htmlspecialchars($w['nama']) ?></span>
|
|
<strong><?= $w['miskin'] ?> RT (<?= $p ?>%)</strong>
|
|
</div>
|
|
<div style="height:7px;background:#F3F4F6;border-radius:4px;overflow:hidden;">
|
|
<div style="height:100%;width:<?= min($p*8,100) ?>%;background:<?= $p>10?'#EF4444':($p>5?'#FB923C':($p>2?'#FBBF24':'#10B981')) ?>;"></div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php if (!$rekapWilayah): ?><p style="color:var(--text-muted);font-size:0.85rem;">Belum ada data wilayah.</p><?php endif; ?>
|
|
</div>
|
|
|
|
<!-- Data terbaru -->
|
|
<div class="card">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
|
|
<h3 style="font-size:0.95rem; font-weight:700;">👥 Rumah Tangga Terbaru</h3>
|
|
<a href="<?= app_url('admin/data_warga.php') ?>" class="btn btn-ghost btn-sm">Lihat Semua</a>
|
|
</div>
|
|
<?php if ($recentWarga): ?>
|
|
<div style="display:flex; flex-direction:column; gap:8px;">
|
|
<?php foreach ($recentWarga as $w): ?>
|
|
<div style="display:flex; align-items:center; justify-content:space-between; padding:10px 12px; background:#F9FAFB; border:1px solid #E5E7EB; border-radius:8px;">
|
|
<div>
|
|
<div style="font-weight:600; font-size:0.88rem;"><?= htmlspecialchars($w['nama_kk']) ?></div>
|
|
<div style="font-size:0.75rem; color:var(--text-muted);"><?= htmlspecialchars($w['kelurahan'] ?: 'Tanpa kelurahan') ?> · Rp <?= number_format($w['penghasilan'],0,',','.') ?></div>
|
|
</div>
|
|
<?= vBadge($w['status_verifikasi']) ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<p style="color:var(--text-muted); text-align:center; padding:20px 0; font-size:0.85rem;">Belum ada data warga</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require_once __DIR__ . '/partials/footer.php'; ?>
|