Initial commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<div style="margin-bottom:20px">
|
||||
<h2 style="font-size:1.2rem;font-weight:700">📋 Log Aktivitas Sistem</h2>
|
||||
<p class="text-muted text-sm">200 aktivitas terbaru tercatat dalam sistem</p>
|
||||
</div>
|
||||
|
||||
<div class="filters-bar">
|
||||
<input type="text" id="search-akt" class="form-control" placeholder="🔍 Cari user, modul, aksi..." style="max-width:300px">
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table id="table-akt">
|
||||
<thead>
|
||||
<tr><th>Waktu</th><th>User</th><th>Role</th><th>Aksi</th><th>Modul</th><th>Deskripsi</th><th>IP</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($data as $a): ?>
|
||||
<tr>
|
||||
<td class="text-xs" style="font-family:monospace;white-space:nowrap"><?= $a['created_at'] ?></td>
|
||||
<td class="text-sm font-bold"><?= e($a['nama_user']??'System') ?></td>
|
||||
<td>
|
||||
<?php $rc=['superadmin'=>'badge-purple','verifikator'=>'badge-blue','rumah_ibadah'=>'badge-green','dinsos'=>'badge-teal','walikota'=>'badge-orange']; ?>
|
||||
<span class="badge <?= $rc[$a['role']??'']??'badge-gray' ?>"><?= e($a['role']??'—') ?></span>
|
||||
</td>
|
||||
<td class="text-sm font-bold"><?= e($a['aksi']) ?></td>
|
||||
<td><span class="badge badge-gray"><?= e($a['modul']??'—') ?></span></td>
|
||||
<td class="text-sm text-muted"><?= e($a['deskripsi']??'') ?></td>
|
||||
<td class="text-xs" style="font-family:monospace"><?= e($a['ip_address']??'') ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php if(empty($data)): ?>
|
||||
<div class="empty-state"><div class="empty-state-icon">📋</div><h3>Belum ada aktivitas</h3></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>document.addEventListener('DOMContentLoaded',()=>App.initTableSearch('search-akt','table-akt'));</script>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// blind_spot.php — Admin view
|
||||
?>
|
||||
<div style="margin-bottom:20px">
|
||||
<h2 style="font-size:1.2rem;font-weight:700">⚠️ Monitoring Blind Spot</h2>
|
||||
<p class="text-muted text-sm"><?= count($data) ?> warga tidak terjangkau radius rumah ibadah manapun</p>
|
||||
</div>
|
||||
|
||||
<?php if(empty($data)): ?>
|
||||
<div class="card"><div class="card-body" style="text-align:center;padding:48px">
|
||||
<div style="font-size:3rem">🎉</div>
|
||||
<h3 style="margin:12px 0 6px;font-size:1.1rem">Tidak Ada Blind Spot!</h3>
|
||||
<p style="color:var(--clr-text-muted)">Seluruh warga miskin sudah berada dalam radius pelayanan rumah ibadah.</p>
|
||||
</div></div>
|
||||
<?php else: ?>
|
||||
|
||||
<div class="card" style="margin-bottom:16px">
|
||||
<div class="card-body no-pad"><div id="bs-map" style="height:320px"></div></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">⚠️</span><h3>Daftar Warga Blind Spot</h3></div>
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Nama</th><th>Kecamatan</th><th>Kelurahan</th><th>Status Kemiskinan</th><th>Prioritas</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($data as $i=>$w): ?>
|
||||
<tr>
|
||||
<td class="text-xs text-muted"><?= $i+1 ?></td>
|
||||
<td style="font-weight:600"><?= e($w['nama']) ?></td>
|
||||
<td class="text-sm"><?= e($w['kecamatan']) ?></td>
|
||||
<td class="text-sm"><?= e($w['kelurahan']) ?></td>
|
||||
<td><?php $sc=['Miskin Ekstrem'=>'badge-red','Miskin'=>'badge-orange','Rentan Miskin'=>'badge-yellow']; ?>
|
||||
<span class="badge <?= $sc[$w['status_kemiskinan']]??'badge-gray' ?>"><?= e($w['status_kemiskinan']) ?></span></td>
|
||||
<td><?php $pc=['Tinggi'=>'badge-red','Sedang'=>'badge-yellow','Rendah'=>'badge-green']; ?>
|
||||
<span class="badge <?= $pc[$w['level_prioritas']]??'badge-gray' ?>"><?= e($w['level_prioritas']) ?></span></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const map = GISMap.init('bs-map', <?= MAP_DEFAULT_LAT ?>, <?= MAP_DEFAULT_LNG ?>, 12);
|
||||
const ri = await App.fetchJSON('<?= APP_URL ?>/api/rumah-ibadah');
|
||||
if(ri) GISMap.addRILayer(ri);
|
||||
const bs = <?= json_encode(array_map(fn($w)=>['lat'=>(float)$w['lat'],'lng'=>(float)$w['lng'],'nama'=>$w['nama'],'status_kemiskinan'=>$w['status_kemiskinan']], array_filter($data,fn($w)=>$w['lat']&&$w['lng']))) ?>;
|
||||
bs.forEach(w => L.circleMarker([w.lat,w.lng],{radius:10,fillColor:'#7c3aed',color:'#fff',weight:2,fillOpacity:0.9}).bindPopup(`<strong>⚠ ${w.nama}</strong><br>${w.status_kemiskinan}`).addTo(map));
|
||||
GISMap.autoFitBounds();
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
// Ekstrak data chart di luar heredoc agar tidak ada konversi array-dalam-string
|
||||
$chartKec = [];
|
||||
$chartKecData = [];
|
||||
foreach ($perKecamatan ?? [] as $row) {
|
||||
$chartKec[] = (string)($row['nama'] ?? '');
|
||||
$chartKecData[] = (int)($row['total'] ?? 0);
|
||||
}
|
||||
|
||||
$chartBulan = [];
|
||||
$chartBantuanData = [];
|
||||
foreach ($trenBantuan ?? [] as $row) {
|
||||
$chartBulan[] = (string)($row['bulan'] ?? '');
|
||||
$chartBantuanData[] = (int)($row['jumlah'] ?? 0);
|
||||
}
|
||||
|
||||
$jsonKec = json_encode($chartKec);
|
||||
$jsonKecData = json_encode($chartKecData);
|
||||
$jsonBulan = json_encode($chartBulan);
|
||||
$jsonBantuanData = json_encode($chartBantuanData);
|
||||
$mapLat = MAP_DEFAULT_LAT;
|
||||
$mapLng = MAP_DEFAULT_LNG;
|
||||
$appUrl = APP_URL;
|
||||
|
||||
$extraJs = <<<JS
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
// Init peta
|
||||
const map = GISMap.init('admin-map', {$mapLat}, {$mapLng}, 13);
|
||||
|
||||
// Load data peta
|
||||
const data = await App.fetchJSON('{$appUrl}/admin/api/peta');
|
||||
if (data) {
|
||||
const wargaLayer = GISMap.addWargaLayer(data.warga || []);
|
||||
const riLayer = GISMap.addRILayer(data.rumah_ibadah || []);
|
||||
const lapLayer = GISMap.addLaporanLayer(data.laporan || []);
|
||||
|
||||
const overlays = {
|
||||
'👥 Warga Miskin': wargaLayer,
|
||||
'⛪ Rumah Ibadah': riLayer,
|
||||
'📋 Laporan Masuk': lapLayer
|
||||
};
|
||||
L.control.layers(GISMap.layers, overlays, {position:'topright', collapsed:true}).addTo(map);
|
||||
|
||||
GISMap.autoFitBounds();
|
||||
|
||||
const heat = await App.fetchJSON('{$appUrl}/dinsos/api/heatmap');
|
||||
if (heat) GISMap.addHeatmap(heat);
|
||||
} else {
|
||||
GISMap.autoFitBounds(true);
|
||||
}
|
||||
|
||||
// Charts — data sudah diekstrak bersih di PHP
|
||||
const kec = {$jsonKec};
|
||||
const kecData = {$jsonKecData};
|
||||
Charts.bar('chart-kecamatan', kec, [{ label: 'Warga Miskin', data: kecData }]);
|
||||
|
||||
const bulan = {$jsonBulan};
|
||||
const bantuanData = {$jsonBantuanData};
|
||||
Charts.line('chart-bantuan', bulan, [{ label: 'Bantuan Disalurkan', data: bantuanData }]);
|
||||
});
|
||||
</script>
|
||||
JS; ?>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon blue">👥</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['total_warga'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Total Warga Miskin</div>
|
||||
<div class="stat-card-sub"><?= number_format((int)($stats['warga_ekstrem'] ?? 0)) ?> miskin ekstrem</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon green">⛪</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['total_ri'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Rumah Ibadah Aktif</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon orange">📋</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['total_laporan'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Total Laporan</div>
|
||||
<div class="stat-card-sub"><?= (int)($stats['laporan_pending'] ?? 0) ?> menunggu</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon teal">📦</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['total_bantuan'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Total Bantuan</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon purple">⚠️</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['blind_spot'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Blind Spot</div>
|
||||
<div class="stat-card-sub">Belum terjangkau rumah ibadah</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-card-icon gray">👤</div>
|
||||
<div class="stat-card-body">
|
||||
<div class="stat-card-value"><?= number_format((int)($stats['total_user'] ?? 0)) ?></div>
|
||||
<div class="stat-card-label">Pengguna Sistem</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Grid: Map + Sidebar -->
|
||||
<div class="dashboard-grid" style="grid-template-columns:1fr 360px;gap:20px;margin-bottom:24px">
|
||||
<!-- PETA UTAMA -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">🗺</span>
|
||||
<h3>Peta Persebaran Kemiskinan Kota Pontianak</h3>
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-ghost btn-sm" onclick="toggleHeatmap()">🌡 Heatmap</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body no-pad" style="position:relative">
|
||||
<div id="admin-map" style="height:480px"></div>
|
||||
<div class="map-legend">
|
||||
<h4>Legenda</h4>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-ekstrem"></div> Miskin Ekstrem</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-miskin"></div> Miskin</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-rentan"></div> Rentan Miskin</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-ri"></div> Rumah Ibadah</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-blind"></div> Blind Spot</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-laporan"></div> Laporan Masuk</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SIDEBAR: Aktivitas & Tabel Kec -->
|
||||
<div style="display:flex;flex-direction:column;gap:16px">
|
||||
<!-- Per Kecamatan -->
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">🗾</span><h3>Sebaran per Kecamatan</h3></div>
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>Kecamatan</th><th>Total</th><th>Ekstrem</th><th>Blind Spot</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach ($perKecamatan ?? [] as $k): ?>
|
||||
<tr>
|
||||
<td style="font-weight:500;font-size:0.82rem"><?= e($k['nama']) ?></td>
|
||||
<td><strong><?= number_format((int)($k['total'] ?? 0)) ?></strong></td>
|
||||
<td><span class="badge badge-red"><?= number_format((int)($k['ekstrem'] ?? 0)) ?></span></td>
|
||||
<td><span class="badge badge-purple"><?= number_format((int)($k['blind_spot'] ?? 0)) ?></span></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Aktivitas Terbaru -->
|
||||
<div class="card" style="flex:1">
|
||||
<div class="card-header"><span class="card-icon">📋</span><h3>Aktivitas Terbaru</h3></div>
|
||||
<div class="card-body no-pad" style="max-height:240px;overflow-y:auto">
|
||||
<?php foreach ($aktivitas ?? [] as $a): ?>
|
||||
<div style="padding:10px 16px;border-bottom:1px solid #f1f5f9">
|
||||
<div style="font-size:0.8rem;font-weight:600"><?= e($a['aksi']) ?></div>
|
||||
<div style="font-size:0.72rem;color:var(--clr-text-muted)"><?= e($a['nama_user'] ?? '-') ?> · <?= e($a['modul'] ?? '') ?></div>
|
||||
<div style="font-size:0.7rem;color:var(--clr-text-muted)"><?= formatTanggal($a['created_at'], true) ?></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Row -->
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px">
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">📊</span><h3>Warga Miskin per Kecamatan</h3></div>
|
||||
<div class="card-body"><div class="chart-wrap"><canvas id="chart-kecamatan"></canvas></div></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">📈</span><h3>Tren Bantuan 6 Bulan Terakhir</h3></div>
|
||||
<div class="card-body"><div class="chart-wrap"><canvas id="chart-bantuan"></canvas></div></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,89 @@
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||
<div><h2 style="font-size:1.2rem;font-weight:700">📦 Manajemen Kategori Bantuan</h2></div>
|
||||
<button class="btn btn-primary" onclick="App.showModal('modal-tambah')">➕ Tambah Kategori</button>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Nama</th><th>Deskripsi</th><th>Satuan</th><th>Status</th><th>Aksi</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($data as $i=>$k): ?>
|
||||
<tr>
|
||||
<td class="text-xs text-muted"><?= $i+1 ?></td>
|
||||
<td style="font-weight:600"><?= e($k['nama']) ?></td>
|
||||
<td class="text-sm text-muted"><?= e($k['deskripsi']??'') ?></td>
|
||||
<td><span class="badge badge-blue"><?= e($k['satuan']??'—') ?></span></td>
|
||||
<td><?= $k['is_active'] ? '<span class="badge badge-green">Aktif</span>' : '<span class="badge badge-gray">Nonaktif</span>' ?></td>
|
||||
<td>
|
||||
<button class="btn btn-ghost btn-sm" onclick='openEdit(<?= json_encode($k) ?>)'>✏️ Edit</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Tambah -->
|
||||
<div class="modal-overlay" id="modal-tambah">
|
||||
<div class="modal">
|
||||
<div class="modal-header"><h3>➕ Tambah Kategori Bantuan</h3><button class="modal-close" onclick="App.hideModal('modal-tambah')">✕</button></div>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/kategori-bantuan/store">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label class="form-label">Nama Kategori <span class="required">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" required></div>
|
||||
<div class="form-group"><label class="form-label">Deskripsi</label>
|
||||
<textarea name="deskripsi" class="form-control" rows="2"></textarea></div>
|
||||
<div class="form-group"><label class="form-label">Satuan</label>
|
||||
<input type="text" name="satuan" class="form-control" placeholder="paket / kg / rupiah"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-tambah')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Edit -->
|
||||
<div class="modal-overlay" id="modal-edit">
|
||||
<div class="modal">
|
||||
<div class="modal-header"><h3>✏️ Edit Kategori</h3><button class="modal-close" onclick="App.hideModal('modal-edit')">✕</button></div>
|
||||
<form method="POST" id="edit-form">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label class="form-label">Nama <span class="required">*</span></label>
|
||||
<input type="text" name="nama" id="edit-nama" class="form-control" required></div>
|
||||
<div class="form-group"><label class="form-label">Deskripsi</label>
|
||||
<textarea name="deskripsi" id="edit-deskripsi" class="form-control" rows="2"></textarea></div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group"><label class="form-label">Satuan</label>
|
||||
<input type="text" name="satuan" id="edit-satuan" class="form-control"></div>
|
||||
<div class="form-group"><label class="form-label">Status</label>
|
||||
<select name="is_active" id="edit-is_active" class="form-control">
|
||||
<option value="1">Aktif</option><option value="0">Nonaktif</option>
|
||||
</select></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-edit')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openEdit(k) {
|
||||
document.getElementById('edit-nama').value = k.nama;
|
||||
document.getElementById('edit-deskripsi').value = k.deskripsi||'';
|
||||
document.getElementById('edit-satuan').value = k.satuan||'';
|
||||
document.getElementById('edit-is_active').value = k.is_active;
|
||||
document.getElementById('edit-form').action = '<?= APP_URL ?>/admin/kategori-bantuan/' + k.id + '/update';
|
||||
App.showModal('modal-edit');
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// monitoring.php — Admin monitoring kemiskinan view
|
||||
?>
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||
<div><h2 style="font-size:1.2rem;font-weight:700">👥 Monitoring Data Kemiskinan</h2>
|
||||
<p class="text-muted text-sm"><?= count($warga) ?> warga aktif terdata dalam sistem</p></div>
|
||||
</div>
|
||||
|
||||
<!-- Peta -->
|
||||
<div class="card" style="margin-bottom:20px">
|
||||
<div class="card-header"><span class="card-icon">🗺</span><h3>Peta Persebaran Seluruh Warga Miskin</h3></div>
|
||||
<div class="card-body no-pad" style="position:relative">
|
||||
<div id="mon-map" style="height:360px"></div>
|
||||
<div class="map-legend">
|
||||
<h4>Legenda</h4>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-ekstrem"></div> Miskin Ekstrem</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-miskin"></div> Miskin</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-rentan"></div> Rentan Miskin</div>
|
||||
<div class="map-legend-item"><div class="map-legend-dot legend-dot-blind"></div> Blind Spot</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search + Table -->
|
||||
<div class="filters-bar"><input type="text" id="search-mon" class="form-control" placeholder="🔍 Cari nama, NIK..." style="max-width:300px"></div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table id="table-mon">
|
||||
<thead><tr><th>#</th><th>Nama</th><th>Wilayah</th><th>Status Kemiskinan</th><th>Prioritas</th><th>Penghasilan</th><th>Tgn</th><th>Rumah Ibadah</th><th>Ket</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($warga as $i=>$w): ?>
|
||||
<tr>
|
||||
<td class="text-xs text-muted"><?= $i+1 ?></td>
|
||||
<td>
|
||||
<div style="font-weight:600;font-size:0.875rem"><?= e($w['nama']) ?></div>
|
||||
<div class="text-xs text-muted"><?= $w['nik'] ? 'NIK: '.e($w['nik']) : '' ?></div>
|
||||
</td>
|
||||
<td class="text-sm"><?= e($w['kecamatan']) ?> › <?= e($w['kelurahan']) ?></td>
|
||||
<td><?php $sc=['Miskin Ekstrem'=>'badge-red','Miskin'=>'badge-orange','Rentan Miskin'=>'badge-yellow']; ?>
|
||||
<span class="badge <?= $sc[$w['status_kemiskinan']]??'badge-gray' ?>"><?= e($w['status_kemiskinan']) ?></span></td>
|
||||
<td><?php $pc=['Tinggi'=>'badge-red','Sedang'=>'badge-yellow','Rendah'=>'badge-green']; ?>
|
||||
<span class="badge <?= $pc[$w['level_prioritas']]??'badge-gray' ?>"><?= e($w['level_prioritas']) ?></span>
|
||||
<div class="text-xs text-muted"><?= $w['skor_prioritas'] ?>/100</div></td>
|
||||
<td class="text-sm"><?= formatRupiah($w['penghasilan_bulanan']??0) ?></td>
|
||||
<td class="text-sm text-center"><?= $w['jumlah_tanggungan'] ?></td>
|
||||
<td class="text-sm"><?= e($w['rumah_ibadah_nama']??'—') ?></td>
|
||||
<td>
|
||||
<?php if($w['is_blind_spot']): ?><span class="badge badge-purple" title="Blind Spot">⚠</span><?php endif; ?>
|
||||
<?php if($w['is_lansia']): ?><span class="badge badge-orange" title="Lansia">👴</span><?php endif; ?>
|
||||
<?php if($w['is_disabilitas']): ?><span class="badge badge-blue" title="Disabilitas">♿</span><?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
App.initTableSearch('search-mon','table-mon');
|
||||
const map = GISMap.init('mon-map', <?= MAP_DEFAULT_LAT ?>, <?= MAP_DEFAULT_LNG ?>, 12);
|
||||
const data = await App.fetchJSON('<?= APP_URL ?>/admin/api/peta');
|
||||
if(data) {
|
||||
GISMap.addRILayer(data.rumah_ibadah||[]);
|
||||
GISMap.addWargaLayer(data.warga||[]);
|
||||
GISMap.autoFitBounds();
|
||||
} else {
|
||||
GISMap.autoFitBounds(true);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,309 @@
|
||||
<?php $extraJs = <<<JS
|
||||
<script>
|
||||
let riMap = null;
|
||||
let riMarker = null;
|
||||
|
||||
function openTambahModal() {
|
||||
App.showModal('modal-tambah');
|
||||
setTimeout(() => {
|
||||
if (!riMap) {
|
||||
riMap = L.map('ri-map-tambah').setView([-0.0263, 109.3425], 13);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:19}).addTo(riMap);
|
||||
riMap.on('click', e => placeRIMarker(e.latlng.lat, e.latlng.lng, 'tambah'));
|
||||
}
|
||||
riMap.invalidateSize();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function placeRIMarker(lat, lng, mode) {
|
||||
const m = mode === 'tambah' ? riMap : editMap;
|
||||
const prefix = mode === 'tambah' ? '' : 'edit-';
|
||||
if (riMarker) m.removeLayer(riMarker);
|
||||
riMarker = L.marker([lat, lng], { draggable: true }).addTo(m);
|
||||
document.getElementById(prefix + 'lat').value = lat.toFixed(7);
|
||||
document.getElementById(prefix + 'lng').value = lng.toFixed(7);
|
||||
riMarker.on('dragend', e => {
|
||||
const pos = e.target.getLatLng();
|
||||
document.getElementById(prefix + 'lat').value = pos.lat.toFixed(7);
|
||||
document.getElementById(prefix + 'lng').value = pos.lng.toFixed(7);
|
||||
});
|
||||
}
|
||||
|
||||
function openEditModal(ri) {
|
||||
document.getElementById('edit-nama').value = ri.nama;
|
||||
document.getElementById('edit-alamat').value = ri.alamat || '';
|
||||
document.getElementById('edit-id_jenis').value = ri.id_jenis;
|
||||
document.getElementById('edit-id_kelurahan').value = ri.id_kelurahan;
|
||||
document.getElementById('edit-radius_meter').value = ri.radius_meter;
|
||||
document.getElementById('edit-nama_ketua').value = ri.nama_ketua || '';
|
||||
document.getElementById('edit-no_hp_pengurus').value = ri.no_hp_pengurus || '';
|
||||
document.getElementById('edit-lat').value = ri.lat;
|
||||
document.getElementById('edit-lng').value = ri.lng;
|
||||
document.getElementById('edit-is_active').value = ri.is_active;
|
||||
document.getElementById('edit-form').action = '<?= APP_URL ?>/admin/rumah-ibadah/' + ri.id + '/update';
|
||||
App.showModal('modal-edit');
|
||||
}
|
||||
</script>
|
||||
JS; ?>
|
||||
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||
<div>
|
||||
<h2 style="font-size:1.2rem;font-weight:700">Manajemen Rumah Ibadah</h2>
|
||||
<p class="text-muted text-sm">Total <?= count($data) ?> rumah ibadah terdaftar</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="openTambahModal()">➕ Tambah Rumah Ibadah</button>
|
||||
</div>
|
||||
|
||||
<!-- PETA RUMAH IBADAH -->
|
||||
<div class="card" style="margin-bottom:20px">
|
||||
<div class="card-header"><span class="card-icon">🗺</span><h3>Peta Rumah Ibadah</h3></div>
|
||||
<div class="card-body no-pad">
|
||||
<div id="ri-overview-map" style="height:320px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEARCH -->
|
||||
<div class="filters-bar">
|
||||
<input type="text" id="search-ri" class="form-control" placeholder="🔍 Cari nama, kelurahan..." style="max-width:300px">
|
||||
</div>
|
||||
|
||||
<!-- TABLE -->
|
||||
<div class="card">
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table id="table-ri">
|
||||
<thead>
|
||||
<tr><th>#</th><th>Nama</th><th>Jenis</th><th>Wilayah</th><th>Ketua</th><th>Radius</th><th>Warga Binaan</th><th>Status</th><th>Aksi</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($data as $i => $r): ?>
|
||||
<tr>
|
||||
<td class="text-muted text-xs"><?= $i+1 ?></td>
|
||||
<td>
|
||||
<div style="font-weight:600;font-size:0.875rem"><?= e($r['nama']) ?></div>
|
||||
<div class="text-muted text-xs"><?= e($r['alamat'] ?? '') ?></div>
|
||||
</td>
|
||||
<td><span class="badge badge-green"><?= e($r['jenis']) ?></span></td>
|
||||
<td class="text-sm"><?= e($r['kecamatan']) ?> › <?= e($r['kelurahan']) ?></td>
|
||||
<td class="text-sm"><?= e($r['nama_ketua'] ?? '—') ?></td>
|
||||
<td class="text-sm"><?= number_format($r['radius_meter']) ?>m</td>
|
||||
<td><strong><?= number_format($r['jml_warga']) ?></strong> warga</td>
|
||||
<td><?= $r['is_active'] ? '<span class="badge badge-green">Aktif</span>' : '<span class="badge badge-gray">Nonaktif</span>' ?></td>
|
||||
<td>
|
||||
<div style="display:flex;gap:6px">
|
||||
<button class="btn btn-ghost btn-sm" onclick='openEditModal(<?= json_encode($r) ?>)'>✏️</button>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/rumah-ibadah/<?= $r['id'] ?>/delete"
|
||||
onsubmit="return confirm('Nonaktifkan <?= addslashes($r['nama']) ?>?')">
|
||||
<?= csrfField() ?>
|
||||
<button type="submit" class="btn btn-ghost btn-sm" style="color:var(--clr-danger)">🗑</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL TAMBAH -->
|
||||
<div class="modal-overlay" id="modal-tambah">
|
||||
<div class="modal" style="max-width:680px">
|
||||
<div class="modal-header">
|
||||
<h3>➕ Tambah Rumah Ibadah</h3>
|
||||
<button class="modal-close" onclick="App.hideModal('modal-tambah')">✕</button>
|
||||
</div>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/rumah-ibadah/store" enctype="multipart/form-data">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Rumah Ibadah <span class="required">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Jenis <span class="required">*</span></label>
|
||||
<select name="id_jenis" class="form-control" required>
|
||||
<?php foreach ($jenis as $j): ?>
|
||||
<option value="<?= $j['id'] ?>"><?= e($j['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Kelurahan <span class="required">*</span></label>
|
||||
<select name="id_kelurahan" class="form-control" required>
|
||||
<?php foreach ($kelurahan as $k): ?>
|
||||
<option value="<?= $k['id'] ?>"><?= e($k['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Alamat</label>
|
||||
<input type="text" name="alamat" class="form-control">
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Ketua/Pengurus</label>
|
||||
<input type="text" name="nama_ketua" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">No HP Pengurus</label>
|
||||
<input type="text" name="no_hp_pengurus" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Akun Pengurus</label>
|
||||
<select name="id_user" class="form-control">
|
||||
<option value="">— Belum Ada —</option>
|
||||
<?php foreach ($pengurusAvail as $p): ?>
|
||||
<option value="<?= $p['id'] ?>"><?= e($p['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Radius Pelayanan (meter) <span class="required">*</span></label>
|
||||
<input type="number" name="radius_meter" class="form-control" value="500" min="100" max="5000" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">📍 Pilih Lokasi pada Peta <span class="required">*</span></label>
|
||||
<div id="ri-map-tambah" style="height:220px;border-radius:8px;border:1px solid var(--clr-border)"></div>
|
||||
<div class="form-row cols-2" style="margin-top:8px">
|
||||
<input type="number" name="lat" id="lat" class="form-control" placeholder="Latitude" step="0.0000001" required>
|
||||
<input type="number" name="lng" id="lng" class="form-control" placeholder="Longitude" step="0.0000001" required>
|
||||
</div>
|
||||
<div class="form-hint">Klik pada peta untuk menandai lokasi</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Foto</label>
|
||||
<input type="file" name="foto" class="form-control" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-tambah')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL EDIT -->
|
||||
<div class="modal-overlay" id="modal-edit">
|
||||
<div class="modal" style="max-width:560px">
|
||||
<div class="modal-header">
|
||||
<h3>✏️ Edit Rumah Ibadah</h3>
|
||||
<button class="modal-close" onclick="App.hideModal('modal-edit')">✕</button>
|
||||
</div>
|
||||
<form method="POST" id="edit-form" enctype="multipart/form-data">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama <span class="required">*</span></label>
|
||||
<input type="text" name="nama" id="edit-nama" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Jenis</label>
|
||||
<select name="id_jenis" id="edit-id_jenis" class="form-control">
|
||||
<?php foreach ($jenis as $j): ?>
|
||||
<option value="<?= $j['id'] ?>"><?= e($j['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Kelurahan</label>
|
||||
<select name="id_kelurahan" id="edit-id_kelurahan" class="form-control">
|
||||
<?php foreach ($kelurahan as $k): ?>
|
||||
<option value="<?= $k['id'] ?>"><?= e($k['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Alamat</label>
|
||||
<input type="text" name="alamat" id="edit-alamat" class="form-control">
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Ketua</label>
|
||||
<input type="text" name="nama_ketua" id="edit-nama_ketua" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">No HP</label>
|
||||
<input type="text" name="no_hp_pengurus" id="edit-no_hp_pengurus" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row cols-3">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Radius (m)</label>
|
||||
<input type="number" name="radius_meter" id="edit-radius_meter" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Status</label>
|
||||
<select name="is_active" id="edit-is_active" class="form-control">
|
||||
<option value="1">Aktif</option><option value="0">Nonaktif</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Foto Baru</label>
|
||||
<input type="file" name="foto" class="form-control" accept="image/*">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Latitude</label>
|
||||
<input type="number" name="lat" id="edit-lat" class="form-control" step="0.0000001">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Longitude</label>
|
||||
<input type="number" name="lng" id="edit-lng" class="form-control" step="0.0000001">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-edit')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
App.initTableSearch('search-ri', 'table-ri');
|
||||
|
||||
// Overview map
|
||||
const ovMap = L.map('ri-overview-map').setView([-0.0263, 109.3425], 12);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:19}).addTo(ovMap);
|
||||
|
||||
const riData = <?= json_encode(array_map(fn($r) => [
|
||||
'id'=>$r['id'],'nama'=>$r['nama'],'lat'=>(float)$r['lat'],'lng'=>(float)$r['lng'],
|
||||
'radius_meter'=>$r['radius_meter'],'jenis'=>$r['jenis'],'kelurahan'=>$r['kelurahan'],
|
||||
'jml_warga'=>$r['jml_warga'],'is_active'=>$r['is_active']
|
||||
], $data)) ?>;
|
||||
|
||||
const riBounds = [];
|
||||
riData.forEach(ri => {
|
||||
if (!ri.lat || !ri.lng) return;
|
||||
const lat = parseFloat(ri.lat), lng = parseFloat(ri.lng);
|
||||
if (isNaN(lat)||isNaN(lng)) return;
|
||||
const icon = L.divIcon({
|
||||
className:'',
|
||||
html:`<div style="background:${ri.is_active?'#16a34a':'#6b7280'};color:#fff;padding:4px 8px;border-radius:4px;font-size:11px;font-weight:700;white-space:nowrap;box-shadow:0 2px 4px rgba(0,0,0,0.2)">${ri.nama}</div>`,
|
||||
iconAnchor:[0,0]
|
||||
});
|
||||
L.marker([lat,lng],{icon}).bindPopup(`<strong>${ri.nama}</strong><br>${ri.jenis}<br>${ri.kelurahan}<br>Radius: ${ri.radius_meter}m<br>Warga: ${ri.jml_warga}`).addTo(ovMap);
|
||||
L.circle([lat,lng],{radius:ri.radius_meter,fillColor:'#16a34a',fillOpacity:0.08,color:'#16a34a',weight:1.5,dashArray:'4,4'}).addTo(ovMap);
|
||||
riBounds.push([lat,lng]);
|
||||
});
|
||||
// Auto-zoom ke seluruh rumah ibadah Kota Pontianak
|
||||
if (riBounds.length > 0) {
|
||||
const b = L.latLngBounds(riBounds);
|
||||
if (b.isValid()) ovMap.flyToBounds(b, {duration:0.6, padding:[30,30], maxZoom:14});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,221 @@
|
||||
<!-- HEADER ROW -->
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||
<div>
|
||||
<h2 style="font-size:1.2rem;font-weight:700">Manajemen User</h2>
|
||||
<p class="text-muted text-sm">Kelola seluruh pengguna sistem SINERGI</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="App.showModal('modal-tambah')">➕ Tambah User</button>
|
||||
</div>
|
||||
|
||||
<!-- SEARCH -->
|
||||
<div class="filters-bar">
|
||||
<input type="text" id="search-user" class="form-control" placeholder="🔍 Cari nama, username, email..." style="max-width:300px">
|
||||
</div>
|
||||
|
||||
<!-- TABLE -->
|
||||
<div class="card">
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table id="table-users">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th><th>Nama</th><th>Username</th><th>Role</th>
|
||||
<th>Wilayah</th><th>No HP</th><th>Status</th><th>Login Terakhir</th><th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($users as $i => $u): ?>
|
||||
<tr>
|
||||
<td class="text-muted text-sm"><?= $i+1 ?></td>
|
||||
<td>
|
||||
<div style="display:flex;align-items:center;gap:10px">
|
||||
<div style="width:32px;height:32px;border-radius:50%;background:var(--clr-primary);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:0.85rem;flex-shrink:0">
|
||||
<?= strtoupper(substr($u['nama'],0,1)) ?>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight:600;font-size:0.875rem"><?= e($u['nama']) ?></div>
|
||||
<div class="text-muted text-xs"><?= e($u['email']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><code style="font-size:0.78rem;background:#f1f5f9;padding:2px 6px;border-radius:4px"><?= e($u['username']) ?></code></td>
|
||||
<td>
|
||||
<?php $roleColors = ['superadmin'=>'purple','verifikator'=>'blue','rumah_ibadah'=>'green','dinsos'=>'teal','walikota'=>'orange']; ?>
|
||||
<span class="badge badge-<?= $roleColors[$u['role_slug']] ?? 'gray' ?>"><?= e($u['role_nama']) ?></span>
|
||||
</td>
|
||||
<td class="text-sm"><?= e($u['kelurahan_nama'] ?? '—') ?></td>
|
||||
<td class="text-sm"><?= e($u['no_hp'] ?? '—') ?></td>
|
||||
<td><?= $u['is_active'] ? '<span class="badge badge-green">Aktif</span>' : '<span class="badge badge-gray">Nonaktif</span>' ?></td>
|
||||
<td class="text-xs text-muted"><?= $u['last_login'] ? formatTanggal($u['last_login'],true) : '—' ?></td>
|
||||
<td>
|
||||
<div style="display:flex;gap:6px">
|
||||
<?php if ($u['id'] != Auth::id()): ?>
|
||||
<button class="btn btn-ghost btn-sm" onclick='openEditModal(<?= json_encode($u) ?>)'>✏️</button>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/users/<?= $u['id'] ?>/delete" style="display:inline"
|
||||
onsubmit="return confirm('Nonaktifkan user <?= addslashes($u['nama']) ?>?')">
|
||||
<?= csrfField() ?>
|
||||
<button type="submit" class="btn btn-ghost btn-sm" style="color:var(--clr-danger)">🗑</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<span class="text-xs text-muted">Akun Anda</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL TAMBAH -->
|
||||
<div class="modal-overlay" id="modal-tambah">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>➕ Tambah User Baru</h3>
|
||||
<button class="modal-close" onclick="App.hideModal('modal-tambah')">✕</button>
|
||||
</div>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/users/store">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Lengkap <span class="required">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Username <span class="required">*</span></label>
|
||||
<input type="text" name="username" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Email <span class="required">*</span></label>
|
||||
<input type="email" name="email" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Password <span class="required">*</span></label>
|
||||
<input type="password" name="password" class="form-control" required minlength="6">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">No HP</label>
|
||||
<input type="text" name="no_hp" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Role <span class="required">*</span></label>
|
||||
<select name="id_role" class="form-control" required>
|
||||
<?php foreach ($roles as $r): ?>
|
||||
<option value="<?= $r['id'] ?>"><?= e($r['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Kelurahan Tugas</label>
|
||||
<select name="id_kelurahan" class="form-control">
|
||||
<option value="">— Semua Wilayah —</option>
|
||||
<?php foreach ($kelurahan as $k): ?>
|
||||
<option value="<?= $k['id'] ?>"><?= e($k['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-tambah')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan User</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL EDIT -->
|
||||
<div class="modal-overlay" id="modal-edit">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>✏️ Edit User</h3>
|
||||
<button class="modal-close" onclick="App.hideModal('modal-edit')">✕</button>
|
||||
</div>
|
||||
<form method="POST" id="edit-form">
|
||||
<?= csrfField() ?>
|
||||
<input type="hidden" name="id" id="edit-id">
|
||||
<div class="modal-body">
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nama Lengkap <span class="required">*</span></label>
|
||||
<input type="text" name="nama" id="edit-nama" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Username <span class="required">*</span></label>
|
||||
<input type="text" name="username" id="edit-username" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Email <span class="required">*</span></label>
|
||||
<input type="email" name="email" id="edit-email" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Password Baru <span class="text-muted">(kosongkan jika tidak diubah)</span></label>
|
||||
<input type="password" name="password" class="form-control" minlength="6">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">No HP</label>
|
||||
<input type="text" name="no_hp" id="edit-no_hp" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Role</label>
|
||||
<select name="id_role" id="edit-id_role" class="form-control">
|
||||
<?php foreach ($roles as $r): ?>
|
||||
<option value="<?= $r['id'] ?>"><?= e($r['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Status</label>
|
||||
<select name="is_active" id="edit-is_active" class="form-control">
|
||||
<option value="1">Aktif</option>
|
||||
<option value="0">Nonaktif</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Kelurahan Tugas</label>
|
||||
<select name="id_kelurahan" id="edit-id_kelurahan" class="form-control">
|
||||
<option value="">— Semua Wilayah —</option>
|
||||
<?php foreach ($kelurahan as $k): ?>
|
||||
<option value="<?= $k['id'] ?>"><?= e($k['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-edit')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
App.initTableSearch('search-user', 'table-users');
|
||||
});
|
||||
|
||||
function openEditModal(u) {
|
||||
document.getElementById('edit-id').value = u.id;
|
||||
document.getElementById('edit-nama').value = u.nama;
|
||||
document.getElementById('edit-username').value = u.username;
|
||||
document.getElementById('edit-email').value = u.email;
|
||||
document.getElementById('edit-no_hp').value = u.no_hp || '';
|
||||
document.getElementById('edit-id_role').value = u.id_role;
|
||||
document.getElementById('edit-id_kelurahan').value = u.id_kelurahan || '';
|
||||
document.getElementById('edit-is_active').value = u.is_active;
|
||||
document.getElementById('edit-form').action = '<?= APP_URL ?>/admin/users/' + u.id + '/update';
|
||||
App.showModal('modal-edit');
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,119 @@
|
||||
<!-- ADMIN WILAYAH VIEW -->
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:20px">
|
||||
<div>
|
||||
<h2 style="font-size:1.2rem;font-weight:700">🗾 Manajemen Wilayah</h2>
|
||||
<p class="text-muted text-sm">Data kecamatan dan kelurahan Kota Pontianak</p>
|
||||
</div>
|
||||
<div style="display:flex;gap:10px">
|
||||
<button class="btn btn-ghost" onclick="App.showModal('modal-kecamatan')">➕ Kecamatan</button>
|
||||
<button class="btn btn-primary" onclick="App.showModal('modal-kelurahan')">➕ Kelurahan</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px">
|
||||
<!-- Kecamatan -->
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">🏙</span><h3>Kecamatan (<?= count($kecamatan) ?>)</h3></div>
|
||||
<div class="card-body no-pad">
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Nama</th><th>Kode</th><th>Jumlah Kelurahan</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($kecamatan as $i=>$k): ?>
|
||||
<tr>
|
||||
<td class="text-xs text-muted"><?= $i+1 ?></td>
|
||||
<td style="font-weight:600"><?= e($k['nama']) ?></td>
|
||||
<td class="text-xs" style="font-family:monospace"><?= e($k['kode']??'') ?></td>
|
||||
<td class="text-sm text-center"><?= number_format($k['jml_kel']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kelurahan -->
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-icon">🏘</span><h3>Kelurahan (<?= count($kelurahan) ?>)</h3></div>
|
||||
<div class="card-body no-pad" style="max-height:400px;overflow-y:auto">
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>#</th><th>Nama</th><th>Kecamatan</th></tr></thead>
|
||||
<tbody>
|
||||
<?php foreach($kelurahan as $i=>$k): ?>
|
||||
<tr>
|
||||
<td class="text-xs text-muted"><?= $i+1 ?></td>
|
||||
<td style="font-weight:500;font-size:0.875rem"><?= e($k['nama']) ?></td>
|
||||
<td class="text-sm text-muted"><?= e($k['kecamatan']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Kecamatan -->
|
||||
<div class="modal-overlay" id="modal-kecamatan">
|
||||
<div class="modal">
|
||||
<div class="modal-header"><h3>➕ Tambah Kecamatan</h3><button class="modal-close" onclick="App.hideModal('modal-kecamatan')">✕</button></div>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/kecamatan/store">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group"><label class="form-label">Nama Kecamatan <span class="required">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" required></div>
|
||||
<div class="form-group"><label class="form-label">Kode Wilayah</label>
|
||||
<input type="text" name="kode" class="form-control"></div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group"><label class="form-label">Latitude</label>
|
||||
<input type="number" name="lat" class="form-control" step="0.0000001"></div>
|
||||
<div class="form-group"><label class="form-label">Longitude</label>
|
||||
<input type="number" name="lng" class="form-control" step="0.0000001"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-kecamatan')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Kelurahan -->
|
||||
<div class="modal-overlay" id="modal-kelurahan">
|
||||
<div class="modal">
|
||||
<div class="modal-header"><h3>➕ Tambah Kelurahan</h3><button class="modal-close" onclick="App.hideModal('modal-kelurahan')">✕</button></div>
|
||||
<form method="POST" action="<?= APP_URL ?>/admin/kelurahan/store">
|
||||
<?= csrfField() ?>
|
||||
<div class="modal-body">
|
||||
<div class="form-group"><label class="form-label">Kecamatan <span class="required">*</span></label>
|
||||
<select name="id_kecamatan" class="form-control" required>
|
||||
<option value="">— Pilih Kecamatan —</option>
|
||||
<?php foreach($kecamatan as $k): ?>
|
||||
<option value="<?= $k['id'] ?>"><?= e($k['nama']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select></div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group"><label class="form-label">Nama Kelurahan <span class="required">*</span></label>
|
||||
<input type="text" name="nama" class="form-control" required></div>
|
||||
<div class="form-group"><label class="form-label">Kode Wilayah</label>
|
||||
<input type="text" name="kode" class="form-control"></div>
|
||||
</div>
|
||||
<div class="form-row cols-2">
|
||||
<div class="form-group"><label class="form-label">Latitude</label>
|
||||
<input type="number" name="lat" class="form-control" step="0.0000001"></div>
|
||||
<div class="form-group"><label class="form-label">Longitude</label>
|
||||
<input type="number" name="lng" class="form-control" step="0.0000001"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-ghost" onclick="App.hideModal('modal-kelurahan')">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user