Upload files to "/"
This commit is contained in:
@@ -0,0 +1,444 @@
|
||||
<?php
|
||||
require_once 'koneksi.php';
|
||||
cekLogin();
|
||||
|
||||
$page = 'peta';
|
||||
$pageTitle = 'Peta Interaktif';
|
||||
$pageSubtitle = '';
|
||||
|
||||
$extraHead = '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
|
||||
<style>
|
||||
/* Peta harus full, override page-wrap padding */
|
||||
#main-wrap { display:flex; flex-direction:column; }
|
||||
.page-wrap { padding:0 !important; display:flex; flex-direction:column; flex:1; overflow:hidden; }
|
||||
|
||||
/* Toolbar */
|
||||
#map-toolbar {
|
||||
background:#fff; border-bottom:1px solid var(--gray-md);
|
||||
padding:8px 16px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;
|
||||
flex-shrink:0; z-index:500;
|
||||
}
|
||||
.mpill {
|
||||
padding:5px 13px; border:none; border-radius:99px; font-size:12px;
|
||||
font-weight:600; cursor:pointer; background:transparent; color:var(--gray); transition:.15s;
|
||||
}
|
||||
.mpill.active { background:#0f172a; color:#fff; }
|
||||
.mpill:hover:not(.active) { background:var(--gray-lt); }
|
||||
.layer-btn {
|
||||
padding:4px 11px; border:1px solid var(--gray-md); border-radius:99px;
|
||||
font-size:12px; font-weight:600; cursor:pointer; background:#fff; color:var(--gray); transition:.15s;
|
||||
}
|
||||
.layer-btn.active { background:#0f172a; color:#fff; border-color:#0f172a; }
|
||||
.stat-pill {
|
||||
font-size:11px; font-weight:700; padding:3px 10px; border-radius:99px;
|
||||
}
|
||||
|
||||
/* Map area */
|
||||
#map {
|
||||
flex:1; width:100%; z-index:100; min-height:0;
|
||||
}
|
||||
|
||||
/* Legend */
|
||||
#map-legend {
|
||||
position:absolute; bottom:24px; right:16px; z-index:400;
|
||||
background:#fff; border-radius:8px; padding:11px 13px;
|
||||
border:1px solid var(--gray-md); box-shadow:0 4px 14px rgba(0,0,0,.08);
|
||||
font-size:12px; min-width:148px; pointer-events:none;
|
||||
}
|
||||
#map-legend .leg-title { font-size:9px; font-weight:700; color:var(--gray); text-transform:uppercase; letter-spacing:.6px; margin-bottom:8px; }
|
||||
.leg-row { display:flex; align-items:center; gap:7px; margin-bottom:5px; font-size:12px; color:var(--dark); }
|
||||
.leg-dot { width:9px; height:9px; border-radius:50%; flex-shrink:0; }
|
||||
.leg-rect { width:16px; height:8px; border-radius:2px; flex-shrink:0; }
|
||||
|
||||
/* Mode hint */
|
||||
#mode-hint {
|
||||
position:absolute; top:14px; left:50%; transform:translateX(-50%); z-index:400;
|
||||
background:rgba(15,23,42,.88); color:#fff; padding:7px 18px; border-radius:99px;
|
||||
font-size:12px; font-weight:500; display:none; pointer-events:none;
|
||||
}
|
||||
|
||||
/* Popup */
|
||||
.leaflet-popup-content-wrapper{border-radius:10px!important;box-shadow:0 8px 28px rgba(0,0,0,.14)!important;padding:0!important;overflow:hidden}
|
||||
.leaflet-popup-content{margin:0!important}
|
||||
.pw{width:270px;font-family:var(--font)}
|
||||
.ph{padding:11px 13px;font-size:13px;font-weight:700;color:#fff;display:flex;align-items:center;gap:6px}
|
||||
.ph.blue{background:linear-gradient(135deg,#1e3a8a,#3b82f6)}
|
||||
.ph.green{background:linear-gradient(135deg,#16a34a,#22c55e)}
|
||||
.ph.red{background:linear-gradient(135deg,#dc2626,#ef4444)}
|
||||
.ph.orange{background:linear-gradient(135deg,#ea580c,#f97316)}
|
||||
.pb{padding:11px 13px}
|
||||
.dr{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid #f9fafb;font-size:12px}
|
||||
.dr:last-child{border-bottom:none}
|
||||
.dr .k{color:var(--gray)}.dr .v{font-weight:700;text-align:right;max-width:55%}
|
||||
.br{display:flex;gap:5px;margin-top:9px}
|
||||
.bp{flex:1;padding:7px;font-size:12px;font-weight:700;border:none;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:4px;transition:.15s;font-family:var(--font)}
|
||||
.bp-primary{background:#1e3a8a;color:#fff}
|
||||
.bp-danger{background:#dc2626;color:#fff}
|
||||
.bp-ghost{background:var(--gray-lt);color:var(--dark)}
|
||||
.sw{margin-top:9px;padding-top:9px;border-top:1px solid #f9fafb}
|
||||
.sw label{font-size:11px;font-weight:700;color:var(--gray);display:flex;justify-content:space-between}
|
||||
.sw .rv{color:#1e3a8a;font-weight:800}
|
||||
input[type=range]{width:100%;accent-color:#1e3a8a;cursor:pointer;margin-top:4px}
|
||||
.fg-p{margin-bottom:7px}
|
||||
.fg-p label{display:block;font-size:10px;font-weight:700;color:var(--gray);text-transform:uppercase;margin-bottom:3px}
|
||||
.fg-p input,.fg-p select,.fg-p textarea{width:100%;padding:6px 9px;border:1px solid var(--gray-md);border-radius:5px;font-size:12px;font-family:var(--font);transition:.15s}
|
||||
.fg-p input:focus,.fg-p select:focus{outline:none;border-color:#1e3a8a}
|
||||
.fg-p input.ro{background:var(--gray-lt);color:var(--gray);font-size:11px;cursor:default}
|
||||
.fc2{display:grid;grid-template-columns:1fr 1fr;gap:7px}
|
||||
</style>';
|
||||
|
||||
include 'includes/sidebar.php';
|
||||
?>
|
||||
|
||||
<!-- TOOLBAR -->
|
||||
<div id="map-toolbar">
|
||||
<!-- Mode -->
|
||||
<div style="display:flex;background:var(--gray-lt);border-radius:99px;padding:3px;gap:1px">
|
||||
<button class="mpill active" data-mode="view" onclick="setMode('view')">Lihat</button>
|
||||
<?php if (in_array($_SESSION['role'],['admin','relawan'])): ?>
|
||||
<button class="mpill" data-mode="miskin" onclick="setMode('miskin')">+ KPM</button>
|
||||
<?php endif; ?>
|
||||
<?php if (in_array($_SESSION['role'],['admin','pengurus'])): ?>
|
||||
<button class="mpill" data-mode="ibadah" onclick="setMode('ibadah')">+ Ibadah</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div style="width:1px;height:18px;background:var(--gray-md)"></div>
|
||||
|
||||
<!-- Layer -->
|
||||
<div style="display:flex;gap:5px">
|
||||
<button class="layer-btn active" id="chip-street" onclick="switchLayer('street')">Jalan</button>
|
||||
<button class="layer-btn" id="chip-satellite" onclick="switchLayer('satellite')">Satelit</button>
|
||||
<button class="layer-btn" id="chip-topo" onclick="switchLayer('topo')">Topografi</button>
|
||||
</div>
|
||||
|
||||
<div style="width:1px;height:18px;background:var(--gray-md)"></div>
|
||||
|
||||
<!-- Toggle -->
|
||||
<div style="display:flex;gap:12px;font-size:12px;font-weight:600;color:var(--gray)">
|
||||
<label style="display:flex;align-items:center;gap:4px;cursor:pointer"><input type="checkbox" id="tog-ibadah" checked onchange="toggleLayer('ibadah',this.checked)"> Ibadah</label>
|
||||
<label style="display:flex;align-items:center;gap:4px;cursor:pointer"><input type="checkbox" id="tog-miskin" checked onchange="toggleLayer('miskin',this.checked)"> KPM</label>
|
||||
<label style="display:flex;align-items:center;gap:4px;cursor:pointer"><input type="checkbox" id="tog-radius" checked onchange="toggleLayer('radius',this.checked)"> Radius</label>
|
||||
<label style="display:flex;align-items:center;gap:4px;cursor:pointer"><input type="checkbox" id="tog-prioritas" onchange="toggleLayer('prioritas',this.checked)"> Prioritas</label>
|
||||
</div>
|
||||
|
||||
<div style="flex:1"></div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div style="display:flex;gap:6px">
|
||||
<span class="stat-pill" style="background:#e0f2fe;color:#0369a1" id="s-ibadah">0 Ibadah</span>
|
||||
<span class="stat-pill" style="background:var(--green-lt);color:var(--green)" id="s-ok">0 Terjangkau</span>
|
||||
<span class="stat-pill" style="background:var(--red-lt);color:var(--red)" id="s-blank">0 Blank Spot</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MAP -->
|
||||
<div style="position:relative;flex:1;display:flex;flex-direction:column;min-height:0">
|
||||
<div id="map"></div>
|
||||
<div id="mode-hint"></div>
|
||||
<div id="map-legend">
|
||||
<div class="leg-title">Legenda</div>
|
||||
<div class="leg-row"><div class="leg-dot" style="background:#2563eb"></div> Rumah Ibadah</div>
|
||||
<div class="leg-row"><div class="leg-rect" style="border:1.5px solid #2563eb;background:rgba(37,99,235,.12)"></div> Radius</div>
|
||||
<div class="leg-row"><div class="leg-dot" style="background:#16a34a"></div> KPM Terjangkau</div>
|
||||
<div class="leg-row"><div class="leg-dot" style="background:#dc2626"></div> KPM Blank Spot</div>
|
||||
<div class="leg-row"><div class="leg-dot" style="background:#f97316"></div> KPM Prioritas</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
<script>
|
||||
// ── Layers ──
|
||||
var layerStreet = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',{attribution:'© CARTO'});
|
||||
var layerSatellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',{attribution:'© Esri'});
|
||||
var layerTopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',{attribution:'© OpenTopoMap'});
|
||||
|
||||
var map = L.map('map',{center:[-0.0263,109.3425],zoom:14,layers:[layerStreet],zoomControl:false});
|
||||
L.control.zoom({position:'bottomleft'}).addTo(map);
|
||||
setTimeout(()=>map.invalidateSize(),300);
|
||||
|
||||
var curBase = 'street';
|
||||
var bases = {street:layerStreet,satellite:layerSatellite,topo:layerTopo};
|
||||
function switchLayer(l){
|
||||
map.removeLayer(bases[curBase]); map.addLayer(bases[l]); curBase=l;
|
||||
document.querySelectorAll('.layer-btn').forEach(b=>b.classList.remove('active'));
|
||||
document.getElementById('chip-'+l).classList.add('active');
|
||||
}
|
||||
|
||||
// ── Icons ──
|
||||
function mkIco(c){
|
||||
return new L.Icon({
|
||||
iconUrl:`https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-${c}.png`,
|
||||
shadowUrl:'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
|
||||
iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]
|
||||
});
|
||||
}
|
||||
var ico={blue:mkIco('blue'),green:mkIco('green'),red:mkIco('red'),orange:mkIco('orange')};
|
||||
|
||||
// ── State ──
|
||||
var dIbadah={},dMiskin={},showL={ibadah:true,miskin:true,radius:true,prioritas:false};
|
||||
var curMode='view',tmpMk=null;
|
||||
|
||||
// ── Mode ──
|
||||
function setMode(m){
|
||||
curMode=m;
|
||||
if(tmpMk){map.removeLayer(tmpMk);tmpMk=null;}
|
||||
document.querySelectorAll('.mpill').forEach(p=>p.classList.toggle('active',p.dataset.mode===m));
|
||||
var hint=document.getElementById('mode-hint');
|
||||
if(m==='view'){hint.style.display='none';map.getContainer().style.cursor='';return;}
|
||||
|
||||
map.getContainer().style.cursor='crosshair';
|
||||
hint.textContent='Mencari GPS perangkat Anda...';
|
||||
hint.style.display='block';
|
||||
|
||||
if(!navigator.geolocation){
|
||||
hint.textContent='GPS tidak tersedia. Klik manual di peta.';
|
||||
return;
|
||||
}
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function(pos){
|
||||
var lat=pos.coords.latitude.toFixed(6), lng=pos.coords.longitude.toFixed(6);
|
||||
var ll=L.latLng(lat,lng);
|
||||
map.flyTo(ll,16);
|
||||
tmpMk=L.marker(ll,{icon:m==='ibadah'?ico.blue:ico.orange}).addTo(map);
|
||||
if(m==='ibadah') formIbadah(lat,lng,ll);
|
||||
else formMiskin(lat,lng,ll);
|
||||
hint.textContent='Lokasi ditemukan. Isi form di bawah ini.';
|
||||
setTimeout(()=>{hint.style.display='none';},2500);
|
||||
},
|
||||
function(){
|
||||
hint.textContent='GPS gagal. Silakan klik lokasi di peta.';
|
||||
},
|
||||
{enableHighAccuracy:true,timeout:7000}
|
||||
);
|
||||
}
|
||||
|
||||
// ── Klik manual ──
|
||||
map.on('click',function(e){
|
||||
if(curMode==='view') return;
|
||||
var lat=e.latlng.lat.toFixed(6), lng=e.latlng.lng.toFixed(6);
|
||||
if(tmpMk) map.removeLayer(tmpMk);
|
||||
tmpMk=L.marker(e.latlng,{icon:curMode==='ibadah'?ico.blue:ico.orange}).addTo(map);
|
||||
if(curMode==='ibadah') formIbadah(lat,lng,e.latlng);
|
||||
else formMiskin(lat,lng,e.latlng);
|
||||
});
|
||||
map.on('popupclose',function(){if(tmpMk){map.removeLayer(tmpMk);tmpMk=null;}});
|
||||
|
||||
// ── Toggle layer ──
|
||||
function toggleLayer(t,show){
|
||||
showL[t]=show;
|
||||
if(t==='ibadah') Object.values(dIbadah).forEach(d=>show?d.mk.addTo(map):map.removeLayer(d.mk));
|
||||
if(t==='radius') Object.values(dIbadah).forEach(d=>show?d.ci.addTo(map):map.removeLayer(d.ci));
|
||||
if(t==='miskin') Object.values(dMiskin).forEach(d=>{
|
||||
if(show){if(!showL.prioritas||d.data.prioritas==1)d.mk.addTo(map);}else map.removeLayer(d.mk);
|
||||
});
|
||||
if(t==='prioritas') Object.values(dMiskin).forEach(d=>{
|
||||
if(show){if(d.data.prioritas==1)d.mk.addTo(map);else map.removeLayer(d.mk);}
|
||||
else{if(showL.miskin)d.mk.addTo(map);}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Form Ibadah ──
|
||||
function formIbadah(lat,lng,ll){
|
||||
var h=`<div class="pw"><div class="ph blue">Tambah Rumah Ibadah</div><div class="pb">
|
||||
<div class="fg-p"><label>Nama Lembaga *</label><input id="fi_nama" placeholder="Masjid Al-Ikhlas..."></div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>Kategori</label><select id="fi_kat"><option>Masjid</option><option>Musholla</option><option>Gereja</option><option>Pura</option><option>Vihara</option><option>Klenteng</option><option>Lainnya</option></select></div>
|
||||
<div class="fg-p"><label>Kuota (KK)</label><input type="number" id="fi_kuota" value="20"></div>
|
||||
</div>
|
||||
<div class="fg-p"><label>Alamat</label><input id="fi_alamat" placeholder="Jl. ..."></div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>Pengurus</label><input id="fi_peng"></div>
|
||||
<div class="fg-p"><label>No. Telp</label><input id="fi_telp"></div>
|
||||
</div>
|
||||
<div class="fg-p"><label>Radius Awal (m)</label><input type="number" id="fi_rad" value="300"></div>
|
||||
<div class="fg-p"><label>Koordinat</label><input class="ro" readonly value="${lat}, ${lng}"></div>
|
||||
<div class="br">
|
||||
<button class="bp bp-ghost" onclick="map.closePopup()">Batal</button>
|
||||
<button class="bp bp-primary" onclick="simpanIbadah('${lat}','${lng}')">Simpan</button>
|
||||
</div></div></div>`;
|
||||
L.popup({maxWidth:290}).setLatLng(ll).setContent(h).openOn(map);
|
||||
}
|
||||
function simpanIbadah(lat,lng){
|
||||
var nama=document.getElementById('fi_nama').value.trim();
|
||||
if(!nama){alert('Nama wajib diisi!');return;}
|
||||
var fd=new FormData();
|
||||
fd.append('aksi','simpan_ibadah');
|
||||
fd.append('nama_ibadah',nama);
|
||||
fd.append('kategori',document.getElementById('fi_kat').value);
|
||||
fd.append('alamat',document.getElementById('fi_alamat').value);
|
||||
fd.append('nama_pengurus',document.getElementById('fi_peng').value);
|
||||
fd.append('no_telp',document.getElementById('fi_telp').value);
|
||||
fd.append('kuota_bantuan',document.getElementById('fi_kuota').value);
|
||||
fd.append('radius_m',document.getElementById('fi_rad').value);
|
||||
fd.append('lat',lat);fd.append('lng',lng);
|
||||
fetch('proses.php',{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
|
||||
if(d.status==='ok'){map.closePopup();loadData();toastP('Rumah ibadah disimpan','success');setMode('view');}
|
||||
else toastP(d.message,'error');
|
||||
});
|
||||
}
|
||||
|
||||
// ── Form KPM ──
|
||||
function formMiskin(lat,lng,ll){
|
||||
var h=`<div class="pw"><div class="ph orange">Tambah Data KPM</div><div class="pb">
|
||||
<div class="fg-p"><label>Nama Kepala Keluarga *</label><input id="fm_nama" placeholder="Nama lengkap..."></div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>NIK</label><input id="fm_nik" maxlength="16" placeholder="16 digit"></div>
|
||||
<div class="fg-p"><label>Tanggal Lahir</label><input type="date" id="fm_tgl"></div>
|
||||
</div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>Tanggungan</label><input type="number" id="fm_tang" value="1" min="0"></div>
|
||||
<div class="fg-p"><label>Pendapatan/bln</label><input type="number" id="fm_pend" value="0"></div>
|
||||
</div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>Kondisi Rumah</label><select id="fm_kond"><option>Tidak Layak</option><option>Sangat Tidak Layak</option><option>Layak</option></select></div>
|
||||
<div class="fg-p"><label>Pekerjaan</label><input id="fm_kerja" placeholder="Buruh..."></div>
|
||||
</div>
|
||||
<div class="fc2">
|
||||
<div class="fg-p"><label>RT/RW</label><input id="fm_rtrw" placeholder="RT 01/RW 02"></div>
|
||||
<div class="fg-p"><label>Kelurahan</label><input id="fm_kel"></div>
|
||||
</div>
|
||||
<div class="fg-p"><label>Koordinat</label><input class="ro" readonly value="${lat}, ${lng}"></div>
|
||||
<div class="br">
|
||||
<button class="bp bp-ghost" onclick="map.closePopup()">Batal</button>
|
||||
<button class="bp bp-primary" style="background:#ea580c" onclick="simpanMiskin('${lat}','${lng}')">Simpan</button>
|
||||
</div></div></div>`;
|
||||
L.popup({maxWidth:290}).setLatLng(ll).setContent(h).openOn(map);
|
||||
}
|
||||
function simpanMiskin(lat,lng){
|
||||
var nama=document.getElementById('fm_nama').value.trim();
|
||||
if(!nama){alert('Nama wajib diisi!');return;}
|
||||
var fd=new FormData();
|
||||
fd.append('aksi','simpan_miskin');
|
||||
fd.append('nama_kk',nama);
|
||||
fd.append('nik',document.getElementById('fm_nik').value);
|
||||
fd.append('tanggal_lahir',document.getElementById('fm_tgl').value);
|
||||
fd.append('jumlah_tanggungan',document.getElementById('fm_tang').value);
|
||||
fd.append('pendapatan_bulanan',document.getElementById('fm_pend').value);
|
||||
fd.append('kondisi_rumah',document.getElementById('fm_kond').value);
|
||||
fd.append('pekerjaan',document.getElementById('fm_kerja').value);
|
||||
fd.append('rt_rw',document.getElementById('fm_rtrw').value);
|
||||
fd.append('kelurahan',document.getElementById('fm_kel').value);
|
||||
fd.append('lat',lat);fd.append('lng',lng);
|
||||
fetch('proses.php',{method:'POST',body:fd}).then(r=>r.json()).then(d=>{
|
||||
if(d.status==='ok'){map.closePopup();loadData();toastP('Data KPM disimpan','success');setMode('view');}
|
||||
else toastP(d.message,'error');
|
||||
});
|
||||
}
|
||||
|
||||
// ── Popup detail ──
|
||||
function popIbadah(row){
|
||||
var canEdit=<?= in_array($_SESSION['role'],['admin','pengurus'])?'true':'false' ?>;
|
||||
var canDel=<?= $_SESSION['role']==='admin'?'true':'false' ?>;
|
||||
return `<div class="pw"><div class="ph blue">${row.kategori} — ${row.nama_ibadah}</div><div class="pb">
|
||||
<div class="dr"><span class="k">Pengurus</span><span class="v">${row.nama_pengurus||'-'}</span></div>
|
||||
<div class="dr"><span class="k">Kuota</span><span class="v">${row.kuota_bantuan} KK</span></div>
|
||||
${canEdit?`<div class="sw"><label>Radius <span class="rv" id="rv_${row.id}">${row.radius_m}</span> m</label>
|
||||
<input type="range" min="100" max="3000" step="50" value="${row.radius_m}"
|
||||
oninput="updRad(${row.id},this.value)" onchange="saveRad(${row.id},this.value)"></div>`
|
||||
:`<div class="dr"><span class="k">Radius</span><span class="v">${row.radius_m} m</span></div>`}
|
||||
${canDel?`<div class="br"><button class="bp bp-danger" onclick="del('ibadah',${row.id})"><i class='fa fa-trash'></i> Hapus</button></div>`:''}
|
||||
</div></div>`;
|
||||
}
|
||||
function popMiskin(row){
|
||||
var ok=row.status_bantuan==='Terjangkau', pr=row.prioritas==1;
|
||||
var canDel=<?= $_SESSION['role']==='admin'?'true':'false' ?>;
|
||||
return `<div class="pw"><div class="ph ${ok?'green':'red'}">${pr?'🚨 ':''}${row.nama_kepala_keluarga}</div><div class="pb">
|
||||
<div class="dr"><span class="k">NIK</span><span class="v">${row.nik||'-'}</span></div>
|
||||
<div class="dr"><span class="k">Kondisi Rumah</span><span class="v">${row.kondisi_rumah}</span></div>
|
||||
<div class="dr"><span class="k">Tanggungan</span><span class="v">${row.jumlah_tanggungan} jiwa</span></div>
|
||||
<div class="dr"><span class="k">Status</span><span class="v" style="color:${ok?'#16a34a':'#dc2626'}">${row.status_bantuan}</span></div>
|
||||
${pr?'<div style="background:var(--red-lt);border-radius:5px;padding:5px 8px;font-size:11px;font-weight:700;color:var(--red);margin-top:6px">Warga Prioritas Bencana</div>':''}
|
||||
${canDel?`<div class="br"><button class="bp bp-danger" onclick="del('miskin',${row.id})"><i class='fa fa-trash'></i> Hapus</button></div>`:''}
|
||||
</div></div>`;
|
||||
}
|
||||
|
||||
// ── Load data ──
|
||||
function loadData(){
|
||||
Object.values(dIbadah).forEach(d=>{map.removeLayer(d.mk);map.removeLayer(d.ci);});
|
||||
Object.values(dMiskin).forEach(d=>map.removeLayer(d.mk));
|
||||
dIbadah={}; dMiskin={};
|
||||
|
||||
fetch('proses.php?aksi=tampil_semua').then(r=>r.json()).then(res=>{
|
||||
res.ibadah.forEach(row=>{
|
||||
var ll=[row.lat,row.lng];
|
||||
var ci=L.circle(ll,{color:'#1e3a8a',fillColor:'#3b82f6',fillOpacity:.1,weight:1.5,radius:parseInt(row.radius_m)}).addTo(map);
|
||||
var mk=L.marker(ll,{icon:ico.blue,draggable:true}).addTo(map);
|
||||
mk.bindPopup(popIbadah(row),{maxWidth:290});
|
||||
mk.on('drag',e=>{ci.setLatLng(e.target.getLatLng());kalkulasi();});
|
||||
mk.on('dragend',e=>{
|
||||
var p=e.target.getLatLng();
|
||||
var fd=new FormData();fd.append('aksi','update_coords');fd.append('jenis','ibadah');fd.append('id',row.id);fd.append('lat',p.lat.toFixed(6));fd.append('lng',p.lng.toFixed(6));
|
||||
fetch('proses.php',{method:'POST',body:fd});
|
||||
});
|
||||
dIbadah[row.id]={mk,ci,data:row};
|
||||
if(!showL.ibadah) map.removeLayer(mk);
|
||||
if(!showL.radius) map.removeLayer(ci);
|
||||
});
|
||||
|
||||
res.miskin.forEach(row=>{
|
||||
var ll=[row.lat,row.lng];
|
||||
var mk=L.marker(ll,{icon:ico.red,draggable:true}).addTo(map);
|
||||
mk.bindPopup(popMiskin(row),{maxWidth:290});
|
||||
mk.on('drag',()=>kalkulasi());
|
||||
mk.on('dragend',e=>{
|
||||
var p=e.target.getLatLng();
|
||||
var fd=new FormData();fd.append('aksi','update_coords');fd.append('jenis','miskin');fd.append('id',row.id);fd.append('lat',p.lat.toFixed(6));fd.append('lng',p.lng.toFixed(6));
|
||||
fetch('proses.php',{method:'POST',body:fd});
|
||||
});
|
||||
dMiskin[row.id]={mk,data:row};
|
||||
if(!showL.miskin) map.removeLayer(mk);
|
||||
});
|
||||
kalkulasi();
|
||||
});
|
||||
}
|
||||
|
||||
function kalkulasi(){
|
||||
var upd=[],ok=0,blank=0;
|
||||
Object.values(dMiskin).forEach(m=>{
|
||||
var ll=m.mk.getLatLng(), masuk=false, pr=m.data.prioritas==1;
|
||||
Object.values(dIbadah).forEach(ib=>{
|
||||
if(!masuk && ll.distanceTo(ib.mk.getLatLng())<=ib.ci.getRadius()) masuk=true;
|
||||
});
|
||||
var st=masuk?'Terjangkau':'Belum Terbantu';
|
||||
m.data.status_bantuan=st;
|
||||
m.mk.setIcon(pr?ico.orange:(masuk?ico.green:ico.red));
|
||||
m.mk.setPopupContent(popMiskin(m.data));
|
||||
masuk?ok++:blank++;
|
||||
upd.push({id:m.data.id,status:st});
|
||||
if(showL.prioritas&&!pr) map.removeLayer(m.mk);
|
||||
else if(showL.miskin) m.mk.addTo(map);
|
||||
});
|
||||
document.getElementById('s-ibadah').textContent = Object.keys(dIbadah).length+' Ibadah';
|
||||
document.getElementById('s-ok').textContent = ok+' Terjangkau';
|
||||
document.getElementById('s-blank').textContent = blank+' Blank Spot';
|
||||
if(upd.length) fetch('proses.php?aksi=update_status_bantuan',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(upd)});
|
||||
}
|
||||
|
||||
window.updRad=function(id,r){
|
||||
var el=document.getElementById('rv_'+id);if(el)el.textContent=r;
|
||||
if(dIbadah[id])dIbadah[id].ci.setRadius(parseInt(r));
|
||||
kalkulasi();
|
||||
};
|
||||
window.saveRad=function(id,r){
|
||||
var fd=new FormData();fd.append('aksi','update_radius');fd.append('id',id);fd.append('radius',r);
|
||||
fetch('proses.php',{method:'POST',body:fd});
|
||||
};
|
||||
window.del=function(j,id){
|
||||
if(!confirm('Hapus data ini?')) return;
|
||||
var fd=new FormData();fd.append('aksi','hapus');fd.append('jenis',j);fd.append('id',id);
|
||||
fetch('proses.php',{method:'POST',body:fd}).then(()=>{map.closePopup();loadData();toastP('Data dihapus','success');});
|
||||
};
|
||||
|
||||
function toastP(msg,type){
|
||||
var el=document.createElement('div');
|
||||
el.innerHTML=(type==='success'?'✅':'❌')+' '+msg;
|
||||
el.style.cssText='position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:99999;background:#fff;border-radius:8px;padding:9px 16px;box-shadow:0 4px 18px rgba(0,0,0,.14);font-size:12px;font-weight:600;border-left:3px solid '+(type==='success'?'#16a34a':'#dc2626');
|
||||
document.body.appendChild(el);
|
||||
setTimeout(()=>el.remove(),3000);
|
||||
}
|
||||
|
||||
loadData();
|
||||
</script>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
+335
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
// ============================================================
|
||||
// proses.php — Backend CRUD lengkap
|
||||
// ============================================================
|
||||
require_once 'koneksi.php';
|
||||
|
||||
// Jika bukan request AJAX/POST dari form, cek session
|
||||
// Tapi untuk redirect POST, boleh tanpa JSON header
|
||||
$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) || isset($_GET['aksi']);
|
||||
if ($isAjax) header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$aksi = $_REQUEST['aksi'] ?? '';
|
||||
$uid = $_SESSION['user_id'] ?? 0;
|
||||
|
||||
// Redirect helper untuk form POST
|
||||
function redir($page, $msg, $type='success') {
|
||||
header("Location: $page?" . ($type==='success'?'success':'error') . "=" . urlencode($msg));
|
||||
exit;
|
||||
}
|
||||
|
||||
switch ($aksi) {
|
||||
|
||||
// ════════ TAMPIL SEMUA (PETA) ════════
|
||||
case 'tampil_semua':
|
||||
$ibadah=[]; $miskin=[];
|
||||
$ri=$conn->query("SELECT * FROM rumah_ibadah ORDER BY id");
|
||||
while($r=$ri->fetch_assoc()) $ibadah[]=$r;
|
||||
$rm=$conn->query("SELECT * FROM rumah_miskin ORDER BY prioritas DESC, id");
|
||||
while($r=$rm->fetch_assoc()) $miskin[]=$r;
|
||||
echo json_encode(['status'=>'ok','ibadah'=>$ibadah,'miskin'=>$miskin]);
|
||||
break;
|
||||
|
||||
// ════════ SIMPAN IBADAH (peta/form) ════════
|
||||
case 'simpan_ibadah':
|
||||
case 'simpan_ibadah_form':
|
||||
$nama = bersih($_POST['nama_ibadah'] ??'', $conn);
|
||||
$kat = bersih($_POST['kategori'] ??'Masjid', $conn);
|
||||
$alamat = bersih($_POST['alamat'] ??'', $conn);
|
||||
$peng = bersih($_POST['nama_pengurus'] ??'', $conn);
|
||||
$telp = bersih($_POST['no_telp'] ??'', $conn);
|
||||
$kuota = (int)($_POST['kuota_bantuan'] ??20);
|
||||
$radius = (int)($_POST['radius_m'] ??300);
|
||||
$lat = (float)($_POST['lat'] ??0);
|
||||
$lng = (float)($_POST['lng'] ??0);
|
||||
|
||||
if(!$nama||!$lat||!$lng){ echo json_encode(['status'=>'error','message'=>'Data tidak lengkap']); break; }
|
||||
|
||||
$sql="INSERT INTO rumah_ibadah(nama_ibadah,kategori,alamat,nama_pengurus,no_telp,kuota_bantuan,radius_m,lat,lng,dibuat_oleh) VALUES('$nama','$kat','$alamat','$peng','$telp',$kuota,$radius,$lat,$lng,$uid)";
|
||||
if($conn->query($sql)){
|
||||
if($aksi==='simpan_ibadah_form') redir('data-ibadah.php','Rumah ibadah berhasil ditambahkan');
|
||||
echo json_encode(['status'=>'ok','id'=>$conn->insert_id]);
|
||||
} else echo json_encode(['status'=>'error','message'=>$conn->error]);
|
||||
break;
|
||||
|
||||
// ════════ SIMPAN KPM (peta/form) ════════
|
||||
case 'simpan_miskin':
|
||||
case 'simpan_miskin_form':
|
||||
$nama = bersih($_POST['nama_kk'] ??'', $conn);
|
||||
$nik = bersih($_POST['nik'] ??'', $conn);
|
||||
$tgl = bersih($_POST['tanggal_lahir'] ??'', $conn);
|
||||
$jk = bersih($_POST['jenis_kelamin'] ??'Laki-laki', $conn);
|
||||
$tang = (int)($_POST['jumlah_tanggungan'] ??0);
|
||||
$pend = (int)($_POST['pendapatan_bulanan'] ??0);
|
||||
$kerja = bersih($_POST['pekerjaan'] ??'', $conn);
|
||||
$kond = bersih($_POST['kondisi_rumah'] ??'Tidak Layak', $conn);
|
||||
$telp = bersih($_POST['no_telp'] ??'', $conn);
|
||||
$rtrw = bersih($_POST['rt_rw'] ??'', $conn);
|
||||
$kel = bersih($_POST['kelurahan'] ??'', $conn);
|
||||
$kec = bersih($_POST['kecamatan'] ??'', $conn);
|
||||
$ket = bersih($_POST['keterangan'] ??'', $conn);
|
||||
$lat = (float)($_POST['lat'] ??0);
|
||||
$lng = (float)($_POST['lng'] ??0);
|
||||
$tglVal= $tgl ? "'$tgl'" : 'NULL';
|
||||
|
||||
if(!$nama||!$lat||!$lng){ echo json_encode(['status'=>'error','message'=>'Data tidak lengkap']); break; }
|
||||
|
||||
$sql="INSERT INTO rumah_miskin(nama_kepala_keluarga,nik,tanggal_lahir,jenis_kelamin,jumlah_tanggungan,pendapatan_bulanan,pekerjaan,kondisi_rumah,no_telp,rt_rw,kelurahan,kecamatan,keterangan,lat,lng,didata_oleh) VALUES('$nama','$nik',$tglVal,'$jk',$tang,$pend,'$kerja','$kond','$telp','$rtrw','$kel','$kec','$ket',$lat,$lng,$uid)";
|
||||
if($conn->query($sql)){
|
||||
if($aksi==='simpan_miskin_form') redir('data-warga.php','Data KPM berhasil ditambahkan');
|
||||
echo json_encode(['status'=>'ok','id'=>$conn->insert_id]);
|
||||
} else echo json_encode(['status'=>'error','message'=>$conn->error]);
|
||||
break;
|
||||
|
||||
// ════════ EDIT IBADAH ════════
|
||||
case 'edit_ibadah':
|
||||
$id = (int)($_POST['id']??0);
|
||||
$nama = bersih($_POST['nama_ibadah'] ??'', $conn);
|
||||
$kat = bersih($_POST['kategori'] ??'', $conn);
|
||||
$alm = bersih($_POST['alamat'] ??'', $conn);
|
||||
$peng = bersih($_POST['nama_pengurus'] ??'', $conn);
|
||||
$telp = bersih($_POST['no_telp'] ??'', $conn);
|
||||
$kuo = (int)($_POST['kuota_bantuan'] ??20);
|
||||
$rad = (int)($_POST['radius_m'] ??300);
|
||||
if(!$id||!$nama){redir('data-ibadah.php','Data tidak lengkap','error');break;}
|
||||
$conn->query("UPDATE rumah_ibadah SET nama_ibadah='$nama',kategori='$kat',alamat='$alm',nama_pengurus='$peng',no_telp='$telp',kuota_bantuan=$kuo,radius_m=$rad WHERE id=$id");
|
||||
redir('data-ibadah.php','Data rumah ibadah diperbarui');
|
||||
break;
|
||||
|
||||
// ════════ EDIT KPM ════════
|
||||
case 'edit_miskin':
|
||||
$id = (int)($_POST['id']??0);
|
||||
$nama = bersih($_POST['nama_kk'] ??'', $conn);
|
||||
$nik = bersih($_POST['nik'] ??'', $conn);
|
||||
$tgl = bersih($_POST['tanggal_lahir'] ??'', $conn);
|
||||
$jk = bersih($_POST['jenis_kelamin'] ??'Laki-laki', $conn);
|
||||
$tang = (int)($_POST['jumlah_tanggungan'] ??0);
|
||||
$pend = (int)($_POST['pendapatan_bulanan'] ??0);
|
||||
$kerja= bersih($_POST['pekerjaan'] ??'', $conn);
|
||||
$kond = bersih($_POST['kondisi_rumah'] ??'', $conn);
|
||||
$stat = bersih($_POST['status_bantuan'] ??'Belum Terbantu', $conn);
|
||||
$rtrw = bersih($_POST['rt_rw'] ??'', $conn);
|
||||
$kel = bersih($_POST['kelurahan'] ??'', $conn);
|
||||
$kec = bersih($_POST['kecamatan'] ??'', $conn);
|
||||
$telp = bersih($_POST['no_telp'] ??'', $conn);
|
||||
$ket = bersih($_POST['keterangan'] ??'', $conn);
|
||||
$tglVal= $tgl ? "'$tgl'" : 'NULL';
|
||||
if(!$id||!$nama){redir('data-warga.php','Data tidak lengkap','error');break;}
|
||||
$conn->query("UPDATE rumah_miskin SET nama_kepala_keluarga='$nama',nik='$nik',tanggal_lahir=$tglVal,jenis_kelamin='$jk',jumlah_tanggungan=$tang,pendapatan_bulanan=$pend,pekerjaan='$kerja',kondisi_rumah='$kond',status_bantuan='$stat',rt_rw='$rtrw',kelurahan='$kel',kecamatan='$kec',no_telp='$telp',keterangan='$ket' WHERE id=$id");
|
||||
redir('data-warga.php','Data KPM diperbarui');
|
||||
break;
|
||||
|
||||
// ════════ UPDATE RADIUS ════════
|
||||
case 'update_radius':
|
||||
$id=$conn->real_escape_string($_POST['id']??0);
|
||||
$r =(int)($_POST['radius']??300);
|
||||
$conn->query("UPDATE rumah_ibadah SET radius_m=$r WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
// ════════ UPDATE KOORDINAT ════════
|
||||
case 'update_coords':
|
||||
$jenis=bersih($_POST['jenis']??'', $conn);
|
||||
$id =(int)($_POST['id']??0);
|
||||
$lat =(float)($_POST['lat']??0);
|
||||
$lng =(float)($_POST['lng']??0);
|
||||
$tbl =($jenis==='ibadah')?'rumah_ibadah':'rumah_miskin';
|
||||
$conn->query("UPDATE $tbl SET lat=$lat,lng=$lng WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
// ════════ UPDATE STATUS BANTUAN MASSAL ════════
|
||||
case 'update_status_bantuan':
|
||||
$updates=json_decode(file_get_contents('php://input'),true);
|
||||
if(!is_array($updates)){echo json_encode(['status'=>'error']);break;}
|
||||
foreach($updates as $item){
|
||||
$id=(int)$item['id'];
|
||||
$st=bersih($item['status'],$conn);
|
||||
$conn->query("UPDATE rumah_miskin SET status_bantuan='$st' WHERE id=$id");
|
||||
}
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
// ════════ HAPUS UMUM ════════
|
||||
case 'hapus':
|
||||
$jenis=bersih($_POST['jenis']??'',$conn);
|
||||
$id=(int)($_POST['id']??0);
|
||||
$tbl=($jenis==='ibadah')?'rumah_ibadah':'rumah_miskin';
|
||||
$conn->query("DELETE FROM $tbl WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
// ════════ SIMPAN BANTUAN ════════
|
||||
case 'simpan_bantuan':
|
||||
$wid =(int)($_POST['warga_id'] ??0);
|
||||
$iid =(int)($_POST['ibadah_id'] ??0) ?: 'NULL';
|
||||
$bid =(int)($_POST['bencana_id'] ??0) ?: 'NULL';
|
||||
$jenis= bersih($_POST['jenis_bantuan']??'',$conn);
|
||||
$jml = bersih($_POST['jumlah'] ??'',$conn);
|
||||
$tgl = bersih($_POST['tanggal'] ??date('Y-m-d'),$conn);
|
||||
$pet = bersih($_POST['petugas'] ??'',$conn);
|
||||
$ket = bersih($_POST['keterangan'] ??'',$conn);
|
||||
if(!$wid||!$jenis){redir('data-warga.php','Data tidak lengkap','error');break;}
|
||||
$conn->query("INSERT INTO bantuan_tersalur(warga_id,ibadah_id,bencana_id,jenis_bantuan,jumlah,tanggal,petugas,keterangan,disalurkan_oleh) VALUES($wid,$iid,$bid,'$jenis','$jml','$tgl','$pet','$ket',$uid)");
|
||||
$conn->query("UPDATE rumah_miskin SET status_bantuan='Sudah Menerima' WHERE id=$wid");
|
||||
redir('data-warga.php','Bantuan berhasil dicatat');
|
||||
break;
|
||||
|
||||
// ════════ BENCANA ════════
|
||||
case 'simpan_bencana':
|
||||
$nama = bersih($_POST['nama_bencana']??'',$conn);
|
||||
$jenis= bersih($_POST['jenis'] ??'Banjir',$conn);
|
||||
$tgl = bersih($_POST['tanggal'] ??date('Y-m-d'),$conn);
|
||||
$lok = bersih($_POST['lokasi'] ??'',$conn);
|
||||
$desk = bersih($_POST['deskripsi'] ??'',$conn);
|
||||
if(!$nama){redir('bencana.php','Nama bencana wajib diisi','error');break;}
|
||||
$conn->query("INSERT INTO bencana(nama_bencana,jenis,tanggal,lokasi,deskripsi,dibuat_oleh) VALUES('$nama','$jenis','$tgl','$lok','$desk',$uid)");
|
||||
redir('bencana.php','Bencana berhasil dicatat');
|
||||
break;
|
||||
|
||||
case 'update_status_bencana':
|
||||
$id=(int)($_POST['id']??0);
|
||||
$st=bersih($_POST['status']??'Aktif',$conn);
|
||||
$conn->query("UPDATE bencana SET status='$st' WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
case 'hapus_bencana':
|
||||
$id=(int)($_POST['id']??0);
|
||||
$conn->query("DELETE FROM bencana WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
// ════════ TERDAMPAK BENCANA ════════
|
||||
case 'tandai_terdampak':
|
||||
$bid =(int)($_POST['bencana_id']??0);
|
||||
$wid =(int)($_POST['warga_id'] ??0);
|
||||
$tkt = bersih($_POST['tingkat'] ??'Sedang',$conn);
|
||||
$ket = bersih($_POST['keterangan']??'',$conn);
|
||||
if(!$bid||!$wid){echo json_encode(['status'=>'error','message'=>'Data tidak lengkap']);break;}
|
||||
// Cek duplikat
|
||||
$cek=$conn->query("SELECT id FROM bencana_terdampak WHERE bencana_id=$bid AND warga_id=$wid");
|
||||
if($cek->num_rows>0){echo json_encode(['status'=>'error','message'=>'Warga sudah ditandai']);break;}
|
||||
$conn->query("INSERT INTO bencana_terdampak(bencana_id,warga_id,tingkat,keterangan,ditandai_oleh) VALUES($bid,$wid,'$tkt','$ket',$uid)");
|
||||
// Set prioritas
|
||||
$conn->query("UPDATE rumah_miskin SET prioritas=1 WHERE id=$wid");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
case 'hapus_terdampak':
|
||||
$id=(int)($_POST['id']??0);
|
||||
// Ambil warga_id sebelum hapus
|
||||
$r=$conn->query("SELECT warga_id FROM bencana_terdampak WHERE id=$id")->fetch_assoc();
|
||||
$conn->query("DELETE FROM bencana_terdampak WHERE id=$id");
|
||||
// Cek apakah masih ada bencana lain
|
||||
if($r){
|
||||
$wid=$r['warga_id'];
|
||||
$sisa=$conn->query("SELECT id FROM bencana_terdampak WHERE warga_id=$wid");
|
||||
if($sisa->num_rows===0) $conn->query("UPDATE rumah_miskin SET prioritas=0 WHERE id=$wid");
|
||||
}
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
case 'list_terdampak':
|
||||
$bid=(int)($_GET['bencana_id']??0);
|
||||
$list=[];
|
||||
$r=$conn->query("SELECT bt.*, rm.nama_kepala_keluarga FROM bencana_terdampak bt LEFT JOIN rumah_miskin rm ON bt.warga_id=rm.id WHERE bt.bencana_id=$bid ORDER BY bt.created_at DESC");
|
||||
while($row=$r->fetch_assoc()) $list[]=$row;
|
||||
echo json_encode(['status'=>'ok','data'=>$list]);
|
||||
break;
|
||||
|
||||
// ════════ USER MANAGEMENT (admin only) ════════
|
||||
case 'tambah_user':
|
||||
if($_SESSION['role']!=='admin'){echo json_encode(['status'=>'error']);break;}
|
||||
$nama = bersih($_POST['nama_lengkap']??'',$conn);
|
||||
$uname = bersih($_POST['username'] ??'',$conn);
|
||||
$email = bersih($_POST['email'] ??'',$conn);
|
||||
$role = bersih($_POST['role'] ??'relawan',$conn);
|
||||
$pw = $_POST['password']??'';
|
||||
$pw2 = $_POST['password2']??'';
|
||||
if(!$nama||!$uname||!$email||!$pw){redir('manajemen-user.php','Semua field wajib diisi','error');break;}
|
||||
if($pw!==$pw2){redir('manajemen-user.php','Password tidak cocok','error');break;}
|
||||
if(strlen($pw)<6){redir('manajemen-user.php','Password minimal 6 karakter','error');break;}
|
||||
$hash=password_hash($pw,PASSWORD_DEFAULT);
|
||||
// Cek duplikat
|
||||
$cek=$conn->query("SELECT id FROM users WHERE username='$uname' OR email='$email'");
|
||||
if($cek->num_rows>0){redir('manajemen-user.php','Username atau email sudah digunakan','error');break;}
|
||||
$conn->query("INSERT INTO users(nama_lengkap,username,email,password,role) VALUES('$nama','$uname','$email','$hash','$role')");
|
||||
redir('manajemen-user.php','User berhasil dibuat');
|
||||
break;
|
||||
|
||||
case 'edit_user':
|
||||
if($_SESSION['role']!=='admin'){echo json_encode(['status'=>'error']);break;}
|
||||
$id =(int)($_POST['id']??0);
|
||||
$nama = bersih($_POST['nama_lengkap']??'',$conn);
|
||||
$uname = bersih($_POST['username'] ??'',$conn);
|
||||
$email = bersih($_POST['email'] ??'',$conn);
|
||||
$role = bersih($_POST['role'] ??'relawan',$conn);
|
||||
$conn->query("UPDATE users SET nama_lengkap='$nama',username='$uname',email='$email',role='$role' WHERE id=$id");
|
||||
redir('manajemen-user.php','Data user diperbarui');
|
||||
break;
|
||||
|
||||
case 'reset_password':
|
||||
if($_SESSION['role']!=='admin'){break;}
|
||||
$id =(int)($_POST['id']??0);
|
||||
$pw =$_POST['password_baru']??'';
|
||||
$pw2 =$_POST['password_baru2']??'';
|
||||
if($pw!==$pw2){redir('manajemen-user.php','Password tidak cocok','error');break;}
|
||||
if(strlen($pw)<6){redir('manajemen-user.php','Password minimal 6 karakter','error');break;}
|
||||
$hash=password_hash($pw,PASSWORD_DEFAULT);
|
||||
$conn->query("UPDATE users SET password='$hash' WHERE id=$id");
|
||||
redir('manajemen-user.php','Password berhasil direset');
|
||||
break;
|
||||
|
||||
case 'toggle_aktif':
|
||||
if($_SESSION['role']!=='admin'){break;}
|
||||
$id=(int)($_POST['id']??0);
|
||||
$ak=(int)($_POST['aktif']??0);
|
||||
$conn->query("UPDATE users SET aktif=$ak WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
case 'hapus_user':
|
||||
if($_SESSION['role']!=='admin'){break;}
|
||||
$id=(int)($_POST['id']??0);
|
||||
if($id===$uid){echo json_encode(['status'=>'error','message'=>'Tidak bisa hapus akun sendiri']);break;}
|
||||
$conn->query("DELETE FROM users WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
|
||||
// ════════ KONFIRMASI BANTUAN (operator/relawan) ════════
|
||||
case 'konfirmasi_bantuan':
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$status = bersih($_POST['status'] ?? 'Menunggu', $conn);
|
||||
$nama_p = bersih($_POST['nama_penerima_konfirmasi'] ?? '', $conn);
|
||||
$catatan= bersih($_POST['catatan_konfirmasi'] ?? '', $conn);
|
||||
if (!$id) { echo json_encode(['status'=>'error','message'=>'ID tidak valid']); break; }
|
||||
$conn->query("UPDATE bantuan_tersalur SET
|
||||
status_konfirmasi='$status',
|
||||
nama_penerima_konfirmasi='$nama_p',
|
||||
catatan_konfirmasi='$catatan',
|
||||
dikonfirmasi_oleh=$uid,
|
||||
tgl_konfirmasi=NOW()
|
||||
WHERE id=$id");
|
||||
// Update status KPM jika dikonfirmasi
|
||||
if ($status === 'Dikonfirmasi') {
|
||||
$wid = $conn->query("SELECT warga_id FROM bantuan_tersalur WHERE id=$id")->fetch_assoc()['warga_id'] ?? 0;
|
||||
if ($wid) $conn->query("UPDATE rumah_miskin SET status_bantuan='Sudah Menerima' WHERE id=$wid");
|
||||
}
|
||||
redir('konfirmasi-bantuan.php?tab='.strtolower($status === 'Dikonfirmasi' ? 'dikonfirmasi' : 'ditolak'),
|
||||
$status === 'Dikonfirmasi' ? 'Bantuan berhasil dikonfirmasi' : 'Laporan berhasil dikirim');
|
||||
break;
|
||||
|
||||
// ════════ HAPUS BANTUAN ════════
|
||||
case 'hapus_bantuan':
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$conn->query("DELETE FROM bantuan_tersalur WHERE id=$id");
|
||||
echo json_encode(['status'=>'ok']);
|
||||
break;
|
||||
|
||||
default:
|
||||
echo json_encode(['status'=>'error','message'=>'Aksi tidak dikenal: '.$aksi]);
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
Reference in New Issue
Block a user