Files
uas-poverty-mapping/api.php
T
2026-06-10 20:20:15 +07:00

284 lines
13 KiB
PHP

<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
$db_host = getenv('DB_HOST') ?: 'localhost';
$db_port = getenv('DB_PORT') ?: '3406';
$db_name = getenv('DB_NAME') ?: 'sipkem';
$db_user = getenv('DB_USER') ?: 'mysql';
$db_pass = getenv('DB_PASS') ?: '';
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8", $user, $pass);
try {
$pdo = new PDO(
"mysql:host={$db_host};port={$db_port};dbname={$db_name};charset=utf8mb4",
$db_user, $db_pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['ok' => false, 'error' => 'Koneksi DB gagal: ' . $e->getMessage()]);
exit;
}
$body = json_decode(file_get_contents('php://input'), true) ?? [];
$action = $body['action'] ?? ($_GET['action'] ?? '');
function pt(float $lng, float $lat): string {
return "POINT($lng $lat)";
}
try {
switch ($action) {
// ── AUTH: REGISTER (Pengguna only) ──────────────────────────────
case 'register':
$nama = trim($body['nama'] ?? '');
$email = trim($body['email'] ?? '');
$pass = $body['password'] ?? '';
if (!$nama || !$email || strlen($pass) < 8) {
echo json_encode(['ok' => false, 'error' => 'Data tidak lengkap.']); break;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo json_encode(['ok' => false, 'error' => 'Format email tidak valid.']); break;
}
// Check duplicate
$chk = $pdo->prepare("SELECT id FROM users WHERE email = :e LIMIT 1");
$chk->execute(['e' => $email]);
if ($chk->fetch()) {
echo json_encode(['ok' => false, 'error' => 'Email sudah terdaftar.']); break;
}
$id = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0,0xffff),
mt_rand(0,0x0fff)|0x4000, mt_rand(0,0x3fff)|0x8000,
mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0,0xffff));
$hash = password_hash($pass, PASSWORD_BCRYPT);
$st = $pdo->prepare(
"INSERT INTO users (id, nama, email, password_hash, role)
VALUES (:id, :nama, :email, :hash, 'pengguna')"
);
$st->execute(['id' => $id, 'nama' => $nama, 'email' => $email, 'hash' => $hash]);
echo json_encode(['ok' => true]);
break;
// ── AUTH: LOGIN ─────────────────────────────────────────────────
case 'login':
$email = trim($body['email'] ?? '');
$pass = $body['password'] ?? '';
$role = $body['role'] ?? 'pengguna'; // 'pengguna' or 'pengurus'
if (!$email || !$pass) {
echo json_encode(['ok' => false, 'error' => 'Email dan kata sandi wajib diisi.']); break;
}
$st = $pdo->prepare("SELECT id, nama, email, password_hash, role FROM users WHERE email = :e LIMIT 1");
$st->execute(['e' => $email]);
$user = $st->fetch();
if (!$user || !password_verify($pass, $user['password_hash'])) {
echo json_encode(['ok' => false, 'error' => 'Email atau kata sandi salah.']); break;
}
// Role mismatch guard
if ($user['role'] !== $role) {
if ($role === 'pengurus') {
echo json_encode(['ok' => false, 'error' => 'Akun ini bukan akun Pengurus.']); break;
} else {
echo json_encode(['ok' => false, 'error' => 'Akun Pengurus tidak bisa masuk sebagai Pengguna.']); break;
}
}
echo json_encode([
'ok' => true,
'user' => ['id' => $user['id'], 'nama' => $user['nama'], 'role' => $user['role']],
]);
break;
// ── LOAD SEMUA DATA ──────────────────────────────────────────────
case 'load':
$ri = $pdo->query(
"SELECT id, nama, jenis, kontak, alamat,
ST_Y(geom) AS lat, ST_X(geom) AS lng,
jangkauan_m
FROM rumah_ibadah ORDER BY dibuat_pada ASC"
)->fetchAll();
$rm = $pdo->query(
"SELECT id, nama_kk, kontak, alamat,
ST_Y(geom) AS lat, ST_X(geom) AS lng,
ri_id, jarak_ke_ri_m
FROM rumah_miskin ORDER BY dibuat_pada ASC"
)->fetchAll();
echo json_encode(['ok' => true, 'ri' => $ri, 'rm' => $rm]);
break;
case 'add_ri':
$st = $pdo->prepare(
"INSERT INTO rumah_ibadah
(id, nama, jenis, kontak, alamat, geom, jangkauan_m)
VALUES (:id,:nama,:jenis,:kontak,:alamat,ST_GeomFromText(:geom),:jangkauan)"
);
$st->execute([
'id' => $body['id'],
'nama' => $body['nama'],
'jenis' => $body['jenis'],
'kontak' => $body['kontak'] ?? '-',
'alamat' => $body['alamat'] ?? '',
'geom' => pt((float)$body['lng'], (float)$body['lat']),
'jangkauan' => (int)($body['jangkauan_m'] ?? 500),
]);
echo json_encode(['ok' => true]);
break;
case 'add_rm':
$st = $pdo->prepare(
"INSERT INTO rumah_miskin
(id, nama_kk, kontak, alamat, geom, ri_id, jarak_ke_ri_m)
VALUES (:id,:nama,:kontak,:alamat,ST_GeomFromText(:geom),:ri_id,:jarak)"
);
$st->execute([
'id' => $body['id'],
'nama' => $body['nama_kk'],
'kontak' => $body['kontak'] ?? '-',
'alamat' => $body['alamat'] ?? '',
'geom' => pt((float)$body['lng'], (float)$body['lat']),
'ri_id' => $body['ri_id'] ?: null,
'jarak' => isset($body['jarak_ke_ri_m']) ? (float)$body['jarak_ke_ri_m'] : null,
]);
echo json_encode(['ok' => true]);
break;
case 'update_ri':
$st = $pdo->prepare("UPDATE rumah_ibadah SET nama=:nama,jenis=:jenis,kontak=:kontak WHERE id=:id");
$st->execute(['nama'=>$body['nama'],'jenis'=>$body['jenis'],'kontak'=>$body['kontak'],'id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'update_ri_range':
$pdo->prepare("UPDATE rumah_ibadah SET jangkauan_m=:j WHERE id=:id")
->execute(['j'=>(int)$body['jangkauan_m'],'id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'update_ri_pos':
$pdo->prepare("UPDATE rumah_ibadah SET geom=ST_GeomFromText(:geom),alamat=:alamat WHERE id=:id")
->execute(['geom'=>pt((float)$body['lng'],(float)$body['lat']),'alamat'=>$body['alamat']??'','id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'update_rm':
$pdo->prepare("UPDATE rumah_miskin SET nama_kk=:nama,kontak=:kontak WHERE id=:id")
->execute(['nama'=>$body['nama_kk'],'kontak'=>$body['kontak'],'id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'update_rm_pos':
$pdo->prepare("UPDATE rumah_miskin SET geom=ST_GeomFromText(:geom),alamat=:alamat WHERE id=:id")
->execute(['geom'=>pt((float)$body['lng'],(float)$body['lat']),'alamat'=>$body['alamat']??'','id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'update_rm_assignment':
$old = $pdo->prepare("SELECT ri_id FROM rumah_miskin WHERE id=:id");
$old->execute(['id' => $body['rm_id']]);
$row = $old->fetch();
$oldRI = $row ? $row['ri_id'] : null;
$newRI = $body['ri_id'] ?: null;
$pdo->prepare("UPDATE rumah_miskin SET ri_id=:ri_id,jarak_ke_ri_m=:jarak WHERE id=:id")
->execute(['ri_id'=>$newRI,'jarak'=>isset($body['jarak_ke_ri_m'])?(float)$body['jarak_ke_ri_m']:null,'id'=>$body['rm_id']]);
if ($oldRI !== $newRI) {
$pdo->prepare("INSERT INTO riwayat_binaan (rm_id,ri_id_lama,ri_id_baru,alasan) VALUES (:rm,:lama,:baru,:alasan)")
->execute(['rm'=>$body['rm_id'],'lama'=>$oldRI,'baru'=>$newRI,'alasan'=>$body['alasan']??'otomatis']);
}
echo json_encode(['ok' => true]);
break;
case 'delete_ri':
$pdo->prepare("DELETE FROM rumah_ibadah WHERE id=:id")->execute(['id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'delete_rm':
$pdo->prepare("DELETE FROM rumah_miskin WHERE id=:id")->execute(['id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
// ── BANTUAN TYPES ────────────────────────────────────────────────
case 'load_bantuan_types':
$rows = $pdo->query("SELECT id,nama,kategori,deskripsi FROM jenis_bantuan ORDER BY dibuat_pada ASC")->fetchAll();
echo json_encode(['ok' => true, 'data' => $rows]);
break;
case 'add_bantuan_type':
$id = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),
mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
$pdo->prepare("INSERT INTO jenis_bantuan (id,nama,kategori,deskripsi) VALUES (:id,:nama,:kategori,:deskripsi)")
->execute(['id'=>$body['id']??$id,'nama'=>$body['nama'],'kategori'=>$body['kategori']??'Lainnya','deskripsi'=>$body['deskripsi']??null]);
echo json_encode(['ok' => true]);
break;
case 'delete_bantuan_type':
$pdo->prepare("DELETE FROM jenis_bantuan WHERE id=:id")->execute(['id'=>$body['id']]);
echo json_encode(['ok' => true]);
break;
case 'load_riwayat_bantuan':
$st = $pdo->prepare(
"SELECT rb.id, rb.tanggal, rb.catatan,
jb.nama AS bantuan_nama, jb.kategori,
u.nama AS dikonfirmasi_oleh
FROM riwayat_bantuan rb
JOIN jenis_bantuan jb ON jb.id = rb.bantuan_id
LEFT JOIN users u ON u.id = rb.user_id
WHERE rb.rm_id = :rm_id
ORDER BY rb.tanggal DESC, rb.dibuat_pada DESC"
);
$st->execute(['rm_id' => $body['rm_id']]);
echo json_encode(['ok' => true, 'data' => $st->fetchAll()]);
break;
case 'add_riwayat_bantuan':
$id = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),
mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
$pdo->prepare(
"INSERT INTO riwayat_bantuan (id,rm_id,bantuan_id,tanggal,catatan,user_id)
VALUES (:id,:rm_id,:bantuan_id,:tanggal,:catatan,:user_id)"
)->execute([
'id' => $body['id'] ?? $id,
'rm_id' => $body['rm_id'],
'bantuan_id' => $body['bantuan_id'],
'tanggal' => $body['tanggal'],
'catatan' => $body['catatan'] ?? null,
'user_id' => $body['user_id'] ?? null,
]);
echo json_encode(['ok' => true]);
break;
default:
http_response_code(400);
echo json_encode(['ok' => false, 'error' => "Action tidak dikenal: $action"]);
}
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
}