# 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.