add files
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$action = $_GET['action'] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
case 'login':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') jsonErr('Method not allowed', 405);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$username = sanitize($b['username'] ?? '');
|
||||
$password = $b['password'] ?? '';
|
||||
if (!$username || !$password) jsonErr('Username dan password wajib diisi.');
|
||||
|
||||
$db = getDB();
|
||||
$st = $db->prepare("SELECT u.id,u.username,u.password,u.nama_lengkap,u.telepon,u.aktif,
|
||||
r.kode as role, r.nama as role_nama, u.rumah_ibadah_id,
|
||||
ri.nama as ri_nama
|
||||
FROM user u
|
||||
JOIN role r ON r.id = u.role_id
|
||||
LEFT JOIN rumah_ibadah ri ON ri.id = u.rumah_ibadah_id
|
||||
WHERE u.username = ?");
|
||||
$st->execute([$username]);
|
||||
$user = $st->fetch();
|
||||
|
||||
if (!$user) jsonErr('Username atau password salah.', 401);
|
||||
if (!$user['aktif']) jsonErr('Akun ini dinonaktifkan. Hubungi administrator.', 403);
|
||||
|
||||
$valid = password_verify($password, $user['password']) || $user['password'] === $password;
|
||||
if (!$valid) jsonErr('Username atau password salah.', 401);
|
||||
|
||||
startSession();
|
||||
$sess = [
|
||||
'id' => (int)$user['id'],
|
||||
'username' => $user['username'],
|
||||
'nama_lengkap'=> $user['nama_lengkap'],
|
||||
'role' => $user['role'],
|
||||
'role_nama' => $user['role_nama'],
|
||||
'ri_id' => $user['rumah_ibadah_id'] ? (int)$user['rumah_ibadah_id'] : null,
|
||||
'ri_nama' => $user['ri_nama'],
|
||||
];
|
||||
$_SESSION['user'] = $sess;
|
||||
log_aksi($sess['id'], 'LOGIN', 'user', $sess['id'], 'Login berhasil');
|
||||
jsonOk($sess, 'Selamat datang, '.$user['nama_lengkap'].'!');
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
$u = getCurrentUser();
|
||||
if ($u) log_aksi($u['id'], 'LOGOUT', 'user', $u['id'], 'Logout');
|
||||
startSession(); session_destroy();
|
||||
jsonOk(null, 'Logout berhasil.');
|
||||
break;
|
||||
|
||||
case 'check':
|
||||
$u = getCurrentUser();
|
||||
if ($u) jsonOk($u);
|
||||
else jsonErr('Tidak ada sesi aktif.', 401);
|
||||
break;
|
||||
|
||||
default:
|
||||
jsonErr('Action tidak dikenali.', 404);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$action = $_GET['action'] ?? '';
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
// ── HISTORI BANTUAN ──
|
||||
if ($action === 'histori') {
|
||||
if ($method === 'GET') {
|
||||
$pid = (int)($_GET['penduduk_id'] ?? 0);
|
||||
if (!$pid) jsonErr('penduduk_id wajib.');
|
||||
$st = $db->prepare("SELECT hb.*, b.nama as bantuan_nama, b.jenis, b.satuan, b.sumber,
|
||||
u.nama_lengkap as disalurkan_nama
|
||||
FROM histori_bantuan hb
|
||||
JOIN bantuan b ON b.id=hb.bantuan_id
|
||||
LEFT JOIN user u ON u.id=hb.disalurkan_oleh
|
||||
WHERE hb.penduduk_id=? ORDER BY hb.tanggal DESC");
|
||||
$st->execute([$pid]);
|
||||
jsonOk($st->fetchAll());
|
||||
}
|
||||
if ($method === 'POST') {
|
||||
requireRole(['superadmin','pengurus']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$pid = (int)($b['penduduk_id'] ?? 0);
|
||||
$bid = (int)($b['bantuan_id'] ?? 0);
|
||||
if (!$pid || !$bid) jsonErr('penduduk_id dan bantuan_id wajib.');
|
||||
$db->prepare("INSERT INTO histori_bantuan (penduduk_id,bantuan_id,disalurkan_oleh,tanggal,jumlah,status,catatan) VALUES (?,?,?,?,?,?,?)")
|
||||
->execute([$pid,$bid,$user['id'],$b['tanggal']??date('Y-m-d'),(float)($b['jumlah']??1),$b['status']??'disalurkan',sanitize($b['catatan']??'')]);
|
||||
$newId=(int)$db->lastInsertId();
|
||||
log_aksi($user['id'],'CREATE','histori_bantuan',$newId,"Catat bantuan penduduk_id:$pid bantuan_id:$bid");
|
||||
jsonOk(['id'=>$newId],'Histori bantuan dicatat.');
|
||||
}
|
||||
if ($method === 'PUT') {
|
||||
requireRole(['superadmin','pengurus']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("UPDATE histori_bantuan SET status=?,catatan=? WHERE id=?")
|
||||
->execute([$b['status']??'disalurkan',sanitize($b['catatan']??''),$id]);
|
||||
jsonOk(null,'Status bantuan diperbarui.');
|
||||
}
|
||||
jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
|
||||
// ── PRIORITAS OTOMATIS ──
|
||||
if ($action === 'prioritas') {
|
||||
$st = $db->query("
|
||||
SELECT p.id, p.nik, p.nama, p.umur, p.profil_umur, p.kondisi_kesehatan,
|
||||
p.status_ekonomi, p.penghasilan, p.status_perkawinan,
|
||||
k.alamat, k.kelurahan, k.lat, k.lng,
|
||||
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') as total_bantuan,
|
||||
CASE
|
||||
WHEN p.status_ekonomi='miskin' AND p.kondisi_kesehatan IN ('sakit_berat','disabilitas') THEN 'SANGAT TINGGI'
|
||||
WHEN p.profil_umur='Lansia' AND p.status_perkawinan IN ('cerai_mati','cerai_hidup') THEN 'SANGAT TINGGI'
|
||||
WHEN p.status_ekonomi='miskin' AND p.kondisi_kesehatan='sakit_ringan' THEN 'TINGGI'
|
||||
WHEN p.status_ekonomi='miskin' AND p.profil_umur='Lansia' THEN 'TINGGI'
|
||||
WHEN p.status_ekonomi='miskin' THEN 'SEDANG'
|
||||
WHEN p.status_ekonomi='rentan' AND p.kondisi_kesehatan != 'sehat' THEN 'SEDANG'
|
||||
ELSE 'RENDAH'
|
||||
END as prioritas
|
||||
FROM v_penduduk p
|
||||
JOIN keluarga k ON k.id=p.keluarga_id
|
||||
WHERE p.status_hidup='hidup'
|
||||
ORDER BY FIELD(prioritas,'SANGAT TINGGI','TINGGI','SEDANG','RENDAH'), total_bantuan ASC
|
||||
LIMIT 100
|
||||
");
|
||||
jsonOk($st->fetchAll());
|
||||
}
|
||||
|
||||
// ── BELUM TERIMA BANTUAN ──
|
||||
if ($action === 'belum_terima') {
|
||||
$st = $db->query("
|
||||
SELECT p.id, p.nik, p.nama, p.umur, p.profil_umur, p.status_ekonomi,
|
||||
p.kondisi_kesehatan, k.kelurahan, k.alamat, k.lat, k.lng
|
||||
FROM v_penduduk p
|
||||
JOIN keluarga k ON k.id=p.keluarga_id
|
||||
WHERE p.status_hidup='hidup'
|
||||
AND p.status_ekonomi IN ('miskin','rentan')
|
||||
AND p.id NOT IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')
|
||||
ORDER BY p.status_ekonomi DESC, p.umur DESC
|
||||
");
|
||||
jsonOk($st->fetchAll());
|
||||
}
|
||||
|
||||
// ── CRUD MASTER BANTUAN ──
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT * FROM bantuan WHERE id=?"); $st->execute([$id]);
|
||||
jsonOk($st->fetch());
|
||||
}
|
||||
jsonOk($db->query("SELECT * FROM bantuan ORDER BY nama")->fetchAll());
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireRole(['superadmin','pengurus']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("INSERT INTO bantuan (nama,jenis,sumber,satuan,nilai_per_satuan,periode) VALUES (?,?,?,?,?,?)")
|
||||
->execute([sanitize($b['nama']??''),$b['jenis']??'lainnya',sanitize($b['sumber']??''),sanitize($b['satuan']??''),(float)($b['nilai_per_satuan']??0),$b['periode']??'sekali']);
|
||||
jsonOk(['id'=>(int)$db->lastInsertId()],'Bantuan ditambahkan.');
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireRole(['superadmin','pengurus']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("UPDATE bantuan SET nama=?,jenis=?,sumber=?,satuan=?,nilai_per_satuan=?,periode=?,aktif=? WHERE id=?")
|
||||
->execute([sanitize($b['nama']??''),$b['jenis']??'lainnya',sanitize($b['sumber']??''),sanitize($b['satuan']??''),(float)($b['nilai_per_satuan']??0),$b['periode']??'sekali',(int)($b['aktif']??1),$id]);
|
||||
jsonOk(null,'Bantuan diperbarui.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$since = $_GET['since'] ?? '1970-01-01 00:00:00';
|
||||
// ambil pesan broadcast + pesan ke/dari user ini
|
||||
$st = $db->prepare("SELECT c.id, c.pesan, c.created_at, c.dibaca,
|
||||
u.nama_lengkap as dari_nama, u.id as dari_id,
|
||||
r.kode as dari_role, u.rumah_ibadah_id,
|
||||
ri.nama as dari_ri,
|
||||
c.ke_user_id
|
||||
FROM chat c
|
||||
JOIN user u ON u.id=c.dari_user_id
|
||||
JOIN role r ON r.id=u.role_id
|
||||
LEFT JOIN rumah_ibadah ri ON ri.id=u.rumah_ibadah_id
|
||||
WHERE (c.ke_user_id IS NULL OR c.ke_user_id=? OR c.dari_user_id=?)
|
||||
AND c.created_at > ?
|
||||
ORDER BY c.created_at ASC LIMIT 100");
|
||||
$st->execute([$user['id'], $user['id'], $since]);
|
||||
$msgs = $st->fetchAll();
|
||||
|
||||
// tandai sudah dibaca
|
||||
$db->prepare("UPDATE chat SET dibaca=1 WHERE ke_user_id=? AND dibaca=0")->execute([$user['id']]);
|
||||
jsonOk($msgs);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
// hanya pengurus, relawan, superadmin
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$pesan = sanitize($b['pesan'] ?? '');
|
||||
if (!$pesan) jsonErr('Pesan tidak boleh kosong.');
|
||||
$ke = !empty($b['ke_user_id']) ? (int)$b['ke_user_id'] : null;
|
||||
|
||||
$db->prepare("INSERT INTO chat (dari_user_id, ke_user_id, pesan) VALUES (?,?,?)")
|
||||
->execute([$user['id'], $ke, $pesan]);
|
||||
$newId = (int)$db->lastInsertId();
|
||||
|
||||
// ambil pesan lengkap untuk response
|
||||
$st = $db->prepare("SELECT c.id, c.pesan, c.created_at, u.nama_lengkap as dari_nama,
|
||||
r.kode as dari_role, ri.nama as dari_ri, c.ke_user_id
|
||||
FROM chat c JOIN user u ON u.id=c.dari_user_id
|
||||
JOIN role r ON r.id=u.role_id
|
||||
LEFT JOIN rumah_ibadah ri ON ri.id=u.rumah_ibadah_id
|
||||
WHERE c.id=?");
|
||||
$st->execute([$newId]);
|
||||
jsonOk($st->fetch(), 'Pesan terkirim.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT k.*, ri.nama as ri_nama, ri.jenis as ri_jenis
|
||||
FROM keluarga k LEFT JOIN rumah_ibadah ri ON ri.id=k.rumah_ibadah_id
|
||||
WHERE k.id=?");
|
||||
$st->execute([$id]);
|
||||
$row = $st->fetch();
|
||||
if (!$row) jsonErr('Tidak ditemukan.', 404);
|
||||
|
||||
// anggota keluarga
|
||||
$an = $db->prepare("SELECT id,nik,nama,jenis_kelamin,umur,profil_umur,
|
||||
status_keluarga,status_perkawinan,status_ekonomi,
|
||||
kondisi_kesehatan,pekerjaan,penghasilan,
|
||||
status_pendidikan,pendidikan_terakhir
|
||||
FROM penduduk WHERE keluarga_id=? AND status_hidup='hidup' ORDER BY
|
||||
FIELD(status_keluarga,'kepala','istri','anak','orang_tua','lainnya')");
|
||||
$an->execute([$id]);
|
||||
$row['anggota'] = $an->fetchAll();
|
||||
jsonOk($row);
|
||||
break;
|
||||
}
|
||||
|
||||
$where = []; $params = [];
|
||||
if (!empty($_GET['status_ekonomi'])) { $where[] = "k.status_ekonomi=?"; $params[] = $_GET['status_ekonomi']; }
|
||||
if (!empty($_GET['kelurahan'])) { $where[] = "k.kelurahan=?"; $params[] = $_GET['kelurahan']; }
|
||||
if (!empty($_GET['rumah_ibadah_id'])) { $where[] = "k.rumah_ibadah_id=?"; $params[] = (int)$_GET['rumah_ibadah_id']; }
|
||||
if (!empty($_GET['q'])) { $where[] = "(k.nama_kk LIKE ? OR k.no_kk LIKE ?)"; $params[] = '%'.$_GET['q'].'%'; $params[] = '%'.$_GET['q'].'%'; }
|
||||
|
||||
$wStr = $where ? 'WHERE '.implode(' AND ',$where) : '';
|
||||
$st = $db->prepare("SELECT k.id, k.no_kk, k.nama_kk, k.alamat, k.rt, k.rw,
|
||||
k.kelurahan, k.kecamatan, k.lat, k.lng, k.status_ekonomi,
|
||||
ri.nama as ri_nama,
|
||||
(SELECT COUNT(*) FROM penduduk p WHERE p.keluarga_id=k.id AND p.status_hidup='hidup') as jumlah_jiwa,
|
||||
(SELECT COUNT(*) FROM histori_bantuan hb JOIN penduduk p ON p.id=hb.penduduk_id WHERE p.keluarga_id=k.id AND hb.status='disalurkan') as total_bantuan_diterima
|
||||
FROM keluarga k LEFT JOIN rumah_ibadah ri ON ri.id=k.rumah_ibadah_id
|
||||
$wStr ORDER BY k.nama_kk ASC LIMIT 500");
|
||||
$st->execute($params);
|
||||
jsonOk($st->fetchAll());
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$no_kk = sanitize($b['no_kk'] ?? '');
|
||||
$nama_kk = sanitize($b['nama_kk'] ?? '');
|
||||
if (!$no_kk || !$nama_kk) jsonErr('No KK dan nama KK wajib diisi.');
|
||||
if (strlen($no_kk) !== 16) jsonErr('No KK harus 16 digit.');
|
||||
|
||||
$chk = $db->prepare("SELECT id FROM keluarga WHERE no_kk=?"); $chk->execute([$no_kk]);
|
||||
if ($chk->fetch()) jsonErr('No KK sudah terdaftar.');
|
||||
|
||||
$db->prepare("INSERT INTO keluarga (no_kk,nama_kk,alamat,rt,rw,kelurahan,kecamatan,lat,lng,rumah_ibadah_id,status_ekonomi,created_by)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
->execute([
|
||||
$no_kk, $nama_kk,
|
||||
sanitize($b['alamat'] ?? ''),
|
||||
sanitize($b['rt'] ?? ''), sanitize($b['rw'] ?? ''),
|
||||
sanitize($b['kelurahan'] ?? ''), sanitize($b['kecamatan'] ?? ''),
|
||||
isset($b['lat']) ? (float)$b['lat'] : null,
|
||||
isset($b['lng']) ? (float)$b['lng'] : null,
|
||||
!empty($b['rumah_ibadah_id']) ? (int)$b['rumah_ibadah_id'] : null,
|
||||
$b['status_ekonomi'] ?? 'rentan',
|
||||
$user['id']
|
||||
]);
|
||||
$newId = (int)$db->lastInsertId();
|
||||
log_aksi($user['id'], 'CREATE', 'keluarga', $newId, "Tambah KK: $nama_kk");
|
||||
jsonOk(['id'=>$newId], 'Keluarga berhasil ditambahkan.');
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("UPDATE keluarga SET nama_kk=?,alamat=?,rt=?,rw=?,kelurahan=?,kecamatan=?,
|
||||
lat=?,lng=?,rumah_ibadah_id=?,status_ekonomi=?,updated_at=NOW() WHERE id=?")
|
||||
->execute([
|
||||
sanitize($b['nama_kk'] ?? ''), sanitize($b['alamat'] ?? ''),
|
||||
sanitize($b['rt'] ?? ''), sanitize($b['rw'] ?? ''),
|
||||
sanitize($b['kelurahan'] ?? ''), sanitize($b['kecamatan'] ?? ''),
|
||||
isset($b['lat']) ? (float)$b['lat'] : null,
|
||||
isset($b['lng']) ? (float)$b['lng'] : null,
|
||||
!empty($b['rumah_ibadah_id']) ? (int)$b['rumah_ibadah_id'] : null,
|
||||
$b['status_ekonomi'] ?? 'rentan',
|
||||
$id
|
||||
]);
|
||||
log_aksi($user['id'], 'UPDATE', 'keluarga', $id, "Edit KK ID: $id");
|
||||
jsonOk(null, 'Data keluarga diperbarui.');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireRole(['superadmin']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$db->prepare("DELETE FROM keluarga WHERE id=?")->execute([$id]);
|
||||
log_aksi($user['id'], 'DELETE', 'keluarga', $id, "Hapus KK ID: $id");
|
||||
jsonOk(null, 'Data keluarga dihapus.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT l.*, p.nama as penduduk_nama, u.nama_lengkap as verifikator
|
||||
FROM laporan l
|
||||
LEFT JOIN penduduk p ON p.id=l.penduduk_id
|
||||
LEFT JOIN user u ON u.id=l.diverifikasi_oleh
|
||||
WHERE l.id=?");
|
||||
$st->execute([$id]); jsonOk($st->fetch()); break;
|
||||
}
|
||||
$where=[]; $params=[];
|
||||
if (!empty($_GET['status'])) { $where[]="l.status=?"; $params[]=$_GET['status']; }
|
||||
if (!empty($_GET['urgensi'])) { $where[]="l.urgensi=?"; $params[]=$_GET['urgensi']; }
|
||||
$w = $where ? 'WHERE '.implode(' AND ',$where) : '';
|
||||
$st = $db->prepare("SELECT l.id, l.pelapor_nama, l.deskripsi, l.lat, l.lng,
|
||||
l.alamat_laporan, l.urgensi, l.status, l.foto,
|
||||
l.created_at, p.nama as penduduk_nama
|
||||
FROM laporan l LEFT JOIN penduduk p ON p.id=l.penduduk_id
|
||||
$w ORDER BY FIELD(l.urgensi,'darurat','tinggi','sedang','rendah'), l.created_at DESC");
|
||||
$st->execute($params); jsonOk($st->fetchAll()); break;
|
||||
|
||||
case 'POST':
|
||||
// masyarakat umum pun bisa lapor (tidak perlu login)
|
||||
$pelapor = sanitize($_POST['pelapor_nama'] ?? '');
|
||||
$telp = sanitize($_POST['pelapor_telepon']?? '');
|
||||
$deskripsi = sanitize($_POST['deskripsi'] ?? '');
|
||||
$alamat = sanitize($_POST['alamat_laporan'] ?? '');
|
||||
$lat = isset($_POST['lat']) ? (float)$_POST['lat'] : null;
|
||||
$lng = isset($_POST['lng']) ? (float)$_POST['lng'] : null;
|
||||
$urgensi = $_POST['urgensi'] ?? 'sedang';
|
||||
$pid = !empty($_POST['penduduk_id']) ? (int)$_POST['penduduk_id'] : null;
|
||||
|
||||
if (!$deskripsi) jsonErr('Deskripsi laporan wajib diisi.');
|
||||
|
||||
// Upload foto
|
||||
$fotoPath = null;
|
||||
if (!empty($_FILES['foto']['tmp_name'])) {
|
||||
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
|
||||
if (!in_array($ext, ['jpg','jpeg','png','webp'])) jsonErr('Format foto harus JPG/PNG/WebP.');
|
||||
if ($_FILES['foto']['size'] > 5 * 1024 * 1024) jsonErr('Ukuran foto maks 5MB.');
|
||||
$fname = 'laporan_' . time() . '_' . rand(1000,9999) . '.' . $ext;
|
||||
move_uploaded_file($_FILES['foto']['tmp_name'], UPLOAD_DIR . $fname);
|
||||
$fotoPath = 'uploads/' . $fname;
|
||||
}
|
||||
|
||||
$db->prepare("INSERT INTO laporan (pelapor_nama,pelapor_telepon,penduduk_id,deskripsi,lat,lng,alamat_laporan,foto,urgensi) VALUES (?,?,?,?,?,?,?,?,?)")
|
||||
->execute([$pelapor,$telp,$pid,$deskripsi,$lat,$lng,$alamat,$fotoPath,$urgensi]);
|
||||
$newId = (int)$db->lastInsertId();
|
||||
$u = getCurrentUser();
|
||||
if ($u) log_aksi($u['id'],'CREATE','laporan',$newId,"Laporan baru: $urgensi");
|
||||
jsonOk(['id'=>$newId],'Laporan berhasil dikirim. Terima kasih!'); break;
|
||||
|
||||
case 'PUT':
|
||||
$u = requireLogin();
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$chk=$db->prepare("SELECT id FROM laporan WHERE id=?"); $chk->execute([$id]);
|
||||
if (!$chk->fetch()) jsonErr('Laporan tidak ditemukan.',404);
|
||||
|
||||
$db->prepare("UPDATE laporan SET status=?,catatan_admin=?,diverifikasi_oleh=?,updated_at=NOW() WHERE id=?")
|
||||
->execute([$b['status']??'pending',sanitize($b['catatan_admin']??''),$u['id'],$id]);
|
||||
log_aksi($u['id'],'UPDATE','laporan',$id,"Update status: ".($b['status']??''));
|
||||
jsonOk(null,'Status laporan diperbarui.'); break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.',405);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// api/log.php — Log Aktivitas
|
||||
require_once __DIR__ . '/../config.php';
|
||||
requireRole(['superadmin', 'pimpinan']);
|
||||
$db = getDB();
|
||||
|
||||
$limit = min((int)($_GET['limit'] ?? 100), 500);
|
||||
$offset = (int)($_GET['offset'] ?? 0);
|
||||
$tabel = $_GET['tabel'] ?? '';
|
||||
$uid = (int)($_GET['user_id'] ?? 0);
|
||||
|
||||
$where = []; $params = [];
|
||||
if ($tabel) { $where[] = "l.tabel=?"; $params[] = $tabel; }
|
||||
if ($uid) { $where[] = "l.user_id=?"; $params[] = $uid; }
|
||||
$w = $where ? 'WHERE '.implode(' AND ',$where) : '';
|
||||
|
||||
$st = getDB()->prepare("SELECT l.id, l.aksi, l.tabel, l.record_id, l.keterangan, l.ip_address, l.created_at,
|
||||
u.username, u.nama_lengkap, r.kode as role
|
||||
FROM log_aktivitas l
|
||||
LEFT JOIN user u ON u.id=l.user_id
|
||||
LEFT JOIN role r ON r.id=u.role_id
|
||||
$w ORDER BY l.created_at DESC LIMIT ? OFFSET ?");
|
||||
$params[] = $limit; $params[] = $offset;
|
||||
$st->execute($params);
|
||||
|
||||
$total = (int)getDB()->query("SELECT COUNT(*) FROM log_aktivitas $w")->fetchColumn();
|
||||
jsonOk(['rows' => $st->fetchAll(), 'total' => $total, 'limit' => $limit, 'offset' => $offset]);
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
// api/pelatihan.php — Manajemen Pelatihan & Riwayat
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$action = $_GET['action'] ?? '';
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
// ── RIWAYAT PELATIHAN PER PENDUDUK ──
|
||||
if ($action === 'riwayat') {
|
||||
$pid = (int)($_GET['penduduk_id'] ?? 0);
|
||||
if (!$pid) jsonErr('penduduk_id wajib.');
|
||||
$st = $db->prepare("SELECT rp.*, p.nama_pelatihan, p.penyelenggara, p.tanggal as tgl_pelatihan
|
||||
FROM riwayat_pelatihan rp
|
||||
JOIN pelatihan p ON p.id=rp.pelatihan_id
|
||||
WHERE rp.penduduk_id=? ORDER BY rp.tanggal_ikut DESC");
|
||||
$st->execute([$pid]);
|
||||
jsonOk($st->fetchAll());
|
||||
}
|
||||
|
||||
// ── DAFTARKAN PESERTA ──
|
||||
if ($action === 'daftar' && $method === 'POST') {
|
||||
requireRole(['superadmin', 'pengurus', 'relawan']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$pid = (int)($b['penduduk_id'] ?? 0);
|
||||
$tid = (int)($b['pelatihan_id'] ?? 0);
|
||||
if (!$pid || !$tid) jsonErr('penduduk_id dan pelatihan_id wajib.');
|
||||
|
||||
// validasi: cek umur >= 18 untuk pelatihan kerja
|
||||
$p = $db->prepare("SELECT umur FROM penduduk WHERE id=?"); $p->execute([$pid]);
|
||||
$row = $p->fetch();
|
||||
if ($row && (int)$row['umur'] < 15) jsonErr('Peserta minimal berusia 15 tahun untuk mengikuti pelatihan.');
|
||||
|
||||
$db->prepare("INSERT INTO riwayat_pelatihan (penduduk_id, pelatihan_id, tanggal_ikut) VALUES (?,?,?)")
|
||||
->execute([$pid, $tid, $b['tanggal_ikut'] ?? date('Y-m-d')]);
|
||||
log_aksi($user['id'], 'CREATE', 'riwayat_pelatihan', (int)$db->lastInsertId(), "Daftar pelatihan pid:$pid tid:$tid");
|
||||
jsonOk(null, 'Peserta berhasil didaftarkan ke pelatihan.');
|
||||
}
|
||||
|
||||
// ── CRUD MASTER PELATIHAN ──
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT p.*, COUNT(rp.id) as jumlah_peserta FROM pelatihan p
|
||||
LEFT JOIN riwayat_pelatihan rp ON rp.pelatihan_id=p.id WHERE p.id=? GROUP BY p.id");
|
||||
$st->execute([$id]);
|
||||
$row = $st->fetch();
|
||||
if (!$row) jsonErr('Tidak ditemukan.', 404);
|
||||
// peserta
|
||||
$ps = $db->prepare("SELECT rp.id, rp.tanggal_ikut, pd.nama, pd.nik, pd.umur
|
||||
FROM riwayat_pelatihan rp JOIN v_penduduk pd ON pd.id=rp.penduduk_id
|
||||
WHERE rp.pelatihan_id=? ORDER BY rp.tanggal_ikut DESC");
|
||||
$ps->execute([$id]);
|
||||
$row['peserta'] = $ps->fetchAll();
|
||||
jsonOk($row);
|
||||
break;
|
||||
}
|
||||
$rows = $db->query("SELECT p.*, COUNT(rp.id) as jumlah_peserta
|
||||
FROM pelatihan p LEFT JOIN riwayat_pelatihan rp ON rp.pelatihan_id=p.id
|
||||
GROUP BY p.id ORDER BY p.tanggal DESC")->fetchAll();
|
||||
jsonOk($rows);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireRole(['superadmin', 'pengurus']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$nama = sanitize($b['nama_pelatihan'] ?? '');
|
||||
if (!$nama) jsonErr('Nama pelatihan wajib diisi.');
|
||||
$db->prepare("INSERT INTO pelatihan (nama_pelatihan, penyelenggara, tanggal, durasi_hari, deskripsi) VALUES (?,?,?,?,?)")
|
||||
->execute([$nama, sanitize($b['penyelenggara'] ?? ''), $b['tanggal'] ?? null,
|
||||
(int)($b['durasi_hari'] ?? 1), sanitize($b['deskripsi'] ?? '')]);
|
||||
jsonOk(['id' => (int)$db->lastInsertId()], 'Pelatihan ditambahkan.');
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireRole(['superadmin', 'pengurus']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("UPDATE pelatihan SET nama_pelatihan=?, penyelenggara=?, tanggal=?, durasi_hari=?, deskripsi=? WHERE id=?")
|
||||
->execute([sanitize($b['nama_pelatihan'] ?? ''), sanitize($b['penyelenggara'] ?? ''),
|
||||
$b['tanggal'] ?? null, (int)($b['durasi_hari'] ?? 1),
|
||||
sanitize($b['deskripsi'] ?? ''), $id]);
|
||||
jsonOk(null, 'Pelatihan diperbarui.');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireRole(['superadmin']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$db->prepare("DELETE FROM pelatihan WHERE id=?")->execute([$id]);
|
||||
jsonOk(null, 'Pelatihan dihapus.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
// ── GET LIST / SINGLE ──
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
// single dengan histori bantuan & riwayat pelatihan
|
||||
$st = $db->prepare("SELECT p.*, k.no_kk, k.alamat as alamat_kk, k.rt, k.rw,
|
||||
k.kelurahan, k.kecamatan, k.rumah_ibadah_id
|
||||
FROM v_penduduk p
|
||||
JOIN keluarga k ON k.id = p.keluarga_id
|
||||
WHERE p.id = ?");
|
||||
$st->execute([$id]);
|
||||
$row = $st->fetch();
|
||||
if (!$row) jsonErr('Data tidak ditemukan.', 404);
|
||||
|
||||
// histori bantuan
|
||||
$hb = $db->prepare("SELECT hb.*, b.nama as bantuan_nama, b.jenis, b.satuan,
|
||||
u.nama_lengkap as disalurkan_nama
|
||||
FROM histori_bantuan hb
|
||||
JOIN bantuan b ON b.id = hb.bantuan_id
|
||||
LEFT JOIN user u ON u.id = hb.disalurkan_oleh
|
||||
WHERE hb.penduduk_id = ? ORDER BY hb.tanggal DESC");
|
||||
$hb->execute([$id]);
|
||||
$row['histori_bantuan'] = $hb->fetchAll();
|
||||
|
||||
// pelatihan
|
||||
$plt = $db->prepare("SELECT rp.*, p.nama_pelatihan, p.penyelenggara
|
||||
FROM riwayat_pelatihan rp
|
||||
JOIN pelatihan p ON p.id = rp.pelatihan_id
|
||||
WHERE rp.penduduk_id = ?");
|
||||
$plt->execute([$id]);
|
||||
$row['riwayat_pelatihan'] = $plt->fetchAll();
|
||||
|
||||
// validasi pendidikan
|
||||
$warn = validasiPendidikan((int)$row['umur'], $row['pendidikan_terakhir'], $row['status_pendidikan']);
|
||||
$row['peringatan_pendidikan'] = $warn;
|
||||
|
||||
jsonOk($row);
|
||||
}
|
||||
|
||||
// list dengan filter
|
||||
$where = ["p.status_hidup = 'hidup'"]; $params = [];
|
||||
if (!empty($_GET['status_ekonomi'])) { $where[] = "p.status_ekonomi = ?"; $params[] = $_GET['status_ekonomi']; }
|
||||
if (!empty($_GET['keluarga_id'])) { $where[] = "p.keluarga_id = ?"; $params[] = (int)$_GET['keluarga_id']; }
|
||||
if (!empty($_GET['kelurahan'])) { $where[] = "k.kelurahan = ?"; $params[] = $_GET['kelurahan']; }
|
||||
if (!empty($_GET['q'])) { $where[] = "(p.nama LIKE ? OR p.nik LIKE ?)"; $params[] = '%'.$_GET['q'].'%'; $params[] = '%'.$_GET['q'].'%'; }
|
||||
|
||||
$wStr = implode(' AND ', $where);
|
||||
$st = $db->prepare("SELECT p.id, p.nik, p.nama, p.jenis_kelamin, p.tanggal_lahir, p.umur,
|
||||
p.profil_umur, p.status_keluarga, p.status_perkawinan,
|
||||
p.status_ekonomi, p.kondisi_kesehatan, p.pekerjaan,
|
||||
p.penghasilan, p.lat, p.lng, p.keluarga_id,
|
||||
k.no_kk, k.kelurahan, k.alamat as alamat_kk,
|
||||
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') as total_bantuan
|
||||
FROM v_penduduk p JOIN keluarga k ON k.id=p.keluarga_id
|
||||
WHERE $wStr ORDER BY p.nama ASC LIMIT 500");
|
||||
$st->execute($params);
|
||||
jsonOk($st->fetchAll());
|
||||
break;
|
||||
|
||||
// ── POST: Tambah ──
|
||||
case 'POST':
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$nik = sanitize($b['nik'] ?? '');
|
||||
$nama = sanitize($b['nama'] ?? '');
|
||||
$tgl = $b['tanggal_lahir'] ?? '';
|
||||
$kjId = (int)($b['keluarga_id'] ?? 0);
|
||||
|
||||
if (!$nik || strlen($nik) !== 16) jsonErr('NIK harus 16 digit.');
|
||||
if (!$nama) jsonErr('Nama wajib diisi.');
|
||||
if (!$tgl) jsonErr('Tanggal lahir wajib diisi.');
|
||||
if (!$kjId) jsonErr('Keluarga (KK) wajib dipilih.');
|
||||
|
||||
// cek NIK unik
|
||||
$chk = $db->prepare("SELECT id FROM penduduk WHERE nik=?"); $chk->execute([$nik]);
|
||||
if ($chk->fetch()) jsonErr('NIK sudah terdaftar di sistem.');
|
||||
|
||||
$umur = hitungUmur($tgl);
|
||||
$pendid = $b['pendidikan_terakhir'] ?? 'tidak_sekolah';
|
||||
$stPend = $b['status_pendidikan'] ?? 'tidak_sekolah';
|
||||
|
||||
$db->prepare("INSERT INTO penduduk
|
||||
(nik,nama,jenis_kelamin,tanggal_lahir,status_keluarga,status_perkawinan,status_hidup,
|
||||
keluarga_id,pendidikan_terakhir,status_pendidikan,pekerjaan,penghasilan,
|
||||
status_ekonomi,kondisi_kesehatan,lat,lng,catatan,created_by)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
|
||||
->execute([
|
||||
$nik, $nama,
|
||||
$b['jenis_kelamin'] ?? 'L',
|
||||
$tgl,
|
||||
$b['status_keluarga'] ?? 'anggota',
|
||||
$b['status_perkawinan'] ?? 'belum_kawin',
|
||||
$b['status_hidup'] ?? 'hidup',
|
||||
$kjId, $pendid, $stPend,
|
||||
sanitize($b['pekerjaan'] ?? ''),
|
||||
(float)($b['penghasilan'] ?? 0),
|
||||
$b['status_ekonomi'] ?? 'rentan',
|
||||
$b['kondisi_kesehatan'] ?? 'sehat',
|
||||
isset($b['lat']) ? (float)$b['lat'] : null,
|
||||
isset($b['lng']) ? (float)$b['lng'] : null,
|
||||
sanitize($b['catatan'] ?? ''),
|
||||
$user['id']
|
||||
]);
|
||||
$newId = (int)$db->lastInsertId();
|
||||
log_aksi($user['id'], 'CREATE', 'penduduk', $newId, "Tambah: $nama (NIK: $nik)");
|
||||
|
||||
$warn = validasiPendidikan($umur, $pendid, $stPend);
|
||||
jsonOk(['id'=>$newId,'peringatan'=>$warn], 'Penduduk berhasil ditambahkan.');
|
||||
break;
|
||||
|
||||
// ── PUT: Edit ──
|
||||
case 'PUT':
|
||||
requireRole(['superadmin','pengurus','relawan']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$chk = $db->prepare("SELECT id,nik FROM penduduk WHERE id=?"); $chk->execute([$id]);
|
||||
if (!$chk->fetch()) jsonErr('Data tidak ditemukan.', 404);
|
||||
|
||||
$tgl = $b['tanggal_lahir'] ?? '';
|
||||
$umur = $tgl ? hitungUmur($tgl) : 0;
|
||||
$pendid = $b['pendidikan_terakhir'] ?? 'tidak_sekolah';
|
||||
$stPend = $b['status_pendidikan'] ?? 'tidak_sekolah';
|
||||
|
||||
$db->prepare("UPDATE penduduk SET
|
||||
nama=?,jenis_kelamin=?,tanggal_lahir=?,status_keluarga=?,status_perkawinan=?,
|
||||
status_hidup=?,keluarga_id=?,pendidikan_terakhir=?,status_pendidikan=?,
|
||||
pekerjaan=?,penghasilan=?,status_ekonomi=?,kondisi_kesehatan=?,
|
||||
lat=?,lng=?,catatan=?,updated_at=NOW() WHERE id=?")
|
||||
->execute([
|
||||
sanitize($b['nama'] ?? ''),
|
||||
$b['jenis_kelamin'] ?? 'L',
|
||||
$tgl,
|
||||
$b['status_keluarga'] ?? 'anggota',
|
||||
$b['status_perkawinan'] ?? 'belum_kawin',
|
||||
$b['status_hidup'] ?? 'hidup',
|
||||
(int)($b['keluarga_id'] ?? 0),
|
||||
$pendid, $stPend,
|
||||
sanitize($b['pekerjaan'] ?? ''),
|
||||
(float)($b['penghasilan'] ?? 0),
|
||||
$b['status_ekonomi'] ?? 'rentan',
|
||||
$b['kondisi_kesehatan'] ?? 'sehat',
|
||||
isset($b['lat']) ? (float)$b['lat'] : null,
|
||||
isset($b['lng']) ? (float)$b['lng'] : null,
|
||||
sanitize($b['catatan'] ?? ''),
|
||||
$id
|
||||
]);
|
||||
log_aksi($user['id'], 'UPDATE', 'penduduk', $id, "Edit ID: $id");
|
||||
$warn = validasiPendidikan($umur, $pendid, $stPend);
|
||||
jsonOk(['peringatan'=>$warn], 'Data berhasil diperbarui.');
|
||||
break;
|
||||
|
||||
// ── DELETE ──
|
||||
case 'DELETE':
|
||||
requireRole(['superadmin']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$chk = $db->prepare("SELECT nama FROM penduduk WHERE id=?"); $chk->execute([$id]);
|
||||
$row = $chk->fetch();
|
||||
if (!$row) jsonErr('Data tidak ditemukan.', 404);
|
||||
$db->prepare("DELETE FROM penduduk WHERE id=?")->execute([$id]);
|
||||
log_aksi($user['id'], 'DELETE', 'penduduk', $id, 'Hapus: '.$row['nama']);
|
||||
jsonOk(null, 'Data berhasil dihapus.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireLogin();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT ri.*,
|
||||
(SELECT COUNT(*) FROM keluarga k WHERE k.rumah_ibadah_id=ri.id) as jumlah_kk,
|
||||
(SELECT COUNT(*) FROM keluarga k JOIN penduduk p ON p.keluarga_id=k.id WHERE k.rumah_ibadah_id=ri.id AND p.status_hidup='hidup') as jumlah_jiwa,
|
||||
(SELECT COUNT(*) FROM keluarga k WHERE k.rumah_ibadah_id=ri.id AND k.status_ekonomi='miskin') as kk_miskin
|
||||
FROM rumah_ibadah ri WHERE ri.id=?");
|
||||
$st->execute([$id]); jsonOk($st->fetch()); break;
|
||||
}
|
||||
$rows = $db->query("SELECT ri.id, ri.nama, ri.jenis, ri.kontak, ri.lat, ri.lng, ri.alamat, ri.kelurahan,
|
||||
(SELECT COUNT(*) FROM keluarga k WHERE k.rumah_ibadah_id=ri.id) as jumlah_kk,
|
||||
(SELECT COUNT(*) FROM keluarga k WHERE k.rumah_ibadah_id=ri.id AND k.status_ekonomi='miskin') as kk_miskin
|
||||
FROM rumah_ibadah ri ORDER BY ri.nama")->fetchAll();
|
||||
foreach ($rows as &$r) { $r['id']=(int)$r['id']; $r['lat']=(float)$r['lat']; $r['lng']=(float)$r['lng']; }
|
||||
jsonOk($rows); break;
|
||||
|
||||
case 'POST':
|
||||
requireRole(['superadmin']);
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$nama = sanitize($b['nama'] ?? '');
|
||||
if (!$nama) jsonErr('Nama wajib diisi.');
|
||||
$db->prepare("INSERT INTO rumah_ibadah (nama,jenis,kontak,lat,lng,alamat,kelurahan) VALUES (?,?,?,?,?,?,?)")
|
||||
->execute([$nama,$b['jenis']??'Masjid',sanitize($b['kontak']??''),(float)($b['lat']??0),(float)($b['lng']??0),sanitize($b['alamat']??''),sanitize($b['kelurahan']??'')]);
|
||||
jsonOk(['id'=>(int)$db->lastInsertId()],'Rumah ibadah ditambahkan.');
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireRole(['superadmin','pengurus']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$db->prepare("UPDATE rumah_ibadah SET nama=?,jenis=?,kontak=?,lat=?,lng=?,alamat=?,kelurahan=?,updated_at=NOW() WHERE id=?")
|
||||
->execute([sanitize($b['nama']??''),$b['jenis']??'Masjid',sanitize($b['kontak']??''),(float)($b['lat']??0),(float)($b['lng']??0),sanitize($b['alamat']??''),sanitize($b['kelurahan']??''),$id]);
|
||||
jsonOk(null,'Data diperbarui.');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireRole(['superadmin']);
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$db->prepare("DELETE FROM rumah_ibadah WHERE id=?")->execute([$id]);
|
||||
jsonOk(null,'Data dihapus.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config.php';
|
||||
requireLogin();
|
||||
$db = getDB();
|
||||
|
||||
// KPI Utama
|
||||
$totalPenduduk = (int)$db->query("SELECT COUNT(*) FROM penduduk WHERE status_hidup='hidup'")->fetchColumn();
|
||||
$totalKeluarga = (int)$db->query("SELECT COUNT(*) FROM keluarga")->fetchColumn();
|
||||
$totalMiskin = (int)$db->query("SELECT COUNT(*) FROM penduduk WHERE status_ekonomi='miskin' AND status_hidup='hidup'")->fetchColumn();
|
||||
$totalRentan = (int)$db->query("SELECT COUNT(*) FROM penduduk WHERE status_ekonomi='rentan' AND status_hidup='hidup'")->fetchColumn();
|
||||
$totalMampu = (int)$db->query("SELECT COUNT(*) FROM penduduk WHERE status_ekonomi='mampu' AND status_hidup='hidup'")->fetchColumn();
|
||||
$totalLaporan = (int)$db->query("SELECT COUNT(*) FROM laporan WHERE status != 'selesai'")->fetchColumn();
|
||||
$laporanDarurat= (int)$db->query("SELECT COUNT(*) FROM laporan WHERE urgensi='darurat' AND status NOT IN ('selesai')")->fetchColumn();
|
||||
$totalBantuan = (int)$db->query("SELECT COUNT(*) FROM histori_bantuan WHERE status='disalurkan'")->fetchColumn();
|
||||
$belumBantuan = (int)$db->query("SELECT COUNT(*) FROM penduduk WHERE status_ekonomi IN ('miskin','rentan') AND status_hidup='hidup' AND id NOT IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')")->fetchColumn();
|
||||
$unreadChat = (int)$db->query("SELECT COUNT(*) FROM chat WHERE dibaca=0")->fetchColumn();
|
||||
|
||||
// Distribusi ekonomi per kelurahan
|
||||
$byKelurahan = $db->query("SELECT k.kelurahan,
|
||||
SUM(CASE WHEN k.status_ekonomi='miskin' THEN 1 ELSE 0 END) as miskin,
|
||||
SUM(CASE WHEN k.status_ekonomi='rentan' THEN 1 ELSE 0 END) as rentan,
|
||||
SUM(CASE WHEN k.status_ekonomi='mampu' THEN 1 ELSE 0 END) as mampu,
|
||||
COUNT(*) as total
|
||||
FROM keluarga k GROUP BY k.kelurahan ORDER BY miskin DESC LIMIT 10")->fetchAll();
|
||||
|
||||
// Distribusi bantuan per jenis
|
||||
$byBantuan = $db->query("SELECT b.nama, b.jenis, COUNT(hb.id) as total_disalurkan
|
||||
FROM bantuan b LEFT JOIN histori_bantuan hb ON hb.bantuan_id=b.id AND hb.status='disalurkan'
|
||||
GROUP BY b.id ORDER BY total_disalurkan DESC")->fetchAll();
|
||||
|
||||
// Distribusi per rumah ibadah
|
||||
$byRI = $db->query("SELECT ri.nama, ri.jenis, ri.lat, ri.lng,
|
||||
COUNT(DISTINCT k.id) as jumlah_kk,
|
||||
SUM(CASE WHEN k.status_ekonomi='miskin' THEN 1 ELSE 0 END) as kk_miskin,
|
||||
(SELECT COUNT(*) FROM v_penduduk p JOIN keluarga k2 ON k2.id=p.keluarga_id WHERE k2.rumah_ibadah_id=ri.id AND p.status_hidup='hidup') as jumlah_jiwa
|
||||
FROM rumah_ibadah ri LEFT JOIN keluarga k ON k.rumah_ibadah_id=ri.id
|
||||
GROUP BY ri.id ORDER BY kk_miskin DESC")->fetchAll();
|
||||
|
||||
// Profil umur
|
||||
$byUmur = $db->query("SELECT profil_umur, COUNT(*) as jumlah
|
||||
FROM v_penduduk WHERE status_hidup='hidup' GROUP BY profil_umur")->fetchAll();
|
||||
|
||||
// Laporan per status
|
||||
$byLaporan = $db->query("SELECT status, urgensi, COUNT(*) as jumlah
|
||||
FROM laporan GROUP BY status, urgensi ORDER BY FIELD(urgensi,'darurat','tinggi','sedang','rendah')")->fetchAll();
|
||||
|
||||
// GeoJSON penduduk untuk peta
|
||||
$geoRows = $db->query("SELECT p.id, p.nik, p.nama, p.umur, p.profil_umur, p.status_ekonomi,
|
||||
p.kondisi_kesehatan, p.penghasilan, k.kelurahan, k.lat, k.lng, k.no_kk,
|
||||
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') as total_bantuan
|
||||
FROM v_penduduk p JOIN keluarga k ON k.id=p.keluarga_id
|
||||
WHERE p.status_hidup='hidup' AND k.lat IS NOT NULL AND k.lng IS NOT NULL
|
||||
LIMIT 1000")->fetchAll();
|
||||
|
||||
$features = [];
|
||||
foreach ($geoRows as $r) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => ['type'=>'Point','coordinates'=>[(float)$r['lng'],(float)$r['lat']]],
|
||||
'properties' => $r
|
||||
];
|
||||
}
|
||||
|
||||
// GeoJSON laporan untuk peta
|
||||
$laporanRows = $db->query("SELECT id,deskripsi,lat,lng,urgensi,status,created_at,foto FROM laporan WHERE lat IS NOT NULL AND lng IS NOT NULL")->fetchAll();
|
||||
$laporanFeatures = [];
|
||||
foreach ($laporanRows as $r) {
|
||||
$laporanFeatures[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => ['type'=>'Point','coordinates'=>[(float)$r['lng'],(float)$r['lat']]],
|
||||
'properties' => $r
|
||||
];
|
||||
}
|
||||
|
||||
jsonOk([
|
||||
'kpi' => [
|
||||
'total_penduduk' => $totalPenduduk,
|
||||
'total_keluarga' => $totalKeluarga,
|
||||
'total_miskin' => $totalMiskin,
|
||||
'total_rentan' => $totalRentan,
|
||||
'total_mampu' => $totalMampu,
|
||||
'total_laporan_aktif' => $totalLaporan,
|
||||
'laporan_darurat' => $laporanDarurat,
|
||||
'total_bantuan_disalurkan' => $totalBantuan,
|
||||
'belum_dapat_bantuan' => $belumBantuan,
|
||||
'unread_chat' => $unreadChat,
|
||||
'pct_miskin' => $totalPenduduk ? round($totalMiskin/$totalPenduduk*100,1) : 0,
|
||||
],
|
||||
'by_kelurahan' => $byKelurahan,
|
||||
'by_bantuan' => $byBantuan,
|
||||
'by_ri' => $byRI,
|
||||
'by_umur' => $byUmur,
|
||||
'by_laporan' => $byLaporan,
|
||||
'geojson_penduduk' => ['type'=>'FeatureCollection','features'=>$features],
|
||||
'geojson_laporan' => ['type'=>'FeatureCollection','features'=>$laporanFeatures],
|
||||
]);
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
// api/user.php — Manajemen User (superadmin only)
|
||||
require_once __DIR__ . '/../config.php';
|
||||
$user = requireRole(['superadmin']);
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$db = getDB();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
if ($id) {
|
||||
$st = $db->prepare("SELECT u.id, u.username, u.nama_lengkap, u.telepon, u.aktif,
|
||||
r.kode as role, r.nama as role_nama, r.id as role_id,
|
||||
ri.nama as ri_nama, u.rumah_ibadah_id, u.created_at
|
||||
FROM user u JOIN role r ON r.id=u.role_id
|
||||
LEFT JOIN rumah_ibadah ri ON ri.id=u.rumah_ibadah_id
|
||||
WHERE u.id=?");
|
||||
$st->execute([$id]);
|
||||
jsonOk($st->fetch());
|
||||
}
|
||||
$rows = $db->query("SELECT u.id, u.username, u.nama_lengkap, u.telepon, u.aktif,
|
||||
r.kode as role, r.nama as role_nama, ri.nama as ri_nama, u.created_at
|
||||
FROM user u JOIN role r ON r.id=u.role_id
|
||||
LEFT JOIN rumah_ibadah ri ON ri.id=u.rumah_ibadah_id
|
||||
ORDER BY r.id, u.nama_lengkap")->fetchAll();
|
||||
jsonOk($rows);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$username = sanitize($b['username'] ?? '');
|
||||
$password = $b['password'] ?? '';
|
||||
$nama = sanitize($b['nama_lengkap'] ?? '');
|
||||
$roleId = (int)($b['role_id'] ?? 5);
|
||||
|
||||
if (!$username || !$password || !$nama) jsonErr('Username, password, dan nama wajib diisi.');
|
||||
if (strlen($username) < 4) jsonErr('Username minimal 4 karakter.');
|
||||
if (strlen($password) < 6) jsonErr('Password minimal 6 karakter.');
|
||||
|
||||
$chk = $db->prepare("SELECT id FROM user WHERE username=?"); $chk->execute([$username]);
|
||||
if ($chk->fetch()) jsonErr('Username sudah digunakan.');
|
||||
|
||||
$hash = password_hash($password, PASSWORD_BCRYPT);
|
||||
$db->prepare("INSERT INTO user (username, password, nama_lengkap, role_id, rumah_ibadah_id, telepon)
|
||||
VALUES (?,?,?,?,?,?)")
|
||||
->execute([$username, $hash, $nama, $roleId,
|
||||
!empty($b['rumah_ibadah_id']) ? (int)$b['rumah_ibadah_id'] : null,
|
||||
sanitize($b['telepon'] ?? '')]);
|
||||
$newId = (int)$db->lastInsertId();
|
||||
log_aksi($user['id'], 'CREATE', 'user', $newId, "Tambah user: $username");
|
||||
jsonOk(['id' => $newId], 'User berhasil ditambahkan.');
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
$b = json_decode(file_get_contents('php://input'), true);
|
||||
$nama = sanitize($b['nama_lengkap'] ?? '');
|
||||
if (!$nama) jsonErr('Nama wajib diisi.');
|
||||
|
||||
$chk = $db->prepare("SELECT id FROM user WHERE id=?"); $chk->execute([$id]);
|
||||
if (!$chk->fetch()) jsonErr('User tidak ditemukan.', 404);
|
||||
|
||||
// Update data dasar
|
||||
$db->prepare("UPDATE user SET nama_lengkap=?, role_id=?, rumah_ibadah_id=?, telepon=?, aktif=? WHERE id=?")
|
||||
->execute([$nama, (int)($b['role_id'] ?? 5),
|
||||
!empty($b['rumah_ibadah_id']) ? (int)$b['rumah_ibadah_id'] : null,
|
||||
sanitize($b['telepon'] ?? ''), (int)($b['aktif'] ?? 1), $id]);
|
||||
|
||||
// Ganti password jika diisi
|
||||
if (!empty($b['password']) && strlen($b['password']) >= 6) {
|
||||
$db->prepare("UPDATE user SET password=? WHERE id=?")
|
||||
->execute([password_hash($b['password'], PASSWORD_BCRYPT), $id]);
|
||||
}
|
||||
log_aksi($user['id'], 'UPDATE', 'user', $id, "Edit user ID: $id");
|
||||
jsonOk(null, 'Data user diperbarui.');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (!$id) jsonErr('ID tidak valid.');
|
||||
if ($id === $user['id']) jsonErr('Tidak dapat menghapus akun sendiri.');
|
||||
$db->prepare("DELETE FROM user WHERE id=?")->execute([$id]);
|
||||
log_aksi($user['id'], 'DELETE', 'user', $id, "Hapus user ID: $id");
|
||||
jsonOk(null, 'User dihapus.');
|
||||
break;
|
||||
|
||||
default: jsonErr('Method tidak didukung.', 405);
|
||||
}
|
||||
Reference in New Issue
Block a user