Files
2026-06-10 18:54:25 +07:00

306 lines
13 KiB
PHP

<?php
// api/laporan.php — Pelaporan Warga oleh Kontributor & Koordinator
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
require_once '../config/db.php';
require_once 'middleware.php';
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'POST' && isset($_POST['_method'])) {
$method = strtoupper($_POST['_method']);
}
$action = $_GET['action'] ?? '';
try {
switch ($method) {
// ── GET: List laporan ──────────────────────────────────────────────────
case 'GET':
$currentUser = requireAuth(['admin', 'petugas', 'koordinator', 'kontributor']);
$role = $currentUser['role'];
$userId = (int)$currentUser['id'];
// Jika ada action=stats untuk admin dashboard
if ($action === 'stats') {
if (!in_array($role, ['admin', 'petugas'])) {
http_response_code(403);
echo json_encode(['success' => false, 'message' => 'Forbidden']);
exit;
}
$stmtStats = $pdo->query("
SELECT status, COUNT(*) as jumlah
FROM laporan_warga
GROUP BY status
");
$stats = [];
while ($r = $stmtStats->fetch(PDO::FETCH_ASSOC)) {
$stats[$r['status']] = (int)$r['jumlah'];
}
$stmtTotal = $pdo->query("SELECT COUNT(*) FROM laporan_warga");
echo json_encode(['success' => true, 'stats' => $stats, 'total' => (int)$stmtTotal->fetchColumn()]);
exit;
}
// Filter berdasarkan role
$where = [];
$params = [];
// Jika ada action=get_petugas
if ($action === 'get_petugas') {
if (!in_array($role, ['admin', 'petugas'])) {
http_response_code(403); echo json_encode(['success' => false, 'message' => 'Forbidden']); exit;
}
$stmt = $pdo->query("SELECT username FROM users WHERE role = 'petugas' ORDER BY username ASC");
$petugas = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo json_encode(['success' => true, 'petugas' => $petugas]);
exit;
}
if ($role === 'kontributor') {
// Kontributor hanya lihat laporan milik sendiri
$where[] = 'lw.pelapor_id = ?';
$params[] = $userId;
} elseif ($role === 'koordinator') {
// Koordinator lihat laporan dari wilayahnya + laporan milik sendiri
$where[] = '(lw.pelapor_id = ? OR lw.koordinator_ibadah_id = ?)';
$params[] = $userId;
$params[] = !empty($currentUser['rumah_ibadah_id']) ? (int)$currentUser['rumah_ibadah_id'] : 0;
} elseif ($role === 'petugas') {
// Petugas hanya lihat laporan yang ditugaskan ke mereka
$where[] = 'lw.ditugaskan_ke = ?';
$params[] = $currentUser['username'];
}
// Admin: lihat semua
// Filter status
if (!empty($_GET['status'])) {
$where[] = 'lw.status = ?';
$params[] = $_GET['status'];
}
// Filter prioritas
if (!empty($_GET['prioritas'])) {
$where[] = 'lw.prioritas = ?';
$params[] = $_GET['prioritas'];
}
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
$sql = "
SELECT
lw.*,
rw.nama_kepala_keluarga,
rw.kelurahan,
rw.kecamatan,
rw.kategori_kemiskinan,
rw.status_bantuan,
u.username AS pelapor_nama,
u.role AS pelapor_role
FROM laporan_warga lw
JOIN rumah_warga rw ON rw.id = lw.rumah_warga_id
JOIN users u ON u.id = lw.pelapor_id
$whereSql
ORDER BY lw.created_at DESC
LIMIT 100
";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Summary counts for filter badges
$stmtSummary = $pdo->query("SELECT status, COUNT(*) as n FROM laporan_warga GROUP BY status");
$summary = [];
while ($r = $stmtSummary->fetch(PDO::FETCH_ASSOC)) {
$summary[$r['status']] = (int)$r['n'];
}
$response = ['success' => true, 'data' => $data, 'summary' => $summary, 'total' => count($data)];
// Sertakan list petugas jika user admin
if ($role === 'admin' || $role === 'petugas') {
$stmtP = $pdo->query("SELECT username FROM users WHERE role = 'petugas' ORDER BY username ASC");
$response['petugas'] = $stmtP->fetchAll(PDO::FETCH_COLUMN);
}
echo json_encode($response);
break;
// ── POST: Buat laporan baru ──────────────────────────────────────────
case 'POST':
$currentUser = requireAuth(['koordinator', 'kontributor']);
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
$rumahWargaId = (int)($input['rumah_warga_id'] ?? 0);
$jenisLaporan = trim($input['jenis_laporan'] ?? '');
$deskripsi = trim($input['deskripsi'] ?? '');
// Penentuan prioritas otomatis berdasarkan jenis laporan
$prioritasMap = [
'warga_meninggal' => 'tinggi',
'warga_pindah' => 'tinggi',
'warga_mampu' => 'tinggi',
'data_ganda' => 'sedang',
'data_tidak_sesuai'=> 'sedang',
'lainnya' => 'rendah'
];
$prioritas = $prioritasMap[$jenisLaporan] ?? 'sedang';
if (!$rumahWargaId || !$jenisLaporan || !$deskripsi) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Data tidak lengkap: rumah_warga_id, jenis_laporan, dan deskripsi wajib diisi.']);
exit;
}
// Cek warga ada
$stmtCek = $pdo->prepare("SELECT id, nama_kepala_keluarga FROM rumah_warga WHERE id = ?");
$stmtCek->execute([$rumahWargaId]);
$warga = $stmtCek->fetch();
if (!$warga) {
http_response_code(404);
echo json_encode(['success' => false, 'message' => 'Data warga tidak ditemukan.']);
exit;
}
// Cek apakah laporan duplikat dalam 7 hari terakhir
$stmtDupCheck = $pdo->prepare("
SELECT id FROM laporan_warga
WHERE rumah_warga_id = ? AND pelapor_id = ?
AND status NOT IN ('selesai', 'ditolak')
AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
");
$stmtDupCheck->execute([$rumahWargaId, $currentUser['id']]);
if ($stmtDupCheck->fetch()) {
http_response_code(409);
echo json_encode(['success' => false, 'message' => 'Anda sudah membuat laporan untuk warga ini dalam 7 hari terakhir. Harap tunggu laporan sebelumnya diproses.']);
exit;
}
$koordinatorIbadahId = !empty($currentUser['rumah_ibadah_id']) ? (int)$currentUser['rumah_ibadah_id'] : null;
$stmtInsert = $pdo->prepare("
INSERT INTO laporan_warga
(rumah_warga_id, pelapor_id, koordinator_ibadah_id, jenis_laporan, deskripsi, prioritas, status)
VALUES (?, ?, ?, ?, ?, ?, 'pending')
");
$stmtInsert->execute([
$rumahWargaId,
$currentUser['id'],
$koordinatorIbadahId,
$jenisLaporan,
$deskripsi,
$prioritas,
]);
echo json_encode([
'success' => true,
'message' => 'Laporan berhasil dikirim. Admin akan meninjau laporan Anda segera.',
'id' => $pdo->lastInsertId()
]);
break;
case 'PUT':
$currentUser = requireAuth(['admin', 'petugas']);
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) $input = $_POST;
$id = (int)($input['id'] ?? 0);
$status = $input['status'] ?? '';
$catatanAdmin = trim($input['catatan_admin'] ?? '');
$ditugaskanKe = trim($input['ditugaskan_ke'] ?? '');
// Ambil dari old state
$stmtDok = $pdo->prepare("SELECT dokumentasi FROM laporan_warga WHERE id = ?");
$stmtDok->execute([$id]);
$oldDok = $stmtDok->fetchColumn();
$dokumentasi = trim($input['dokumentasi'] ?? $oldDok ?? '');
// Handle file upload
if (isset($_FILES['dokumentasi_file']) && $_FILES['dokumentasi_file']['error'] === UPLOAD_ERR_OK) {
$uploadDir = '../uploads/dokumentasi/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$ext = strtolower(pathinfo($_FILES['dokumentasi_file']['name'], PATHINFO_EXTENSION));
$allowedExts = ['jpg', 'jpeg', 'png', 'pdf'];
if (in_array($ext, $allowedExts)) {
$filename = 'dok_' . $id . '_' . time() . '.' . $ext;
$dest = $uploadDir . $filename;
if (move_uploaded_file($_FILES['dokumentasi_file']['tmp_name'], $dest)) {
$dokumentasi = 'uploads/dokumentasi/' . $filename;
}
}
}
$allowedStatus = ['pending', 'ditinjau', 'diproses', 'selesai', 'ditolak'];
if (!$id || !in_array($status, $allowedStatus)) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'ID dan status valid wajib diisi.']);
exit;
}
// Jika petugas, pastikan hanya bisa update dokumentasi, status, catatan. (ditugaskan_ke biarkan tetap)
if ($currentUser['role'] === 'petugas') {
$stmt = $pdo->prepare("
UPDATE laporan_warga
SET status = ?, catatan_admin = ?, dokumentasi = ?, updated_at = NOW()
WHERE id = ? AND ditugaskan_ke = ?
");
$stmt->execute([$status, $catatanAdmin, $dokumentasi, $id, $currentUser['username']]);
} else {
// Admin bisa update semua
$stmt = $pdo->prepare("
UPDATE laporan_warga
SET status = ?, catatan_admin = ?, ditugaskan_ke = ?, dokumentasi = ?, updated_at = NOW()
WHERE id = ?
");
$stmt->execute([$status, $catatanAdmin, $ditugaskanKe ?: null, $dokumentasi, $id]);
}
$statusLabel = [
'pending' => 'Menunggu',
'ditinjau' => 'Sedang Ditinjau',
'diproses' => 'Sedang Diproses',
'selesai' => 'Selesai',
'ditolak' => 'Ditolak',
];
echo json_encode([
'success' => true,
'message' => 'Laporan berhasil diperbarui ke status: ' . ($statusLabel[$status] ?? $status)
]);
break;
// ── DELETE: Hapus laporan (admin only) ──────────────────────────────
case 'DELETE':
$currentUser = requireAuth(['admin']);
$id = (int)($_GET['id'] ?? 0);
if (!$id) {
$input = json_decode(file_get_contents('php://input'), true);
$id = (int)($input['id'] ?? 0);
}
if (!$id) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'ID laporan wajib diisi.']);
exit;
}
$stmt = $pdo->prepare("DELETE FROM laporan_warga WHERE id = ?");
$stmt->execute([$id]);
echo json_encode(['success' => true, 'message' => 'Laporan berhasil dihapus.']);
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Kesalahan sistem: ' . $e->getMessage()]);
}