141 lines
5.8 KiB
PHP
141 lines
5.8 KiB
PHP
<?php ob_start(); ?>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
const map = GISMap.init('verif-map', <?= MAP_DEFAULT_LAT ?>, <?= MAP_DEFAULT_LNG ?>, 14);
|
||
|
||
const laporan = <?= json_encode(array_map(fn($l) => [
|
||
'lat' => (float)$l['lat'], 'lng' => (float)$l['lng'],
|
||
'nama_warga' => $l['nama_warga'], 'kode_laporan' => $l['kode_laporan'],
|
||
'status' => $l['status']
|
||
], array_filter($laporanTerbaru, fn($l) => $l['lat'] && $l['lng']))) ?>;
|
||
|
||
laporan.forEach(l => {
|
||
const color = l.status === 'terverifikasi' ? '#16a34a' : l.status === 'ditolak' ? '#dc2626' : '#0284c7';
|
||
L.circleMarker([l.lat, l.lng], {radius:9,fillColor:color,color:'#fff',weight:2,fillOpacity:0.9})
|
||
.bindPopup(`<strong>${l.nama_warga}</strong><br><code>${l.kode_laporan}</code>`)
|
||
.addTo(map);
|
||
GISMap._allMarkerBounds.push([l.lat, l.lng]);
|
||
});
|
||
GISMap.autoFitBounds(laporan.length === 0);
|
||
|
||
const statsData = await App.fetchJSON('<?= APP_URL ?>/verifikator/api/stats');
|
||
if (statsData?.data) {
|
||
const d = statsData.data;
|
||
Charts.donut('chart-status',
|
||
['Menunggu', 'Diproses', 'Terverifikasi', 'Ditolak'],
|
||
[d.menunggu, d.diproses, d.terverifikasi, d.ditolak],
|
||
['#d97706','#0284c7','#16a34a','#dc2626']
|
||
);
|
||
}
|
||
});
|
||
</script>
|
||
<?php $extraJs = ob_get_clean(); ?>
|
||
|
||
<!-- Stats -->
|
||
<div class="stats-grid">
|
||
<div class="stat-card">
|
||
<div class="stat-card-icon orange">📋</div>
|
||
<div class="stat-card-body">
|
||
<div class="stat-card-value"><?= number_format($stats['laporan_menunggu'] ?? 0) ?></div>
|
||
<div class="stat-card-label">Laporan Menunggu</div>
|
||
<div class="stat-card-sub"><a href="<?= APP_URL ?>/verifikator/laporan?status=menunggu" style="color:var(--clr-primary-l)">Lihat semua →</a></div>
|
||
</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-card-icon blue">🔄</div>
|
||
<div class="stat-card-body">
|
||
<div class="stat-card-value"><?= number_format($stats['laporan_diproses'] ?? 0) ?></div>
|
||
<div class="stat-card-label">Sedang Diproses</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($stats['total_warga'] ?? 0) ?></div>
|
||
<div class="stat-card-label">Warga Terverifikasi</div>
|
||
</div>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="stat-card-icon red">🔥</div>
|
||
<div class="stat-card-body">
|
||
<div class="stat-card-value"><?= number_format($stats['prioritas_tinggi'] ?? 0) ?></div>
|
||
<div class="stat-card-label">Prioritas Tinggi</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($stats['blind_spot'] ?? 0) ?></div>
|
||
<div class="stat-card-label">Blind Spot</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Grid: Peta + Chart -->
|
||
<div class="dashboard-grid" style="margin-bottom:20px">
|
||
<!-- PETA -->
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-icon">🗺</span><h3>Peta Laporan Kelurahan Saya</h3></div>
|
||
<div class="card-body no-pad">
|
||
<div id="verif-map" style="height:380px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SIDEBAR: Donut + Laporan List -->
|
||
<div style="display:flex;flex-direction:column;gap:16px">
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-icon">📊</span><h3>Status Laporan</h3></div>
|
||
<div class="card-body"><div class="chart-wrap" style="height:180px"><canvas id="chart-status"></canvas></div></div>
|
||
</div>
|
||
|
||
<div class="card" style="flex:1">
|
||
<div class="card-header">
|
||
<span class="card-icon">📋</span><h3>Laporan Terbaru</h3>
|
||
<div class="card-actions"><a href="<?= APP_URL ?>/verifikator/laporan" class="btn btn-ghost btn-sm">Semua</a></div>
|
||
</div>
|
||
<div class="card-body no-pad" style="max-height:300px;overflow-y:auto">
|
||
<?php foreach ($laporanTerbaru as $l): ?>
|
||
<a href="<?= APP_URL ?>/verifikator/laporan/<?= $l['id'] ?>" style="display:block;text-decoration:none;color:inherit">
|
||
<div class="sidebar-panel-item">
|
||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||
<h4><?= e($l['nama_warga']) ?></h4>
|
||
<?php
|
||
$badge = match($l['status']) {
|
||
'menunggu' => 'badge-yellow', 'diproses' => 'badge-blue',
|
||
'terverifikasi' => 'badge-green', 'ditolak' => 'badge-red', default => 'badge-gray'
|
||
};
|
||
$label = match($l['status']) {
|
||
'menunggu'=>'Menunggu','diproses'=>'Diproses',
|
||
'terverifikasi'=>'Terverifikasi','ditolak'=>'Ditolak', default=>$l['status']
|
||
};
|
||
?>
|
||
<span class="badge <?= $badge ?>"><?= $label ?></span>
|
||
</div>
|
||
<p><?= e($l['kode_laporan']) ?> · <?= formatTanggal($l['created_at']) ?></p>
|
||
</div>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
<?php if (empty($laporanTerbaru)): ?>
|
||
<div class="empty-state" style="padding:24px">
|
||
<div class="empty-state-icon">📭</div>
|
||
<p>Belum ada laporan masuk</p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quick Actions -->
|
||
<div class="card">
|
||
<div class="card-header"><span class="card-icon">⚡</span><h3>Aksi Cepat</h3></div>
|
||
<div class="card-body">
|
||
<div style="display:flex;gap:12px;flex-wrap:wrap">
|
||
<a href="<?= APP_URL ?>/verifikator/laporan?status=menunggu" class="btn btn-accent">
|
||
📋 Verifikasi Laporan (<?= $stats['laporan_menunggu'] ?? 0 ?>)
|
||
</a>
|
||
<a href="<?= APP_URL ?>/verifikator/warga/tambah" class="btn btn-primary">➕ Tambah Data Warga</a>
|
||
<a href="<?= APP_URL ?>/verifikator/warga?level=Tinggi" class="btn btn-danger">🔥 Warga Prioritas Tinggi</a>
|
||
</div>
|
||
</div>
|
||
</div>
|