Files
UAS_WEBGIS_AlifaAisyahRahma…/PROJECT_CONTEXT.md
T
2026-06-10 20:41:42 +07:00

351 lines
14 KiB
Markdown

# 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
```php
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:
```php
// 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
```php
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
```toml
# 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
1. **Dua proyek terpisah** dengan database berbeda: `webgis_sig` (Layer) dan `webgis_rumah_ibadah` (Poverty Mapping).
2. **Koneksi DB berbeda**: Project Layer pakai `mysqli`, Project Rumah Ibadah pakai `PDO`.
3. **Auth hanya di Project 2** — Project 1 tidak punya autentikasi sama sekali.
4. **Session PHP** (`$_SESSION['user']`) digunakan untuk auth di Project 2; pengurus login via kode RI bukan dari tabel `users`.
5. **Semua file frontend** adalah single-page (satu file `index.html` besar) — tidak ada framework JS.
6. **GeoJSON** disimpan sebagai text di kolom `geojson LONGTEXT`, bukan tipe spatial MySQL.
7. **CORS** sudah dibuka untuk semua origin (`*`) di kedua config.php.
8. **Upload foto** hanya ada di Project 2 (laporan masyarakat), disimpan di folder `uploads/`.
9. **Re-assign otomatis** terjadi setiap kali ada perubahan pada tabel `rumah_ibadah` atau `keluarga_miskin` di Project 2.
10. **Walikota read-only**: fungsi `blockWalikotaWrite()` di `config.php` memblokir POST/PUT/DELETE untuk role walikota.