14 KiB
PROJECT CONTEXT — WebGIS Portal Kota Pontianak
Nama Mahasiswa: Alifa Aisyah Rahmani
NIM: D1041231042
Mata Kuliah: UAS Web GIS
Bahasa / Framework: PHP (vanilla), JavaScript (vanilla), MySQL, LeafletJS
Server dev: Laragon (Apache + MySQL) —localhost
📁 Struktur Direktori
www/ ← root proyek (localhost)
├── index.php ← Portal utama (landing page WebGIS)
├── nixpacks.toml ← Konfigurasi deploy (Railway): php -S 0.0.0.0:8080
├── rumah_ibadah.sql ← Backup SQL database rumah ibadah
├── sig.sql ← Backup SQL database GIS layer
│
├── Web GIS Layer/ ← PROJECT 1: Manajemen layer spasial
│ ├── index.html ← UI utama (single-page app)
│ ├── config.php ← Koneksi DB (mysqli), helpers
│ ├── api_jalan.php ← CRUD data jalan (polyline GeoJSON)
│ ├── api_parsil.php ← CRUD data parsil tanah (polygon GeoJSON)
│ ├── api_spbu.php ← CRUD data SPBU (point GeoJSON)
│ └── database.sql ← Skema DB: data_jalan, data_parsil, data_spbu
│
└── Web GIS Rumah Ibadah/ ← PROJECT 2: Poverty Mapping + Rumah Ibadah
├── index.html ← UI utama (single-page app, ~137KB)
├── index.php ← Redirect ke index.html
├── config.php ← Koneksi DB (PDO), utilitas lengkap
├── api_auth.php ← Autentikasi (login/logout/check session)
├── api_rumah_ibadah.php ← CRUD rumah ibadah + reset password pengurus
├── api_keluarga_miskin.php ← CRUD keluarga miskin + auto-assign Haversine
├── api_laporan.php ← Laporan masyarakat (publik, tanpa login)
├── api_histori_bantuan.php ← Histori penyaluran bantuan sosial
├── api_dashboard.php ← Statistik dashboard walikota
├── database.sql ← Skema DB lengkap + seed data
├── PENJELASAN_SISTEM_SRS_MANUAL.md ← Dokumentasi SRS & Manual Book
└── uploads/ ← Foto laporan masyarakat
🗺️ PROJECT 1 — Web GIS Layer (Jalan, Parsil, SPBU)
Tujuan
Sistem manajemen layer spasial untuk Kota Pontianak: menggambar dan mengelola data jalan (polyline), parsil tanah (polygon), dan SPBU (point marker) langsung di peta interaktif.
Stack Teknologi
| Komponen | Teknologi |
|---|---|
| Frontend | HTML5, CSS3, JavaScript vanilla |
| Peta | LeafletJS 1.9.4, Leaflet.draw |
| Backend | PHP + mysqli |
| Database | MySQL — webgis_sig |
| Tile | OpenStreetMap / Google Satellite |
Database — webgis_sig
Tabel data_jalan (geometri: LineString GeoJSON)
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT AUTO_INCREMENT PK | |
nama_jalan |
VARCHAR(150) | |
status_jalan |
ENUM | Jalan Nasional, Jalan Provinsi, Jalan Kabupaten |
panjang_m |
DECIMAL(12,2) | Dihitung otomatis oleh LeafletJS |
geojson |
LONGTEXT | Format LineString GeoJSON |
keterangan |
TEXT | |
created_at, updated_at |
TIMESTAMP |
Tabel data_parsil (geometri: Polygon GeoJSON)
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT AUTO_INCREMENT PK | |
nama_parsil |
VARCHAR(150) | |
status_hak |
ENUM | SHM, SHGB, SHGU, SHP |
luas_m2 |
DECIMAL(15,2) | Dihitung otomatis oleh LeafletJS |
geojson |
LONGTEXT | Format Polygon GeoJSON |
pemilik |
VARCHAR(150) | Opsional |
keterangan |
TEXT |
Tabel data_spbu (geometri: Point GeoJSON)
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT AUTO_INCREMENT PK | |
nama_spbu |
VARCHAR(150) | |
telepon |
VARCHAR(20) | |
buka_24jam |
TINYINT(1) | 1=hijau, 0=merah |
lat, lng |
DECIMAL(10,7) | |
geojson |
LONGTEXT | Format Point GeoJSON |
API Endpoints — Web GIS Layer
Semua API menggunakan Content-Type: application/json dan method GET/POST/PUT/DELETE.
GET api_jalan.php → list semua jalan
GET api_jalan.php?id=N → detail satu jalan
POST api_jalan.php → tambah jalan (body: nama_jalan, status_jalan, panjang_m, geojson, keterangan)
PUT api_jalan.php → update jalan (body: id, ...)
DELETE api_jalan.php?id=N → hapus jalan
(Pola sama untuk api_parsil.php dan api_spbu.php)
Fitur Utama — Web GIS Layer
- ✅ Gambar polyline (jalan) & polygon (parsil) langsung di peta via Leaflet.draw
- ✅ CRUD penuh: tambah, edit, hapus dari sidebar
- ✅ Kalkulasi panjang (meter) & luas (m²) otomatis saat menggambar
- ✅ Layer switcher: Street Map & Satellite view
- ✅ Popup detail saat klik marker/layer
- ✅ Filter data per tab (Jalan / Parsil / SPBU)
- ✅ SPBU marker berwarna: hijau (24 jam) vs merah (tidak)
config.php — Web GIS Layer
define('DB_HOST', getenv('DB_HOST') ?: 'vg4so4ccs0444o4cgkssgos8');
define('DB_PORT', getenv('DB_PORT') ?: 3306);
define('DB_NAME', getenv('DB_NAME') ?: 'default');
define('DB_USER', getenv('DB_USER') ?: 'mysql');
define('DB_PASS', getenv('DB_PASS') ?: '...'); // password Railway
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT);
Koneksi: mysqli (bukan PDO). Response format: {"status": "success"|"error", "data": [...]}.
🕌 PROJECT 2 — WebGIS Poverty Mapping & Rumah Ibadah
Tujuan
Pemetaan keluarga miskin di Kota Pontianak dengan pendekatan berbasis rumah ibadah sebagai unit pembina sosial. Rumah ibadah punya radius cakupan (km); keluarga miskin yang lokasinya masuk dalam radius otomatis ditugaskan sebagai KK binaan rumah ibadah terdekat (algoritma Haversine).
Stack Teknologi
| Komponen | Teknologi |
|---|---|
| Frontend | HTML5, CSS3, JavaScript vanilla, LeafletJS 1.9.4 |
| Backend | PHP + PDO |
| Database | MySQL — webgis_rumah_ibadah (atau default di Railway) |
| Peta | CARTO Voyager tiles + Nominatim (reverse geocoding) |
| Ekspor | SheetJS (Excel), jsPDF + autoTable (PDF) |
| Autentikasi | PHP Session ($_SESSION['user']) |
Database — webgis_rumah_ibadah
Tabel rumah_ibadah
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT PK AUTO_INCREMENT | |
nama |
VARCHAR(200) | |
jenis |
ENUM | Masjid, Gereja, Pura, Vihara, Klenteng, Lainnya |
alamat |
TEXT | |
lat, lng |
DECIMAL(10,7) | Koordinat |
radius_km |
FLOAT | Default 2.0 km |
kode_pengurus |
VARCHAR(20) UNIQUE | Format: RI-MSJ-4821 |
password_pengurus |
VARCHAR(255) | bcrypt hash |
kecamatan |
ENUM | 6 kecamatan Pontianak |
created_at |
TIMESTAMP |
Tabel users
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT PK | |
nama |
VARCHAR(150) | |
username |
VARCHAR(100) UNIQUE | |
password |
VARCHAR(255) | bcrypt |
role |
ENUM | admin, pengurus, walikota |
rumah_ibadah_id |
INT FK NULL | Hanya untuk pengurus |
Tabel keluarga_miskin
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT PK | |
nik |
VARCHAR(20) UNIQUE | |
nama_kepala_keluarga |
VARCHAR(200) | |
tanggal_lahir |
DATE | |
pendidikan |
ENUM | Tidak Sekolah, SD, SMP, SMA, D3, S1, S2/S3 |
jumlah_anggota |
INT | |
alamat |
TEXT | |
kecamatan |
ENUM | 6 kecamatan |
lat, lng |
DECIMAL(10,7) | |
tingkat_kemiskinan |
ENUM | Sangat Miskin, Miskin, Hampir Miskin |
status_dtks |
ENUM | Terdaftar DTKS, Belum DTKS, Sedang Diusulkan |
riwayat_penyakit |
JSON | Array: ["Stunting","TBC",...] |
rumah_ibadah_id |
INT FK NULL | Auto-assign |
jarak_ke_ibadah |
FLOAT | km, auto-assign |
Tabel laporan_masyarakat
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT PK | |
nama_terlapor, nik_terlapor |
VARCHAR | Boleh null |
nama_pelapor, no_hp |
VARCHAR | Boleh anonim |
alamat_terlapor |
TEXT | |
lat, lng |
DECIMAL(10,7) | |
deskripsi |
TEXT | |
foto |
VARCHAR(255) | Path relatif uploads/... |
status |
ENUM | Baru, Diverifikasi, Ditolak |
alasan_tolak |
TEXT | |
ditangani_oleh |
INT FK | → users.id |
converted_to_kk_id |
INT FK | → keluarga_miskin.id |
Tabel histori_bantuan
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
INT PK | |
kk_id |
INT FK | → keluarga_miskin.id |
jenis_bantuan |
ENUM | PKH, BPNT/Sembako, Beras Bansos, KIS-PBI, Bansos Tunai Pemkot, Rutilahu, PMT Stunting, CSR Swasta, Lainnya |
nominal |
BIGINT | Rupiah (0 jika non-uang) |
keterangan |
TEXT | |
tanggal_penyaluran |
DATE | |
sumber_dana |
ENUM | APBN, APBD, CSR, Lainnya |
penanggung_jawab |
INT FK | → users.id |
Tabel rate_limit
Pembatasan submit laporan masyarakat: maks 5 submit per IP per jam.
API Endpoints — Web GIS Rumah Ibadah
Response format standar: {"success": true/false, "data": ..., "message": "..."}.
# Auth
POST api_auth.php?action=login body: {username, password}
POST api_auth.php?action=logout
GET api_auth.php?action=check
# Rumah Ibadah
GET api_rumah_ibadah.php → list semua (publik)
GET api_rumah_ibadah.php?id=N → detail + jumlah_kk_binaan
POST api_rumah_ibadah.php → tambah (admin only)
PUT api_rumah_ibadah.php → update (admin + pengurus RI sendiri)
DELETE api_rumah_ibadah.php?id=N → hapus (admin only)
PATCH api_rumah_ibadah.php → reset password pengurus (admin only)
# Keluarga Miskin
GET api_keluarga_miskin.php → list (pengurus hanya KK binaan)
GET api_keluarga_miskin.php?id=N → detail
POST api_keluarga_miskin.php → tambah (admin + pengurus)
PUT api_keluarga_miskin.php → update
DELETE api_keluarga_miskin.php?id=N → hapus (admin only)
# Laporan Masyarakat
GET api_laporan.php → list (admin + walikota)
POST api_laporan.php → kirim laporan (publik, tanpa login)
PUT api_laporan.php → kelola status (admin)
# Histori Bantuan
GET api_histori_bantuan.php?kk_id=N → list bantuan per KK
POST api_histori_bantuan.php → tambah bantuan
DELETE api_histori_bantuan.php?id=N → hapus bantuan
# Dashboard
GET api_dashboard.php → statistik agregat (admin + walikota)
Hak Akses (Role-Based Access Control)
| Aksi | Publik | Pengurus | Admin | Walikota |
|---|---|---|---|---|
| Lihat peta & data | ✅ | ✅ | ✅ | ✅ |
| Kirim laporan | ✅ | ✅ | ✅ | ✅ |
| Kelola Rumah Ibadah | ❌ | ✅ (RI sendiri) | ✅ | ❌ |
| Tambah/Hapus RI | ❌ | ❌ | ✅ | ❌ |
| Kelola KK | ❌ | ✅ (KK binaan) | ✅ | ❌ |
| Hapus KK | ❌ | ❌ | ✅ | ❌ |
| Verifikasi laporan | ❌ | ❌ | ✅ | ❌ |
| Dashboard + Ekspor | ❌ | ❌ | ✅ | ✅ |
Logika Bisnis Penting
Auto-Assign Haversine
Setiap kali KK ditambah/diupdate, atau ketika RI berubah/dihapus:
// config.php — fungsi autoAssign()
// Iterasi semua RI, hitung jarak Haversine ke KK
// Assign KK ke RI yang paling dekat DAN radiusnya mencakup posisi KK
// Jika tidak ada RI yang mencakup → rumah_ibadah_id = NULL
Generate Kode Pengurus
Format: RI-[3HURUF]-[4DIGIT]
Mapping jenis: Masjid→MSJ, Gereja→GRJ, Pura→PRA, Vihara→VHR, Klenteng→KLT, Lainnya→LNY
Upload Foto Laporan
- Tipe: JPG, PNG, GIF, WebP — maks 5MB
- Disimpan di
uploads/laporan_[timestamp]_[hex].ext - Helper:
handleUpload(string $fieldName): ?string
Data Demo (Testing)
| Akun | Username | Password |
|---|---|---|
| Admin | admin |
admin123 |
| Walikota | walikota |
admin123 |
| Pengurus Masjid Raya | RI-MSJ-4821 |
pengurus123 |
| Pengurus Gereja Katedral | RI-GRJ-7153 |
pengurus123 |
Database seed: 2 rumah ibadah, 5 keluarga miskin, 1 laporan masyarakat, 2 histori bantuan.
config.php — Web GIS Rumah Ibadah
define('DB_HOST', getenv('DB_HOST') ?: 'vg4so4ccs0444o4cgkssgos8');
define('DB_PORT', getenv('DB_PORT') ?: 3306);
define('DB_NAME', getenv('DB_NAME') ?: 'default');
define('DB_USER', getenv('DB_USER') ?: 'mysql');
define('DB_PASS', getenv('DB_PASS') ?: '...');
$pdo = new PDO("mysql:host=...", DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
]);
Koneksi: PDO (bukan mysqli). CORS headers diset di config.php (allow all origins).
🌐 Portal Utama (index.php)
Landing page modern (dark mode, glassmorphism) yang menampilkan dua card proyek:
- Card 1 — WebGIS Layer (biru): link ke
/Web GIS Layer/index.html - Card 2 — WebGIS Poverty Mapping & Rumah Ibadah (ungu): link ke
/Web GIS Rumah Ibadah/index.html
Stack: vanilla HTML/CSS/JS, Google Fonts (Inter + Space Grotesk), FontAwesome 6.5.1, animasi canvas.
🚀 Deployment
# nixpacks.toml
[start]
cmd = "php -S 0.0.0.0:8080 -t ."
Platform: Railway dengan DB host eksternal MySQL. Variabel env: DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS.
📝 Catatan Penting untuk Claude
- Dua proyek terpisah dengan database berbeda:
webgis_sig(Layer) danwebgis_rumah_ibadah(Poverty Mapping). - Koneksi DB berbeda: Project Layer pakai
mysqli, Project Rumah Ibadah pakaiPDO. - Auth hanya di Project 2 — Project 1 tidak punya autentikasi sama sekali.
- Session PHP (
$_SESSION['user']) digunakan untuk auth di Project 2; pengurus login via kode RI bukan dari tabelusers. - Semua file frontend adalah single-page (satu file
index.htmlbesar) — tidak ada framework JS. - GeoJSON disimpan sebagai text di kolom
geojson LONGTEXT, bukan tipe spatial MySQL. - CORS sudah dibuka untuk semua origin (
*) di kedua config.php. - Upload foto hanya ada di Project 2 (laporan masyarakat), disimpan di folder
uploads/. - Re-assign otomatis terjadi setiap kali ada perubahan pada tabel
rumah_ibadahataukeluarga_miskindi Project 2. - Walikota read-only: fungsi
blockWalikotaWrite()diconfig.phpmemblokir POST/PUT/DELETE untuk role walikota.