189 lines
7.6 KiB
PHP
189 lines
7.6 KiB
PHP
<?php
|
|
// Ekstrak data chart di luar heredoc agar tidak ada konversi array-dalam-string
|
|
$chartKec = [];
|
|
$chartKecData = [];
|
|
foreach ($perKecamatan ?? [] as $row) {
|
|
$chartKec[] = (string)($row['nama'] ?? '');
|
|
$chartKecData[] = (int)($row['total'] ?? 0);
|
|
}
|
|
|
|
$chartBulan = [];
|
|
$chartBantuanData = [];
|
|
foreach ($trenBantuan ?? [] as $row) {
|
|
$chartBulan[] = (string)($row['bulan'] ?? '');
|
|
$chartBantuanData[] = (int)($row['jumlah'] ?? 0);
|
|
}
|
|
|
|
$jsonKec = json_encode($chartKec);
|
|
$jsonKecData = json_encode($chartKecData);
|
|
$jsonBulan = json_encode($chartBulan);
|
|
$jsonBantuanData = json_encode($chartBantuanData);
|
|
$mapLat = MAP_DEFAULT_LAT;
|
|
$mapLng = MAP_DEFAULT_LNG;
|
|
$appUrl = APP_URL;
|
|
|
|
$extraJs = <<<JS
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
// Init peta
|
|
const map = GISMap.init('admin-map', {$mapLat}, {$mapLng}, 13);
|
|
|
|
// Load data peta
|
|
const data = await App.fetchJSON('{$appUrl}/admin/api/peta');
|
|
if (data) {
|
|
const wargaLayer = GISMap.addWargaLayer(data.warga || []);
|
|
const riLayer = GISMap.addRILayer(data.rumah_ibadah || []);
|
|
const lapLayer = GISMap.addLaporanLayer(data.laporan || []);
|
|
|
|
const overlays = {
|
|
'👥 Warga Miskin': wargaLayer,
|
|
'⛪ Rumah Ibadah': riLayer,
|
|
'📋 Laporan Masuk': lapLayer
|
|
};
|
|
L.control.layers(GISMap.layers, overlays, {position:'topright', collapsed:true}).addTo(map);
|
|
|
|
GISMap.autoFitBounds();
|
|
|
|
const heat = await App.fetchJSON('{$appUrl}/dinsos/api/heatmap');
|
|
if (heat) GISMap.addHeatmap(heat);
|
|
} else {
|
|
GISMap.autoFitBounds(true);
|
|
}
|
|
|
|
// Charts — data sudah diekstrak bersih di PHP
|
|
const kec = {$jsonKec};
|
|
const kecData = {$jsonKecData};
|
|
Charts.bar('chart-kecamatan', kec, [{ label: 'Warga Miskin', data: kecData }]);
|
|
|
|
const bulan = {$jsonBulan};
|
|
const bantuanData = {$jsonBantuanData};
|
|
Charts.line('chart-bantuan', bulan, [{ label: 'Bantuan Disalurkan', data: bantuanData }]);
|
|
});
|
|
</script>
|
|
JS; ?>
|
|
|
|
<!-- Stats Grid -->
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon blue">👥</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['total_warga'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Total Warga Miskin</div>
|
|
<div class="stat-card-sub"><?= number_format((int)($stats['warga_ekstrem'] ?? 0)) ?> miskin ekstrem</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon green">⛪</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['total_ri'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Rumah Ibadah Aktif</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon orange">📋</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['total_laporan'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Total Laporan</div>
|
|
<div class="stat-card-sub"><?= (int)($stats['laporan_pending'] ?? 0) ?> menunggu</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon teal">📦</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['total_bantuan'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Total Bantuan</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon purple">⚠️</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['blind_spot'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Blind Spot</div>
|
|
<div class="stat-card-sub">Belum terjangkau rumah ibadah</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-card-icon gray">👤</div>
|
|
<div class="stat-card-body">
|
|
<div class="stat-card-value"><?= number_format((int)($stats['total_user'] ?? 0)) ?></div>
|
|
<div class="stat-card-label">Pengguna Sistem</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dashboard Grid: Map + Sidebar -->
|
|
<div class="dashboard-grid" style="grid-template-columns:1fr 360px;gap:20px;margin-bottom:24px">
|
|
<!-- PETA UTAMA -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="card-icon">🗺</span>
|
|
<h3>Peta Persebaran Kemiskinan Kota Pontianak</h3>
|
|
<div class="card-actions">
|
|
<button class="btn btn-ghost btn-sm" onclick="toggleHeatmap()">🌡 Heatmap</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body no-pad" style="position:relative">
|
|
<div id="admin-map" style="height:480px"></div>
|
|
<div class="map-legend">
|
|
<h4>Legenda</h4>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-ekstrem"></div> Miskin Ekstrem</div>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-miskin"></div> Miskin</div>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-rentan"></div> Rentan Miskin</div>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-ri"></div> Rumah Ibadah</div>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-blind"></div> Blind Spot</div>
|
|
<div class="map-legend-item"><div class="map-legend-dot legend-dot-laporan"></div> Laporan Masuk</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- SIDEBAR: Aktivitas & Tabel Kec -->
|
|
<div style="display:flex;flex-direction:column;gap:16px">
|
|
<!-- Per Kecamatan -->
|
|
<div class="card">
|
|
<div class="card-header"><span class="card-icon">🗾</span><h3>Sebaran per Kecamatan</h3></div>
|
|
<div class="card-body no-pad">
|
|
<div class="table-wrap">
|
|
<table>
|
|
<thead><tr><th>Kecamatan</th><th>Total</th><th>Ekstrem</th><th>Blind Spot</th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($perKecamatan ?? [] as $k): ?>
|
|
<tr>
|
|
<td style="font-weight:500;font-size:0.82rem"><?= e($k['nama']) ?></td>
|
|
<td><strong><?= number_format((int)($k['total'] ?? 0)) ?></strong></td>
|
|
<td><span class="badge badge-red"><?= number_format((int)($k['ekstrem'] ?? 0)) ?></span></td>
|
|
<td><span class="badge badge-purple"><?= number_format((int)($k['blind_spot'] ?? 0)) ?></span></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Aktivitas Terbaru -->
|
|
<div class="card" style="flex:1">
|
|
<div class="card-header"><span class="card-icon">📋</span><h3>Aktivitas Terbaru</h3></div>
|
|
<div class="card-body no-pad" style="max-height:240px;overflow-y:auto">
|
|
<?php foreach ($aktivitas ?? [] as $a): ?>
|
|
<div style="padding:10px 16px;border-bottom:1px solid #f1f5f9">
|
|
<div style="font-size:0.8rem;font-weight:600"><?= e($a['aksi']) ?></div>
|
|
<div style="font-size:0.72rem;color:var(--clr-text-muted)"><?= e($a['nama_user'] ?? '-') ?> · <?= e($a['modul'] ?? '') ?></div>
|
|
<div style="font-size:0.7rem;color:var(--clr-text-muted)"><?= formatTanggal($a['created_at'], true) ?></div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Charts Row -->
|
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px">
|
|
<div class="card">
|
|
<div class="card-header"><span class="card-icon">📊</span><h3>Warga Miskin per Kecamatan</h3></div>
|
|
<div class="card-body"><div class="chart-wrap"><canvas id="chart-kecamatan"></canvas></div></div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header"><span class="card-icon">📈</span><h3>Tren Bantuan 6 Bulan Terakhir</h3></div>
|
|
<div class="card-body"><div class="chart-wrap"><canvas id="chart-bantuan"></canvas></div></div>
|
|
</div>
|
|
</div>
|