Add auto-import DB script and update connection fallback

This commit is contained in:
Nama Kamu
2026-06-11 14:30:22 +07:00
commit 2aa30691f1
44 changed files with 8042 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
# WebGIS Pengentasan Kemiskinan — UAS 06 (FIXED)
## 📦 Struktur Folder WAJIB
```
webgis_uas06/ ← taruh di htdocs/
├── database_uas_06.sql ← Import ke MySQL PERTAMA
├── koneksi.php
├── auth.php
├── ambil.php
├── index.php
├── login.php
├── uploads/ ← buat folder ini (chmod 777)
└── api/
├── dashboard.php
├── penduduk.php
├── bantuan.php
├── laporan.php
├── ibadah.php
├── user.php
└── chat.php
```
> ⚠️ PENTING: File dashboard.php, penduduk.php, dll HARUS berada di folder `api/`
> bukan di root. Jika salah letak → semua halaman gagal memuat.
## 🚀 Cara Install
1. Import database: buka phpMyAdmin → Import → `database_uas_06.sql`
2. Copy folder `webgis_uas06/` ke `C:\xampp\htdocs\`
3. Pastikan folder `uploads/` ada di dalam webgis_uas06/
4. Akses: `http://localhost/webgis_uas06/login.php`
## 👤 Akun Demo (password: `password`)
| Role | Email |
|------|-------|
| Pengurus (Admin) | admin@uas.id |
| Pimpinan Daerah | pimpinan@uas.id |
| Masyarakat | warga@uas.id |
## 🐛 Bug yang Diperbaiki
- ✅ Dashboard gagal memuat → fixed null-check pada query result
- ✅ Penduduk gagal memuat & filter miskin/rentan tidak ada data → fixed
- ✅ Simpan penduduk baru gagal → fixed bind_param & NULL handling
- ✅ Edit penduduk gagal → fixed query UPDATE
- ✅ Laporan filter tidak berfungsi → fixed query WHERE
- ✅ Bantuan/histori gagal muat → fixed error handling
- ✅ Chat gagal (unread error saat belum login) → fixed null check user_id
- ✅ Ibadah & User gagal memuat → fixed error response
- ✅ Detail penduduk gagal → sudah benar, path api/ fixed
- ✅ Semua file API dipindah ke folder api/ sesuai path di index.php
+39
View File
@@ -0,0 +1,39 @@
<?php
include 'koneksi.php';
$tipe=$_GET['tipe']??'semua';
$data=[];
if ($tipe==='semua'||$tipe==='ibadah') {
$res=$conn->query("SELECT ri.*,
(SELECT COUNT(*) FROM penduduk p WHERE p.rumah_ibadah_id=ri.id AND p.status_hidup='hidup') AS total_penduduk,
(SELECT COUNT(*) FROM penduduk p WHERE p.rumah_ibadah_id=ri.id AND p.status_ekonomi='miskin') AS total_miskin
FROM rumah_ibadah ri");
if($res) while($r=$res->fetch_assoc()){$r['tipe']='ibadah';$data[]=$r;}
}
if ($tipe==='semua'||$tipe==='penduduk') {
$where=["p.lat IS NOT NULL","p.lng IS NOT NULL","p.status_hidup='hidup'"];
if(!empty($_GET['status_ekonomi'])){$se=$conn->real_escape_string($_GET['status_ekonomi']);$where[]="p.status_ekonomi='$se'";}
if(!empty($_GET['rumah_ibadah_id'])){$ri_id=(int)$_GET['rumah_ibadah_id'];$where[]="p.rumah_ibadah_id=$ri_id";}
if(!empty($_GET['status_bantuan'])){
if($_GET['status_bantuan']==='sudah') $where[]="p.id IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')";
else $where[]="p.id NOT IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')";
}
$w=implode(' AND ',$where);
$res=$conn->query("SELECT p.id,p.nik,p.nama,p.jenis_kelamin,
TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,
p.status_ekonomi,p.pekerjaan,p.penghasilan,p.lat,p.lng,p.rumah_ibadah_id,
ri.nama AS nama_ibadah,
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') AS total_bantuan
FROM penduduk p
LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id
WHERE $w");
if($res) while($r=$res->fetch_assoc()){$r['tipe']='penduduk';$r['penghasilan']=(float)$r['penghasilan'];$data[]=$r;}
}
if ($tipe==='semua'||$tipe==='laporan') {
$res=$conn->query("SELECT id,pelapor,deskripsi,lat,lng,urgensi,status,created_at FROM laporan WHERE lat IS NOT NULL AND lng IS NOT NULL");
if($res) while($r=$res->fetch_assoc()){$r['tipe']='laporan';$data[]=$r;}
}
json_out($data);
+31
View File
@@ -0,0 +1,31 @@
<?php
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'cek';
if ($aksi === 'cek') {
if (!empty($_SESSION['user_id'])) json_out(['login'=>true,'user'=>$_SESSION['user']]);
else json_out(['login'=>false]);
}
if ($aksi === 'login') {
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
if (!$email || !$password) json_out(['error'=>'Email dan password wajib diisi'],400);
$stmt = $conn->prepare("SELECT u.*,r.nama AS role_nama FROM user u JOIN role r ON u.role_id=r.id WHERE u.email=? AND u.aktif=1 LIMIT 1");
$stmt->bind_param('s',$email);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
$stmt->close();
if (!$user || !password_verify($password,$user['password'])) json_out(['error'=>'Email atau password salah'],401);
unset($user['password']);
$_SESSION['user_id'] = $user['id'];
$_SESSION['user'] = $user;
log_aktivitas($conn,$user['id'],'LOGIN','user',$user['id'],'Login berhasil');
json_out(['login'=>true,'user'=>$user]);
}
if ($aksi === 'logout') {
session_destroy();
json_out(['logout'=>true]);
}
+116
View File
@@ -0,0 +1,116 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'list_bantuan';
if ($aksi === 'list_bantuan') {
$res=$conn->query("SELECT * FROM bantuan ORDER BY jenis,nama");
if(!$res) json_out(['error'=>$conn->error],500);
$rows=[]; while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'simpan_master') {
$nm=$conn->real_escape_string($_POST['nama']??'');
$jn=$conn->real_escape_string($_POST['jenis']??'sembako');
$sm=$conn->real_escape_string($_POST['sumber']??'');
$bt=$conn->real_escape_string($_POST['bentuk']??'');
$conn->query("INSERT INTO bantuan (nama,jenis,sumber,bentuk) VALUES ('$nm','$jn','$sm','$bt')");
if($conn->error) json_out(['error'=>$conn->error],500);
json_out(['success'=>true,'id'=>$conn->insert_id]);
}
if ($aksi === 'edit_master') {
$id=(int)($_POST['id']??0);
$nm=$conn->real_escape_string($_POST['nama']??'');
$jn=$conn->real_escape_string($_POST['jenis']??'sembako');
$sm=$conn->real_escape_string($_POST['sumber']??'');
$bt=$conn->real_escape_string($_POST['bentuk']??'');
$conn->query("UPDATE bantuan SET nama='$nm',jenis='$jn',sumber='$sm',bentuk='$bt' WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'hapus_master') {
$id=(int)($_POST['id']??0);
$conn->query("DELETE FROM histori_bantuan WHERE bantuan_id=$id");
$conn->query("DELETE FROM bantuan WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'histori') {
$where=['1=1']; $params=[]; $types='';
if(!empty($_GET['penduduk_id'])){$where[]="hb.penduduk_id=?";$params[]=(int)$_GET['penduduk_id'];$types.='i';}
if(!empty($_GET['bantuan_id'])){$where[]="hb.bantuan_id=?";$params[]=(int)$_GET['bantuan_id'];$types.='i';}
if(!empty($_GET['status'])){$where[]="hb.status=?";$params[]=$_GET['status'];$types.='s';}
if(!empty($_GET['tgl_dari'])){$where[]="hb.tanggal>=?";$params[]=$_GET['tgl_dari'];$types.='s';}
if(!empty($_GET['tgl_sampai'])){$where[]="hb.tanggal<=?";$params[]=$_GET['tgl_sampai'];$types.='s';}
$w=implode(' AND ',$where);
$sql="SELECT hb.*,b.nama AS nama_bantuan,b.jenis,b.sumber,p.nama AS nama_penduduk,p.status_ekonomi,p.nik,u.nama AS nama_pengurus
FROM histori_bantuan hb
JOIN bantuan b ON hb.bantuan_id=b.id
JOIN penduduk p ON hb.penduduk_id=p.id
LEFT JOIN user u ON hb.disalurkan_oleh=u.id
WHERE $w ORDER BY hb.tanggal DESC,hb.id DESC";
if($params){$stmt=$conn->prepare($sql);$stmt->bind_param($types,...$params);$stmt->execute();$res=$stmt->get_result();$stmt->close();}
else $res=$conn->query($sql);
$rows=[]; while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'salurkan') {
$pid=(int)($_POST['penduduk_id']??0);
$bid=(int)($_POST['bantuan_id']??0);
$tgl=$conn->real_escape_string($_POST['tanggal']??date('Y-m-d'));
$jml=$conn->real_escape_string($_POST['jumlah']??'');
$ket=$conn->real_escape_string($_POST['keterangan']??'');
$uid=!empty($_SESSION['user_id'])?(int)$_SESSION['user_id']:'NULL';
$conn->query("INSERT INTO histori_bantuan (penduduk_id,bantuan_id,tanggal,jumlah,status,disalurkan_oleh,keterangan) VALUES ($pid,$bid,'$tgl','$jml','disalurkan',$uid,'$ket')");
if($conn->error) json_out(['error'=>$conn->error],500);
$new_id=$conn->insert_id;
if($uid!=='NULL'){
log_aktivitas($conn,$uid,'CREATE','histori_bantuan',$new_id,'Salurkan bantuan ke penduduk id='.$pid);
}
json_out(['success'=>true,'id'=>$new_id]);
}
if ($aksi === 'edit_histori') {
$id=(int)($_POST['id']??0);
$status=$conn->real_escape_string($_POST['status']??'disalurkan');
$jml=$conn->real_escape_string($_POST['jumlah']??'');
$ket=$conn->real_escape_string($_POST['keterangan']??'');
$conn->query("UPDATE histori_bantuan SET status='$status',jumlah='$jml',keterangan='$ket' WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'hapus_histori') {
$id=(int)($_POST['id']??0);
$conn->query("DELETE FROM histori_bantuan WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'belum_dibantu') {
$sql="SELECT p.id,p.nik,p.nama,p.status_ekonomi,TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,ri.nama AS nama_ibadah,k.kelurahan
FROM penduduk p
LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id
LEFT JOIN keluarga k ON p.keluarga_id=k.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 FIELD(p.status_ekonomi,'miskin','rentan'),p.nama";
$res=$conn->query($sql); $rows=[];
while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'statistik') {
$sql="SELECT b.id,b.nama,b.jenis,COUNT(hb.id) AS total_salur,SUM(hb.status='disalurkan') AS berhasil
FROM bantuan b
LEFT JOIN histori_bantuan hb ON hb.bantuan_id=b.id
GROUP BY b.id ORDER BY total_salur DESC";
$res=$conn->query($sql); $rows=[];
while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
+51
View File
@@ -0,0 +1,51 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'inbox';
$uid = (int)($_SESSION['user_id']??0);
if ($aksi === 'inbox') {
if(!$uid) json_out([]);
$sql="SELECT p.*,u.nama AS nama_pengirim
FROM pesan p
JOIN user u ON p.dari_user=u.id
WHERE (p.ke_user=$uid OR p.ke_user IS NULL)
ORDER BY p.created_at DESC LIMIT 80";
$res=$conn->query($sql); $rows=[];
if($res) while($r=$res->fetch_assoc()) $rows[]=$r;
// tandai dibaca
$conn->query("UPDATE pesan SET dibaca=1 WHERE ke_user=$uid AND dibaca=0");
json_out(array_reverse($rows));
}
if ($aksi === 'history') {
$ke=(int)($_GET['ke']??0);
$res=$conn->query("SELECT p.*,u.nama AS nama_pengirim FROM pesan p JOIN user u ON p.dari_user=u.id WHERE (p.dari_user=$uid AND p.ke_user=$ke) OR (p.dari_user=$ke AND p.ke_user=$uid) ORDER BY p.created_at ASC LIMIT 100");
$rows=[]; if($res) while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'kirim') {
if(!$uid) json_out(['error'=>'Belum login'],401);
$ke=!empty($_POST['ke_user'])?(int)$_POST['ke_user']:'NULL';
$isi=$conn->real_escape_string(trim($_POST['isi']??''));
if(!$isi) json_out(['error'=>'Pesan kosong'],400);
$conn->query("INSERT INTO pesan (dari_user,ke_user,isi) VALUES ($uid,$ke,'$isi')");
if($conn->error) json_out(['error'=>$conn->error],500);
json_out(['success'=>true,'id'=>$conn->insert_id,'time'=>date('H:i')]);
}
if ($aksi === 'kontak') {
$res=$conn->query("SELECT u.id,u.nama,r.nama AS role FROM user u JOIN role r ON u.role_id=r.id WHERE u.aktif=1".($uid?" AND u.id!=$uid":'')." ORDER BY u.nama");
$rows=[]; if($res) while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'unread') {
if(!$uid){ json_out(['count'=>0]); }
$res=$conn->query("SELECT COUNT(*) c FROM pesan WHERE (ke_user=$uid OR ke_user IS NULL) AND dibaca=0 AND dari_user!=$uid");
json_out(['count'=>(int)($res->fetch_assoc()['c']??0)]);
}
+43
View File
@@ -0,0 +1,43 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
ob_clean();
$tp=$conn->query("SELECT COUNT(*) c FROM penduduk WHERE status_hidup='hidup'")->fetch_assoc()['c'];
$tm=$conn->query("SELECT COUNT(*) c FROM penduduk WHERE status_ekonomi='miskin' AND status_hidup='hidup'")->fetch_assoc()['c'];
$tr=$conn->query("SELECT COUNT(*) c FROM penduduk WHERE status_ekonomi='rentan' AND status_hidup='hidup'")->fetch_assoc()['c'];
$ta=$conn->query("SELECT COUNT(*) c FROM penduduk WHERE status_ekonomi='mampu' AND status_hidup='hidup'")->fetch_assoc()['c'];
$tk=$conn->query("SELECT COUNT(*) c FROM keluarga")->fetch_assoc()['c'];
$tl=$conn->query("SELECT COUNT(*) c FROM laporan")->fetch_assoc()['c'];
$tld=$conn->query("SELECT COUNT(*) c FROM laporan WHERE urgensi='darurat' AND status='pending'")->fetch_assoc()['c'];
$tlp=$conn->query("SELECT COUNT(*) c FROM laporan WHERE status='pending'")->fetch_assoc()['c'];
$tbs=$conn->query("SELECT COUNT(*) c FROM histori_bantuan WHERE status='disalurkan'")->fetch_assoc()['c'];
$tbd=$conn->query("SELECT COUNT(*) c 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')")->fetch_assoc()['c'];
$twi=$conn->query("SELECT COUNT(DISTINCT kelurahan) c FROM keluarga")->fetch_assoc()['c'];
$tri_res=$conn->query("SELECT COUNT(DISTINCT CONCAT(rt,rw,kelurahan)) c FROM keluarga")->fetch_assoc()['c'];
// per-bulan bantuan (6 bln terakhir)
$tren=[]; $res=$conn->query("SELECT DATE_FORMAT(tanggal,'%Y-%m') bln,COUNT(*) jml FROM histori_bantuan WHERE tanggal>=DATE_SUB(CURDATE(),INTERVAL 6 MONTH) GROUP BY bln ORDER BY bln");
if($res) while($r=$res->fetch_assoc()) $tren[]=$r;
// statistik ibadah
$stat_ibadah=[]; $res=$conn->query("SELECT * FROM v_statistik_ibadah");
if($res) while($r=$res->fetch_assoc()) $stat_ibadah[]=$r;
// prioritas
$prioritas=[]; $res=$conn->query("SELECT p.id,p.nik,p.nama,p.status_ekonomi,TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,ri.nama AS nama_ibadah,(SELECT COUNT(*) FROM laporan la WHERE la.penduduk_id=p.id AND la.urgensi IN ('tinggi','darurat') AND la.status!='selesai') AS lap_darurat FROM penduduk p LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id WHERE p.status_hidup='hidup' AND p.status_ekonomi IN ('miskin','rentan') ORDER BY lap_darurat DESC,FIELD(p.status_ekonomi,'miskin','rentan') LIMIT 10");
if($res) while($r=$res->fetch_assoc()) $prioritas[]=$r;
// aktivitas
$aktivitas=[]; $res=$conn->query("SELECT la.*,u.nama AS nama_user FROM log_aktivitas la LEFT JOIN user u ON la.user_id=u.id ORDER BY la.created_at DESC LIMIT 15");
if($res) while($r=$res->fetch_assoc()) $aktivitas[]=$r;
json_out([
'total_penduduk'=>(int)$tp,'total_miskin'=>(int)$tm,'total_rentan'=>(int)$tr,'total_mampu'=>(int)$ta,
'total_keluarga'=>(int)$tk,'total_laporan'=>(int)$tl,'total_darurat'=>(int)$tld,'laporan_pending'=>(int)$tlp,
'total_bantuan_salur'=>(int)$tbs,'belum_dibantu'=>(int)$tbd,'total_wilayah'=>(int)$twi,'total_rt_rw'=>(int)$tri_res,
'tren_bantuan'=>$tren,'stat_ibadah'=>$stat_ibadah,'prioritas'=>$prioritas,'aktivitas'=>$aktivitas,
]);
+285
View File
@@ -0,0 +1,285 @@
-- ============================================================
-- WebGIS Pengentasan Kemiskinan | Database: uas_06
-- Jalankan sekali untuk setup awal
-- ============================================================
CREATE DATABASE IF NOT EXISTS uas_06 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE uas_06;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS log_aktivitas;
DROP TABLE IF EXISTS pesan;
DROP TABLE IF EXISTS histori_bantuan;
DROP TABLE IF EXISTS bantuan;
DROP TABLE IF EXISTS laporan;
DROP TABLE IF EXISTS pelatihan;
DROP TABLE IF EXISTS penduduk;
DROP TABLE IF EXISTS keluarga;
DROP TABLE IF EXISTS rumah_ibadah;
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS role;
SET FOREIGN_KEY_CHECKS = 1;
-- ── 1. ROLE ─────────────────────────────────────────────────
CREATE TABLE role (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(50) NOT NULL,
deskripsi TEXT
) ENGINE=InnoDB;
INSERT INTO role (nama, deskripsi) VALUES
('masyarakat', 'Hanya dapat melihat data dan membuat laporan'),
('pengurus', 'Input & update data penduduk, verifikasi laporan, salurkan bantuan'),
('pimpinan', 'Read-only, monitoring dashboard');
-- ── 2. USER ─────────────────────────────────────────────────
CREATE TABLE user (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role_id INT NOT NULL DEFAULT 1,
aktif TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (role_id) REFERENCES role(id)
) ENGINE=InnoDB;
-- Password untuk semua akun demo: "password"
INSERT INTO user (nama, email, password, role_id) VALUES
('Admin Utama', 'admin@uas.id', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 2),
('Pimpinan Daerah', 'pimpinan@uas.id', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 3),
('Warga Biasa', 'warga@uas.id', '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 1),
('Pengurus Masjid', 'pengurus2@uas.id','$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 2);
-- ── 3. RUMAH IBADAH ─────────────────────────────────────────
CREATE TABLE rumah_ibadah (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(150) NOT NULL,
jenis ENUM('masjid','gereja','pura','vihara','klenteng','lainnya') DEFAULT 'masjid',
kontak VARCHAR(20),
alamat VARCHAR(255),
lat DOUBLE NOT NULL,
lng DOUBLE NOT NULL,
radius DOUBLE DEFAULT 500,
user_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO rumah_ibadah (nama, jenis, kontak, alamat, lat, lng, radius, user_id) VALUES
('Masjid Al-Ikhlas', 'masjid', '081234567890', 'Jl. Merdeka No.1, Pontianak Kota', 0.0269, 109.3425, 600, 1),
('Gereja Santo Yosef', 'gereja', '081298765432', 'Jl. Veteran No.5, Pontianak Selatan', 0.0310, 109.3300, 500, 1),
('Masjid Al-Furqon', 'masjid', '085678901234', 'Jl. Sudirman No.10, Pontianak Barat', 0.0200, 109.3500, 550, 4);
-- ── 4. KELUARGA (Kartu Keluarga) ────────────────────────────
CREATE TABLE keluarga (
id INT AUTO_INCREMENT PRIMARY KEY,
no_kk VARCHAR(20) NOT NULL UNIQUE,
alamat VARCHAR(255),
rt VARCHAR(5),
rw VARCHAR(5),
kelurahan VARCHAR(100),
kecamatan VARCHAR(100),
lat DOUBLE,
lng DOUBLE,
rumah_ibadah_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (rumah_ibadah_id) REFERENCES rumah_ibadah(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO keluarga (no_kk, alamat, rt, rw, kelurahan, kecamatan, lat, lng, rumah_ibadah_id) VALUES
('6171010101010001','Jl. Dahlia No.3', '001','001','Sungai Bangkong','Pontianak Kota', 0.0250,109.3410,1),
('6171010101010002','Jl. Melati No.7', '002','001','Sungai Bangkong','Pontianak Kota', 0.0280,109.3440,1),
('6171010101010003','Jl. Kenanga No.12','001','002','Benua Melayu', 'Pontianak Selatan',0.0215,109.3480,2),
('6171010101010004','Jl. Mawar No.5', '003','002','Akcaya', 'Pontianak Selatan',0.0195,109.3460,2),
('6171010101010005','Jl. Anggrek No.8', '001','003','Bansir Laut', 'Pontianak Tenggara',0.0175,109.3510,3);
-- ── 5. PENDUDUK ──────────────────────────────────────────────
CREATE TABLE penduduk (
id INT AUTO_INCREMENT PRIMARY KEY,
nik VARCHAR(16) NOT NULL UNIQUE,
nama VARCHAR(150) NOT NULL,
jenis_kelamin ENUM('L','P') NOT NULL DEFAULT 'L',
tanggal_lahir DATE NOT NULL,
status_keluarga ENUM('kepala_keluarga','anggota') DEFAULT 'anggota',
status_perkawinan ENUM('belum_kawin','kawin','cerai_hidup','cerai_mati') DEFAULT 'belum_kawin',
status_hidup ENUM('hidup','meninggal') DEFAULT 'hidup',
pekerjaan VARCHAR(100),
penghasilan DECIMAL(15,2) DEFAULT 0,
status_ekonomi ENUM('miskin','rentan','mampu') DEFAULT 'rentan',
pendidikan_terakhir ENUM('tidak_sekolah','SD','SMP','SMA','D3','S1','S2','S3') DEFAULT 'tidak_sekolah',
status_pendidikan ENUM('sekolah','tidak_sekolah','lulus') DEFAULT 'tidak_sekolah',
keluarga_id INT,
rumah_ibadah_id INT,
lat DOUBLE,
lng DOUBLE,
no_hp VARCHAR(20),
jenis_bantuan VARCHAR(255),
foto VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (keluarga_id) REFERENCES keluarga(id) ON DELETE SET NULL,
FOREIGN KEY (rumah_ibadah_id) REFERENCES rumah_ibadah(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO penduduk (nik,nama,jenis_kelamin,tanggal_lahir,status_keluarga,status_perkawinan,pekerjaan,penghasilan,status_ekonomi,pendidikan_terakhir,status_pendidikan,keluarga_id,rumah_ibadah_id,lat,lng,no_hp,jenis_bantuan) VALUES
('6171010101010001','Ahmad Fauzi', 'L','1985-03-15','kepala_keluarga','kawin', 'Buruh Harian', 800000, 'miskin','SD', 'lulus', 1,1,0.02500,109.34100,'081234567891','sembako'),
('6171010101010002','Siti Aminah', 'P','1988-07-20','anggota', 'kawin', 'Ibu RT', 0, 'miskin','SMP','lulus', 1,1,0.02510,109.34110,NULL, 'sembako'),
('6171010101010003','Budi Santoso', 'L','2012-01-10','anggota', 'belum_kawin','Pelajar', 0, 'miskin','SMP','sekolah', 1,1,0.02520,109.34090,NULL, NULL),
('6171010101010004','Dewi Rahayu', 'P','1979-11-05','kepala_keluarga','cerai_mati','Pedagang', 1500000,'rentan','SMA','lulus', 2,1,0.02800,109.34400,'085678901235','kesehatan'),
('6171010101010005','Rizky Pratama', 'L','2008-06-22','anggota', 'belum_kawin','Pelajar', 0, 'rentan','SMP','sekolah', 2,1,0.02790,109.34420,NULL, NULL),
('6171010101010006','Hendra Wijaya', 'L','1992-09-30','kepala_keluarga','kawin', 'Wiraswasta', 3000000,'mampu', 'S1', 'lulus', 3,2,0.02150,109.34800,'087890123456',NULL),
('6171010101010007','Lina Marlina', 'P','1995-04-18','anggota', 'kawin', 'Guru Honorer', 1800000,'rentan','S1', 'lulus', 3,2,0.02155,109.34810,'081122334455','pendidikan'),
('6171010101010008','Samsul Bahri', 'L','1970-08-25','kepala_keluarga','kawin', 'Nelayan', 600000, 'miskin','SD', 'lulus', 4,2,0.01950,109.34600,'089988776655','sembako'),
('6171010101010009','Aisyah Putri', 'P','1975-12-30','anggota', 'kawin', 'Ibu RT', 0, 'miskin','SD', 'lulus', 4,2,0.01960,109.34590,NULL, NULL),
('6171010101010010','Muhammad Yusuf','L','2005-09-15','anggota', 'belum_kawin','Pelajar', 0, 'miskin','SMA','sekolah', 4,2,0.01970,109.34580,NULL, NULL),
('6171010101010011','Surya Darma', 'L','1988-02-14','kepala_keluarga','kawin', 'Tukang Ojek', 1200000,'rentan','SMP','lulus', 5,3,0.01750,109.35100,'082233445566','ekonomi'),
('6171010101010012','Ratna Sari', 'P','1990-06-08','anggota', 'kawin', 'Pedagang Kecil', 800000, 'rentan','SMA','lulus', 5,3,0.01760,109.35110,NULL, NULL);
-- ── 6. PELATIHAN ────────────────────────────────────────────
CREATE TABLE pelatihan (
id INT AUTO_INCREMENT PRIMARY KEY,
penduduk_id INT NOT NULL,
nama_pelatihan VARCHAR(150),
penyelenggara VARCHAR(100),
tahun YEAR,
keterangan TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (penduduk_id) REFERENCES penduduk(id) ON DELETE CASCADE
) ENGINE=InnoDB;
INSERT INTO pelatihan (penduduk_id, nama_pelatihan, penyelenggara, tahun) VALUES
(1,'Pelatihan Menjahit','Dinas Tenaga Kerja',2023),
(4,'Pelatihan UMKM','Kementerian Koperasi',2022),
(11,'Pelatihan Ojek Online','Grab/Gojek',2023);
-- ── 7. BANTUAN (Master) ─────────────────────────────────────
CREATE TABLE bantuan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(150) NOT NULL,
jenis ENUM('sembako','pendidikan','kesehatan','ekonomi','perumahan','lainnya') DEFAULT 'sembako',
sumber VARCHAR(150),
bentuk VARCHAR(255),
keterangan TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
INSERT INTO bantuan (nama, jenis, sumber, bentuk) VALUES
('Sembako Bulanan', 'sembako', 'Rumah Ibadah', '10kg beras + minyak goreng 1L + gula 1kg'),
('Beasiswa Pendidikan', 'pendidikan', 'Pemerintah Daerah','Rp 500.000/bulan'),
('BPJS Kesehatan', 'kesehatan', 'Pemerintah Pusat', 'Kartu BPJS PBI gratis'),
('Modal Usaha Mikro', 'ekonomi', 'Donatur/CSR', 'Rp 1.000.000 Rp 5.000.000 sekali'),
('Perbaikan Rumah', 'perumahan', 'Pemerintah Daerah','Material bangunan senilai Rp 10.000.000');
-- ── 8. HISTORI BANTUAN ──────────────────────────────────────
CREATE TABLE histori_bantuan (
id INT AUTO_INCREMENT PRIMARY KEY,
penduduk_id INT NOT NULL,
bantuan_id INT NOT NULL,
tanggal DATE NOT NULL,
jumlah VARCHAR(100),
status ENUM('direncanakan','disalurkan','ditolak') DEFAULT 'direncanakan',
disalurkan_oleh INT,
keterangan TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (penduduk_id) REFERENCES penduduk(id) ON DELETE CASCADE,
FOREIGN KEY (bantuan_id) REFERENCES bantuan(id) ON DELETE CASCADE,
FOREIGN KEY (disalurkan_oleh) REFERENCES user(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO histori_bantuan (penduduk_id,bantuan_id,tanggal,jumlah,status,disalurkan_oleh,keterangan) VALUES
(1,1,'2024-01-10','10kg beras + minyak 1L','disalurkan',1,'Penyaluran Januari 2024'),
(1,3,'2024-02-01','1 kartu BPJS', 'disalurkan',1,'Didaftarkan BPJS PBI'),
(2,1,'2024-01-10','10kg beras + minyak 1L','disalurkan',1,'Penyaluran Januari 2024'),
(4,2,'2024-03-01','Rp 500.000', 'disalurkan',1,'Beasiswa anak sekolah'),
(8,1,'2024-01-15','10kg beras', 'disalurkan',4,'Bantuan Masjid Al-Furqon'),
(9,3,'2024-02-15','1 kartu BPJS', 'disalurkan',4,'BPJS untuk ibu'),
(11,4,'2024-04-01','Rp 2.000.000', 'disalurkan',4,'Modal usaha ojek online');
-- ── 9. LAPORAN MASYARAKAT ────────────────────────────────────
CREATE TABLE laporan (
id INT AUTO_INCREMENT PRIMARY KEY,
pelapor VARCHAR(100),
penduduk_id INT,
deskripsi TEXT NOT NULL,
lat DOUBLE,
lng DOUBLE,
foto VARCHAR(255),
urgensi ENUM('rendah','sedang','tinggi','darurat') DEFAULT 'sedang',
status ENUM('pending','diverifikasi','diproses','selesai') DEFAULT 'pending',
diverifikasi_oleh INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (penduduk_id) REFERENCES penduduk(id) ON DELETE SET NULL,
FOREIGN KEY (diverifikasi_oleh) REFERENCES user(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO laporan (pelapor,penduduk_id,deskripsi,lat,lng,urgensi,status) VALUES
('Anonim', 1,'Pak Ahmad sakit keras sudah seminggu dan tidak punya biaya berobat. Kondisi sangat memprihatinkan.',0.02505,109.34105,'darurat','pending'),
('Pak RT 02', 8,'Keluarga Pak Samsul di Jl. Mawar sudah 3 hari tidak makan. Sangat membutuhkan bantuan pangan segera.',0.01955,109.34605,'darurat','diverifikasi'),
('Bu Dewi', NULL,'Ada anak putus sekolah di RT 003 karena orang tuanya tidak mampu bayar uang gedung.',0.02810,109.34410,'tinggi','pending'),
('Pengurus Masjid',10,'Muhammad Yusuf butuh beasiswa lanjut SMA, keluarga tidak mampu.',0.01970,109.34580,'sedang','diproses'),
('Warga RT 001', NULL,'Jalan di Jl. Anggrek rusak parah, bahaya bagi warga lansia.',0.01760,109.35115,'rendah','pending');
-- ── 10. LOG AKTIVITAS ────────────────────────────────────────
CREATE TABLE log_aktivitas (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
aksi VARCHAR(50),
tabel VARCHAR(50),
data_id INT,
keterangan TEXT,
ip_address VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO log_aktivitas (user_id,aksi,tabel,data_id,keterangan) VALUES
(1,'LOGIN','user',1,'Login pertama kali'),
(1,'CREATE','histori_bantuan',1,'Salurkan sembako untuk Ahmad Fauzi'),
(4,'CREATE','histori_bantuan',5,'Salurkan sembako untuk Samsul Bahri'),
(1,'UPDATE','laporan',2,'Verifikasi laporan darurat');
-- ── 11. PESAN / CHAT ────────────────────────────────────────
CREATE TABLE pesan (
id INT AUTO_INCREMENT PRIMARY KEY,
dari_user INT NOT NULL,
ke_user INT,
isi TEXT NOT NULL,
dibaca TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (dari_user) REFERENCES user(id) ON DELETE CASCADE,
FOREIGN KEY (ke_user) REFERENCES user(id) ON DELETE SET NULL
) ENGINE=InnoDB;
INSERT INTO pesan (dari_user,ke_user,isi,dibaca) VALUES
(1,NULL,'Selamat datang di sistem WebGIS Kemiskinan UAS 06. Semua pengurus harap aktif memperbarui data.',1),
(4,NULL,'Sudah ada 3 laporan darurat baru masuk. Mohon segera ditindaklanjuti.',0),
(1,NULL,'Penyaluran bantuan bulan Januari 2024 sudah selesai untuk wilayah Pontianak Kota.',1);
-- ── 12. VIEWS ───────────────────────────────────────────────
CREATE OR REPLACE VIEW v_penduduk AS
SELECT
p.*,
TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,
k.no_kk, k.rt, k.rw, k.kelurahan, k.kecamatan,
ri.nama AS nama_ibadah, ri.jenis AS jenis_ibadah,
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') AS total_bantuan_diterima
FROM penduduk p
LEFT JOIN keluarga k ON p.keluarga_id=k.id
LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id;
CREATE OR REPLACE VIEW v_statistik_ibadah AS
SELECT
ri.id, ri.nama, ri.jenis,
COUNT(p.id) AS total_penduduk,
SUM(p.status_ekonomi='miskin') AS total_miskin,
SUM(p.status_ekonomi='rentan') AS total_rentan,
SUM(p.status_ekonomi='mampu') AS total_mampu
FROM rumah_ibadah ri
LEFT JOIN penduduk p ON p.rumah_ibadah_id=ri.id AND p.status_hidup='hidup'
GROUP BY ri.id;
-- ── SELESAI ──────────────────────────────────────────────────
SELECT 'Database uas_06 berhasil dibuat!' AS status;
+49
View File
@@ -0,0 +1,49 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'list';
if ($aksi === 'list') {
$res=$conn->query("SELECT ri.*,
(SELECT COUNT(*) FROM penduduk p WHERE p.rumah_ibadah_id=ri.id AND p.status_hidup='hidup') AS total_penduduk,
(SELECT COUNT(*) FROM penduduk p WHERE p.rumah_ibadah_id=ri.id AND p.status_ekonomi='miskin' AND p.status_hidup='hidup') AS total_miskin
FROM rumah_ibadah ri ORDER BY ri.nama");
if(!$res) json_out(['error'=>$conn->error],500);
$rows=[]; while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'simpan') {
$nm=$conn->real_escape_string($_POST['nama']??'');
$jn=$conn->real_escape_string($_POST['jenis']??'masjid');
$kt=$conn->real_escape_string($_POST['kontak']??'');
$al=$conn->real_escape_string($_POST['alamat']??'');
$lat=(float)($_POST['lat']??0);
$lng=(float)($_POST['lng']??0);
$rad=(float)($_POST['radius']??500);
$conn->query("INSERT INTO rumah_ibadah (nama,jenis,kontak,alamat,lat,lng,radius) VALUES ('$nm','$jn','$kt','$al',$lat,$lng,$rad)");
if($conn->error) json_out(['error'=>$conn->error],500);
json_out(['success'=>true,'id'=>$conn->insert_id]);
}
if ($aksi === 'edit') {
$id=(int)($_POST['id']??0);
$nm=$conn->real_escape_string($_POST['nama']??'');
$jn=$conn->real_escape_string($_POST['jenis']??'masjid');
$kt=$conn->real_escape_string($_POST['kontak']??'');
$al=$conn->real_escape_string($_POST['alamat']??'');
$rad=(float)($_POST['radius']??500);
$conn->query("UPDATE rumah_ibadah SET nama='$nm',jenis='$jn',kontak='$kt',alamat='$al',radius=$rad WHERE id=$id");
if($conn->error) json_out(['error'=>$conn->error],500);
json_out(['success'=>true]);
}
if ($aksi === 'hapus') {
$id=(int)($_POST['id']??0);
$conn->query("UPDATE penduduk SET rumah_ibadah_id=NULL WHERE rumah_ibadah_id=$id");
$conn->query("DELETE FROM rumah_ibadah WHERE id=$id");
json_out(['success'=>true]);
}
+1671
View File
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
<?php
// ============================================================
// koneksi.php Database uas_06
// ============================================================
$host = getenv('DB_HOST') ?: 'localhost';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASSWORD') ?: '';
$db = getenv('DB_NAME') ?: 'uas_06';
$conn = mysqli_connect($host, $user, $pass, $db);
if (!$conn) {
http_response_code(500);
header('Content-Type: application/json');
die(json_encode(['error' => 'Koneksi database gagal: ' . mysqli_connect_error()]));
}
$conn->set_charset('utf8mb4');
function log_aktivitas($conn, $user_id, $aksi, $tabel, $data_id = null, $ket = '') {
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$stmt = $conn->prepare("INSERT INTO log_aktivitas (user_id,aksi,tabel,data_id,keterangan,ip_address) VALUES (?,?,?,?,?,?)");
if($stmt){
$stmt->bind_param('ississ', $user_id, $aksi, $tabel, $data_id, $ket, $ip);
$stmt->execute();
$stmt->close();
}
}
function json_out($data, $code = 200) {
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
function requireLogin() {
session_start();
if (empty($_SESSION['user_id'])) {
json_out(['error' => 'Belum login', 'redirect' => 'login.php'], 401);
}
return $_SESSION['user'];
}
+85
View File
@@ -0,0 +1,85 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'list';
if ($aksi === 'list') {
$where=['1=1'];
if(!empty($_GET['status'])){$where[]="l.status='".$conn->real_escape_string($_GET['status'])."'";}
if(!empty($_GET['urgensi'])){$where[]="l.urgensi='".$conn->real_escape_string($_GET['urgensi'])."'";}
if(!empty($_GET['q'])){
$q=$conn->real_escape_string($_GET['q']);
$where[]="(l.pelapor LIKE '%$q%' OR l.deskripsi LIKE '%$q%')";
}
$w=implode(' AND ',$where);
$sql="SELECT l.*,p.nama AS nama_penduduk,p.status_ekonomi,p.nik,u.nama AS nama_verifikator
FROM laporan l
LEFT JOIN penduduk p ON l.penduduk_id=p.id
LEFT JOIN user u ON l.diverifikasi_oleh=u.id
WHERE $w
ORDER BY FIELD(l.urgensi,'darurat','tinggi','sedang','rendah'),l.created_at DESC";
$res=$conn->query($sql);
if(!$res) json_out(['error'=>$conn->error],500);
$rows=[]; while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'detail') {
$id=(int)($_GET['id']??0);
$res=$conn->query("SELECT l.*,p.nama AS nama_penduduk,u.nama AS nama_verifikator FROM laporan l LEFT JOIN penduduk p ON l.penduduk_id=p.id LEFT JOIN user u ON l.diverifikasi_oleh=u.id WHERE l.id=$id LIMIT 1");
json_out($res->fetch_assoc()??['error'=>'Tidak ditemukan']);
}
if ($aksi === 'kirim') {
$pel=$conn->real_escape_string(trim($_POST['pelapor']??'Anonim'));
if(empty($pel)) $pel='Anonim';
$desk=$conn->real_escape_string(trim($_POST['deskripsi']??''));
if(!$desk) json_out(['error'=>'Deskripsi wajib'],400);
$lat=!empty($_POST['lat'])?(float)$_POST['lat']:'NULL';
$lng=!empty($_POST['lng'])?(float)$_POST['lng']:'NULL';
$urg=$conn->real_escape_string($_POST['urgensi']??'sedang');
$pid=!empty($_POST['penduduk_id'])?(int)$_POST['penduduk_id']:'NULL';
$foto='NULL';
if(!empty($_FILES['foto']['name'])){
$ext=pathinfo($_FILES['foto']['name'],PATHINFO_EXTENSION);
$fname='laporan_'.time().'.'.$ext;
$uploadDir=__DIR__.'/uploads/bukti/';
if(!is_dir($uploadDir)) mkdir($uploadDir,0777,true);
move_uploaded_file($_FILES['foto']['tmp_name'],$uploadDir.$fname);
$foto="'".$fname."'";
}
$conn->query("INSERT INTO laporan (pelapor,penduduk_id,deskripsi,lat,lng,foto,urgensi) VALUES ('$pel',$pid,'$desk',$lat,$lng,$foto,'$urg')");
if($conn->error) json_out(['error'=>$conn->error],500);
if(!empty($_SESSION['user_id'])){
log_aktivitas($conn,(int)$_SESSION['user_id'],'CREATE','laporan',$conn->insert_id,'Kirim laporan oleh '.$pel);
}
json_out(['success'=>true,'id'=>$conn->insert_id]);
}
if ($aksi === 'edit') {
$id=(int)($_POST['id']??0);
$desk=$conn->real_escape_string($_POST['deskripsi']??'');
$urg=$conn->real_escape_string($_POST['urgensi']??'sedang');
$pel=$conn->real_escape_string($_POST['pelapor']??'');
$status=$conn->real_escape_string($_POST['status']??'pending');
$uid=!empty($_SESSION['user_id'])?(int)$_SESSION['user_id']:'NULL';
$conn->query("UPDATE laporan SET pelapor='$pel',deskripsi='$desk',urgensi='$urg',status='$status',diverifikasi_oleh=$uid WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'update_status') {
$id=(int)($_POST['id']??0);
$status=$conn->real_escape_string($_POST['status']??'pending');
$uid=!empty($_SESSION['user_id'])?(int)$_SESSION['user_id']:'NULL';
$conn->query("UPDATE laporan SET status='$status',diverifikasi_oleh=$uid WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'hapus') {
$id=(int)($_POST['id']??0);
$conn->query("DELETE FROM laporan WHERE id=$id");
json_out(['success'=>true]);
}
+110
View File
@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Login WebGIS Kemiskinan UAS 06</title>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"/>
<style>
:root{--bg:#0d1117;--surface:#161b22;--card:#1c2230;--border:#30363d;--text:#e6edf3;--muted:#8b949e;--accent:#58a6ff;--red:#f85149;--green:#3fb950}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Plus Jakarta Sans',sans-serif;background:var(--bg);color:var(--text);min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.wrap{width:100%;max-width:900px;display:grid;grid-template-columns:1fr 1fr;gap:0;border-radius:16px;overflow:hidden;box-shadow:0 8px 48px rgba(0,0,0,.7);border:1px solid var(--border)}
.left{background:linear-gradient(135deg,#0d1117 0%,#1a2332 100%);padding:48px 40px;display:flex;flex-direction:column;justify-content:center;position:relative;overflow:hidden}
.left::before{content:'';position:absolute;top:-60px;right:-60px;width:240px;height:240px;background:rgba(88,166,255,.06);border-radius:50%}
.left::after{content:'';position:absolute;bottom:-40px;left:-40px;width:180px;height:180px;background:rgba(63,185,80,.05);border-radius:50%}
.left-ico{font-size:40px;margin-bottom:20px;display:block}
.left h1{font-size:26px;font-weight:800;letter-spacing:-0.5px;margin-bottom:10px;line-height:1.2}
.left p{font-size:13px;color:var(--muted);line-height:1.6;margin-bottom:28px}
.feat{display:flex;align-items:center;gap:10px;margin-bottom:10px;font-size:12px;color:var(--muted)}
.feat i{color:var(--accent);width:16px}
.right{background:var(--surface);padding:48px 40px}
.right h2{font-size:20px;font-weight:800;margin-bottom:6px}
.right .sub{font-size:12px;color:var(--muted);margin-bottom:28px}
.fg{margin-bottom:16px}
.fg label{font-size:11px;font-weight:700;color:var(--muted);display:block;margin-bottom:5px;text-transform:uppercase;letter-spacing:.4px}
.fg input{width:100%;background:var(--card);border:1px solid var(--border);color:var(--text);padding:10px 13px;border-radius:8px;font-size:13px;font-family:inherit;outline:none;transition:border .15s}
.fg input:focus{border-color:var(--accent)}
.btn-login{width:100%;background:var(--accent);color:#0d1117;border:none;padding:11px;border-radius:8px;font-size:14px;font-weight:800;font-family:inherit;cursor:pointer;transition:background .15s;margin-top:4px}
.btn-login:hover{background:#79c0ff}
.btn-login:disabled{opacity:.6;cursor:not-allowed}
.err{background:rgba(248,81,73,.08);border:1px solid rgba(248,81,73,.25);border-radius:7px;padding:9px 12px;font-size:12px;color:var(--red);margin-bottom:14px;display:none;align-items:center;gap:7px}
.demo-box{background:var(--card);border:1px solid var(--border);border-radius:8px;padding:14px;margin-top:20px}
.demo-box strong{display:block;font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:1px;margin-bottom:10px}
.demo-row{display:flex;align-items:center;justify-content:space-between;padding:5px 0;border-bottom:1px solid var(--border);font-size:12px}
.demo-row:last-child{border:none}
.demo-row .role{color:var(--muted);font-size:11px}
.demo-row .creds{font-size:11px;color:var(--accent);cursor:pointer}
.demo-row .creds:hover{text-decoration:underline}
@media(max-width:650px){.wrap{grid-template-columns:1fr}.left{display:none}}
</style>
</head>
<body>
<div class="wrap">
<div class="left">
<span class="left-ico">🗺️</span>
<h1>WebGIS Pengentasan Kemiskinan</h1>
<p>Sistem informasi geografis berbasis masyarakat untuk monitoring dan pengentasan kemiskinan yang terintegrasi dengan rumah ibadah.</p>
<div class="feat"><i class="fas fa-map-marked-alt"></i> Peta sebaran penduduk real-time</div>
<div class="feat"><i class="fas fa-gift"></i> Manajemen bantuan sosial</div>
<div class="feat"><i class="fas fa-flag"></i> Sistem laporan masyarakat</div>
<div class="feat"><i class="fas fa-chart-bar"></i> Dashboard statistik kemiskinan</div>
<div class="feat"><i class="fas fa-comments"></i> Komunikasi antar pengurus</div>
<div class="feat"><i class="fas fa-user-shield"></i> Sistem multi-role & autentikasi</div>
</div>
<div class="right">
<h2>Masuk ke Sistem</h2>
<p class="sub">Silakan login dengan akun yang telah terdaftar</p>
<div class="err" id="err"><i class="fas fa-exclamation-circle"></i><span id="err-txt"></span></div>
<form onsubmit="doLogin(event)">
<div class="fg"><label>Email</label><input type="email" id="email" placeholder="email@domain.com" required autofocus></div>
<div class="fg"><label>Password</label><input type="password" id="pass" placeholder="••••••••" required></div>
<button type="submit" class="btn-login" id="btn-submit"><i class="fas fa-sign-in-alt"></i> Masuk</button>
</form>
<div class="demo-box">
<strong>Akun Demo klik untuk isi otomatis</strong>
<div class="demo-row">
<div><div style="font-weight:700">Admin/Pengurus</div><div class="role">Akses penuh input & verifikasi</div></div>
<span class="creds" onclick="fillDemo('admin@uas.id','password')">Gunakan </span>
</div>
<div class="demo-row">
<div><div style="font-weight:700">Pimpinan Daerah</div><div class="role">Read-only + dashboard</div></div>
<span class="creds" onclick="fillDemo('pimpinan@uas.id','password')">Gunakan </span>
</div>
<div class="demo-row">
<div><div style="font-weight:700">Masyarakat</div><div class="role">Hanya lihat & laporan</div></div>
<span class="creds" onclick="fillDemo('warga@uas.id','password')">Gunakan </span>
</div>
</div>
</div>
</div>
<script>
function fillDemo(e,p){
document.getElementById('email').value=e;
document.getElementById('pass').value=p;
document.getElementById('email').focus();
}
function doLogin(e){
e.preventDefault();
const btn=document.getElementById('btn-submit');
btn.disabled=true; btn.innerHTML='<i class="fas fa-spinner fa-spin"></i> Memverifikasi...';
document.getElementById('err').style.display='none';
const body=new URLSearchParams({aksi:'login',email:document.getElementById('email').value,password:document.getElementById('pass').value});
fetch('auth.php',{method:'POST',body}).then(r=>r.json()).then(d=>{
if(d.login){ window.location.href='index.php'; }
else {
const el=document.getElementById('err');
document.getElementById('err-txt').textContent=d.error||'Login gagal';
el.style.display='flex';
btn.disabled=false; btn.innerHTML='<i class="fas fa-sign-in-alt"></i> Masuk';
}
}).catch(()=>{
document.getElementById('err-txt').textContent='Tidak dapat terhubung ke server';
document.getElementById('err').style.display='flex';
btn.disabled=false; btn.innerHTML='<i class="fas fa-sign-in-alt"></i> Masuk';
});
}
</script>
</body>
</html>
+188
View File
@@ -0,0 +1,188 @@
<?php
error_reporting(0);
ini_set('display_errors', 0);
ob_start();
session_start();
include 'koneksi.php';
ob_clean(); // buang output apapun sebelum json_out
$aksi = $_REQUEST['aksi'] ?? 'list';
// ── LIST ─────────────────────────────────────────────────────
if ($aksi === 'list') {
$where = ["p.status_hidup='hidup'"];
$params = []; $types = '';
if (!empty($_GET['status_ekonomi'])) { $where[] = "p.status_ekonomi=?"; $params[] = $_GET['status_ekonomi']; $types .= 's'; }
if (!empty($_GET['rumah_ibadah_id'])) { $where[] = "p.rumah_ibadah_id=?"; $params[] = (int)$_GET['rumah_ibadah_id']; $types .= 'i'; }
if (!empty($_GET['status_bantuan'])) {
if ($_GET['status_bantuan'] === 'sudah') $where[] = "p.id IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')";
else $where[] = "p.id NOT IN (SELECT DISTINCT penduduk_id FROM histori_bantuan WHERE status='disalurkan')";
}
if (!empty($_GET['kelurahan'])) { $where[] = "k.kelurahan LIKE ?"; $params[] = '%'.$_GET['kelurahan'].'%'; $types .= 's'; }
if (!empty($_GET['penghasilan_min'])) { $where[] = "p.penghasilan>=?"; $params[] = (float)$_GET['penghasilan_min']; $types .= 'd'; }
if (!empty($_GET['penghasilan_max'])) { $where[] = "p.penghasilan<=?"; $params[] = (float)$_GET['penghasilan_max']; $types .= 'd'; }
if (!empty($_GET['q'])) { $like = '%'.$_GET['q'].'%'; $where[] = "(p.nama LIKE ? OR p.nik LIKE ?)"; $params[] = $like; $params[] = $like; $types .= 'ss'; }
$w = implode(' AND ', $where);
$sql = "SELECT p.id,p.nik,p.nama,p.jenis_kelamin,p.tanggal_lahir,
TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,
p.status_keluarga,p.status_ekonomi,p.status_hidup,
p.pekerjaan,p.penghasilan,p.pendidikan_terakhir,p.status_pendidikan,
p.lat,p.lng,p.no_hp,p.jenis_bantuan,p.created_at,
k.no_kk,k.rt,k.rw,k.kelurahan,k.kecamatan,
ri.nama AS nama_ibadah,
(SELECT COUNT(*) FROM histori_bantuan hb WHERE hb.penduduk_id=p.id AND hb.status='disalurkan') AS total_bantuan
FROM penduduk p
LEFT JOIN keluarga k ON p.keluarga_id=k.id
LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id
WHERE $w ORDER BY p.nama";
if ($params) {
$stmt = $conn->prepare($sql);
$stmt->bind_param($types,...$params);
$stmt->execute(); $res = $stmt->get_result(); $stmt->close();
} else {
$res = $conn->query($sql);
}
if(!$res) json_out(['error'=>$conn->error],500);
$rows = [];
while ($r = $res->fetch_assoc()) { $r['penghasilan']=(float)$r['penghasilan']; $rows[]=$r; }
json_out($rows);
}
// ── DETAIL ─────────────────────────────────────────────
if ($aksi === 'detail') {
$id = (int)($_GET['id']??0);
$stmt = $conn->prepare("SELECT p.*,TIMESTAMPDIFF(YEAR,p.tanggal_lahir,CURDATE()) AS umur,k.no_kk,k.rt,k.rw,k.kelurahan,k.kecamatan,ri.nama AS nama_ibadah,ri.jenis AS jenis_ibadah FROM penduduk p LEFT JOIN keluarga k ON p.keluarga_id=k.id LEFT JOIN rumah_ibadah ri ON p.rumah_ibadah_id=ri.id WHERE p.id=?");
$stmt->bind_param('i',$id); $stmt->execute();
$data = $stmt->get_result()->fetch_assoc(); $stmt->close();
if (!$data) json_out(['error'=>'Tidak ditemukan'],404);
if ($data['keluarga_id']) {
$stmt2 = $conn->prepare("SELECT p2.id,p2.nik,p2.nama,p2.jenis_kelamin,TIMESTAMPDIFF(YEAR,p2.tanggal_lahir,CURDATE()) AS umur,p2.status_keluarga,p2.pekerjaan,p2.status_ekonomi FROM penduduk p2 WHERE p2.keluarga_id=? AND p2.id!=?");
$stmt2->bind_param('ii',$data['keluarga_id'],$id); $stmt2->execute();
$res2=$stmt2->get_result(); $anggota=[];
while($r=$res2->fetch_assoc()) $anggota[]=$r;
$stmt2->close(); $data['anggota_keluarga']=$anggota;
} else $data['anggota_keluarga']=[];
$stmt3 = $conn->prepare("SELECT hb.*,b.nama AS nama_bantuan,b.jenis FROM histori_bantuan hb JOIN bantuan b ON hb.bantuan_id=b.id WHERE hb.penduduk_id=? ORDER BY hb.tanggal DESC");
$stmt3->bind_param('i',$id); $stmt3->execute();
$res3=$stmt3->get_result(); $histori=[];
while($r=$res3->fetch_assoc()) $histori[]=$r;
$stmt3->close(); $data['histori_bantuan']=$histori;
json_out($data);
}
// ── SIMPAN ─────────────────────────────────────────────
if ($aksi === 'simpan') {
$nik = trim($_POST['nik']??'');
$nama = trim($_POST['nama']??'');
$jk = $_POST['jenis_kelamin']??'L';
$tgl = $_POST['tanggal_lahir']??'';
$stk = $_POST['status_keluarga']??'anggota';
$stm = $_POST['status_perkawinan']??'belum_kawin';
$pek = $_POST['pekerjaan']??'';
$pgh = (float)($_POST['penghasilan']??0);
$sek = $_POST['status_ekonomi']??'rentan';
$pend = $_POST['pendidikan_terakhir']??'tidak_sekolah';
$spend= $_POST['status_pendidikan']??'tidak_sekolah';
$kid = !empty($_POST['keluarga_id'])?(int)$_POST['keluarga_id']:null;
$lat = !empty($_POST['lat'])?(float)$_POST['lat']:null;
$lng = !empty($_POST['lng'])?(float)$_POST['lng']:null;
$nohp = $_POST['no_hp']??'';
$jban = $_POST['jenis_bantuan']??'';
if (!$nik||!$nama||!$tgl) json_out(['error'=>'NIK, nama, dan tanggal lahir wajib diisi'],400);
$cek=$conn->prepare("SELECT id FROM penduduk WHERE nik=?");
$cek->bind_param('s',$nik); $cek->execute();
if($cek->get_result()->num_rows>0) { $cek->close(); json_out(['error'=>'NIK sudah terdaftar'],400); }
$cek->close();
// cari ibadah terdekat
$ibadah_id=null;
if($lat!==null && $lng!==null){
$si=$conn->prepare("SELECT id FROM rumah_ibadah ORDER BY (6371*acos(cos(radians(?))*cos(radians(lat))*cos(radians(lng)-radians(?))+sin(radians(?))*sin(radians(lat)))) ASC LIMIT 1");
$si->bind_param('ddd',$lat,$lng,$lat); $si->execute();
$ri=$si->get_result()->fetch_assoc(); $si->close();
$ibadah_id=$ri['id']??null;
}
// Build query with NULL handling
$lat_sql = $lat!==null ? $lat : 'NULL';
$lng_sql = $lng!==null ? $lng : 'NULL';
$kid_sql = $kid!==null ? $kid : 'NULL';
$ibd_sql = $ibadah_id!==null ? $ibadah_id : 'NULL';
$conn->query("INSERT INTO penduduk
(nik,nama,jenis_kelamin,tanggal_lahir,status_keluarga,status_perkawinan,
pekerjaan,penghasilan,status_ekonomi,pendidikan_terakhir,status_pendidikan,
keluarga_id,rumah_ibadah_id,lat,lng,no_hp,jenis_bantuan)
VALUES (
'".$conn->real_escape_string($nik)."',
'".$conn->real_escape_string($nama)."',
'".$conn->real_escape_string($jk)."',
'".$conn->real_escape_string($tgl)."',
'".$conn->real_escape_string($stk)."',
'".$conn->real_escape_string($stm)."',
'".$conn->real_escape_string($pek)."',
$pgh,
'".$conn->real_escape_string($sek)."',
'".$conn->real_escape_string($pend)."',
'".$conn->real_escape_string($spend)."',
$kid_sql,$ibd_sql,$lat_sql,$lng_sql,
'".$conn->real_escape_string($nohp)."',
'".$conn->real_escape_string($jban)."'
)");
if($conn->error) json_out(['error'=>$conn->error],500);
$new_id=$conn->insert_id;
if(!empty($_SESSION['user_id'])){
log_aktivitas($conn,(int)$_SESSION['user_id'],'CREATE','penduduk',$new_id,'Tambah penduduk: '.$nama);
}
$umur=(int)date_diff(date_create($tgl),date_create('today'))->y;
$warning=null;
if($umur>=7&&$umur<=12&&$spend!='sekolah') $warning='Umur 7-12 th seharusnya masih SD.';
elseif($umur>=13&&$umur<=15&&$spend!='sekolah') $warning='Umur 13-15 th seharusnya masih SMP.';
elseif($umur>=16&&$umur<=18&&$spend=='tidak_sekolah') $warning='Umur 16-18 th biasanya masih SMA/SMK, mohon verifikasi.';
json_out(['success'=>true,'id'=>$new_id,'warning'=>$warning]);
}
// ── EDIT ───────────────────────────────────────────────
if ($aksi === 'edit') {
$id=(int)($_POST['id']??0);
$nm = $conn->real_escape_string($_POST['nama']??'');
$jk = $conn->real_escape_string($_POST['jenis_kelamin']??'L');
$tgl = $conn->real_escape_string($_POST['tanggal_lahir']??'');
$stk = $conn->real_escape_string($_POST['status_keluarga']??'anggota');
$stm = $conn->real_escape_string($_POST['status_perkawinan']??'belum_kawin');
$sh = $conn->real_escape_string($_POST['status_hidup']??'hidup');
$pek = $conn->real_escape_string($_POST['pekerjaan']??'');
$pgh = (float)($_POST['penghasilan']??0);
$sek = $conn->real_escape_string($_POST['status_ekonomi']??'rentan');
$pend= $conn->real_escape_string($_POST['pendidikan_terakhir']??'tidak_sekolah');
$spend=$conn->real_escape_string($_POST['status_pendidikan']??'tidak_sekolah');
$nohp= $conn->real_escape_string($_POST['no_hp']??'');
$jban= $conn->real_escape_string($_POST['jenis_bantuan']??'');
$conn->query("UPDATE penduduk SET
nama='$nm',jenis_kelamin='$jk',tanggal_lahir='$tgl',
status_keluarga='$stk',status_perkawinan='$stm',status_hidup='$sh',
pekerjaan='$pek',penghasilan=$pgh,status_ekonomi='$sek',
pendidikan_terakhir='$pend',status_pendidikan='$spend',
no_hp='$nohp',jenis_bantuan='$jban'
WHERE id=$id");
if($conn->error) json_out(['error'=>$conn->error],500);
if(!empty($_SESSION['user_id'])){
log_aktivitas($conn,(int)$_SESSION['user_id'],'UPDATE','penduduk',$id,'Edit penduduk id='.$id);
}
json_out(['success'=>true]);
}
// ── HAPUS ──────────────────────────────────────────────
if ($aksi === 'hapus') {
$id=(int)($_POST['id']??0);
$conn->query("DELETE FROM histori_bantuan WHERE penduduk_id=$id");
$conn->query("DELETE FROM pelatihan WHERE penduduk_id=$id");
$conn->query("DELETE FROM laporan WHERE penduduk_id=$id");
$conn->query("DELETE FROM penduduk WHERE id=$id");
json_out(['success'=>true]);
}
+52
View File
@@ -0,0 +1,52 @@
<?php
error_reporting(0);
ini_set("display_errors", 0);
ob_start();
session_start();
include 'koneksi.php';
$aksi = $_REQUEST['aksi'] ?? 'list';
if ($aksi === 'list') {
$res=$conn->query("SELECT u.id,u.nama,u.email,u.aktif,u.created_at,r.nama AS role_nama,r.id AS role_id FROM user u JOIN role r ON u.role_id=r.id ORDER BY u.nama");
if(!$res) json_out(['error'=>$conn->error],500);
$rows=[]; while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}
if ($aksi === 'simpan') {
$nm=$conn->real_escape_string($_POST['nama']??'');
$em=$conn->real_escape_string($_POST['email']??'');
$pw=password_hash($_POST['password']??'password',PASSWORD_DEFAULT);
$rid=(int)($_POST['role_id']??1);
$cek=$conn->query("SELECT id FROM user WHERE email='$em'")->num_rows;
if($cek>0) json_out(['error'=>'Email sudah digunakan'],400);
$conn->query("INSERT INTO user (nama,email,password,role_id) VALUES ('$nm','$em','$pw',$rid)");
if($conn->error) json_out(['error'=>$conn->error],500);
json_out(['success'=>true,'id'=>$conn->insert_id]);
}
if ($aksi === 'edit') {
$id=(int)($_POST['id']??0);
$nm=$conn->real_escape_string($_POST['nama']??'');
$em=$conn->real_escape_string($_POST['email']??'');
$rid=(int)($_POST['role_id']??1);
$akt=(int)($_POST['aktif']??1);
$conn->query("UPDATE user SET nama='$nm',email='$em',role_id=$rid,aktif=$akt WHERE id=$id");
if(!empty($_POST['password'])){
$pw=password_hash($_POST['password'],PASSWORD_DEFAULT);
$conn->query("UPDATE user SET password='$pw' WHERE id=$id");
}
json_out(['success'=>true]);
}
if ($aksi === 'hapus') {
$id=(int)($_POST['id']??0);
$conn->query("DELETE FROM user WHERE id=$id");
json_out(['success'=>true]);
}
if ($aksi === 'roles') {
$res=$conn->query("SELECT * FROM role"); $rows=[];
while($r=$res->fetch_assoc()) $rows[]=$r;
json_out($rows);
}