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); }