First commit / commit pertama
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/auth_check.php';
|
||||
requireAnyRole(['pimpinan']);
|
||||
$pdo = Database::getConnection();
|
||||
$pageTitle = 'Analisis Spasial';
|
||||
$activeNav = 'analisis';
|
||||
$extraHead = '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">';
|
||||
require_once __DIR__ . '/partials/header.php';
|
||||
require_once __DIR__ . '/../partials/analisis_body.php';
|
||||
require_once __DIR__ . '/partials/footer.php';
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/auth_check.php';
|
||||
requireAnyRole(['pimpinan']);
|
||||
$pdo = Database::getConnection();
|
||||
$user = currentUser();
|
||||
|
||||
// KPI
|
||||
$total = (int)$pdo->query("SELECT COUNT(*) FROM warga_miskin")->fetchColumn();
|
||||
$dibantu = (int)$pdo->query("SELECT COUNT(DISTINCT warga_id) FROM bantuan_sosial WHERE is_aktif=1")->fetchColumn();
|
||||
$terverif = (int)$pdo->query("SELECT COUNT(*) FROM warga_miskin WHERE status_verifikasi='terverifikasi'")->fetchColumn();
|
||||
$cakupan = $total > 0 ? round($dibantu / $total * 100, 1) : 0;
|
||||
|
||||
// Zona prioritas (skor sama dgn api/zona_prioritas)
|
||||
$zrows = $pdo->query("
|
||||
SELECT w.nama, w.jumlah_penduduk,
|
||||
COUNT(DISTINCT wm.id) AS miskin,
|
||||
COUNT(DISTINCT CASE WHEN bs.id IS NOT NULL THEN wm.id END) AS dibantu
|
||||
FROM wilayah w
|
||||
LEFT JOIN warga_miskin wm ON ST_Contains(w.geom, wm.geom)
|
||||
LEFT JOIN bantuan_sosial bs ON bs.warga_id=wm.id AND bs.is_aktif=1
|
||||
GROUP BY w.id
|
||||
")->fetchAll();
|
||||
$zona = [];
|
||||
foreach ($zrows as $r) {
|
||||
$m = (int)$r['miskin']; $p = (int)$r['jumlah_penduduk'];
|
||||
$persen = $p > 0 ? round($m/$p*100,2) : 0;
|
||||
$cak = $m > 0 ? round($r['dibantu']/$m*100,1) : 0;
|
||||
$gap = $m > 0 ? (100-$cak) : 0;
|
||||
$skor = round($persen*2 + $gap*0.2 + $m*1, 1);
|
||||
$level = $skor > 35 ? 'Tinggi' : ($skor > 20 ? 'Sedang' : 'Rendah');
|
||||
$zona[] = ['nama'=>$r['nama'],'skor'=>$skor,'level'=>$level,'persen'=>$persen,'cakupan'=>$cak];
|
||||
}
|
||||
usort($zona, fn($a,$b)=>$b['skor']<=>$a['skor']);
|
||||
$zonaTinggi = count(array_filter($zona, fn($z)=>$z['level']==='Tinggi'));
|
||||
|
||||
$pageTitle = 'Dashboard Eksekutif';
|
||||
$activeNav = 'dashboard';
|
||||
$extraHead = '';
|
||||
require_once __DIR__ . '/partials/header.php';
|
||||
?>
|
||||
<div class="page-header" style="margin-bottom:18px;">
|
||||
<h1 style="font-size:1.4rem;">👋 Selamat datang, <?= htmlspecialchars($user['nama_lengkap'] ?: $user['username']) ?></h1>
|
||||
<p>Ringkasan eksekutif kondisi kemiskinan & penyaluran bantuan sosial kota.</p>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card primary"><div class="stat-icon"><i class="fas fa-house-user"></i></div>
|
||||
<div class="stat-body"><div class="stat-label">Total RT Miskin</div><div class="stat-value"><?= $total ?></div><div class="stat-change"><?= count($zona) ?> kelurahan</div></div></div>
|
||||
<div class="stat-card info"><div class="stat-icon"><i class="fas fa-hand-holding-heart"></i></div>
|
||||
<div class="stat-body"><div class="stat-label">Cakupan Bantuan</div><div class="stat-value"><?= $cakupan ?>%</div><div class="stat-change"><?= $dibantu ?> RT dibantu</div></div></div>
|
||||
<div class="stat-card success"><div class="stat-icon"><i class="fas fa-check-circle"></i></div>
|
||||
<div class="stat-body"><div class="stat-label">Terverifikasi</div><div class="stat-value"><?= $terverif ?></div><div class="stat-change">dari <?= $total ?> data</div></div></div>
|
||||
<div class="stat-card danger"><div class="stat-icon"><i class="fas fa-triangle-exclamation"></i></div>
|
||||
<div class="stat-body"><div class="stat-label">Zona Prioritas Tinggi</div><div class="stat-value"><?= $zonaTinggi ?></div><div class="stat-change">kelurahan</div></div></div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px;">
|
||||
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Cakupan Bantuan</h3><canvas id="cPie" height="200"></canvas></div>
|
||||
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Penerima per Jenis Bantuan</h3><canvas id="cBar" height="200"></canvas></div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:1.4fr 1fr;gap:18px;margin-bottom:18px;">
|
||||
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Tren 12 Bulan</h3><canvas id="cTren" height="150"></canvas></div>
|
||||
<div class="card"><h3 style="font-size:0.95rem;margin-bottom:10px;">Komparatif Kelurahan (radar)</h3><canvas id="cRadar" height="150"></canvas></div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:18px;">
|
||||
<div class="card">
|
||||
<h3 style="font-size:0.95rem;margin-bottom:10px;">🏆 Zona Prioritas Teratas</h3>
|
||||
<?php foreach (array_slice($zona,0,4) as $i=>$z): $c=['Tinggi'=>'#EF4444','Sedang'=>'#FB923C','Rendah'=>'#10B981'][$z['level']]; ?>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;padding:9px 0;border-bottom:1px solid #F3F4F6;">
|
||||
<div><strong>#<?= $i+1 ?> <?= htmlspecialchars($z['nama']) ?></strong>
|
||||
<div style="font-size:0.74rem;color:#9CA3AF;">% miskin <?= $z['persen'] ?>% · cakupan <?= $z['cakupan'] ?>%</div></div>
|
||||
<span class="badge" style="background:<?= $c ?>22;color:<?= $c ?>;">Skor <?= $z['skor'] ?> · <?= $z['level'] ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="card" style="display:flex;flex-direction:column;justify-content:center;gap:10px;">
|
||||
<h3 style="font-size:0.95rem;">Tindak Lanjut</h3>
|
||||
<a href="<?= app_url('pimpinan/analisis.php') ?>" class="btn btn-primary"><i class="fas fa-chart-line"></i> Buka Analisis Spasial</a>
|
||||
<a href="<?= app_url('pimpinan/pelaporan.php') ?>" class="btn btn-success"><i class="fas fa-file-pdf"></i> Laporan & Cetak</a>
|
||||
<a href="<?= app_url('pimpinan/peta.php') ?>" class="btn btn-ghost"><i class="fas fa-map"></i> Peta Interaktif</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
const DAPI = APP_BASE + '/api';
|
||||
(async ()=>{
|
||||
const cak = (await (await fetch(`${DAPI}/cakupan_bantuan.php`)).json()).data;
|
||||
new Chart(cPie,{type:'doughnut',data:{labels:['Dibantu','Belum'],datasets:[{data:[cak.dibantu,cak.belum_dibantu],backgroundColor:['#10B981','#E5E7EB']}]},options:{plugins:{legend:{position:'bottom'}}}});
|
||||
new Chart(cBar,{type:'bar',data:{labels:cak.per_jenis.map(j=>j.kode),datasets:[{label:'Penerima',data:cak.per_jenis.map(j=>j.penerima),backgroundColor:'#2563EB'}]},options:{plugins:{legend:{display:false}},scales:{y:{beginAtZero:true,ticks:{precision:0}}}}});
|
||||
|
||||
const tr = (await (await fetch(`${DAPI}/tren.php`)).json()).data;
|
||||
new Chart(cTren,{type:'line',data:{labels:tr.labels,datasets:[
|
||||
{label:'Kumulatif Warga',data:tr.kumulatif,borderColor:'#2563EB',backgroundColor:'#2563EB22',fill:true,tension:.3},
|
||||
{label:'Bantuan Baru',data:tr.bantuan_baru,borderColor:'#10B981',tension:.3}
|
||||
]},options:{scales:{y:{beginAtZero:true,ticks:{precision:0}}}}});
|
||||
|
||||
const km = (await (await fetch(`${DAPI}/komparatif.php`)).json()).data;
|
||||
new Chart(cRadar,{type:'radar',data:{labels:km.labels,datasets:[
|
||||
{label:'% Miskin',data:km.persentase_miskin,borderColor:'#EF4444',backgroundColor:'#EF444422'},
|
||||
{label:'Cakupan %',data:km.cakupan_bantuan,borderColor:'#10B981',backgroundColor:'#10B98122'}
|
||||
]},options:{scales:{r:{beginAtZero:true}}}});
|
||||
})();
|
||||
</script>
|
||||
<?php require_once __DIR__ . '/partials/footer.php'; ?>
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/auth_check.php';
|
||||
requireAnyRole(['pimpinan']);
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
// Fetch user's own reports
|
||||
$stmt = $pdo->prepare("SELECT id, kategori, deskripsi, status, created_at FROM laporan_warga WHERE user_id = ? ORDER BY id DESC");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$rows = $stmt->fetchAll();
|
||||
|
||||
$pageTitle = 'Laporan Warga';
|
||||
$activeNav = 'laporan';
|
||||
$extraHead = '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">';
|
||||
require_once __DIR__ . '/partials/header.php';
|
||||
|
||||
function badgeStatus($status) {
|
||||
if($status === 'menunggu') return 'badge-warning';
|
||||
if($status === 'diproses') return 'badge-info';
|
||||
if($status === 'selesai') return 'badge-success';
|
||||
if($status === 'ditolak') return 'badge-danger';
|
||||
return 'badge-primary';
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="page-header">
|
||||
<div class="breadcrumb"><span>User</span><span class="sep">/</span><span>Laporan Warga</span></div>
|
||||
<h1>📢 Laporan Fasilitas & Infrastruktur</h1>
|
||||
<p>Laporkan masalah infrastruktur seperti jalan rusak, banjir, atau fasilitas umum yang terbengkalai.</p>
|
||||
</div>
|
||||
|
||||
<div class="page-toolbar">
|
||||
<div class="search-box">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" id="searchInput" placeholder="Cari laporan saya..." oninput="filterTable('searchInput','lapTable')">
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="openModal('modalTambah')">
|
||||
<i class="fas fa-plus"></i> Buat Laporan Baru
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table class="data-table" id="lapTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Kategori</th>
|
||||
<th>Deskripsi Singkat</th>
|
||||
<th>Status</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($rows as $i => $r): ?>
|
||||
<tr>
|
||||
<td style="color:var(--text-muted)"><?= $i+1 ?></td>
|
||||
<td><strong><?= htmlspecialchars($r['kategori']) ?></strong></td>
|
||||
<td style="color:var(--text-secondary); max-width: 250px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
||||
<?= htmlspecialchars($r['deskripsi']) ?>
|
||||
</td>
|
||||
<td><span class="badge <?= badgeStatus($r['status']) ?>"><?= ucfirst($r['status']) ?></span></td>
|
||||
<td style="color:var(--text-muted); font-size:0.8rem;"><?= date('d M Y, H:i', strtotime($r['created_at'])) ?></td>
|
||||
<td>
|
||||
<div class="actions">
|
||||
<?php if($r['status'] === 'menunggu'): ?>
|
||||
<button class="btn btn-danger btn-sm btn-icon" onclick="hapus(<?= $r['id'] ?>)" title="Batalkan Laporan"><i class="fas fa-trash"></i></button>
|
||||
<?php else: ?>
|
||||
<span style="font-size:0.75rem; color:var(--text-muted);">Dikunci</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (!$rows): ?>
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;padding:40px;color:var(--text-muted);">
|
||||
Anda belum pernah membuat laporan.
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Modal Tambah Laporan -->
|
||||
<div class="modal-overlay" id="modalTambah">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<span class="modal-title">📢 Buat Laporan Baru</span>
|
||||
<button class="modal-close" onclick="closeModal('modalTambah')">×</button>
|
||||
</div>
|
||||
<form id="formTambah">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Kategori Masalah *</label>
|
||||
<select name="kategori" class="form-control" required>
|
||||
<option value="Jalan Rusak">Jalan Rusak</option>
|
||||
<option value="Banjir">Banjir</option>
|
||||
<option value="Fasilitas Terbengkalai">Fasilitas Terbengkalai</option>
|
||||
<option value="Lampu Jalan Mati">Lampu Jalan Mati</option>
|
||||
<option value="Lainnya">Lainnya</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Deskripsi Lengkap *</label>
|
||||
<textarea name="deskripsi" class="form-control" placeholder="Jelaskan detail masalahnya..." required rows="3"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Pilih Lokasi di Peta *</label>
|
||||
<div id="miniMapTambah" style="height:200px;border-radius:8px;border:1px solid #E5E7EB;margin-bottom:10px;z-index:1;"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
|
||||
<input type="number" name="lat" id="latTambah" class="form-control" placeholder="Latitude" step="any" required readonly style="background:#F9FAFB;">
|
||||
<input type="number" name="lng" id="lngTambah" class="form-control" placeholder="Longitude" step="any" required readonly style="background:#F9FAFB;">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-ghost" onclick="closeModal('modalTambah')">Batal</button>
|
||||
<button class="btn btn-primary" onclick="simpan()"><i class="fas fa-paper-plane"></i> Kirim Laporan</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $extraScript = <<<'JS'
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script>
|
||||
const API = APP_BASE + '/api/laporan.php';
|
||||
|
||||
let miniMap = null, miniMarker = null;
|
||||
const originalOpenModal = window.openModal;
|
||||
window.openModal = function(id) {
|
||||
originalOpenModal(id);
|
||||
if(id === 'modalTambah') {
|
||||
setTimeout(() => {
|
||||
if(!miniMap) {
|
||||
miniMap = L.map('miniMapTambah').setView([-0.0583, 109.3448], 13);
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png').addTo(miniMap);
|
||||
miniMap.on('click', function(e) {
|
||||
const lat = e.latlng.lat;
|
||||
const lng = e.latlng.lng;
|
||||
if(!miniMarker) miniMarker = L.marker([lat, lng]).addTo(miniMap);
|
||||
else miniMarker.setLatLng([lat, lng]);
|
||||
document.getElementById('latTambah').value = lat.toFixed(6);
|
||||
document.getElementById('lngTambah').value = lng.toFixed(6);
|
||||
});
|
||||
} else {
|
||||
miniMap.invalidateSize();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
async function simpan() {
|
||||
const f = document.getElementById('formTambah');
|
||||
const lat = parseFloat(f.lat.value), lng = parseFloat(f.lng.value);
|
||||
if (!f.kategori.value || !f.deskripsi.value || isNaN(lat) || isNaN(lng)) {
|
||||
showToast('Lengkapi kategori, deskripsi, dan pilih lokasi!','error');
|
||||
return;
|
||||
}
|
||||
const res = await fetch(API, {
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body: JSON.stringify({
|
||||
kategori: f.kategori.value,
|
||||
deskripsi: f.deskripsi.value,
|
||||
geometry: { type:'Point', coordinates:[lng, lat] }
|
||||
})
|
||||
});
|
||||
const d = await res.json();
|
||||
if(d.status === 'success') {
|
||||
showToast('Laporan berhasil dikirim!');
|
||||
setTimeout(() => location.reload(), 900);
|
||||
} else {
|
||||
showToast(d.message,'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function hapus(id) {
|
||||
if(!confirm('Apakah Anda yakin ingin membatalkan laporan ini?')) return;
|
||||
const res = await fetch(API + '?id=' + id, { method:'DELETE' });
|
||||
const d = await res.json();
|
||||
if(d.status === 'success') {
|
||||
showToast('Laporan dibatalkan!');
|
||||
setTimeout(() => location.reload(), 900);
|
||||
} else {
|
||||
showToast(d.message,'error');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
JS; ?>
|
||||
<?php require_once __DIR__ . '/partials/footer.php'; ?>
|
||||
@@ -0,0 +1,54 @@
|
||||
</div><!-- /admin-content -->
|
||||
</main><!-- /admin-main -->
|
||||
|
||||
<!-- Toast Container -->
|
||||
<div class="toast-container" id="toastContainer"></div>
|
||||
|
||||
<script>
|
||||
// ── Clock ──
|
||||
function updateClock() {
|
||||
const now = new Date();
|
||||
document.getElementById('clockText').textContent =
|
||||
now.toLocaleTimeString('id-ID', { hour:'2-digit', minute:'2-digit', second:'2-digit' });
|
||||
}
|
||||
updateClock();
|
||||
setInterval(updateClock, 1000);
|
||||
|
||||
// ── Toast utility ──
|
||||
window.showToast = function(msg, type = 'success') {
|
||||
const t = document.createElement('div');
|
||||
t.className = `toast ${type}`;
|
||||
const icons = { success: 'check-circle', error: 'exclamation-circle', info: 'info-circle' };
|
||||
t.innerHTML = `<i class="fas fa-${icons[type]||'info-circle'}" style="margin-right:8px;"></i>${msg}`;
|
||||
document.getElementById('toastContainer').appendChild(t);
|
||||
setTimeout(() => { t.style.opacity = '0'; setTimeout(() => t.remove(), 400); }, 3000);
|
||||
};
|
||||
|
||||
// ── Modal helpers ──
|
||||
window.openModal = function(id) {
|
||||
document.getElementById(id)?.classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
};
|
||||
window.closeModal = function(id) {
|
||||
document.getElementById(id)?.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
// Close modal on overlay click
|
||||
document.querySelectorAll('.modal-overlay').forEach(overlay => {
|
||||
overlay.addEventListener('click', e => {
|
||||
if (e.target === overlay) closeModal(overlay.id);
|
||||
});
|
||||
});
|
||||
|
||||
// ── Search filter ──
|
||||
window.filterTable = function(inputId, tableId) {
|
||||
const q = document.getElementById(inputId)?.value.toLowerCase() || '';
|
||||
document.querySelectorAll(`#${tableId} tbody tr`).forEach(row => {
|
||||
row.style.display = row.textContent.toLowerCase().includes(q) ? '' : 'none';
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<?= $extraScript ?? '' ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* User Layout — sidebar + topbar (read-only mode, beda style dari admin)
|
||||
* Variables expected from parent: $pageTitle, $activeNav
|
||||
*/
|
||||
$user = currentUser();
|
||||
$initial = strtoupper(substr($user['nama_lengkap'] ?: $user['username'], 0, 1));
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= htmlspecialchars($pageTitle ?? 'Portal Pimpinan') ?> — WebGIS Kemiskinan</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;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">
|
||||
<link rel="stylesheet" href="<?= app_url('assets/css/main.css') ?>?v=20260610-spbu-snackbar">
|
||||
<link rel="stylesheet" href="<?= app_url('assets/css/admin.css') ?>">
|
||||
<script>const APP_BASE = '<?= app_url() ?>';</script>
|
||||
<?= $extraHead ?? '' ?>
|
||||
</head>
|
||||
<body class="admin-page user-portal <?= $bodyClass ?? '' ?>">
|
||||
|
||||
<!-- ══ SIDEBAR ══ -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="sidebar-brand">
|
||||
<div class="brand-icon" style="background:linear-gradient(135deg,#10B981,#059669);">🗺️</div>
|
||||
<div class="brand-text">
|
||||
<span class="brand-name">WebGIS</span>
|
||||
<span class="brand-sub">Pimpinan</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="sidebar-nav">
|
||||
<div class="nav-section-title">Menu</div>
|
||||
<a href="<?= app_url('pimpinan/index.php') ?>"
|
||||
class="nav-item <?= ($activeNav==='dashboard') ? 'active' : '' ?>">
|
||||
<span class="nav-icon"><i class="fas fa-chart-pie"></i></span> Dashboard Eksekutif
|
||||
</a>
|
||||
<a href="<?= app_url('pimpinan/peta.php') ?>"
|
||||
class="nav-item <?= ($activeNav==='peta') ? 'active' : '' ?>">
|
||||
<span class="nav-icon"><i class="fas fa-map-marked-alt"></i></span> Peta Interaktif
|
||||
</a>
|
||||
<a href="<?= app_url('pimpinan/analisis.php') ?>"
|
||||
class="nav-item <?= ($activeNav==='analisis') ? 'active' : '' ?>">
|
||||
<span class="nav-icon"><i class="fas fa-chart-line"></i></span> Analisis Spasial
|
||||
</a>
|
||||
<a href="<?= app_url('pimpinan/pelaporan.php') ?>"
|
||||
class="nav-item <?= ($activeNav==='pelaporan') ? 'active' : '' ?>">
|
||||
<span class="nav-icon"><i class="fas fa-file-pdf"></i></span> Laporan & Cetak
|
||||
</a>
|
||||
<a href="<?= app_url('pimpinan/laporan.php') ?>"
|
||||
class="nav-item <?= ($activeNav==='laporan') ? 'active' : '' ?>">
|
||||
<span class="nav-icon"><i class="fas fa-bullhorn"></i></span> Laporan Warga
|
||||
</a>
|
||||
|
||||
<div class="nav-section-title">Informasi</div>
|
||||
<div class="user-info" style="background:rgba(16,185,129,0.08);border-color:rgba(16,185,129,0.2);">
|
||||
<i class="fas fa-info-circle" style="color:#059669;font-size:1.1rem;"></i>
|
||||
<div style="font-size:0.78rem;color:var(--text-secondary);line-height:1.4;">
|
||||
Anda masuk sebagai <strong style="color:#059669">Pimpinan</strong>. Akses penuh data & laporan eksekutif (mode baca).
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar" style="background:linear-gradient(135deg,#10B981,#059669);"><?= $initial ?></div>
|
||||
<div class="user-details">
|
||||
<div class="user-name"><?= htmlspecialchars($user['nama_lengkap'] ?: $user['username']) ?></div>
|
||||
<div class="user-role">Pimpinan</div>
|
||||
</div>
|
||||
<a href="<?= app_url('logout.php') ?>" class="user-logout" title="Keluar">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- ══ MAIN CONTENT ══ -->
|
||||
<main class="admin-main">
|
||||
<div class="topbar">
|
||||
<span class="topbar-title"><?= htmlspecialchars($pageTitle ?? 'Beranda') ?></span>
|
||||
<div class="topbar-actions">
|
||||
<div class="topbar-time" id="clock">
|
||||
<i class="fas fa-clock"></i> <span id="clockText"></span>
|
||||
</div>
|
||||
<span class="badge badge-success" style="font-size:0.7rem;padding:5px 10px;">
|
||||
<i class="fas fa-eye"></i> Mode Baca
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin-content">
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/auth_check.php';
|
||||
requireAnyRole(['pimpinan']);
|
||||
$pdo = Database::getConnection();
|
||||
$pageTitle = 'Laporan & Cetak';
|
||||
$activeNav = 'pelaporan';
|
||||
require_once __DIR__ . '/partials/header.php';
|
||||
require_once __DIR__ . '/../partials/laporan_body.php';
|
||||
require_once __DIR__ . '/partials/footer.php';
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/auth_check.php';
|
||||
requireAnyRole(['pimpinan']);
|
||||
|
||||
$pageTitle = 'Peta Interaktif';
|
||||
$activeNav = 'peta';
|
||||
$extraHead = '
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
|
||||
';
|
||||
require_once __DIR__ . '/partials/header.php';
|
||||
?>
|
||||
<div class="page-header" style="margin-bottom:12px;">
|
||||
<h1>🗺️ Peta Pemetaan Kemiskinan</h1>
|
||||
<p>Sebaran rumah tangga miskin, choropleth tingkat kemiskinan, heatmap kepadatan, dan fasilitas publik.</p>
|
||||
</div>
|
||||
<div style="position:relative;">
|
||||
<div id="skpl-map" style="height:74vh;border-radius:12px;border:1px solid #E5E7EB;z-index:1;"></div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>
|
||||
<script src="<?= app_url('assets/js/skpl-layers.js') ?>?v=2"></script>
|
||||
<script>const SKPL_ROLE = 'pimpinan';</script>
|
||||
<script src="<?= app_url('assets/js/skpl-map.js') ?>?v=1"></script>
|
||||
<?php $extraScript = ''; ?>
|
||||
<?php require_once __DIR__ . '/partials/footer.php'; ?>
|
||||
Reference in New Issue
Block a user