6215b4367a
Sistem WebGIS analisis sebaran penduduk miskin dan jangkauan rumah ibadah. Fitur: peta interaktif Leaflet.js, CRUD rumah ibadah & penduduk miskin, auto-kategorisasi haversine, heatmap, export PDF/CSV, dashboard analitik, manajemen pengguna (superadmin/admin), login sistem. Teknologi: PHP, MySQL, Leaflet.js, OpenStreetMap, Nominatim Geocoding, mPDF. Catatan: jalankan `composer install` di folder uas/ untuk install dependencies. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
209 lines
8.7 KiB
PHP
209 lines
8.7 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../vendor/autoload.php';
|
|
include '../koneksi.php';
|
|
include '../auth.php';
|
|
requireLogin();
|
|
|
|
// ── Data ─────────────────────────────────────────────────────────────────────
|
|
$allIbadah = mysqli_fetch_all(
|
|
mysqli_query($conn, "SELECT * FROM rumah_ibadah ORDER BY nama"),
|
|
MYSQLI_ASSOC
|
|
);
|
|
|
|
$allPenduduk = mysqli_fetch_all(
|
|
mysqli_query($conn,
|
|
"SELECT p.*, i.nama AS ibadah_nama
|
|
FROM penduduk_miskin p
|
|
LEFT JOIN rumah_ibadah i ON i.id = p.rumah_ibadah_id
|
|
ORDER BY p.kk_nama"),
|
|
MYSQLI_ASSOC
|
|
);
|
|
|
|
// Anggota count per penduduk
|
|
$anggotaCounts = [];
|
|
$res = mysqli_query($conn, "SELECT penduduk_id, COUNT(*) as cnt FROM anggota_keluarga GROUP BY penduduk_id");
|
|
while ($r = mysqli_fetch_assoc($res)) {
|
|
$anggotaCounts[$r['penduduk_id']] = (int)$r['cnt'];
|
|
}
|
|
|
|
// ── Statistik ─────────────────────────────────────────────────────────────────
|
|
$total = count($allPenduduk);
|
|
$sudah = count(array_filter($allPenduduk, fn($p) => $p['status_bantuan'] === 'sudah_dibantu'));
|
|
$belum = count(array_filter($allPenduduk, fn($p) => $p['status_bantuan'] === 'belum_dibantu'));
|
|
$menunggu = count(array_filter($allPenduduk, fn($p) => $p['status_bantuan'] === 'menunggu_verifikasi'));
|
|
$pctSudah = $total > 0 ? round($sudah / $total * 100, 1) : 0;
|
|
|
|
$bulan = ['','Januari','Februari','Maret','April','Mei','Juni',
|
|
'Juli','Agustus','September','Oktober','November','Desember'];
|
|
$tgl = date('j') . ' ' . $bulan[(int)date('n')] . ' ' . date('Y');
|
|
$cetakOleh = htmlspecialchars(currentUser()['nama'] ?? 'Admin');
|
|
|
|
// ── Baris tabel ibadah ────────────────────────────────────────────────────────
|
|
$rowsIbadah = '';
|
|
foreach ($allIbadah as $i => $ib) {
|
|
$binaan = count(array_filter($allPenduduk, fn($p) => $p['rumah_ibadah_id'] == $ib['id']));
|
|
$bg = ($i % 2 === 0) ? '#ffffff' : '#f9fafb';
|
|
$rowsIbadah .= "
|
|
<tr style='background:{$bg}'>
|
|
<td style='text-align:center'>" . ($i + 1) . "</td>
|
|
<td><b>" . htmlspecialchars($ib['nama']) . "</b></td>
|
|
<td style='text-align:center'>" . htmlspecialchars($ib['jenis']) . "</td>
|
|
<td style='text-align:center'>{$ib['radius']} m</td>
|
|
<td style='text-align:center'><b style='color:#1a7a3e'>{$binaan}</b></td>
|
|
</tr>";
|
|
}
|
|
if (!$rowsIbadah) {
|
|
$rowsIbadah = "<tr><td colspan='5' style='text-align:center;color:#999'>Belum ada data rumah ibadah.</td></tr>";
|
|
}
|
|
|
|
// ── Baris tabel penduduk ─────────────────────────────────────────────────────
|
|
$statusLabel = [
|
|
'belum_dibantu' => 'Belum Dibantu',
|
|
'sudah_dibantu' => 'Sudah Dibantu',
|
|
'menunggu_verifikasi'=> 'Menunggu Verifikasi',
|
|
];
|
|
$statusColor = [
|
|
'belum_dibantu' => '#c0392b',
|
|
'sudah_dibantu' => '#1a7a3e',
|
|
'menunggu_verifikasi'=> '#856404',
|
|
];
|
|
|
|
$rowsPenduduk = '';
|
|
foreach ($allPenduduk as $i => $p) {
|
|
$bg = ($i % 2 === 0) ? '#ffffff' : '#f9fafb';
|
|
$status = $p['status_bantuan'];
|
|
$slbl = $statusLabel[$status] ?? $status;
|
|
$scol = $statusColor[$status] ?? '#333';
|
|
$jml = $p['jumlah_anggota'] ?? ($anggotaCounts[$p['id']] ?? 1);
|
|
$jarak = $p['jarak_meter'] ? round($p['jarak_meter']) . ' m' : '-';
|
|
$tglB = $p['tanggal_bantuan']
|
|
? date('d/m/Y', strtotime($p['tanggal_bantuan'])) : '-';
|
|
|
|
$rowsPenduduk .= "
|
|
<tr style='background:{$bg}'>
|
|
<td style='text-align:center'>" . ($i + 1) . "</td>
|
|
<td><b>" . htmlspecialchars($p['kk_nama']) . "</b>" .
|
|
($p['nik'] ? "<br><span style='font-size:8px;color:#888'>{$p['nik']}</span>" : '') .
|
|
"</td>
|
|
<td style='font-size:9px'>" . htmlspecialchars($p['alamat'] ?? '-') . "</td>
|
|
<td style='text-align:center'>{$jml}</td>
|
|
<td style='font-size:9px'>" . htmlspecialchars($p['ibadah_nama'] ?? '-') . "</td>
|
|
<td style='text-align:center'>{$jarak}</td>
|
|
<td style='text-align:center;color:{$scol};font-weight:bold'>{$slbl}</td>
|
|
<td style='font-size:9px'>" . htmlspecialchars($p['jenis_bantuan'] ?? '-') . "</td>
|
|
<td style='text-align:center'>{$tglB}</td>
|
|
</tr>";
|
|
}
|
|
if (!$rowsPenduduk) {
|
|
$rowsPenduduk = "<tr><td colspan='9' style='text-align:center;color:#999'>Belum ada data penduduk miskin.</td></tr>";
|
|
}
|
|
|
|
// ── HTML Template ─────────────────────────────────────────────────────────────
|
|
$html = <<<HTML
|
|
<style>
|
|
body { font-family: sans-serif; font-size: 10.5px; color: #1a1a1a; }
|
|
h1 { font-size: 15px; text-align: center; color: #1e3a5f; margin-bottom: 2px; }
|
|
.sub { text-align: center; font-size: 9.5px; color: #555; margin-bottom: 14px; }
|
|
.section { font-size: 11px; font-weight: bold; color: #1e3a5f;
|
|
border-bottom: 2px solid #1e3a5f; padding-bottom: 3px; margin: 12px 0 7px; }
|
|
table { width: 100%; border-collapse: collapse; font-size: 9.5px; }
|
|
th { background: #1e3a5f; color: white; padding: 5px 4px; text-align: center; }
|
|
td { padding: 4px 5px; border-bottom: 1px solid #e5e7eb; vertical-align: middle; }
|
|
.sg { width: 100%; border-collapse: collapse; margin-bottom: 6px; }
|
|
.sc { width: 25%; padding: 8px; text-align: center; border: 1px solid #d1d5db; border-radius: 4px; }
|
|
.sn { font-size: 20px; font-weight: bold; margin-bottom: 2px; }
|
|
.sl { font-size: 8.5px; color: #6b7280; }
|
|
.g { color: #1a7a3e; }
|
|
.r { color: #c0392b; }
|
|
.y { color: #856404; }
|
|
</style>
|
|
|
|
<h1>LAPORAN SEBARAN PENDUDUK MISKIN</h1>
|
|
<div class="sub">
|
|
Sistem WebGIS GeoMiskin — Universitas Tanjungpura |
|
|
Dicetak: {$tgl} |
|
|
Oleh: {$cetakOleh}
|
|
</div>
|
|
|
|
<div class="section">Ringkasan Statistik</div>
|
|
<table class="sg">
|
|
<tr>
|
|
<td class="sc">
|
|
<div class="sn">{$total}</div>
|
|
<div class="sl">Total KK Miskin</div>
|
|
</td>
|
|
<td class="sc">
|
|
<div class="sn g">{$sudah}</div>
|
|
<div class="sl">Sudah Dibantu ({$pctSudah}%)</div>
|
|
</td>
|
|
<td class="sc">
|
|
<div class="sn r">{$belum}</div>
|
|
<div class="sl">Belum Dibantu</div>
|
|
</td>
|
|
<td class="sc">
|
|
<div class="sn y">{$menunggu}</div>
|
|
<div class="sl">Menunggu Verifikasi</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<div class="section">Data Rumah Ibadah</div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th width="5%">No</th>
|
|
<th width="35%">Nama Rumah Ibadah</th>
|
|
<th width="20%">Jenis</th>
|
|
<th width="15%">Radius</th>
|
|
<th width="25%">KK Binaan</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>{$rowsIbadah}</tbody>
|
|
</table>
|
|
|
|
<div class="section">Daftar Penduduk Miskin</div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th width="4%">No</th>
|
|
<th width="14%">Nama KK / NIK</th>
|
|
<th width="16%">Alamat</th>
|
|
<th width="5%">Jiwa</th>
|
|
<th width="14%">Rumah Ibadah</th>
|
|
<th width="8%">Jarak</th>
|
|
<th width="13%">Status</th>
|
|
<th width="14%">Jenis Bantuan</th>
|
|
<th width="12%">Tgl Bantuan</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>{$rowsPenduduk}</tbody>
|
|
</table>
|
|
HTML;
|
|
|
|
// ── Generate PDF ───────────────────────────────────────────────────────────────
|
|
try {
|
|
$mpdf = new \Mpdf\Mpdf([
|
|
'mode' => 'utf-8',
|
|
'format' => 'A4-L',
|
|
'margin_top' => 12,
|
|
'margin_bottom' => 12,
|
|
'margin_left' => 10,
|
|
'margin_right' => 10,
|
|
]);
|
|
$mpdf->SetTitle('Laporan Sebaran Penduduk Miskin');
|
|
$mpdf->SetAuthor('GeoMiskin WebGIS');
|
|
$mpdf->WriteHTML($html);
|
|
$fname = 'laporan_penduduk_miskin_' . date('Y-m-d') . '.pdf';
|
|
$mpdf->Output($fname, 'D');
|
|
} catch (\Mpdf\MpdfException $e) {
|
|
http_response_code(500);
|
|
echo '<pre style="font-family:monospace;padding:20px">
|
|
<b>Gagal membuat PDF:</b> ' . htmlspecialchars($e->getMessage()) . '
|
|
|
|
Pastikan extension GD aktif di XAMPP:
|
|
1. Buka C:\\xampp\\php\\php.ini
|
|
2. Cari ;extension=gd → hapus tanda titik koma
|
|
3. Restart Apache di XAMPP Control Panel
|
|
</pre>';
|
|
}
|