pertama dan terakhir
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
|
||||
// Warga miskin yang berada di luar semua radius bantuan rumah ibadah.
|
||||
$sql = "
|
||||
SELECT
|
||||
w.id,
|
||||
w.nama_kk,
|
||||
w.penghasilan,
|
||||
ST_AsGeoJSON(w.geom) AS geojson,
|
||||
ri.nama AS rumah_ibadah_terdekat,
|
||||
ST_Distance_Sphere(w.geom, ri.geom) AS jarak_meter,
|
||||
ri.radius_bantuan_meter,
|
||||
(ST_Distance_Sphere(w.geom, ri.geom) - ri.radius_bantuan_meter) AS selisih_meter
|
||||
FROM warga_miskin w
|
||||
JOIN rumah_ibadah ri
|
||||
JOIN (
|
||||
SELECT
|
||||
nearest_distance.warga_id,
|
||||
MIN(nearest_distance.jarak_meter) AS min_jarak_meter
|
||||
FROM (
|
||||
SELECT
|
||||
w2.id AS warga_id,
|
||||
ST_Distance_Sphere(w2.geom, ri2.geom) AS jarak_meter
|
||||
FROM warga_miskin w2
|
||||
CROSS JOIN rumah_ibadah ri2
|
||||
) nearest_distance
|
||||
GROUP BY nearest_distance.warga_id
|
||||
) nearest
|
||||
ON nearest.warga_id = w.id
|
||||
AND ABS(ST_Distance_Sphere(w.geom, ri.geom) - nearest.min_jarak_meter) < 0.001
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM rumah_ibadah ri_in_radius
|
||||
WHERE ST_Distance_Sphere(w.geom, ri_in_radius.geom) <= ri_in_radius.radius_bantuan_meter
|
||||
)
|
||||
GROUP BY w.id
|
||||
ORDER BY selisih_meter DESC
|
||||
";
|
||||
|
||||
$stmt = $pdo->query($sql);
|
||||
$features = [];
|
||||
|
||||
while ($r = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($r['geojson']),
|
||||
'properties' => [
|
||||
'id' => (int)$r['id'],
|
||||
'nama_kk' => $r['nama_kk'],
|
||||
'jarak_km' => round(((float)$r['jarak_meter']) / 1000, 2),
|
||||
'radius_km' => round(((int)$r['radius_bantuan_meter']) / 1000, 2),
|
||||
'selisih_km' => round(((float)$r['selisih_meter']) / 1000, 2),
|
||||
'rumah_ibadah_terdekat' => $r['rumah_ibadah_terdekat']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Blank Spot');
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/session.php';
|
||||
|
||||
/**
|
||||
* Shared response helper for all API endpoints
|
||||
*/
|
||||
header('Content-Type: application/json');
|
||||
$allowedOrigin = getenv('CORS_ALLOWED_ORIGIN');
|
||||
if ($allowedOrigin !== false && $allowedOrigin !== '') {
|
||||
header('Access-Control-Allow-Origin: ' . $allowedOrigin);
|
||||
header('Vary: 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; }
|
||||
|
||||
function sendSuccess($data, string $message = 'OK', int $code = 200): void {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit;
|
||||
}
|
||||
|
||||
function sendError(string $message = 'Bad Request', int $code = 400): void {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message, 'data' => null]);
|
||||
exit;
|
||||
}
|
||||
|
||||
function getInput(): array {
|
||||
return json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
}
|
||||
|
||||
function requireApiRole(string $role): void {
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
startAppSession();
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['user_id'], $_SESSION['role'])) {
|
||||
sendError('Unauthorized', 401);
|
||||
}
|
||||
|
||||
if ($_SESSION['role'] !== $role) {
|
||||
sendError('Forbidden', 403);
|
||||
}
|
||||
}
|
||||
|
||||
function requireAdminForMutation(): void {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
requireApiRole('admin');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection(); $method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT id,nama,jenis_jalan,created_at,ST_AsGeoJSON(geom) as geojson FROM jalan ORDER BY id DESC");
|
||||
$features=[];
|
||||
while($r=$stmt->fetch()) $features[]=['type'=>'Feature','geometry'=>json_decode($r['geojson']),'properties'=>['id'=>$r['id'],'nama'=>$r['nama'],'jenis_jalan'=>$r['jenis_jalan'],'created_at'=>$r['created_at']]];
|
||||
sendSuccess(['type'=>'FeatureCollection','features'=>$features],'Data Jalan'); break;
|
||||
case 'POST':
|
||||
$d=getInput(); if(empty($d['nama'])||empty($d['geometry'])) sendError('Nama & geometri wajib');
|
||||
$pdo->prepare("INSERT INTO jalan(nama,jenis_jalan,geom) VALUES(?,?,ST_GeomFromGeoJSON(?))")->execute([$d['nama'],$d['jenis_jalan']??'Lokal',json_encode($d['geometry'])]);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()],'Jalan disimpan',201); break;
|
||||
case 'PUT':
|
||||
$d=getInput(); $id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("UPDATE jalan SET nama=?,jenis_jalan=? WHERE id=?")->execute([$d['nama'],$d['jenis_jalan'],$id]);
|
||||
sendSuccess(null,'Jalan diperbarui'); break;
|
||||
case 'DELETE':
|
||||
$id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("DELETE FROM jalan WHERE id=?")->execute([$id]); sendSuccess(null,'Jalan dihapus'); break;
|
||||
default: sendError('Method not allowed',405);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection(); $method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT id,nama_pemilik,status_kepemilikan,luas,created_at,ST_AsGeoJSON(geom) as geojson FROM kavling ORDER BY id DESC");
|
||||
$features=[];
|
||||
while($r=$stmt->fetch()) $features[]=['type'=>'Feature','geometry'=>json_decode($r['geojson']),'properties'=>['id'=>$r['id'],'nama_pemilik'=>$r['nama_pemilik'],'status_kepemilikan'=>$r['status_kepemilikan'],'luas'=>$r['luas'],'created_at'=>$r['created_at']]];
|
||||
sendSuccess(['type'=>'FeatureCollection','features'=>$features],'Data Kavling'); break;
|
||||
case 'POST':
|
||||
$d=getInput(); if(empty($d['nama_pemilik'])||empty($d['status_kepemilikan'])||empty($d['geometry'])) sendError('Data tidak lengkap');
|
||||
$pdo->prepare("INSERT INTO kavling(nama_pemilik,status_kepemilikan,luas,geom) VALUES(?,?,?,ST_GeomFromGeoJSON(?))")->execute([$d['nama_pemilik'],$d['status_kepemilikan'],$d['luas']??0,json_encode($d['geometry'])]);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()],'Kavling disimpan',201); break;
|
||||
case 'PUT':
|
||||
$d=getInput(); $id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
if(!empty($d['geometry'])){
|
||||
$pdo->prepare("UPDATE kavling SET geom=ST_GeomFromGeoJSON(?) WHERE id=?")->execute([json_encode($d['geometry']),$id]);
|
||||
} else {
|
||||
$pdo->prepare("UPDATE kavling SET nama_pemilik=?,status_kepemilikan=?,luas=? WHERE id=?")->execute([$d['nama_pemilik'],$d['status_kepemilikan'],$d['luas']??0,$id]);
|
||||
}
|
||||
sendSuccess(null,'Kavling diperbarui'); break;
|
||||
case 'DELETE':
|
||||
$id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("DELETE FROM kavling WHERE id=?")->execute([$id]); sendSuccess(null,'Kavling dihapus'); break;
|
||||
default: sendError('Method not allowed',405);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection(); $method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT id,nama_kawasan,created_at,ST_AsGeoJSON(geom) as geojson FROM kawasan_kumuh ORDER BY id DESC");
|
||||
$features=[];
|
||||
while($r=$stmt->fetch()) $features[]=['type'=>'Feature','geometry'=>json_decode($r['geojson']),'properties'=>['id'=>$r['id'],'nama_kawasan'=>$r['nama_kawasan'],'created_at'=>$r['created_at']]];
|
||||
sendSuccess(['type'=>'FeatureCollection','features'=>$features],'Data Kawasan Kumuh'); break;
|
||||
case 'POST':
|
||||
$d=getInput(); if(empty($d['nama_kawasan'])||empty($d['geometry'])) sendError('Data tidak lengkap');
|
||||
$pdo->prepare("INSERT INTO kawasan_kumuh(nama_kawasan,geom) VALUES(?,ST_GeomFromGeoJSON(?))")->execute([$d['nama_kawasan'],json_encode($d['geometry'])]);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()],'Kawasan disimpan',201); break;
|
||||
case 'PUT':
|
||||
$d=getInput(); $id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("UPDATE kawasan_kumuh SET nama_kawasan=? WHERE id=?")->execute([$d['nama_kawasan'],$id]);
|
||||
sendSuccess(null,'Kawasan diperbarui'); break;
|
||||
case 'DELETE':
|
||||
$id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("DELETE FROM kawasan_kumuh WHERE id=?")->execute([$id]); sendSuccess(null,'Kawasan dihapus'); break;
|
||||
default: sendError('Method not allowed',405);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/session.php';
|
||||
startAppSession();
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
try {
|
||||
if ($method === 'GET') {
|
||||
// Jika parameter my_reports=1, hanya laporan milik user yang login
|
||||
// Jika tidak dan role=admin, ambil semua.
|
||||
$my_reports = $_GET['my_reports'] ?? 0;
|
||||
|
||||
$sql = "SELECT l.*, ST_X(l.geometry) as lng, ST_Y(l.geometry) as lat, u.nama_lengkap, u.username
|
||||
FROM laporan_warga l
|
||||
JOIN users u ON l.user_id = u.id ";
|
||||
|
||||
if ($my_reports || $_SESSION['role'] !== 'admin') {
|
||||
// User biasa hanya boleh melihat laporannya sendiri di tabel dashboard,
|
||||
// tapi mungkin butuh lihat semua laporan di peta publik?
|
||||
// Untuk peta public (semua laporan disetujui atau diproses), tambahkan parameter public=1
|
||||
if (isset($_GET['public']) && $_GET['public'] == 1) {
|
||||
$sql .= " WHERE l.status IN ('diproses', 'selesai') ";
|
||||
} else {
|
||||
$sql .= " WHERE l.user_id = " . (int)$_SESSION['user_id'];
|
||||
}
|
||||
}
|
||||
$sql .= " ORDER BY l.id DESC";
|
||||
|
||||
$rows = $pdo->query($sql)->fetchAll();
|
||||
|
||||
$features = [];
|
||||
foreach ($rows as $row) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'user_id' => $row['user_id'],
|
||||
'pelapor' => $row['nama_lengkap'] ?: $row['username'],
|
||||
'kategori' => $row['kategori'],
|
||||
'deskripsi' => $row['deskripsi'],
|
||||
'status' => $row['status'],
|
||||
'created_at' => $row['created_at']
|
||||
],
|
||||
'geometry' => [
|
||||
'type' => 'Point',
|
||||
'coordinates' => [(float)$row['lng'], (float)$row['lat']]
|
||||
]
|
||||
];
|
||||
}
|
||||
echo json_encode([
|
||||
'type' => 'FeatureCollection',
|
||||
'features' => $features
|
||||
]);
|
||||
}
|
||||
elseif ($method === 'POST') {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['kategori'], $input['deskripsi'], $input['geometry'])) {
|
||||
throw new Exception("Data tidak lengkap.");
|
||||
}
|
||||
$coords = $input['geometry']['coordinates'];
|
||||
$stmt = $pdo->prepare("INSERT INTO laporan_warga (user_id, kategori, deskripsi, geometry) VALUES (?, ?, ?, ST_GeomFromText(?))");
|
||||
$stmt->execute([
|
||||
$_SESSION['user_id'],
|
||||
$input['kategori'],
|
||||
$input['deskripsi'],
|
||||
"POINT({$coords[0]} {$coords[1]})"
|
||||
]);
|
||||
echo json_encode(['status' => 'success', 'message' => 'Laporan berhasil dibuat.']);
|
||||
}
|
||||
elseif ($method === 'PUT') {
|
||||
if ($_SESSION['role'] !== 'admin') throw new Exception("Unauthorized");
|
||||
$id = $_GET['id'] ?? 0;
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$status = $input['status'] ?? 'menunggu';
|
||||
$stmt = $pdo->prepare("UPDATE laporan_warga SET status = ? WHERE id = ?");
|
||||
$stmt->execute([$status, $id]);
|
||||
echo json_encode(['status' => 'success', 'message' => 'Status laporan diperbarui.']);
|
||||
}
|
||||
elseif ($method === 'DELETE') {
|
||||
$id = $_GET['id'] ?? 0;
|
||||
// User bisa hapus kalau status menunggu. Admin bisa hapus semua.
|
||||
if ($_SESSION['role'] === 'admin') {
|
||||
$stmt = $pdo->prepare("DELETE FROM laporan_warga WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare("DELETE FROM laporan_warga WHERE id = ? AND user_id = ? AND status = 'menunggu'");
|
||||
$stmt->execute([$id, $_SESSION['user_id']]);
|
||||
}
|
||||
echo json_encode(['status' => 'success', 'message' => 'Laporan dihapus.']);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
|
||||
function normalizeRadius($value): int {
|
||||
$radius = (int)($value ?? 1000);
|
||||
if ($radius < 100) return 100;
|
||||
if ($radius > 10000) return 10000;
|
||||
return $radius;
|
||||
}
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("
|
||||
SELECT
|
||||
r.id,
|
||||
r.nama,
|
||||
r.agama,
|
||||
r.radius_bantuan_meter,
|
||||
r.created_at,
|
||||
ST_AsGeoJSON(r.geom) AS geojson,
|
||||
IFNULL(AVG(u.rating), 0) AS avg_rating,
|
||||
COUNT(u.id) AS total_ulasan
|
||||
FROM rumah_ibadah r
|
||||
LEFT JOIN ulasan_fasilitas u
|
||||
ON u.fasilitas_id = r.id
|
||||
AND u.fasilitas_tipe = 'rumah_ibadah'
|
||||
GROUP BY r.id
|
||||
ORDER BY r.id DESC
|
||||
");
|
||||
|
||||
$features = [];
|
||||
while ($r = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($r['geojson']),
|
||||
'properties' => [
|
||||
'id' => (int)$r['id'],
|
||||
'nama' => $r['nama'],
|
||||
'agama' => $r['agama'],
|
||||
'radius_bantuan_meter' => (int)$r['radius_bantuan_meter'],
|
||||
'radius_bantuan_km' => round(((int)$r['radius_bantuan_meter']) / 1000, 2),
|
||||
'created_at' => $r['created_at'],
|
||||
'avg_rating' => round((float)$r['avg_rating'], 1),
|
||||
'total_ulasan' => (int)$r['total_ulasan']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Rumah Ibadah');
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$d = getInput();
|
||||
if (empty($d['nama']) || empty($d['agama']) || empty($d['geometry'])) {
|
||||
sendError('Data tidak lengkap');
|
||||
}
|
||||
|
||||
$radius = normalizeRadius($d['radius_bantuan_meter'] ?? null);
|
||||
$pdo->prepare("
|
||||
INSERT INTO rumah_ibadah (nama, agama, radius_bantuan_meter, geom)
|
||||
VALUES (?, ?, ?, ST_GeomFromGeoJSON(?))
|
||||
")->execute([$d['nama'], $d['agama'], $radius, json_encode($d['geometry'])]);
|
||||
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Rumah Ibadah disimpan', 201);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
$d = getInput();
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID wajib');
|
||||
|
||||
if (!empty($d['geometry'])) {
|
||||
$pdo->prepare("UPDATE rumah_ibadah SET geom = ST_GeomFromGeoJSON(?) WHERE id = ?")
|
||||
->execute([json_encode($d['geometry']), $id]);
|
||||
} else {
|
||||
$radius = normalizeRadius($d['radius_bantuan_meter'] ?? null);
|
||||
$pdo->prepare("
|
||||
UPDATE rumah_ibadah
|
||||
SET nama = ?, agama = ?, radius_bantuan_meter = ?
|
||||
WHERE id = ?
|
||||
")->execute([$d['nama'], $d['agama'], $radius, $id]);
|
||||
}
|
||||
|
||||
sendSuccess(null, 'Rumah Ibadah diperbarui');
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID wajib');
|
||||
|
||||
$pdo->prepare("DELETE FROM rumah_ibadah WHERE id = ?")->execute([$id]);
|
||||
sendSuccess(null, 'Rumah Ibadah dihapus');
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT s.id, s.nama, s.deskripsi, s.buka_24_jam, s.created_at, ST_AsGeoJSON(s.geom) as geojson,
|
||||
IFNULL(AVG(u.rating), 0) as avg_rating, COUNT(u.id) as total_ulasan
|
||||
FROM spbu s
|
||||
LEFT JOIN ulasan_fasilitas u ON u.fasilitas_id = s.id AND u.fasilitas_tipe = 'spbu'
|
||||
GROUP BY s.id
|
||||
ORDER BY s.id DESC");
|
||||
$features = [];
|
||||
while ($r = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type'=>'Feature',
|
||||
'geometry'=>json_decode($r['geojson']),
|
||||
'properties'=>[
|
||||
'id'=>$r['id'],
|
||||
'nama'=>$r['nama'],
|
||||
'deskripsi'=>$r['deskripsi'],
|
||||
'buka_24_jam'=>(int)$r['buka_24_jam'],
|
||||
'created_at'=>$r['created_at'],
|
||||
'avg_rating'=>round($r['avg_rating'], 1),
|
||||
'total_ulasan'=>$r['total_ulasan']
|
||||
]
|
||||
];
|
||||
}
|
||||
sendSuccess(['type'=>'FeatureCollection','features'=>$features], 'Data SPBU');
|
||||
break;
|
||||
case 'POST':
|
||||
$d = getInput();
|
||||
if (empty($d['nama']) || empty($d['geometry'])) sendError('Nama dan geometri wajib diisi');
|
||||
$stmt = $pdo->prepare("INSERT INTO spbu (nama, deskripsi, buka_24_jam, geom) VALUES (?,?,?,ST_GeomFromGeoJSON(?))");
|
||||
$stmt->execute([$d['nama'], $d['deskripsi']??'', (int)($d['buka_24_jam']??0), json_encode($d['geometry'])]);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()], 'SPBU disimpan', 201);
|
||||
break;
|
||||
case 'PUT':
|
||||
$d = getInput(); $id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID wajib disertakan');
|
||||
if (!empty($d['geometry'])) {
|
||||
$stmt = $pdo->prepare("UPDATE spbu SET geom=ST_GeomFromGeoJSON(?) WHERE id=?");
|
||||
$stmt->execute([json_encode($d['geometry']), $id]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare("UPDATE spbu SET nama=?, deskripsi=?, buka_24_jam=? WHERE id=?");
|
||||
$stmt->execute([$d['nama'], $d['deskripsi']??'', (int)($d['buka_24_jam']??0), $id]);
|
||||
}
|
||||
sendSuccess(null, 'SPBU diperbarui');
|
||||
break;
|
||||
case 'DELETE':
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID wajib disertakan');
|
||||
$pdo->prepare("DELETE FROM spbu WHERE id=?")->execute([$id]);
|
||||
sendSuccess(null, 'SPBU dihapus');
|
||||
break;
|
||||
default: sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
date_default_timezone_set('Asia/Jakarta');
|
||||
|
||||
$row = $pdo->query("
|
||||
SELECT
|
||||
COUNT(*) AS total_spbu,
|
||||
SUM(CASE WHEN buka_24_jam = 1 THEN 1 ELSE 0 END) AS spbu_buka
|
||||
FROM spbu
|
||||
")->fetch();
|
||||
|
||||
$total = (int)($row['total_spbu'] ?? 0);
|
||||
$open = (int)($row['spbu_buka'] ?? 0);
|
||||
|
||||
sendSuccess([
|
||||
'total_spbu' => $total,
|
||||
'spbu_buka' => $open,
|
||||
'spbu_tutup' => max(0, $total - $open),
|
||||
'basis_perhitungan' => 'buka_24_jam',
|
||||
'server_time' => date('Y-m-d H:i:s'),
|
||||
'timezone' => date_default_timezone_get()
|
||||
], 'Status SPBU');
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection();
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') sendError('Method not allowed', 405);
|
||||
$lat = (float)($_GET['lat'] ?? 0); $lng = (float)($_GET['lng'] ?? 0);
|
||||
if (!$lat || !$lng) sendError('lat dan lng wajib diisi');
|
||||
$wkt = sprintf('POINT(%F %F)', $lng, $lat);
|
||||
$stmt = $pdo->prepare("SELECT id, nama, buka_24_jam, ST_AsGeoJSON(geom) as geojson,
|
||||
ST_Distance_Sphere(geom, ST_GeomFromText(?)) / 1000 as jarak_km
|
||||
FROM spbu ORDER BY jarak_km ASC LIMIT 1");
|
||||
$stmt->execute([$wkt]);
|
||||
$r = $stmt->fetch();
|
||||
if (!$r) sendError('Tidak ada SPBU di database', 404);
|
||||
sendSuccess(['type'=>'Feature','geometry'=>json_decode($r['geojson']),'properties'=>['id'=>$r['id'],'nama'=>$r['nama'],'buka_24_jam'=>(int)$r['buka_24_jam'],'jarak_km'=>round($r['jarak_km'],2)]], 'SPBU terdekat');
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection();
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') sendError('Method not allowed', 405);
|
||||
|
||||
// Summary counts
|
||||
$counts = $pdo->query("SELECT
|
||||
(SELECT COUNT(*) FROM spbu) as total_spbu,
|
||||
(SELECT COUNT(*) FROM jalan) as total_jalan,
|
||||
(SELECT COUNT(*) FROM kavling) as total_kavling,
|
||||
(SELECT COUNT(*) FROM rumah_ibadah) as total_rumah_ibadah,
|
||||
(SELECT COUNT(*) FROM warga_miskin) as total_warga_miskin,
|
||||
(SELECT COUNT(*) FROM kawasan_kumuh) as total_kawasan_kumuh,
|
||||
(SELECT COUNT(*) FROM spbu WHERE buka_24_jam=1) as spbu_24jam
|
||||
")->fetch();
|
||||
|
||||
// Choropleth: kawasan kumuh + jumlah warga di dalamnya
|
||||
$sql = "SELECT k.id, k.nama_kawasan, ST_AsGeoJSON(k.geom) as geojson,
|
||||
COUNT(w.id) as jumlah_warga,
|
||||
COALESCE(SUM(w.jumlah_tanggungan),0) as total_tanggungan
|
||||
FROM kawasan_kumuh k
|
||||
LEFT JOIN warga_miskin w ON ST_Contains(k.geom, w.geom)
|
||||
GROUP BY k.id";
|
||||
$stmt = $pdo->query($sql);
|
||||
$features = [];
|
||||
$merahCount = 0;
|
||||
while ($r = $stmt->fetch()) {
|
||||
$jumlah = (int)$r['jumlah_warga'];
|
||||
if ($jumlah > 3) $merahCount++;
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($r['geojson']),
|
||||
'properties' => [
|
||||
'id' => $r['id'],
|
||||
'nama_kawasan' => $r['nama_kawasan'],
|
||||
'jumlah_warga' => $jumlah,
|
||||
'total_tanggungan' => (int)$r['total_tanggungan'],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// Rumah ibadah by agama
|
||||
$byAgama = $pdo->query("SELECT agama, COUNT(*) as total FROM rumah_ibadah GROUP BY agama")->fetchAll();
|
||||
|
||||
// Kavling by status
|
||||
$byStatus = $pdo->query("SELECT status_kepemilikan, COUNT(*) as total FROM kavling GROUP BY status_kepemilikan")->fetchAll();
|
||||
|
||||
sendSuccess([
|
||||
'counts' => $counts,
|
||||
'kawasan_merah' => $merahCount,
|
||||
'choropleth' => ['type' => 'FeatureCollection', 'features' => $features],
|
||||
'rumah_by_agama' => $byAgama,
|
||||
'kavling_by_status' => $byStatus,
|
||||
], 'Statistik OK');
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../config/session.php';
|
||||
startAppSession();
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'user') {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Hanya pengguna terdaftar yang dapat memberikan ulasan']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
try {
|
||||
if ($method === 'POST') {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['fasilitas_tipe'], $input['fasilitas_id'], $input['rating'])) {
|
||||
throw new Exception("Data ulasan tidak lengkap.");
|
||||
}
|
||||
|
||||
$tipe = $input['fasilitas_tipe'];
|
||||
if (!in_array($tipe, ['spbu', 'rumah_ibadah'])) throw new Exception("Tipe fasilitas tidak valid");
|
||||
|
||||
$fasilitas_id = (int)$input['fasilitas_id'];
|
||||
$rating = (int)$input['rating'];
|
||||
$komentar = trim($input['komentar'] ?? '');
|
||||
|
||||
if ($rating < 1 || $rating > 5) throw new Exception("Rating harus antara 1 sampai 5");
|
||||
|
||||
// Cek apakah sudah pernah mengulas
|
||||
$check = $pdo->prepare("SELECT id FROM ulasan_fasilitas WHERE user_id = ? AND fasilitas_tipe = ? AND fasilitas_id = ?");
|
||||
$check->execute([$_SESSION['user_id'], $tipe, $fasilitas_id]);
|
||||
if ($check->fetch()) {
|
||||
throw new Exception("Anda sudah memberikan ulasan untuk fasilitas ini.");
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO ulasan_fasilitas (user_id, fasilitas_tipe, fasilitas_id, rating, komentar) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$_SESSION['user_id'], $tipe, $fasilitas_id, $rating, $komentar]);
|
||||
|
||||
echo json_encode(['status' => 'success', 'message' => 'Ulasan berhasil disimpan! Terima kasih atas partisipasi Anda.']);
|
||||
} else {
|
||||
throw new Exception("Method not allowed");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection(); $method = $_SERVER['REQUEST_METHOD'];
|
||||
requireApiRole('admin');
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT id,username,role,nama_lengkap,created_at FROM users ORDER BY id ASC");
|
||||
sendSuccess($stmt->fetchAll(), 'Data Users'); break;
|
||||
case 'POST':
|
||||
$d=getInput();
|
||||
if(empty($d['username'])||empty($d['password'])||empty($d['role'])) sendError('Data tidak lengkap');
|
||||
$hash = password_hash($d['password'], PASSWORD_BCRYPT);
|
||||
try {
|
||||
$pdo->prepare("INSERT INTO users(username,password,role,nama_lengkap) VALUES(?,?,?,?)")->execute([$d['username'],$hash,$d['role'],$d['nama_lengkap']??'']);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()],'User disimpan',201);
|
||||
} catch(Exception $e) { sendError('Username sudah digunakan'); }
|
||||
break;
|
||||
case 'PUT':
|
||||
$d=getInput(); $id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
if(!empty($d['password'])) {
|
||||
$hash=password_hash($d['password'],PASSWORD_BCRYPT);
|
||||
$pdo->prepare("UPDATE users SET username=?,password=?,role=?,nama_lengkap=? WHERE id=?")->execute([$d['username'],$hash,$d['role'],$d['nama_lengkap']??'',$id]);
|
||||
} else {
|
||||
$pdo->prepare("UPDATE users SET username=?,role=?,nama_lengkap=? WHERE id=?")->execute([$d['username'],$d['role'],$d['nama_lengkap']??'',$id]);
|
||||
}
|
||||
sendSuccess(null,'User diperbarui'); break;
|
||||
case 'DELETE':
|
||||
$id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
if($id==1) sendError('Admin utama tidak dapat dihapus');
|
||||
$pdo->prepare("DELETE FROM users WHERE id=?")->execute([$id]); sendSuccess(null,'User dihapus'); break;
|
||||
default: sendError('Method not allowed',405);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php require_once __DIR__ . '/../config/db.php'; require_once __DIR__ . '/helpers.php';
|
||||
$pdo = Database::getConnection(); $method = $_SERVER['REQUEST_METHOD'];
|
||||
requireAdminForMutation();
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$stmt = $pdo->query("SELECT id,nama_kk,penghasilan,jumlah_tanggungan,created_at,ST_AsGeoJSON(geom) as geojson FROM warga_miskin ORDER BY id DESC");
|
||||
$features=[];
|
||||
while($r=$stmt->fetch()) $features[]=['type'=>'Feature','geometry'=>json_decode($r['geojson']),'properties'=>['id'=>$r['id'],'nama_kk'=>$r['nama_kk'],'penghasilan'=>$r['penghasilan'],'jumlah_tanggungan'=>$r['jumlah_tanggungan'],'created_at'=>$r['created_at']]];
|
||||
sendSuccess(['type'=>'FeatureCollection','features'=>$features],'Data Warga Miskin'); break;
|
||||
case 'POST':
|
||||
$d=getInput(); if(empty($d['nama_kk'])||empty($d['geometry'])) sendError('Data tidak lengkap');
|
||||
$pdo->prepare("INSERT INTO warga_miskin(nama_kk,penghasilan,jumlah_tanggungan,geom) VALUES(?,?,?,ST_GeomFromGeoJSON(?))")->execute([$d['nama_kk'],$d['penghasilan']??0,$d['jumlah_tanggungan']??0,json_encode($d['geometry'])]);
|
||||
sendSuccess(['id'=>$pdo->lastInsertId()],'Warga disimpan',201); break;
|
||||
case 'PUT':
|
||||
$d=getInput(); $id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
if(!empty($d['geometry'])){
|
||||
$pdo->prepare("UPDATE warga_miskin SET geom=ST_GeomFromGeoJSON(?) WHERE id=?")->execute([json_encode($d['geometry']),$id]);
|
||||
} else {
|
||||
$pdo->prepare("UPDATE warga_miskin SET nama_kk=?,penghasilan=?,jumlah_tanggungan=? WHERE id=?")->execute([$d['nama_kk'],$d['penghasilan']??0,$d['jumlah_tanggungan']??0,$id]);
|
||||
}
|
||||
sendSuccess(null,'Warga diperbarui'); break;
|
||||
case 'DELETE':
|
||||
$id=$_GET['id']??null; if(!$id) sendError('ID wajib');
|
||||
$pdo->prepare("DELETE FROM warga_miskin WHERE id=?")->execute([$id]); sendSuccess(null,'Warga dihapus'); break;
|
||||
default: sendError('Method not allowed',405);
|
||||
}
|
||||
Reference in New Issue
Block a user