feat: add dashboard feature with modular API endpoints and UI integration

This commit is contained in:
Syariffullah
2026-06-11 09:17:48 +07:00
parent b77d4f6869
commit db3ff299c1
13 changed files with 1054 additions and 17 deletions
+40 -2
View File
@@ -4,11 +4,29 @@ require_once '../auth_helper.php';
requireAdminOrPengelola();
include_once '../db_connect.php';
// Ambil info ibadah pengelola jika role pengelola
$currentUser = getCurrentUser();
$ibadahFilter = null; // null = admin (tidak dibatasi)
if ($currentUser && $currentUser['role'] === 'pengelola') {
$ibadah_id = $currentUser['ibadah_id'];
if (!$ibadah_id) {
echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']);
exit;
}
$res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id");
if (!$res || $res->num_rows === 0) {
echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']);
exit;
}
$ibadahFilter = $res->fetch_assoc();
}
$data = json_decode(file_get_contents("php://input"));
if (is_array($data)) {
$conn->begin_transaction();
$inserted = 0;
$skipped = 0;
$errors = [];
foreach ($data as $item) {
if (isset($item->lat) && isset($item->lng) && $item->lat !== '' && $item->lng !== '') {
@@ -18,6 +36,21 @@ if (is_array($data)) {
$lat = (float)$item->lat;
$lng = (float)$item->lng;
// Jika pengelola, cek apakah item berada dalam radius ibadahnya
if ($ibadahFilter !== null) {
$R = 6371000;
$lat1 = deg2rad((float)$ibadahFilter['lat']);
$lat2 = deg2rad($lat);
$dLat = $lat2 - $lat1;
$dLng = deg2rad($lng - (float)$ibadahFilter['lng']);
$a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2);
$dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a));
if ($dist > (float)$ibadahFilter['radius']) {
$skipped++;
continue; // Lewati item di luar radius
}
}
$query = "INSERT INTO penduduk_miskin (nama, kategori_bantuan, jumlah_jiwa, lat, lng)
VALUES ('$nama', '$kategori', $jumlah_jiwa, $lat, $lng)";
@@ -31,10 +64,15 @@ if (is_array($data)) {
if (empty($errors) && $inserted > 0) {
$conn->commit();
echo json_encode(["status" => "success", "message" => "Berhasil mengimpor $inserted data penduduk miskin."]);
$msg = "Berhasil mengimpor $inserted data penduduk miskin.";
if ($skipped > 0) $msg .= " ($skipped data di luar radius diabaikan.)";
echo json_encode(["status" => "success", "message" => $msg]);
} else if ($inserted === 0) {
$conn->rollback();
echo json_encode(["status" => "error", "message" => "Tidak ada data valid yang diimpor."]);
$msg = $skipped > 0
? "Semua $skipped data berada di luar radius rumah ibadah Anda, tidak ada yang diimpor."
: "Tidak ada data valid yang diimpor.";
echo json_encode(["status" => "error", "message" => $msg]);
} else {
$conn->rollback();
echo json_encode(["status" => "error", "message" => "Gagal mengimpor beberapa data. Transaksi dibatalkan.", "errors" => $errors]);
+32
View File
@@ -27,6 +27,38 @@ if (!empty($_POST)) {
}
}
// Validasi pengelola: hanya boleh tambah jika lokasi berada dalam radius ibadah yang dikelolanya
$currentUser = getCurrentUser();
if ($currentUser && $currentUser['role'] === 'pengelola') {
$ibadah_id = $currentUser['ibadah_id'];
if (!$ibadah_id) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']);
exit;
}
// Ambil data ibadah (lat, lng, radius)
$res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id");
if (!$res || $res->num_rows === 0) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']);
exit;
}
$ib = $res->fetch_assoc();
// Hitung jarak menggunakan Haversine formula
$R = 6371000; // meter
$lat1 = deg2rad((float)$ib['lat']);
$lat2 = deg2rad($lat);
$dLat = $lat2 - $lat1;
$dLng = deg2rad($lng - (float)$ib['lng']);
$a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2);
$dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a));
if ($dist > (float)$ib['radius']) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Lokasi penduduk di luar radius rumah ibadah Anda. Hanya boleh menambah penduduk dalam radius yang dikelola.']);
exit;
}
}
if ($lat != 0 && $lng != 0) {
$upload_dir = "../../uploads/";
if (!file_exists($upload_dir)) {
+43
View File
@@ -9,6 +9,49 @@ $data = json_decode(file_get_contents("php://input"));
if(!empty($data->id)) {
$id = (int)$data->id;
// Validasi pengelola: hanya boleh hapus penduduk dalam radius ibadah yang dikelolanya
$currentUser = getCurrentUser();
if ($currentUser && $currentUser['role'] === 'pengelola') {
$ibadah_id = $currentUser['ibadah_id'];
if (!$ibadah_id) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']);
exit;
}
// Ambil koordinat penduduk
$mRes = $conn->query("SELECT lat, lng FROM penduduk_miskin WHERE id=$id");
if (!$mRes || $mRes->num_rows === 0) {
echo json_encode(['status' => 'error', 'message' => 'Data penduduk tidak ditemukan.']);
exit;
}
$mRow = $mRes->fetch_assoc();
$pLat = (float)$mRow['lat'];
$pLng = (float)$mRow['lng'];
// Ambil data ibadah
$iRes = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id");
if (!$iRes || $iRes->num_rows === 0) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']);
exit;
}
$ib = $iRes->fetch_assoc();
// Hitung jarak Haversine
$R = 6371000;
$lat1 = deg2rad((float)$ib['lat']);
$lat2 = deg2rad($pLat);
$dLat = $lat2 - $lat1;
$dLng = deg2rad($pLng - (float)$ib['lng']);
$a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2);
$dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a));
if ($dist > (float)$ib['radius']) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Penduduk ini berada di luar radius rumah ibadah Anda. Tidak diizinkan menghapus.']);
exit;
}
}
$query = "DELETE FROM penduduk_miskin WHERE id=$id";
if($conn->query($query)) {
+41
View File
@@ -30,6 +30,47 @@ if (!empty($_POST)) {
}
}
// Validasi pengelola: hanya boleh edit penduduk yang lokasinya dalam radius ibadah yang dikelolanya
$currentUser = getCurrentUser();
if ($currentUser && $currentUser['role'] === 'pengelola') {
$ibadah_id = $currentUser['ibadah_id'];
if (!$ibadah_id) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Akun pengelola tidak terhubung ke rumah ibadah manapun.']);
exit;
}
$res = $conn->query("SELECT lat, lng, radius FROM rumah_ibadah WHERE id=$ibadah_id");
if (!$res || $res->num_rows === 0) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Rumah ibadah yang dikelola tidak ditemukan.']);
exit;
}
$ib = $res->fetch_assoc();
// Gunakan koordinat penduduk yang sedang diedit (dari DB jika lat/lng 0, atau dari input)
$checkLat = $lat;
$checkLng = $lng;
if ($checkLat == 0 && $checkLng == 0 && $id > 0) {
$mRes = $conn->query("SELECT lat, lng FROM penduduk_miskin WHERE id=$id");
if ($mRes && $mRow = $mRes->fetch_assoc()) {
$checkLat = (float)$mRow['lat'];
$checkLng = (float)$mRow['lng'];
}
}
$R = 6371000;
$lat1 = deg2rad((float)$ib['lat']);
$lat2 = deg2rad($checkLat);
$dLat = $lat2 - $lat1;
$dLng = deg2rad($checkLng - (float)$ib['lng']);
$a = sin($dLat/2)*sin($dLat/2) + cos($lat1)*cos($lat2)*sin($dLng/2)*sin($dLng/2);
$dist = $R * 2 * atan2(sqrt($a), sqrt(1-$a));
if ($dist > (float)$ib['radius']) {
http_response_code(403);
echo json_encode(['status' => 'error', 'message' => 'Penduduk ini berada di luar radius rumah ibadah Anda. Tidak diizinkan mengedit.']);
exit;
}
}
if ($id > 0) {
// Get current files to delete them if updated
$old_foto_rumah = null;