first commit
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
// ============================================================
|
||||
// API: Laporan Masyarakat
|
||||
// POST: publik (tanpa login, rate-limited) | GET: admin+walikota | PUT: admin
|
||||
// ============================================================
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
// ── POST: Submit laporan baru (tanpa auth, dengan rate limit) ─
|
||||
if ($method === 'POST') {
|
||||
// Rate limit: maks 5 submit per jam per IP
|
||||
$ip = getClientIP();
|
||||
if (!checkRateLimit($pdo, $ip)) {
|
||||
jsonResponse(null, 'Anda telah mencapai batas maksimal 5 laporan per jam. Silakan coba lagi nanti.', false, 429);
|
||||
}
|
||||
|
||||
// Ambil data dari form multipart (karena ada file upload)
|
||||
$nama_terlapor = clean($_POST['nama_terlapor'] ?? '');
|
||||
$nik_terlapor = clean($_POST['nik_terlapor'] ?? '');
|
||||
$nama_pelapor = clean($_POST['nama_pelapor'] ?? '');
|
||||
$no_hp = clean($_POST['no_hp'] ?? '');
|
||||
$alamat_terlapor = clean($_POST['alamat_terlapor'] ?? '');
|
||||
$lat = (float)($_POST['lat'] ?? 0);
|
||||
$lng = (float)($_POST['lng'] ?? 0);
|
||||
$deskripsi = clean($_POST['deskripsi'] ?? '');
|
||||
|
||||
if (!$alamat_terlapor || !$lat || !$lng || !$deskripsi) {
|
||||
jsonResponse(null, 'Alamat, koordinat, dan deskripsi wajib diisi.', false, 400);
|
||||
}
|
||||
|
||||
// Validasi NIK jika diisi (harus 16 digit angka)
|
||||
if ($nik_terlapor && !preg_match('/^\d{16}$/', $nik_terlapor)) {
|
||||
jsonResponse(null, 'NIK harus 16 digit angka.', false, 400);
|
||||
}
|
||||
|
||||
// Handle upload foto (opsional)
|
||||
$fotoPath = handleUpload('foto');
|
||||
|
||||
// Simpan laporan
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO laporan_masyarakat
|
||||
(nama_terlapor, nik_terlapor, nama_pelapor, no_hp, alamat_terlapor, lat, lng, deskripsi, foto, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'Baru')
|
||||
");
|
||||
$stmt->execute([
|
||||
$nama_terlapor ?: null,
|
||||
$nik_terlapor ?: null,
|
||||
$nama_pelapor ?: null,
|
||||
$no_hp ?: null,
|
||||
$alamat_terlapor,
|
||||
$lat, $lng,
|
||||
$deskripsi,
|
||||
$fotoPath
|
||||
]);
|
||||
|
||||
$newId = (int)$pdo->lastInsertId();
|
||||
|
||||
jsonResponse(['id' => $newId], 'Laporan berhasil dikirim. Terima kasih atas partisipasi Anda.');
|
||||
}
|
||||
|
||||
// ── GET: Daftar laporan (admin & walikota) ───────────────────
|
||||
if ($method === 'GET') {
|
||||
$user = requireRole(['admin', 'walikota']);
|
||||
|
||||
$id = isset($_GET['id']) ? (int)$_GET['id'] : null;
|
||||
|
||||
if ($id) {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT lm.*,
|
||||
u.nama AS nama_penangan,
|
||||
kk.nama_kepala_keluarga AS nama_kk_converted
|
||||
FROM laporan_masyarakat lm
|
||||
LEFT JOIN users u ON lm.ditangani_oleh = u.id
|
||||
LEFT JOIN keluarga_miskin kk ON lm.converted_to_kk_id = kk.id
|
||||
WHERE lm.id = ?
|
||||
");
|
||||
$stmt->execute([$id]);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
if (!$row) {
|
||||
jsonResponse(null, 'Laporan tidak ditemukan.', false, 404);
|
||||
}
|
||||
|
||||
jsonResponse($row, 'Detail laporan.');
|
||||
}
|
||||
|
||||
// Filter status
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($_GET['status'])) {
|
||||
$where[] = 'lm.status = ?';
|
||||
$params[] = clean($_GET['status']);
|
||||
}
|
||||
|
||||
$sql = "
|
||||
SELECT lm.*,
|
||||
u.nama AS nama_penangan,
|
||||
kk.nama_kepala_keluarga AS nama_kk_converted
|
||||
FROM laporan_masyarakat lm
|
||||
LEFT JOIN users u ON lm.ditangani_oleh = u.id
|
||||
LEFT JOIN keluarga_miskin kk ON lm.converted_to_kk_id = kk.id
|
||||
";
|
||||
if (!empty($where)) {
|
||||
$sql .= ' WHERE ' . implode(' AND ', $where);
|
||||
}
|
||||
$sql .= ' ORDER BY lm.created_at DESC';
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$rows = $stmt->fetchAll();
|
||||
|
||||
jsonResponse($rows, 'Daftar laporan masyarakat.');
|
||||
}
|
||||
|
||||
// ── PUT: Update status laporan (admin only) ──────────────────
|
||||
if ($method === 'PUT') {
|
||||
$user = requireRole(['admin']);
|
||||
$body = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
|
||||
$id = (int)($body['id'] ?? 0);
|
||||
$status = clean($body['status'] ?? '');
|
||||
$alasan_tolak = clean($body['alasan_tolak'] ?? '');
|
||||
$converted_to_kk = isset($body['converted_to_kk_id']) ? (int)$body['converted_to_kk_id'] : null;
|
||||
|
||||
if (!$id || !$status) {
|
||||
jsonResponse(null, 'ID dan status wajib diisi.', false, 400);
|
||||
}
|
||||
|
||||
$validStatus = ['Baru', 'Diverifikasi', 'Ditolak'];
|
||||
if (!in_array($status, $validStatus)) {
|
||||
jsonResponse(null, 'Status tidak valid. Pilih: Baru, Diverifikasi, atau Ditolak.', false, 400);
|
||||
}
|
||||
|
||||
// Jika ditolak, wajib ada alasan
|
||||
if ($status === 'Ditolak' && empty($alasan_tolak)) {
|
||||
jsonResponse(null, 'Alasan penolakan wajib diisi.', false, 400);
|
||||
}
|
||||
|
||||
// Update laporan
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE laporan_masyarakat SET
|
||||
status = ?,
|
||||
alasan_tolak = ?,
|
||||
ditangani_oleh = ?,
|
||||
converted_to_kk_id = ?
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([
|
||||
$status,
|
||||
$status === 'Ditolak' ? $alasan_tolak : null,
|
||||
$user['id'],
|
||||
$status === 'Diverifikasi' ? $converted_to_kk : null,
|
||||
$id
|
||||
]);
|
||||
|
||||
if ($stmt->rowCount() === 0) {
|
||||
jsonResponse(null, 'Laporan tidak ditemukan.', false, 404);
|
||||
}
|
||||
|
||||
jsonResponse(null, 'Status laporan berhasil diperbarui ke: ' . $status);
|
||||
}
|
||||
|
||||
// ── Method tidak didukung ────────────────────────────────────
|
||||
jsonResponse(null, 'Method tidak didukung.', false, 405);
|
||||
Reference in New Issue
Block a user