fix: update final code deployment

This commit is contained in:
muthianura
2026-06-15 21:53:17 +07:00
parent 62a5a26fe0
commit 9cc6fcf52d
42 changed files with 177 additions and 23 deletions
+175
View File
@@ -0,0 +1,175 @@
<?php
session_start();
if(!isset($_SESSION['user'])) { header('Location: login.php'); exit; }
if($_SESSION['role']!=='superadmin') { header('Location: index.php'); exit; }
require_once 'config.php';
$per_page = 15;
$page = max(1, intval($_GET['page'] ?? 1));
$cari = trim($_GET['cari'] ?? '');
$offset = ($page - 1) * $per_page;
$where = '';
if($cari !== '') {
$c = $conn->real_escape_string($cari);
$where = "WHERE ri.nama LIKE '%$c%' OR ri.alamat LIKE '%$c%' OR ri.pic LIKE '%$c%' OR ri.jenis LIKE '%$c%'";
}
$total_rows = $conn->query("SELECT COUNT(*) c FROM rumah_ibadah ri $where")->fetch_assoc()['c'];
$total_pages = max(1, ceil($total_rows / $per_page));
$page = min($page, $total_pages);
$offset = ($page - 1) * $per_page;
$data = $conn->query("
SELECT ri.*, COUNT(pm.id) AS jumlah_binaan, SUM(pm.jumlah_anggota) AS total_jiwa
FROM rumah_ibadah ri
LEFT JOIN penduduk_miskin pm ON pm.rumah_ibadah_id = ri.id
$where
GROUP BY ri.id ORDER BY ri.nama ASC
LIMIT $per_page OFFSET $offset
");
$all = $conn->query("SELECT ri.nama,ri.jenis,ri.alamat,ri.pic,ri.no_wa,ri.radius,COUNT(pm.id) AS jumlah_binaan,SUM(pm.jumlah_anggota) AS total_jiwa FROM rumah_ibadah ri LEFT JOIN penduduk_miskin pm ON pm.rumah_ibadah_id=ri.id GROUP BY ri.id ORDER BY ri.nama");
$all_rows=[];
while($r=$all->fetch_assoc()) $all_rows[]=$r;
$jenis_colors=['Masjid'=>'blue','Gereja'=>'violet','Pura'=>'amber','Vihara'=>'green','Kelenteng'=>'cyan','Lainnya'=>'gray'];
$current = basename($_SERVER['PHP_SELF']);
function pag_url($p,$cari){
$q=$cari!==''?'&cari='.urlencode($cari):'';
return '?page='.$p.$q;
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Rumah Ibadah — Pemetaan Kemiskinan Terpadu</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{--bg:#f0f4f8;--white:#fff;--border:#e2e8f0;--text:#1e293b;--text2:#64748b;--text3:#94a3b8;--blue:#2563eb;--blue-lt:#dbeafe;--green:#16a34a;--green-lt:#dcfce7;--red:#dc2626;--red-lt:#fee2e2;--amber:#d97706;--amber-lt:#fef3c7;--violet:#7c3aed;--violet-lt:#ede9fe;--cyan:#0891b2;--cyan-lt:#cffafe;--sidebar:240px;--radius:12px;--shadow:0 1px 3px rgba(0,0,0,.08),0 4px 16px rgba(0,0,0,.06)}
*{box-sizing:border-box;margin:0;padding:0}body{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--text);min-height:100vh;display:flex}
#sidebar{width:var(--sidebar);min-width:var(--sidebar);background:var(--white);border-right:1px solid var(--border);display:flex;flex-direction:column;position:fixed;top:0;left:0;height:100vh;box-shadow:2px 0 8px rgba(0,0,0,.05);z-index:100}
.sb-brand{padding:20px 16px 16px;border-bottom:1px solid var(--border)}.sb-brand-logo{width:40px;height:40px;border-radius:10px;background:linear-gradient(135deg,#7c3aed,#2563eb);display:flex;align-items:center;justify-content:center;font-size:18px;margin-bottom:10px}.sb-brand h1{font-size:13px;font-weight:700;color:var(--text);line-height:1.3}.sb-brand p{font-size:10px;color:var(--text3);margin-top:2px}
.sb-nav{flex:1;overflow-y:auto;padding:10px 8px}.sb-lbl{font-size:9px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.8px;padding:10px 8px 4px}
.sb-item{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:8px;cursor:pointer;font-size:13px;font-weight:500;color:var(--text2);transition:all .15s;text-decoration:none;margin-bottom:2px;border:1px solid transparent}.sb-item:hover{background:var(--bg);color:var(--text)}.sb-item.active{background:var(--violet-lt);color:var(--violet);border-color:#ddd6fe;font-weight:600}.sb-item .ico{font-size:15px;width:20px;text-align:center}
.sb-footer{padding:10px;border-top:1px solid var(--border)}
.btn-logout{width:100%;padding:8px;background:var(--red-lt);border:1px solid #fca5a5;border-radius:8px;font-size:12px;color:var(--red);cursor:pointer;font-family:inherit;font-weight:600;display:flex;align-items:center;justify-content:center;gap:6px;text-decoration:none;transition:all .15s}.btn-logout:hover{background:var(--red);color:#fff}
#main{margin-left:var(--sidebar);flex:1;display:flex;flex-direction:column;min-height:100vh}
.topbar{height:56px;background:var(--white);border-bottom:1px solid var(--border);display:flex;align-items:center;padding:0 24px;gap:12px;position:sticky;top:0;z-index:50}.topbar h2{font-size:15px;font-weight:700;flex:1}.topbar span{font-size:12px;color:var(--text3)}
.content{padding:24px;flex:1}
.page-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}
.page-title h2{font-size:17px;font-weight:800}.page-title p{font-size:12px;color:var(--text3);margin-top:2px}
.btn-dl{display:inline-flex;align-items:center;gap:7px;padding:8px 16px;background:var(--green);color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;font-family:inherit;transition:background .15s}.btn-dl:hover{background:#15803d}
.tbl-wrap{background:var(--white);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow)}
.tbl-toolbar{padding:12px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px}
.tbl-toolbar form{display:flex;gap:8px;flex:1}.tbl-toolbar input{flex:1;padding:7px 10px;border:1px solid var(--border);border-radius:8px;font-family:inherit;font-size:12.5px;color:var(--text);background:var(--bg);outline:none}.tbl-toolbar input:focus{border-color:var(--blue);background:#fff}
.tbl-toolbar button{padding:7px 14px;background:var(--blue);color:#fff;border:none;border-radius:8px;font-size:12.5px;font-weight:600;cursor:pointer;font-family:inherit}
.tbl-info{font-size:12px;color:var(--text3);white-space:nowrap}
table{width:100%;border-collapse:collapse;font-size:12.5px}
thead th{padding:10px 14px;text-align:left;font-size:10px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.5px;background:var(--bg);border-bottom:1px solid var(--border);white-space:nowrap}
tbody td{padding:10px 14px;border-bottom:1px solid var(--border);vertical-align:middle}
tbody tr:last-child td{border-bottom:none}tbody tr:hover{background:#fafbfc}
.badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:20px;font-size:10px;font-weight:700}
.badge-blue{background:var(--blue-lt);color:var(--blue)}.badge-green{background:var(--green-lt);color:var(--green)}.badge-red{background:var(--red-lt);color:var(--red)}.badge-amber{background:var(--amber-lt);color:var(--amber)}.badge-violet{background:var(--violet-lt);color:var(--violet)}.badge-cyan{background:var(--cyan-lt);color:var(--cyan)}.badge-gray{background:var(--bg);color:var(--text2);border:1px solid var(--border)}
.pagination{display:flex;align-items:center;gap:5px;padding:12px 14px;border-top:1px solid var(--border);flex-wrap:wrap}
.pag-btn{padding:5px 11px;border:1px solid var(--border);border-radius:7px;background:var(--white);font-size:12px;font-weight:600;cursor:pointer;color:var(--text2);text-decoration:none;transition:all .15s;display:inline-flex;align-items:center}
.pag-btn:hover{border-color:var(--blue);color:var(--blue)}.pag-btn.active{background:var(--blue);color:#fff;border-color:var(--blue)}.pag-btn.disabled{opacity:.4;pointer-events:none}
.pag-info{font-size:12px;color:var(--text3);margin-left:auto}
</style>
</head>
<body>
<aside id="sidebar">
<div class="sb-brand"><div class="sb-brand-logo"><svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#fff" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg></div><h1>Kemiskinan Terpadu</h1><p>Panel Superadmin</p></div>
<nav class="sb-nav">
<div class="sb-lbl">Menu</div>
<a href="dashboard.php" class="sb-item <?= $current==='dashboard.php'?'active':'' ?>"><span class="ico"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg></span> Dashboard</a>
<a href="data_penduduk.php" class="sb-item <?= $current==='data_penduduk.php'?'active':'' ?>"><span class="ico"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75"/></svg></span> Data Penduduk</a>
<a href="data_ibadah.php" class="sb-item <?= $current==='data_ibadah.php'?'active':'' ?>"><span class="ico"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 21h18M5 21V7l7-4 7 4v14"/><path d="M9 21v-6h6v6"/></svg></span> Rumah Ibadah</a>
<div class="sb-lbl">Navigasi</div>
<a href="index.php?readonly=1" class="sb-item" target="_blank"><span class="ico"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg></span> Lihat Peta GIS</a>
</nav>
<div class="sb-footer">
<?php include __DIR__.'/includes/user-profile.php'; ?>
<a href="logout.php" class="btn-logout" data-confirm-logout>Keluar</a>
</div>
</aside>
<?php include __DIR__.'/includes/confirm-modal.php'; ?>
<main id="main">
<div class="topbar"><h2>Rumah Ibadah</h2><span>Total <?= $total_rows ?> tempat ibadah</span></div>
<div class="content">
<div class="page-head">
<div class="page-title">
<h2>Daftar Rumah Ibadah</h2>
<p>Halaman <?= $page ?> dari <?= $total_pages ?> · <?= $total_rows ?> data total</p>
</div>
<button class="btn-dl" onclick="downloadCSV()"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg> Download Excel</button>
</div>
<div class="tbl-wrap">
<div class="tbl-toolbar">
<form method="GET" action="">
<div style="position:relative;flex:1;display:flex;align-items:center;">
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" style="position:absolute;left:10px;color:var(--text3)"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
<input type="text" name="cari" value="<?= htmlspecialchars($cari) ?>" placeholder="Cari nama, jenis, PIC, alamat..." style="padding-left:32px;width:100%;">
</div>
<button type="submit">Cari</button>
<?php if($cari): ?><a href="data_ibadah.php" style="padding:7px 12px;border:1px solid var(--border);border-radius:8px;font-size:12px;color:var(--text2);text-decoration:none">✕ Reset</a><?php endif ?>
</form>
<span class="tbl-info"><?= $per_page*(($page-1)+1)-($per_page-1) ?><?= min($per_page*$page,$total_rows) ?> dari <?= $total_rows ?></span>
</div>
<table>
<thead>
<tr><th>#</th><th>Nama</th><th>Jenis</th><th>Alamat</th><th>PIC</th><th>No. WA</th><th>Radius</th><th>Binaan (KK)</th><th>Total Jiwa</th></tr>
</thead>
<tbody>
<?php $no=($page-1)*$per_page+1; while($r=$data->fetch_assoc()):
$col=$jenis_colors[$r['jenis']]??'gray'; ?>
<tr>
<td style="color:var(--text3);font-family:'DM Mono',monospace"><?= $no++ ?></td>
<td><b><?= htmlspecialchars($r['nama']) ?></b></td>
<td><span class="badge badge-<?= $col ?>"><?= $r['jenis'] ?></span></td>
<td style="color:var(--text2);max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis" title="<?= htmlspecialchars($r['alamat']??'') ?>"><?= htmlspecialchars($r['alamat']??'—') ?></td>
<td><?= htmlspecialchars($r['pic']??'—') ?></td>
<td style="font-family:'DM Mono',monospace;font-size:11.5px"><?= htmlspecialchars($r['no_wa']??'—') ?></td>
<td style="font-family:'DM Mono',monospace"><?= number_format($r['radius']) ?> m</td>
<td style="text-align:center"><span class="badge <?= $r['jumlah_binaan']>0?'badge-green':'badge-gray' ?>"><?= $r['jumlah_binaan'] ?> KK</span></td>
<td style="text-align:center;font-family:'DM Mono',monospace"><?= $r['total_jiwa'] ?? 0 ?></td>
</tr>
<?php endwhile ?>
</tbody>
</table>
<div class="pagination">
<a href="<?= pag_url(1,$cari) ?>" class="pag-btn <?= $page<=1?'disabled':'' ?>">«</a>
<a href="<?= pag_url(max(1,$page-1),$cari) ?>" class="pag-btn <?= $page<=1?'disabled':'' ?>"></a>
<?php $from=max(1,$page-2);$to=min($total_pages,$page+2);
for($i=$from;$i<=$to;$i++): ?>
<a href="<?= pag_url($i,$cari) ?>" class="pag-btn <?= $i===$page?'active':'' ?>"><?= $i ?></a>
<?php endfor ?>
<a href="<?= pag_url(min($total_pages,$page+1),$cari) ?>" class="pag-btn <?= $page>=$total_pages?'disabled':'' ?>"></a>
<a href="<?= pag_url($total_pages,$cari) ?>" class="pag-btn <?= $page>=$total_pages?'disabled':'' ?>">»</a>
<span class="pag-info">Halaman <?= $page ?> / <?= $total_pages ?></span>
</div>
</div>
</div>
</main>
<script>
const allData = <?= json_encode($all_rows) ?>;
function downloadCSV(){
if(!allData.length) return;
const keys=['Nama','Jenis','Alamat','PIC','No WA','Radius (m)','Jumlah Binaan (KK)','Total Jiwa'];
const map =['nama','jenis','alamat','pic','no_wa','radius','jumlah_binaan','total_jiwa'];
const rows=[keys,...allData.map(r=>map.map(k=>'"'+(r[k]??'')+'"'))];
const csv='\uFEFF'+rows.map(r=>r.join(',')).join('\n');
const a=document.createElement('a');
a.href='data:text/csv;charset=utf-8,'+encodeURIComponent(csv);
a.download='rumah_ibadah_<?= date('Ymd') ?>.csv';
a.click();
}
</script>
</body></html>