[masjid, ...]
$masjidCoverage = []; // masjidId -> ['kk'=>[], 'jiwa'=>0]
foreach ($allMasjid as $m) {
$masjidCoverage[$m['id']] = ['kk' => [], 'jiwa' => 0];
}
foreach ($allKemiskinan as $kk) {
$kkCoverage[$kk['id']] = [];
foreach ($allMasjid as $m) {
$dist = haversine($kk['lat'], $kk['lng'], $m['lat'], $m['lng']);
if ($dist <= (int)$m['radius_m']) {
$kkCoverage[$kk['id']][] = $m;
$masjidCoverage[$m['id']]['kk'][] = $kk;
$masjidCoverage[$m['id']]['jiwa'] += (int)$kk['jumlah_kk'];
}
}
}
// ── Statistik ringkasan ───────────────────────────────────────────────────
$totalKK = count($allKemiskinan);
$totalJiwa = array_sum(array_column($allKemiskinan, 'jumlah_kk'));
$countT = 0; $jiwaT = 0;
foreach ($allKemiskinan as $kk) {
if (count($kkCoverage[$kk['id']]) > 0) { $countT++; $jiwaT += (int)$kk['jumlah_kk']; }
}
$countTT = $totalKK - $countT;
$jiwaTT = $totalJiwa - $jiwaT;
$pct = $totalKK > 0 ? number_format(($countT / $totalKK) * 100, 1) : '0.0';
$pctTT = $totalKK > 0 ? number_format((($countTT) / $totalKK) * 100, 1) : '0.0';
// ── Tanggal dalam format Indonesia ───────────────────────────────────────
$bulan = ['','Januari','Februari','Maret','April','Mei','Juni',
'Juli','Agustus','September','Oktober','November','Desember'];
$tgl = date('j') . ' ' . $bulan[(int)date('n')] . ' ' . date('Y');
// ── Baris tabel masjid ────────────────────────────────────────────────────
$rowsMasjid = '';
foreach ($allMasjid as $i => $m) {
$cov = $masjidCoverage[$m['id']];
$bg = ($i % 2 === 0) ? '#ffffff' : '#f9fafb';
$rowsMasjid .= "
| " . ($i+1) . " |
{$m['nama_masjid']} |
{$m['radius_m']} |
" . count($cov['kk']) . " |
{$cov['jiwa']} |
";
}
if (!$rowsMasjid) $rowsMasjid = "| Belum ada data masjid. |
";
// ── Baris tabel KK miskin ─────────────────────────────────────────────────
$rowsKK = '';
foreach ($allKemiskinan as $i => $kk) {
$covers = $kkCoverage[$kk['id']];
$covered = count($covers) > 0;
// Jarak ke masjid terdekat
$minDist = '-';
if (count($allMasjid) > 0) {
$dists = array_map(fn($m) => haversine($kk['lat'], $kk['lng'], $m['lat'], $m['lng']), $allMasjid);
$minDist = min($dists);
}
$statusTxt = $covered
? 'Terjangkau'
: 'Tidak Terjangkau';
$masjidNames = $covered ? implode(', ', array_column($covers, 'nama_masjid')) : '-';
$bg = ($i % 2 === 0) ? '#ffffff' : '#f9fafb';
$pkhTxt = $kk['pkh'] ? '✓' : '-';
$bpntTxt = $kk['bpnt'] ? '✓' : '-';
$bltTxt = $kk['blt'] ? '✓' : '-';
$rowsKK .= "
| " . ($i+1) . " |
{$kk['nama_kk']} |
{$kk['jumlah_kk']} |
{$kk['alamat']} |
{$pkhTxt} |
{$bpntTxt} |
{$bltTxt} |
{$statusTxt} |
{$masjidNames} |
{$minDist} |
";
}
if (!$rowsKK) $rowsKK = "| Belum ada data kemiskinan. |
";
// ── Template HTML untuk mPDF ──────────────────────────────────────────────
$html = <<
body { font-family: sans-serif; font-size: 11px; color: #222; }
h1 { font-size: 16px; text-align: center; margin-bottom: 2px; color: #1a3a5c; }
.subtitle { text-align: center; font-size: 10px; color: #555; margin-bottom: 16px; }
.section { font-size: 12px; font-weight: bold; color: #1a3a5c;
border-bottom: 2px solid #1a3a5c; padding-bottom: 3px; margin: 14px 0 8px; }
table { width: 100%; border-collapse: collapse; font-size: 10px; }
th { background: #1a3a5c; color: white; padding: 6px 5px; text-align: center; }
td { padding: 5px; border-bottom: 1px solid #e0e0e0; vertical-align: top; }
.stat-grid { width: 100%; border-collapse: collapse; margin-bottom: 4px; }
.stat-cell { width: 25%; padding: 8px; text-align: center; border: 1px solid #ddd; }
.stat-big { font-size: 22px; font-weight: bold; }
.stat-lbl { font-size: 9px; color: #666; margin-top: 2px; }
.green { color: #1a7a3e; }
.red { color: #c0392b; }
Laporan Analisis Kemiskinan & Jangkauan Masjid
Tanggal Cetak: {$tgl} | Sumber Data: Sistem WebGIS
Ringkasan Statistik
|
{$totalKK}
Total KK Miskin
|
{$totalJiwa}
Total Jiwa
|
{$countT} ({$pct}%)
KK Terjangkau • {$jiwaT} jiwa
|
{$countTT} ({$pctTT}%)
KK Tidak Terjangkau • {$jiwaTT} jiwa
|
Statistik per Masjid
| No |
Nama Masjid |
Radius (m) |
KK Terjangkau |
Jiwa Terjangkau |
{$rowsMasjid}
Daftar KK Miskin & Status Jangkauan
| No |
Nama KK |
Jiwa |
Alamat |
PKH |
BPNT |
BLT |
Status |
Dijangkau Masjid |
Jarak Terdekat (m) |
{$rowsKK}
HTML;
// ── Generate PDF ──────────────────────────────────────────────────────────
try {
$mpdf = new \Mpdf\Mpdf([
'mode' => 'utf-8',
'format' => 'A4-L', // landscape untuk tabel lebar
'margin_top' => 14,
'margin_bottom' => 14,
'margin_left' => 12,
'margin_right' => 12,
]);
$mpdf->SetTitle('Laporan Analisis Kemiskinan & Jangkauan Masjid');
$mpdf->WriteHTML($html);
$fname = 'laporan_kemiskinan_' . date('Y-m-d') . '.pdf';
$mpdf->Output($fname, 'D'); // 'D' = force download
} catch (\Mpdf\MpdfException $e) {
http_response_code(500);
echo 'Gagal membuat PDF: ' . htmlspecialchars($e->getMessage()) . "\n\n"
. "Pastikan extension PHP GD aktif di XAMPP:\n"
. " 1. Buka C:\\xampp\\php\\php.ini\n"
. " 2. Cari ;extension=gd dan hapus tanda titik koma\n"
. " 3. Restart Apache di XAMPP Control Panel";
}