Coba Commit
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* jalan.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Jalan (LineString).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* kavling.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Kavling (Polygon).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once '../config/db.php';
|
||||
<?php
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
export const BASE_URL = '';
|
||||
const getBaseUrl = () => {
|
||||
const segments = window.location.pathname.split('/');
|
||||
const targetIndex = segments.findIndex(seg => ['01', '02', '03', 'versi'].includes(seg));
|
||||
if (targetIndex !== -1) {
|
||||
return segments.slice(0, targetIndex).join('/');
|
||||
}
|
||||
return '';
|
||||
};
|
||||
export const BASE_URL = getBaseUrl();
|
||||
|
||||
const createService = (endpoint) => ({
|
||||
getAll: async () => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* jalan.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Jalan (LineString).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* kavling.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Kavling (Polygon).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* rumah_ibadah.php
|
||||
* Tanggung Jawab: Operasi CRUD Rumah Ibadah + Endpoint analisis jangkauan Haversine.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
require_once '../utils/geo_helper.php';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once '../config/db.php';
|
||||
<?php
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* warga_miskin.php
|
||||
* Tanggung Jawab: Operasi CRUD untuk Warga Miskin.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
export const BASE_URL = '';
|
||||
const getBaseUrl = () => {
|
||||
const segments = window.location.pathname.split('/');
|
||||
const targetIndex = segments.findIndex(seg => ['01', '02', '03', 'versi'].includes(seg));
|
||||
if (targetIndex !== -1) {
|
||||
return segments.slice(0, targetIndex).join('/');
|
||||
}
|
||||
return '';
|
||||
};
|
||||
export const BASE_URL = getBaseUrl();
|
||||
|
||||
const createService = (endpoint) => ({
|
||||
getAll: async () => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* jalan.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Jalan (LineString).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* kavling.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Kavling (Polygon).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* rumah_ibadah.php
|
||||
* Tanggung Jawab: Operasi CRUD Rumah Ibadah + Endpoint analisis jangkauan Haversine.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
require_once '../utils/geo_helper.php';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once '../config/db.php';
|
||||
<?php
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* statistik.php
|
||||
* Tanggung Jawab: Menyediakan data analisis spasial menggunakan Point in Polygon (ST_Contains).
|
||||
* Menghitung kepadatan warga miskin dalam setiap kavling.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* warga_miskin.php
|
||||
* Tanggung Jawab: Operasi CRUD untuk Warga Miskin.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
export const BASE_URL = '';
|
||||
const getBaseUrl = () => {
|
||||
const segments = window.location.pathname.split('/');
|
||||
const targetIndex = segments.findIndex(seg => ['01', '02', '03', 'versi'].includes(seg));
|
||||
if (targetIndex !== -1) {
|
||||
return segments.slice(0, targetIndex).join('/');
|
||||
}
|
||||
return '';
|
||||
};
|
||||
export const BASE_URL = getBaseUrl();
|
||||
|
||||
const createService = (endpoint) => ({
|
||||
getAll: async () => {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
# WebGIS Poverty Map
|
||||
# D1041231071 — WebGIS Smart City Project
|
||||
**Naufal Zaky R | UAS WebGIS**
|
||||
|
||||
Aplikasi WebGIS PHP + MySQL untuk pemetaan data kemiskinan, fasilitas, laporan warga, dan analisis blank spot bantuan.
|
||||
Aplikasi WebGIS berbasis PHP + MySQL untuk pemetaan data kemiskinan, fasilitas umum, laporan warga, dan analisis blank spot bantuan sosial di Kota Pontianak.
|
||||
|
||||
## Stack
|
||||
## Stack Teknologi
|
||||
|
||||
- PHP 8.2 Apache
|
||||
- MySQL/MariaDB
|
||||
- Leaflet
|
||||
- PDO MySQL
|
||||
- MySQL / MariaDB + PostGIS
|
||||
- Leaflet.js (peta interaktif)
|
||||
- PDO MySQL (koneksi database)
|
||||
|
||||
## Deploy Coolify
|
||||
## Cara Deploy (Coolify)
|
||||
|
||||
1. Buat database MySQL/MariaDB di Coolify.
|
||||
2. Import `database/webgis_db.sql` ke database tersebut.
|
||||
2. Import `db_scripts/webgis_naufal_zaky.sql` ke database tersebut.
|
||||
3. Buat aplikasi baru dari repo ini.
|
||||
4. Pilih build menggunakan `Dockerfile` di root repository.
|
||||
5. Set environment variable:
|
||||
@@ -28,9 +29,7 @@ DB_USERNAME=user_database
|
||||
DB_PASSWORD=password_database
|
||||
```
|
||||
|
||||
Root aplikasi menampilkan halaman pemilih progres dari `index.html`. Versi final berjalan di `/project_final`, jadi gunakan `APP_BASE_PATH=/project_final` untuk deploy Coolify ini.
|
||||
|
||||
`CORS_ALLOWED_ORIGIN` boleh dikosongkan untuk same-origin deployment. Isi dengan domain aplikasi jika API memang perlu diakses dari origin lain.
|
||||
Aplikasi final berjalan di `/webgis_app`. Gunakan `APP_BASE_PATH=/webgis_app` untuk deploy.
|
||||
|
||||
## Akun Awal
|
||||
|
||||
@@ -39,23 +38,38 @@ Setelah import SQL:
|
||||
- Admin: `admin / admin123`
|
||||
- Pengguna: `pengguna / user123`
|
||||
|
||||
Ganti password akun demo setelah deploy jika aplikasi dibuka publik.
|
||||
> Ganti password akun demo setelah deploy jika aplikasi dibuka publik.
|
||||
|
||||
## Struktur Penting
|
||||
## Struktur Project
|
||||
|
||||
- `index.html` - halaman awal untuk memilih progres.
|
||||
- `01/`, `02/`, `03/`, `final/` - progres pertemuan.
|
||||
- `project_final/` - aplikasi final yang berjalan di `/project_final`.
|
||||
- `database/webgis_db.sql` - struktur dan seed database lengkap.
|
||||
- `Dockerfile` - image PHP Apache untuk Coolify.
|
||||
- `.env.example` - contoh environment variable deploy.
|
||||
```
|
||||
D1041231071_NaufalZakyR_UAS_WebGISProject/
|
||||
├── beranda.html ← Halaman pemilih progres
|
||||
├── webgis_app/ ← Aplikasi final (main app)
|
||||
│ ├── panel_admin/ ← Halaman & fitur admin
|
||||
│ ├── panel_user/ ← Halaman & fitur pengguna
|
||||
│ ├── endpoints/ ← API endpoint PHP
|
||||
│ ├── core_config/ ← Konfigurasi (DB, session, auth)
|
||||
│ └── public_assets/ ← CSS & JS (global, panel, map)
|
||||
├── db_scripts/ ← SQL scripts database
|
||||
│ ├── buat_tabel.sql
|
||||
│ ├── data_awal_wilayah.sql
|
||||
│ ├── data_awal_pengguna.sql
|
||||
│ └── webgis_naufal_zaky.sql
|
||||
├── version_01/ ← Progres pertemuan 1
|
||||
├── version_02/ ← Progres pertemuan 2
|
||||
├── version_03/ ← Progres pertemuan 3
|
||||
├── legacy_version/ ← Versi lama (referensi)
|
||||
├── Dockerfile ← Docker image untuk Coolify
|
||||
└── .env ← Konfigurasi environment
|
||||
```
|
||||
|
||||
## Local XAMPP
|
||||
## Jalankan di XAMPP Lokal
|
||||
|
||||
Untuk menjalankan dari XAMPP seperti struktur lama, set base path:
|
||||
Set konfigurasi di `.env`:
|
||||
|
||||
```env
|
||||
APP_BASE_PATH=/project/project_final
|
||||
APP_BASE_PATH=/D1041231071_NaufalZakyR_UAS_WebGISProject/webgis_app
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=webgis_db
|
||||
@@ -63,4 +77,5 @@ DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
```
|
||||
|
||||
Import `database/webgis_db.sql`, lalu buka `/project/project_final/login.php`.
|
||||
Import `db_scripts/webgis_naufal_zaky.sql` ke phpMyAdmin, lalu buka:
|
||||
`http://localhost/D1041231071_NaufalZakyR_UAS_WebGISProject/webgis_app/login.php`
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
|
||||
<style>
|
||||
:root {
|
||||
/* Matching project_final/main.css */
|
||||
/* Matching webgis_app/main.css */
|
||||
--primary: #2563EB;
|
||||
--primary-light: #3B82F6;
|
||||
--primary-dark: #1D4ED8;
|
||||
@@ -302,7 +302,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Final (UAS) -->
|
||||
<a href="project_final/" class="card final" style="animation-delay: 0.25s;">
|
||||
<a href="webgis_app/" class="card final" style="animation-delay: 0.25s;">
|
||||
<div class="card-icon-wrap">
|
||||
<i class="fas fa-laptop-code"></i>
|
||||
</div>
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
<?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(ST_SRID(w.geom, 4326), ST_SRID(ri.geom, 4326)) AS jarak_meter,
|
||||
ri.radius_bantuan_meter,
|
||||
(ST_Distance_Sphere(ST_SRID(w.geom, 4326), ST_SRID(ri.geom, 4326)) - 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(ST_SRID(w2.geom, 4326), ST_SRID(ri2.geom, 4326)) 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(ST_SRID(w.geom, 4326), ST_SRID(ri.geom, 4326)) - nearest.min_jarak_meter) < 0.001
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM rumah_ibadah ri_in_radius
|
||||
WHERE ST_Distance_Sphere(ST_SRID(w.geom, 4326), ST_SRID(ri_in_radius.geom, 4326)) <= 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');
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
try {
|
||||
$pdo = Database::getConnection();
|
||||
$stmt = $pdo->query("SELECT id, ST_SRID(geom) as srid FROM warga_miskin LIMIT 5");
|
||||
echo "warga_miskin SRIDs: \n";
|
||||
while ($row = $stmt->fetch()) echo $row['id'] . " => " . $row['srid'] . "\n";
|
||||
|
||||
$stmt = $pdo->query("SELECT id, ST_SRID(geom) as srid FROM rumah_ibadah LIMIT 5");
|
||||
echo "rumah_ibadah SRIDs: \n";
|
||||
while ($row = $stmt->fetch()) echo $row['id'] . " => " . $row['srid'] . "\n";
|
||||
} catch (Exception $e) {
|
||||
echo "ERROR: " . $e->getMessage();
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
try {
|
||||
$pdo = Database::getConnection();
|
||||
$tables = ['spbu', 'rumah_ibadah', 'jalan', 'kavling', 'kawasan_kumuh', 'warga_miskin'];
|
||||
foreach ($tables as $t) {
|
||||
$pdo->exec("UPDATE $t SET geom = ST_SRID(geom, 4326) WHERE ST_SRID(geom) != 4326");
|
||||
}
|
||||
echo "SRID FIXED";
|
||||
} catch (Exception $e) {
|
||||
echo "ERROR: " . $e->getMessage();
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?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()]);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?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');
|
||||
@@ -1,13 +0,0 @@
|
||||
<?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(ST_SRID(geom, 4326), ST_SRID(ST_GeomFromText(?), 4326)) / 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');
|
||||
@@ -1,53 +0,0 @@
|
||||
<?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');
|
||||
@@ -1,50 +0,0 @@
|
||||
<?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()]);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config/session.php';
|
||||
startAppSession();
|
||||
if (isset($_SESSION['user_id'])) {
|
||||
if ($_SESSION['role'] === 'admin') {
|
||||
header('Location: admin/index.php');
|
||||
} else {
|
||||
header('Location: user/index.php');
|
||||
}
|
||||
exit;
|
||||
}
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* jalan.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Jalan (LineString).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* kavling.php
|
||||
* Tanggung Jawab: Menangani operasi CRUD untuk entitas Kavling (Polygon).
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* rumah_ibadah.php
|
||||
* Tanggung Jawab: Operasi CRUD Rumah Ibadah + Endpoint analisis jangkauan Haversine.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
require_once '../utils/geo_helper.php';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once '../config/db.php';
|
||||
<?php
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* statistik.php
|
||||
* Tanggung Jawab: Menyediakan data analisis spasial menggunakan Point in Polygon (ST_Contains).
|
||||
* Menghitung kepadatan warga miskin dalam setiap kavling.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* warga_miskin.php
|
||||
* Tanggung Jawab: Operasi CRUD untuk Warga Miskin.
|
||||
*/
|
||||
|
||||
require_once '../config/db.php';
|
||||
require_once '../core_config/database.php';
|
||||
require_once '../utils/response_helper.php';
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
+9
-1
@@ -1,4 +1,12 @@
|
||||
export const BASE_URL = '';
|
||||
const getBaseUrl = () => {
|
||||
const segments = window.location.pathname.split('/');
|
||||
const targetIndex = segments.findIndex(seg => ['01', '02', '03', 'versi'].includes(seg));
|
||||
if (targetIndex !== -1) {
|
||||
return segments.slice(0, targetIndex).join('/');
|
||||
}
|
||||
return '';
|
||||
};
|
||||
export const BASE_URL = getBaseUrl();
|
||||
|
||||
const createService = (endpoint) => ({
|
||||
getAll: async () => {
|
||||
@@ -0,0 +1,13 @@
|
||||
RewriteEngine On
|
||||
|
||||
# Specific file mappings from old API names to new refactored endpoint names
|
||||
RewriteRule ^api/kawasan_kumuh\.php$ endpoints/api_kawasan.php [L,QSA]
|
||||
RewriteRule ^api/rumah_ibadah\.php$ endpoints/api_fasilitas.php [L,QSA]
|
||||
RewriteRule ^api/users\.php$ endpoints/api_pengguna.php [L,QSA]
|
||||
RewriteRule ^api/spbu_terdekat\.php$ endpoints/api_spbu_nearby.php [L,QSA]
|
||||
RewriteRule ^api/blank_spot\.php$ endpoints/area_blank.php [L,QSA]
|
||||
RewriteRule ^api/check_srid\.php$ endpoints/cek_srid.php [L,QSA]
|
||||
RewriteRule ^api/fix_srid\.php$ endpoints/perbaiki_srid.php [L,QSA]
|
||||
|
||||
# General pattern mapping: api/filename.php -> endpoints/api_filename.php
|
||||
RewriteRule ^api/([a-zA-Z0-9_]+)\.php$ endpoints/api_$1.php [L,QSA]
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/area_blank.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/cek_srid.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/perbaiki_srid.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_jalan.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_kavling.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_kawasan.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_laporan.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_fasilitas.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_spbu.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_spbu_status.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_spbu_nearby.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_statistik.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_ulasan.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_pengguna.php';
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../endpoints/api_warga_miskin.php';
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
<?php
|
||||
/**
|
||||
* Singleton PDO connection.
|
||||
*
|
||||
* Coolify: set DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, and DB_PASSWORD
|
||||
* from the database service credentials.
|
||||
*/
|
||||
require_once __DIR__ . '/env_loader.php';
|
||||
class Database {
|
||||
private static $conn = null;
|
||||
|
||||
@@ -45,7 +46,7 @@ class Database {
|
||||
// Auto-initialize database if empty
|
||||
$stmt = self::$conn->query("SHOW TABLES LIKE 'users'");
|
||||
if ($stmt->rowCount() == 0) {
|
||||
$sqlFile = __DIR__ . '/../../database/webgis_db.sql';
|
||||
$sqlFile = __DIR__ . '/../../db_scripts/webgis_naufal_zaky.sql';
|
||||
if (file_exists($sqlFile)) {
|
||||
$sql = file_get_contents($sqlFile);
|
||||
self::$conn->exec($sql);
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Simple .env loader.
|
||||
* Reads the .env file from the repository root and sets environment variables
|
||||
* via putenv() so getenv() calls throughout the app work correctly.
|
||||
* Only loads once per request.
|
||||
*/
|
||||
function loadEnv(): void {
|
||||
static $loaded = false;
|
||||
if ($loaded) return;
|
||||
|
||||
// Walk up from webgis_app/config to the repository root
|
||||
$envFile = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . '.env';
|
||||
|
||||
if (!file_exists($envFile)) {
|
||||
$loaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if (!empty($lines)) {
|
||||
if (substr($lines[0], 0, 3) === "\xEF\xBB\xBF") {
|
||||
$lines[0] = substr($lines[0], 3);
|
||||
}
|
||||
}
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
// Skip comments
|
||||
if ($line === '' || $line[0] === '#') continue;
|
||||
|
||||
if (strpos($line, '=') === false) continue;
|
||||
|
||||
[$key, $value] = explode('=', $line, 2);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
|
||||
// Remove surrounding quotes if present
|
||||
if (strlen($value) >= 2 &&
|
||||
(($value[0] === '"' && $value[-1] === '"') ||
|
||||
($value[0] === "'" && $value[-1] === "'"))) {
|
||||
$value = substr($value, 1, -1);
|
||||
}
|
||||
|
||||
// Only set if not already defined in the environment (server env wins)
|
||||
if (getenv($key) === false) {
|
||||
putenv("{$key}={$value}");
|
||||
$_ENV[$key] = $value;
|
||||
$_SERVER[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$loaded = true;
|
||||
}
|
||||
|
||||
// Auto-load on include
|
||||
loadEnv();
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* auth_check.php — Middleware: pastikan user sudah login dan role sesuai.
|
||||
* Usage: require_once __DIR__ . '/../config/auth_check.php';
|
||||
* Usage: require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
* requireRole('admin'); // atau 'user'
|
||||
*/
|
||||
require_once __DIR__ . '/session.php';
|
||||
require_once __DIR__ . '/session_mgr.php';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
startAppSession();
|
||||
@@ -27,9 +27,9 @@ function requireRole(string $role, ?string $redirect = null): void {
|
||||
if ($_SESSION['role'] !== $role) {
|
||||
// Redirect ke dashboard yang sesuai role-nya
|
||||
if ($_SESSION['role'] === 'admin') {
|
||||
header('Location: ' . app_url('admin/index.php'));
|
||||
header('Location: ' . app_url('panel_admin/index.php'));
|
||||
} else {
|
||||
header('Location: ' . app_url('user/index.php'));
|
||||
header('Location: ' . app_url('panel_user/index.php'));
|
||||
}
|
||||
exit;
|
||||
}
|
||||
@@ -43,3 +43,24 @@ function currentUser(): array {
|
||||
'nama_lengkap'=> $_SESSION['nama_lengkap']?? '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* API-safe auth helpers: return JSON 401/403 instead of redirecting.
|
||||
* Use these in endpoints called via fetch/AJAX.
|
||||
*/
|
||||
function requireApiLogin(): void {
|
||||
if (!isLoggedIn()) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Autentikasi diperlukan']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function requireApiRole(string $role): void {
|
||||
requireApiLogin();
|
||||
if ($_SESSION['role'] !== $role) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Akses ditolak: role tidak sesuai']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/app.php';
|
||||
require_once __DIR__ . '/settings.php';
|
||||
|
||||
function startAppSession(): void {
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
@@ -2,13 +2,14 @@
|
||||
/**
|
||||
* Application path helpers.
|
||||
*
|
||||
* Set APP_BASE_PATH to the subdirectory that serves project_final.
|
||||
* In this repository's Coolify image the final app runs at /project_final.
|
||||
* Set APP_BASE_PATH to the subdirectory that serves webgis_app.
|
||||
* In this repository's Coolify image the final app runs at /webgis_app.
|
||||
*/
|
||||
require_once __DIR__ . '/env_loader.php';
|
||||
function app_base_path(): string {
|
||||
$basePath = getenv('APP_BASE_PATH');
|
||||
if ($basePath === false) {
|
||||
$basePath = '/project/project_final';
|
||||
$basePath = '/project/webgis_app';
|
||||
}
|
||||
|
||||
$basePath = trim($basePath);
|
||||
@@ -20,6 +21,9 @@ function app_base_path(): string {
|
||||
}
|
||||
|
||||
function app_url(string $path = ''): string {
|
||||
if ($path === '') {
|
||||
return app_base_path();
|
||||
}
|
||||
$path = '/' . ltrim($path, '/');
|
||||
return app_base_path() . $path;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* api_fasilitas.php
|
||||
* Endpoint: CRUD untuk layer Rumah Ibadah (Point).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama, agama, radius_bantuan_meter, created_at,
|
||||
ST_AsGeoJSON(geom) AS geojson FROM rumah_ibadah"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama' => $row['nama'],
|
||||
'agama' => $row['agama'],
|
||||
'radius_bantuan_meter' => $row['radius_bantuan_meter'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Rumah Ibadah berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Rumah Ibadah: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama']) || !isset($input['agama']) || !isset($input['geometry'])) {
|
||||
sendError('Nama, agama, dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO rumah_ibadah (nama, agama, radius_bantuan_meter, geom)
|
||||
VALUES (:nama, :agama, :radius_bantuan_meter, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama' => $input['nama'],
|
||||
':agama' => $input['agama'],
|
||||
':radius_bantuan_meter' => $input['radius_bantuan_meter'] ?? 1000,
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Rumah Ibadah berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Rumah Ibadah: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Rumah Ibadah wajib disertakan');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!$input) sendError('Data tidak valid');
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"UPDATE rumah_ibadah SET nama = :nama, agama = :agama, radius_bantuan_meter = :radius_bantuan_meter WHERE id = :id"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama' => $input['nama'],
|
||||
':agama' => $input['agama'],
|
||||
':radius_bantuan_meter' => $input['radius_bantuan_meter'] ?? 1000,
|
||||
':id' => $id,
|
||||
]);
|
||||
sendSuccess(null, 'Data Rumah Ibadah berhasil diperbarui');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal memperbarui Rumah Ibadah: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Rumah Ibadah wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM rumah_ibadah WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Rumah Ibadah berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Rumah Ibadah: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* api_jalan.php
|
||||
* Endpoint: CRUD untuk layer Jalan (LineString).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama, jenis_jalan, created_at, ST_AsGeoJSON(geom) AS geojson FROM jalan"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama' => $row['nama'],
|
||||
'jenis_jalan' => $row['jenis_jalan'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Jalan berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Jalan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama']) || !isset($input['geometry'])) {
|
||||
sendError('Nama dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO jalan (nama, jenis_jalan, geom)
|
||||
VALUES (:nama, :jenis_jalan, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama' => $input['nama'],
|
||||
':jenis_jalan' => $input['jenis_jalan'] ?? 'Lokal',
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Jalan berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Jalan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Jalan wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM jalan WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Jalan berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Jalan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* api_kavling.php
|
||||
* Endpoint: CRUD untuk layer Kavling (Polygon).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama_pemilik, status_kepemilikan, luas, created_at,
|
||||
ST_AsGeoJSON(geom) AS geojson FROM kavling"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama_pemilik' => $row['nama_pemilik'],
|
||||
'status_kepemilikan' => $row['status_kepemilikan'],
|
||||
'luas' => $row['luas'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Kavling berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Kavling: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama_pemilik']) || !isset($input['geometry'])) {
|
||||
sendError('Nama pemilik dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO kavling (nama_pemilik, status_kepemilikan, luas, geom)
|
||||
VALUES (:nama_pemilik, :status_kepemilikan, :luas, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama_pemilik' => $input['nama_pemilik'],
|
||||
':status_kepemilikan' => $input['status_kepemilikan'] ?? 'SHM',
|
||||
':luas' => $input['luas'] ?? 0,
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Kavling berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Kavling: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Kavling wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM kavling WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Kavling berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Kavling: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* api_kawasan.php
|
||||
* Endpoint: CRUD untuk layer Kawasan Kumuh (Polygon).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama_kawasan, created_at, ST_AsGeoJSON(geom) AS geojson FROM kawasan_kumuh"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama_kawasan' => $row['nama_kawasan'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Kawasan Kumuh berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Kawasan Kumuh: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama_kawasan']) || !isset($input['geometry'])) {
|
||||
sendError('Nama kawasan dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO kawasan_kumuh (nama_kawasan, geom)
|
||||
VALUES (:nama_kawasan, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama_kawasan' => $input['nama_kawasan'],
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Kawasan Kumuh berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Kawasan Kumuh: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Kawasan Kumuh wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM kawasan_kumuh WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Kawasan Kumuh berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Kawasan Kumuh: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* api_laporan.php
|
||||
* Endpoint: CRUD untuk Laporan Warga.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
require_once __DIR__ . '/../core_config/session_mgr.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
startAppSession();
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
requireApiLogin();
|
||||
try {
|
||||
$userId = $_SESSION['user_id'] ?? null;
|
||||
$role = $_SESSION['role'] ?? 'user';
|
||||
|
||||
if ($role === 'admin') {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT lw.id, lw.user_id, u.username, lw.kategori, lw.deskripsi,
|
||||
lw.status, lw.created_at, ST_AsGeoJSON(lw.geometry) AS geojson
|
||||
FROM laporan_warga lw
|
||||
JOIN users u ON u.id = lw.user_id
|
||||
ORDER BY lw.created_at DESC"
|
||||
);
|
||||
} else {
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT id, user_id, kategori, deskripsi, status, created_at,
|
||||
ST_AsGeoJSON(geometry) AS geojson
|
||||
FROM laporan_warga WHERE user_id = :uid ORDER BY created_at DESC"
|
||||
);
|
||||
$stmt->execute([':uid' => $userId]);
|
||||
}
|
||||
|
||||
$rows = $stmt->fetchAll();
|
||||
foreach ($rows as &$r) {
|
||||
$r['geojson'] = json_decode($r['geojson']);
|
||||
}
|
||||
sendSuccess($rows, 'Data Laporan berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil laporan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiLogin();
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['kategori']) || !isset($input['deskripsi']) || !isset($input['geometry'])) {
|
||||
sendError('Kategori, deskripsi, dan geometri wajib diisi');
|
||||
}
|
||||
$userId = $_SESSION['user_id'];
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO laporan_warga (user_id, kategori, deskripsi, geometry)
|
||||
VALUES (:user_id, :kategori, :deskripsi, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':user_id' => $userId,
|
||||
':kategori' => $input['kategori'],
|
||||
':deskripsi'=> $input['deskripsi'],
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Laporan berhasil dikirim', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan laporan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id || !isset($input['status'])) sendError('ID dan status wajib disertakan');
|
||||
$allowed = ['menunggu', 'diproses', 'selesai', 'ditolak'];
|
||||
if (!in_array($input['status'], $allowed)) sendError('Status tidak valid');
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE laporan_warga SET status = :status WHERE id = :id");
|
||||
$stmt->execute([':status' => $input['status'], ':id' => $id]);
|
||||
sendSuccess(null, 'Status laporan berhasil diperbarui');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal memperbarui laporan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID laporan wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM laporan_warga WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Laporan berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus laporan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* api_pengguna.php
|
||||
* Endpoint: Manajemen data Pengguna (hanya Admin).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
requireApiRole('admin');
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, username, role, nama_lengkap, created_at FROM users ORDER BY created_at DESC"
|
||||
);
|
||||
sendSuccess($stmt->fetchAll(), 'Data Pengguna berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data pengguna: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['username'], $input['password'])) {
|
||||
sendError('Username dan password wajib diisi');
|
||||
}
|
||||
try {
|
||||
$hash = password_hash($input['password'], PASSWORD_BCRYPT);
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO users (username, password, role, nama_lengkap)
|
||||
VALUES (:username, :password, :role, :nama_lengkap)"
|
||||
);
|
||||
$stmt->execute([
|
||||
':username' => $input['username'],
|
||||
':password' => $hash,
|
||||
':role' => $input['role'] ?? 'user',
|
||||
':nama_lengkap'=> $input['nama_lengkap'] ?? null,
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Pengguna berhasil dibuat', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal membuat pengguna: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID pengguna wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Pengguna berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus pengguna: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* api_spbu.php
|
||||
* Endpoint: CRUD untuk layer SPBU (Point).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama, deskripsi, buka_24_jam, created_at,
|
||||
ST_AsGeoJSON(geom) AS geojson FROM spbu"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama' => $row['nama'],
|
||||
'deskripsi' => $row['deskripsi'],
|
||||
'buka_24_jam' => (bool) $row['buka_24_jam'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data SPBU berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data SPBU: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama']) || !isset($input['geometry'])) {
|
||||
sendError('Nama dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO spbu (nama, deskripsi, buka_24_jam, geom)
|
||||
VALUES (:nama, :deskripsi, :buka_24_jam, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama' => $input['nama'],
|
||||
':deskripsi' => $input['deskripsi'] ?? '',
|
||||
':buka_24_jam' => isset($input['buka_24_jam']) && $input['buka_24_jam'] ? 1 : 0,
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data SPBU berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan SPBU: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID SPBU wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM spbu WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data SPBU berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus SPBU: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* api_spbu_nearby.php
|
||||
* Endpoint: Mencari SPBU terdekat dari titik koordinat pengguna.
|
||||
* Query params: lat, lng, radius (meter, default 5000)
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method !== 'GET') { sendError('Method not allowed', 405); }
|
||||
|
||||
$lat = isset($_GET['lat']) ? (float) $_GET['lat'] : null;
|
||||
$lng = isset($_GET['lng']) ? (float) $_GET['lng'] : null;
|
||||
$radius = isset($_GET['radius']) ? (int) $_GET['radius'] : 5000;
|
||||
|
||||
if ($lat === null || $lng === null) { sendError('Parameter lat dan lng wajib disertakan'); }
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT id, nama, deskripsi, buka_24_jam, created_at,
|
||||
ST_AsGeoJSON(geom) AS geojson,
|
||||
ST_Distance_Sphere(geom, ST_GeomFromText(:point)) AS jarak_meter
|
||||
FROM spbu
|
||||
WHERE ST_Distance_Sphere(geom, ST_GeomFromText(:point)) <= :radius
|
||||
ORDER BY jarak_meter ASC"
|
||||
);
|
||||
$stmt->execute([':point' => "POINT({$lng} {$lat})", ':radius' => $radius]);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama' => $row['nama'],
|
||||
'deskripsi' => $row['deskripsi'],
|
||||
'buka_24_jam' => (bool) $row['buka_24_jam'],
|
||||
'jarak_meter' => round($row['jarak_meter'], 2),
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'SPBU Terdekat berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil SPBU Terdekat: ' . $e->getMessage(), 500);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* api_spbu_status.php
|
||||
* Endpoint: Mengambil ringkasan status SPBU (berapa 24 jam, berapa tidak).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method !== 'GET') {
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT
|
||||
COUNT(*) AS total,
|
||||
SUM(buka_24_jam = 1) AS buka_24_jam,
|
||||
SUM(buka_24_jam = 0) AS tidak_24_jam
|
||||
FROM spbu"
|
||||
);
|
||||
$summary = $stmt->fetch();
|
||||
sendSuccess($summary, 'Status SPBU berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil status SPBU: ' . $e->getMessage(), 500);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* api_statistik.php
|
||||
* Endpoint: Mengembalikan ringkasan statistik keseluruhan data WebGIS.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
if ($method !== 'GET') { sendError('Method not allowed', 405); }
|
||||
|
||||
try {
|
||||
$counts = [];
|
||||
|
||||
$tables = [
|
||||
'spbu' => 'total_spbu',
|
||||
'rumah_ibadah' => 'total_rumah_ibadah',
|
||||
'jalan' => 'total_jalan',
|
||||
'kavling' => 'total_kavling',
|
||||
'kawasan_kumuh' => 'total_kawasan_kumuh',
|
||||
'warga_miskin' => 'total_warga_miskin',
|
||||
'laporan_warga' => 'total_laporan',
|
||||
'users' => 'total_users',
|
||||
];
|
||||
|
||||
foreach ($tables as $table => $key) {
|
||||
$row = $pdo->query("SELECT COUNT(*) AS cnt FROM `{$table}`")->fetch();
|
||||
$counts[$key] = (int) $row['cnt'];
|
||||
}
|
||||
|
||||
// Additional SPBU breakdown
|
||||
$spbuStatus = $pdo->query(
|
||||
"SELECT SUM(buka_24_jam=1) AS buka_24_jam, SUM(buka_24_jam=0) AS tidak_24_jam FROM spbu"
|
||||
)->fetch();
|
||||
$counts['spbu_buka_24_jam'] = (int) $spbuStatus['buka_24_jam'];
|
||||
$counts['spbu_tidak_24_jam'] = (int) $spbuStatus['tidak_24_jam'];
|
||||
|
||||
// Laporan by status
|
||||
$laporanStatus = $pdo->query(
|
||||
"SELECT status, COUNT(*) AS cnt FROM laporan_warga GROUP BY status"
|
||||
)->fetchAll();
|
||||
$counts['laporan_by_status'] = [];
|
||||
foreach ($laporanStatus as $row) {
|
||||
$counts['laporan_by_status'][$row['status']] = (int) $row['cnt'];
|
||||
}
|
||||
|
||||
sendSuccess($counts, 'Statistik berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil statistik: ' . $e->getMessage(), 500);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* api_ulasan.php
|
||||
* Endpoint: CRUD untuk Ulasan Fasilitas (SPBU / Rumah Ibadah).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
require_once __DIR__ . '/../core_config/session_mgr.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
startAppSession();
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$tipe = $_GET['tipe'] ?? null;
|
||||
$fid = $_GET['fasilitas_id'] ?? null;
|
||||
try {
|
||||
if ($tipe && $fid) {
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT uf.id, uf.user_id, u.username, uf.fasilitas_tipe,
|
||||
uf.fasilitas_id, uf.rating, uf.komentar, uf.created_at
|
||||
FROM ulasan_fasilitas uf
|
||||
JOIN users u ON u.id = uf.user_id
|
||||
WHERE uf.fasilitas_tipe = :tipe AND uf.fasilitas_id = :fid
|
||||
ORDER BY uf.created_at DESC"
|
||||
);
|
||||
$stmt->execute([':tipe' => $tipe, ':fid' => $fid]);
|
||||
} else {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT uf.id, uf.user_id, u.username, uf.fasilitas_tipe,
|
||||
uf.fasilitas_id, uf.rating, uf.komentar, uf.created_at
|
||||
FROM ulasan_fasilitas uf
|
||||
JOIN users u ON u.id = uf.user_id
|
||||
ORDER BY uf.created_at DESC"
|
||||
);
|
||||
}
|
||||
sendSuccess($stmt->fetchAll(), 'Data Ulasan berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil ulasan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiLogin();
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['fasilitas_tipe'], $input['fasilitas_id'], $input['rating'])) {
|
||||
sendError('fasilitas_tipe, fasilitas_id, dan rating wajib diisi');
|
||||
}
|
||||
$allowed = ['spbu', 'rumah_ibadah'];
|
||||
if (!in_array($input['fasilitas_tipe'], $allowed)) sendError('fasilitas_tipe tidak valid');
|
||||
if ($input['rating'] < 1 || $input['rating'] > 5) sendError('Rating harus antara 1-5');
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO ulasan_fasilitas (user_id, fasilitas_tipe, fasilitas_id, rating, komentar)
|
||||
VALUES (:user_id, :fasilitas_tipe, :fasilitas_id, :rating, :komentar)"
|
||||
);
|
||||
$stmt->execute([
|
||||
':user_id' => $_SESSION['user_id'],
|
||||
':fasilitas_tipe'=> $input['fasilitas_tipe'],
|
||||
':fasilitas_id' => $input['fasilitas_id'],
|
||||
':rating' => $input['rating'],
|
||||
':komentar' => $input['komentar'] ?? null,
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Ulasan berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan ulasan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID ulasan wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM ulasan_fasilitas WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Ulasan berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus ulasan: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* api_warga_miskin.php
|
||||
* Endpoint: CRUD untuk layer Warga Miskin (Point).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama_kk, penghasilan, jumlah_tanggungan, created_at,
|
||||
ST_AsGeoJSON(geom) AS geojson FROM warga_miskin"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama_kk' => $row['nama_kk'],
|
||||
'penghasilan' => $row['penghasilan'],
|
||||
'jumlah_tanggungan' => $row['jumlah_tanggungan'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Warga Miskin berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Warga Miskin: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama_kk']) || !isset($input['geometry'])) {
|
||||
sendError('Nama KK dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO warga_miskin (nama_kk, penghasilan, jumlah_tanggungan, geom)
|
||||
VALUES (:nama_kk, :penghasilan, :jumlah_tanggungan, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama_kk' => $input['nama_kk'],
|
||||
':penghasilan' => $input['penghasilan'] ?? 0,
|
||||
':jumlah_tanggungan' => $input['jumlah_tanggungan'] ?? 0,
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Warga Miskin berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Warga Miskin: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Warga Miskin wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM warga_miskin WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Warga Miskin berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Warga Miskin: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* area_blank.php
|
||||
* Endpoint: Blank Spot — area tanpa sinyal seluler.
|
||||
* Menggunakan tabel kawasan_kumuh sebagai proxy (tidak ada tabel blank_spot tersendiri).
|
||||
* Mengembalikan FeatureCollection kosong jika tabel belum ada.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
function sendSuccess($data = null, $message = 'Success', $code = 200) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'success', 'message' => $message, 'data' => $data]);
|
||||
exit();
|
||||
}
|
||||
function sendError($message = 'Error', $code = 400) {
|
||||
http_response_code($code);
|
||||
echo json_encode(['status' => 'error', 'message' => $message]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
// Check if blank_spot table exists, otherwise return empty collection
|
||||
$check = $pdo->query("SHOW TABLES LIKE 'blank_spot'")->rowCount();
|
||||
if ($check === 0) {
|
||||
sendSuccess(
|
||||
['type' => 'FeatureCollection', 'features' => []],
|
||||
'Tabel blank_spot belum tersedia'
|
||||
);
|
||||
}
|
||||
$stmt = $pdo->query(
|
||||
"SELECT id, nama, keterangan, created_at, ST_AsGeoJSON(geom) AS geojson FROM blank_spot"
|
||||
);
|
||||
$features = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$features[] = [
|
||||
'type' => 'Feature',
|
||||
'geometry' => json_decode($row['geojson']),
|
||||
'properties' => [
|
||||
'id' => $row['id'],
|
||||
'nama' => $row['nama'],
|
||||
'keterangan' => $row['keterangan'],
|
||||
'created_at' => $row['created_at'],
|
||||
],
|
||||
];
|
||||
}
|
||||
sendSuccess(['type' => 'FeatureCollection', 'features' => $features], 'Data Blank Spot berhasil diambil');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal mengambil data Blank Spot: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
requireApiRole('admin');
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
if (!isset($input['nama']) || !isset($input['geometry'])) {
|
||||
sendError('Nama dan geometri wajib diisi');
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO blank_spot (nama, keterangan, geom)
|
||||
VALUES (:nama, :keterangan, ST_GeomFromGeoJSON(:geometry))"
|
||||
);
|
||||
$stmt->execute([
|
||||
':nama' => $input['nama'],
|
||||
':keterangan' => $input['keterangan'] ?? '',
|
||||
':geometry' => json_encode($input['geometry']),
|
||||
]);
|
||||
sendSuccess(['id' => $pdo->lastInsertId()], 'Data Blank Spot berhasil disimpan', 201);
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menyimpan Blank Spot: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
requireApiRole('admin');
|
||||
$id = $_GET['id'] ?? null;
|
||||
if (!$id) sendError('ID Blank Spot wajib disertakan');
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM blank_spot WHERE id = :id");
|
||||
$stmt->execute([':id' => $id]);
|
||||
sendSuccess(null, 'Data Blank Spot berhasil dihapus');
|
||||
} catch (PDOException $e) {
|
||||
sendError('Gagal menghapus Blank Spot: ' . $e->getMessage(), 500);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sendError('Method not allowed', 405);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* cek_srid.php
|
||||
* Utility: Cek SRID (Spatial Reference ID) dari semua kolom geometri.
|
||||
* Hanya untuk Admin / debugging.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
requireApiRole('admin');
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
try {
|
||||
$tables = ['spbu', 'rumah_ibadah', 'jalan', 'kavling', 'kawasan_kumuh', 'warga_miskin'];
|
||||
$results = [];
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT ST_SRID(geom) AS srid, COUNT(*) AS jumlah
|
||||
FROM `{$table}`
|
||||
GROUP BY ST_SRID(geom)"
|
||||
);
|
||||
$results[$table] = $stmt->fetchAll();
|
||||
}
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['status' => 'success', 'data' => $results]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* perbaiki_srid.php
|
||||
* Utility: Perbaiki SRID semua geometri ke SRID 0 (tidak terdefinisi, kompatibel dengan MySQL).
|
||||
* Hanya untuk Admin / debugging.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../core_config/database.php';
|
||||
require_once __DIR__ . '/../core_config/middleware_auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
requireApiRole('admin');
|
||||
|
||||
$pdo = Database::getConnection();
|
||||
|
||||
try {
|
||||
$tables = ['spbu', 'rumah_ibadah', 'jalan', 'kavling', 'kawasan_kumuh', 'warga_miskin'];
|
||||
$updated = [];
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$affected = $pdo->exec(
|
||||
"UPDATE `{$table}` SET geom = ST_GeomFromWKB(ST_AsWKB(geom), 0) WHERE ST_SRID(geom) != 0"
|
||||
);
|
||||
$updated[$table] = ['rows_updated' => $affected];
|
||||
}
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['status' => 'success', 'message' => 'SRID diperbaiki', 'data' => $updated]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config/app.php';
|
||||
<?php
|
||||
require_once __DIR__ . '/core_config/settings.php';
|
||||
|
||||
$host = getenv('DB_HOST') ?: 'localhost';
|
||||
$port = getenv('DB_PORT') ?: 3306;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user