Upload files to "includes"

This commit is contained in:
2026-06-03 05:07:26 +00:00
parent 5c11a3caa5
commit 4ad385c60a
2 changed files with 353 additions and 0 deletions
+35
View File
@@ -0,0 +1,35 @@
</div><!-- end page-body -->
</div><!-- end #main -->
<script>
// Toast utility
function toast(msg, type) {
var icons = { success:'✅', error:'❌', info:'️', warning:'⚠️' };
var el = document.createElement('div');
el.className = 'toast ' + (type||'');
el.innerHTML = '<span>' + (icons[type]||'️') + '</span> ' + msg;
document.getElementById('toast-wrap').appendChild(el);
setTimeout(() => { el.style.opacity='0'; el.style.transition='.3s'; setTimeout(()=>el.remove(),300); }, 3500);
}
// Modal helpers
function openModal(id) { document.getElementById(id).classList.add('show'); }
function closeModal(id) { document.getElementById(id).classList.remove('show'); }
// Close modal on overlay click
document.querySelectorAll('.modal-overlay').forEach(el => {
el.addEventListener('click', function(e) {
if (e.target === this) this.classList.remove('show');
});
});
<?php if (isset($_GET['success'])): ?>
toast('<?= htmlspecialchars($_GET['success']) ?>', 'success');
<?php endif; ?>
<?php if (isset($_GET['error'])): ?>
toast('<?= htmlspecialchars($_GET['error']) ?>', 'error');
<?php endif; ?>
</script>
<?= $extraScript ?? '' ?>
</body>
</html>
+318
View File
@@ -0,0 +1,318 @@
<?php
if (session_status() === PHP_SESSION_NONE) session_start();
$page = $page ?? '';
$current_role = $_SESSION['role'] ?? '';
$user_display_name = $_SESSION['nama'] ?? 'Pengguna';
$roleLabel = [
'admin' => 'Administrator',
'pemerintah' => 'Pemerintah',
'pengurus' => 'Operator Lembaga',
'relawan' => 'Relawan',
];
// Badge bencana aktif & konfirmasi menunggu
$bAktif = 0;
$menungguKonf = 0;
if (isset($conn)) {
$bAktif = $conn->query("SELECT COUNT(*) AS c FROM bencana WHERE status='Aktif'")->fetch_assoc()['c'] ?? 0;
if (in_array($current_role, ['pengurus','relawan'])) {
$menungguKonf = $conn->query("SELECT COUNT(*) AS c FROM bantuan_tersalur WHERE status_konfirmasi='Menunggu'")->fetch_assoc()['c'] ?? 0;
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($pageTitle ?? 'WebGIS Poverty Mapping') ?></title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"/>
<style>
/* ── RESET ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
--blue:#3b82f6;--blue-dk:#1d4ed8;--blue-lt:#eff6ff;
--green:#16a34a;--green-lt:#f0fdf4;
--red:#dc2626;--red-lt:#fef2f2;
--orange:#ea580c;--orange-lt:#fff7ed;
--purple:#7c3aed;--purple-lt:#faf5ff;
--yellow:#d97706;--yellow-lt:#fffbeb;
--gray:#6b7280;--gray-lt:#f9fafb;--gray-md:#e5e7eb;
--dark:#111827;--white:#fff;
--sb-w:250px;
--radius:8px;--radius-sm:6px;--radius-lg:12px;
--font:'Inter',sans-serif;
}
/* ── BODY ── */
body{font-family:var(--font);background:#f3f4f6;color:var(--dark);display:flex;min-height:100vh}
/* ── SIDEBAR ── */
#sidebar{
width:var(--sb-w);min-height:100vh;background:#0f172a;
display:flex;flex-direction:column;
position:fixed;top:0;left:0;z-index:600;
}
.sb-brand{
padding:18px 16px 14px;
border-bottom:1px solid rgba(255,255,255,.06);
display:flex;align-items:center;gap:10px;
}
.sb-brand-ico{
width:30px;height:30px;background:var(--blue);border-radius:7px;
display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.sb-brand-ico i{color:#fff;font-size:13px}
.sb-brand strong{font-size:13px;font-weight:800;color:#fff;letter-spacing:-.2px}
.sb-brand span{font-size:10px;color:rgba(255,255,255,.3);display:block;margin-top:1px}
.sb-user{
padding:12px 14px;border-bottom:1px solid rgba(255,255,255,.06);
display:flex;align-items:center;gap:9px;
}
.sb-av{
width:30px;height:30px;border-radius:7px;flex-shrink:0;
display:flex;align-items:center;justify-content:center;
font-size:12px;font-weight:700;color:#fff;
background:linear-gradient(135deg,var(--blue),#8b5cf6);
}
.sb-user-info strong{font-size:12px;color:#fff;display:block;font-weight:600;line-height:1.3}
.sb-user-info span{
font-size:9px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
color:#10b981;display:inline-flex;align-items:center;gap:4px;
background:rgba(16,185,129,.12);padding:1px 6px;border-radius:4px;margin-top:2px;
}
.sb-nav{flex:1;padding:8px;overflow-y:auto}
.sb-nav::-webkit-scrollbar{width:3px}
.sb-nav::-webkit-scrollbar-thumb{background:rgba(255,255,255,.06);border-radius:99px}
.sb-sec{
font-size:9px;font-weight:700;color:rgba(255,255,255,.2);
text-transform:uppercase;letter-spacing:.9px;
padding:10px 8px 4px;
}
.sb-a{
display:flex;align-items:center;gap:9px;padding:8px 10px;
color:rgba(255,255,255,.45);font-size:13px;font-weight:500;
text-decoration:none;border-radius:var(--radius-sm);
margin-bottom:1px;transition:.15s;position:relative;
}
.sb-a i{width:14px;text-align:center;font-size:13px;color:rgba(255,255,255,.2);transition:.15s;flex-shrink:0}
.sb-a:hover{background:rgba(255,255,255,.05);color:#fff}
.sb-a:hover i{color:rgba(255,255,255,.6)}
.sb-a.on{background:rgba(59,130,246,.18);color:var(--blue);font-weight:600}
.sb-a.on i{color:var(--blue)}
.sb-a.on::before{content:'';position:absolute;left:0;top:20%;height:60%;width:3px;background:var(--blue);border-radius:0 3px 3px 0}
.sb-badge{margin-left:auto;background:var(--red);color:#fff;font-size:9px;font-weight:700;padding:1px 5px;border-radius:99px}
.sb-foot{padding:10px 8px;border-top:1px solid rgba(255,255,255,.06)}
.sb-out{
display:flex;align-items:center;gap:9px;padding:8px 10px;
color:#f87171;font-size:12px;font-weight:600;text-decoration:none;
border-radius:var(--radius-sm);transition:.15s;
}
.sb-out i{font-size:12px}
.sb-out:hover{background:rgba(239,68,68,.12);color:#ef4444}
/* ── MAIN WRAPPER ── */
#main-wrap{
margin-left:var(--sb-w);
flex:1;display:flex;flex-direction:column;min-height:100vh;
/* penting: tidak overflow tersembunyi, biarkan konten mengisi */
}
/* ── TOPBAR ── */
#topbar{
background:#fff;border-bottom:1px solid var(--gray-md);
height:50px;padding:0 22px;
display:flex;align-items:center;gap:12px;
position:sticky;top:0;z-index:500;
}
.tb-title{font-size:14px;font-weight:700;color:var(--dark);flex:1}
.tb-title span{font-size:12px;font-weight:400;color:var(--gray);margin-left:6px}
.tb-right{display:flex;align-items:center;gap:10px}
.tb-date{font-size:12px;color:var(--gray)}
.tb-role{font-size:11px;font-weight:600;color:#fff;padding:3px 10px;border-radius:5px;background:var(--blue)}
/* ── PAGE ── */
.page-wrap{padding:20px 22px;flex:1}
.page-head{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:18px}
.page-head h2{font-size:18px;font-weight:800}
.page-head p{font-size:13px;color:var(--gray);margin-top:3px}
/* ── CARD ── */
.card{background:#fff;border-radius:var(--radius);border:1px solid var(--gray-md)}
.card-hd{padding:13px 16px;border-bottom:1px solid var(--gray-md);display:flex;align-items:center;justify-content:space-between}
.card-hd h3{font-size:13px;font-weight:700}
.card-bd{padding:16px}
/* ── STAT GRID ── */
.sg{display:grid;gap:12px;margin-bottom:16px}
.sg4{grid-template-columns:repeat(4,1fr)}
.sg3{grid-template-columns:repeat(3,1fr)}
.sg2{grid-template-columns:repeat(2,1fr)}
.sbox{background:#fff;border-radius:var(--radius);padding:16px;border:1px solid var(--gray-md);display:flex;align-items:center;gap:12px}
.sico{width:38px;height:38px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0}
.snum{font-size:22px;font-weight:800;line-height:1}
.slbl{font-size:11px;color:var(--gray);font-weight:500;margin-top:2px}
/* ── TABLE ── */
.tbl-w{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
thead th{background:var(--gray-lt);padding:8px 13px;font-weight:700;color:var(--gray);font-size:10px;text-transform:uppercase;letter-spacing:.5px;text-align:left;border-bottom:1px solid var(--gray-md)}
tbody td{padding:10px 13px;border-bottom:1px solid #f9fafb;color:var(--dark);vertical-align:middle}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:#fafafa}
/* ── BADGE ── */
.badge{display:inline-flex;align-items:center;font-size:10px;font-weight:600;padding:2px 7px;border-radius:4px}
.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-orange{background:var(--orange-lt);color:var(--orange)}
.badge-purple{background:var(--purple-lt);color:var(--purple)}
.badge-yellow{background:var(--yellow-lt);color:var(--yellow)}
.badge-gray{background:var(--gray-lt);color:var(--gray)}
/* ── BTN ── */
.btn{display:inline-flex;align-items:center;gap:5px;padding:7px 14px;font-family:var(--font);font-size:13px;font-weight:600;border:none;border-radius:var(--radius-sm);cursor:pointer;text-decoration:none;transition:.15s}
.btn:hover{opacity:.88}
.btn-sm{padding:5px 10px;font-size:12px}
.btn-primary{background:var(--blue);color:#fff}
.btn-success{background:var(--green);color:#fff}
.btn-danger{background:var(--red);color:#fff}
.btn-warning{background:var(--orange);color:#fff}
.btn-purple{background:var(--purple);color:#fff}
.btn-ghost{background:var(--gray-lt);color:var(--dark);border:1px solid var(--gray-md)}
.btn-ghost:hover{background:var(--gray-md)}
/* ── FORM ── */
.fg{margin-bottom:13px}
.fg label{display:block;font-size:11px;font-weight:600;color:var(--gray);text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}
.fc{width:100%;padding:8px 10px;border:1px solid var(--gray-md);border-radius:var(--radius-sm);font-family:var(--font);font-size:13px;color:var(--dark);transition:.15s;background:#fff}
.fc:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(59,130,246,.08)}
.form-control{width:100%;padding:8px 10px;border:1px solid var(--gray-md);border-radius:var(--radius-sm);font-family:var(--font);font-size:13px;color:var(--dark);transition:.15s;background:#fff}
.form-control:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(59,130,246,.08)}
.form-group{margin-bottom:13px}
.form-group label{display:block;font-size:11px;font-weight:600;color:var(--gray);text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}
.form-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.form-grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
/* ── MODAL ── */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:9000;display:none;align-items:center;justify-content:center}
.modal-overlay.show{display:flex}
.modal-box{background:#fff;border-radius:var(--radius-lg);width:90%;max-width:540px;max-height:90vh;overflow-y:auto;box-shadow:0 16px 48px rgba(0,0,0,.15)}
.modal-head{padding:15px 18px;border-bottom:1px solid var(--gray-md);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;background:#fff;z-index:10}
.modal-head h3{font-size:14px;font-weight:700}
.modal-body{padding:18px}
.modal-foot{padding:12px 18px;border-top:1px solid var(--gray-md);display:flex;justify-content:flex-end;gap:8px}
.btn-close{background:none;border:none;font-size:15px;cursor:pointer;color:var(--gray);width:26px;height:26px;border-radius:5px;display:flex;align-items:center;justify-content:center}
.btn-close:hover{background:var(--gray-lt)}
/* ── TOAST ── */
#toast-wrap{position:fixed;top:13px;right:13px;z-index:99999;display:flex;flex-direction:column;gap:7px}
.toast{background:#fff;border-radius:var(--radius-sm);padding:10px 13px;box-shadow:0 4px 16px rgba(0,0,0,.12);font-size:13px;font-weight:600;display:flex;align-items:center;gap:8px;min-width:200px;border-left:3px solid var(--blue);animation:tIn .2s ease}
.toast.success{border-left-color:var(--green)}.toast.error{border-left-color:var(--red)}
@keyframes tIn{from{transform:translateX(28px);opacity:0}to{transform:none;opacity:1}}
.divider{border:none;border-top:1px solid var(--gray-md);margin:14px 0}
@media(max-width:768px){
#sidebar{transform:translateX(-100%)}
#main-wrap{margin-left:0}
.sg4,.sg3{grid-template-columns:repeat(2,1fr)}
.form-grid-2,.form-grid-3{grid-template-columns:1fr}
}
</style>
<?= $extraHead ?? '' ?>
</head>
<body>
<div id="toast-wrap"></div>
<!-- SIDEBAR -->
<nav id="sidebar">
<div class="sb-brand">
<div class="sb-brand-ico"><i class="fa fa-map-location-dot"></i></div>
<div>
<strong>Poverty Mapping</strong>
<span>WebGIS v2.0</span>
</div>
</div>
<div class="sb-user">
<div class="sb-av"><?= strtoupper(substr($user_display_name,0,1)) ?></div>
<div class="sb-user-info">
<strong><?= htmlspecialchars($user_display_name) ?></strong>
<span><i class="fa fa-circle" style="font-size:6px"></i> <?= $roleLabel[$current_role] ?? $current_role ?></span>
</div>
</div>
<div class="sb-nav">
<?php if ($current_role === 'admin'): ?>
<div class="sb-sec">Utama</div>
<a href="index.php" class="sb-a <?= $page==='beranda'?'on':'' ?>"><i class="fa fa-house"></i> Beranda</a>
<div class="sb-sec">Laporan</div>
<a href="laporan.php" class="sb-a <?= $page==='laporan'?'on':'' ?>"><i class="fa fa-chart-bar"></i> Laporan & Statistik</a>
<div class="sb-sec">Administrasi</div>
<a href="manajemen-user.php" class="sb-a <?= $page==='users'?'on':'' ?>"><i class="fa fa-user-gear"></i> Manajemen User</a>
<?php elseif ($current_role === 'pemerintah'): ?>
<div class="sb-sec">Utama</div>
<a href="index.php" class="sb-a <?= $page==='beranda'?'on':'' ?>"><i class="fa fa-house"></i> Beranda</a>
<a href="peta.php" class="sb-a <?= $page==='peta'?'on':'' ?>"><i class="fa fa-map"></i> Peta Interaktif</a>
<div class="sb-sec">Data</div>
<a href="data-ibadah.php" class="sb-a <?= $page==='ibadah'?'on':'' ?>"><i class="fa fa-mosque"></i> Rumah Ibadah</a>
<a href="data-warga.php" class="sb-a <?= $page==='warga'?'on':'' ?>"><i class="fa fa-users"></i> Data KPM</a>
<div class="sb-sec">Program</div>
<a href="bencana.php" class="sb-a <?= $page==='bencana'?'on':'' ?>">
<i class="fa fa-triangle-exclamation"></i> Bencana & Prioritas
<?php if ($bAktif > 0) echo "<span class='sb-badge'>$bAktif</span>"; ?>
</a>
<a href="bantuan.php" class="sb-a <?= $page==='bantuan'?'on':'' ?>"><i class="fa fa-hand-holding-heart"></i> Bantuan Tersalur</a>
<div class="sb-sec">Analisis</div>
<a href="laporan.php" class="sb-a <?= $page==='laporan'?'on':'' ?>"><i class="fa fa-chart-bar"></i> Laporan & Statistik</a>
<?php elseif (in_array($current_role, ['pengurus','relawan'])): ?>
<div class="sb-sec">Utama</div>
<a href="index.php" class="sb-a <?= $page==='beranda'?'on':'' ?>"><i class="fa fa-house"></i> Beranda</a>
<a href="peta.php" class="sb-a <?= $page==='peta'?'on':'' ?>"><i class="fa fa-map"></i> Peta Interaktif</a>
<div class="sb-sec">Data</div>
<a href="data-warga.php" class="sb-a <?= $page==='warga'?'on':'' ?>"><i class="fa fa-users"></i> Data KPM</a>
<a href="data-ibadah.php" class="sb-a <?= $page==='ibadah'?'on':'' ?>"><i class="fa fa-mosque"></i> Rumah Ibadah</a>
<div class="sb-sec">Program</div>
<a href="bencana.php" class="sb-a <?= $page==='bencana'?'on':'' ?>">
<i class="fa fa-triangle-exclamation"></i> Bencana & Prioritas
<?php if ($bAktif > 0) echo "<span class='sb-badge'>$bAktif</span>"; ?>
</a>
<a href="konfirmasi-bantuan.php" class="sb-a <?= $page==='konfirmasi'?'on':'' ?>">
<i class="fa fa-clipboard-check"></i> Konfirmasi Bantuan
<?php if ($menungguKonf > 0) echo "<span class='sb-badge'>$menungguKonf</span>"; ?>
</a>
<div class="sb-sec">Analisis</div>
<a href="laporan.php" class="sb-a <?= $page==='laporan'?'on':'' ?>"><i class="fa fa-chart-bar"></i> Laporan</a>
<?php endif; ?>
</div>
<div class="sb-foot">
<a href="logout.php" class="sb-out"><i class="fa fa-right-from-bracket"></i> Keluar</a>
</div>
</nav>
<!-- MAIN -->
<div id="main-wrap">
<div id="topbar">
<div class="tb-title">
<?= htmlspecialchars($pageTitle ?? 'Dashboard') ?>
<span><?= htmlspecialchars($pageSubtitle ?? '') ?></span>
</div>
<div class="tb-right">
<span class="tb-date"><?= date('d M Y') ?></span>
<div class="tb-role"><?= $roleLabel[$current_role] ?? $current_role ?></div>
</div>
</div>
<div class="page-wrap">