diff --git a/Dockerfile b/Dockerfile
index 7d38ffc..6b5a89b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,22 @@
-FROM nginx:alpine
+FROM php:8.2-apache
-COPY index.html /usr/share/nginx/html/index.html
+# Install PHP extensions & enable Apache modules
+RUN docker-php-ext-install mysqli pdo pdo_mysql \
+ && a2enmod rewrite headers
+
+# Allow .htaccess overrides and enable rewrite for all directories
+RUN sed -i 's|AllowOverride None|AllowOverride All|g' /etc/apache2/apache2.conf \
+ && echo "ServerName localhost" >> /etc/apache2/apache2.conf
+
+# Set working directory
+WORKDIR /var/www/html
+
+# Copy application files
+COPY . /var/www/html/
+
+# Set proper permissions for web server
+RUN chown -R www-data:www-data /var/www/html \
+ && find /var/www/html -type d -exec chmod 755 {} \; \
+ && find /var/www/html -type f -exec chmod 644 {} \;
EXPOSE 80
diff --git a/choropleth/index.html b/choropleth/index.html
new file mode 100644
index 0000000..89e8030
--- /dev/null
+++ b/choropleth/index.html
@@ -0,0 +1,824 @@
+
+
+
+
+
+
+
+ WebGIS Choropleth Penduduk Pontianak - BPS 2023
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/db_init/01_povertymap.sql b/db_init/01_povertymap.sql
new file mode 100644
index 0000000..1fc8235
--- /dev/null
+++ b/db_init/01_povertymap.sql
@@ -0,0 +1,85 @@
+CREATE DATABASE IF NOT EXISTS webgis_poverty_mapping
+ CHARACTER SET utf8mb4
+ COLLATE utf8mb4_unicode_ci;
+
+USE webgis_poverty_mapping;
+
+CREATE TABLE users (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ username VARCHAR(50) NOT NULL UNIQUE,
+ password VARCHAR(255) NOT NULL,
+ nama_lengkap VARCHAR(150) NOT NULL,
+ role ENUM('admin','surveyor','pemangku') NOT NULL DEFAULT 'surveyor',
+ is_active TINYINT(1) NOT NULL DEFAULT 1,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+-- Admin default β password: admin123
+-- Hash di-generate dengan password_hash('admin123', PASSWORD_BCRYPT)
+INSERT INTO users (username, password, nama_lengkap, role) VALUES
+ ('admin', '$2y$10$Xb5FU6uo67rVETXAlSYJ..wn8IudyYwGzUbyMe8yQ1TLFlvt.S9F6', 'Administrator', 'admin');
+
+CREATE TABLE rumah_ibadah (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ nama VARCHAR(200) NOT NULL,
+ jenis ENUM('masjid','gereja','pura','klenteng','vihara','lain') NOT NULL DEFAULT 'masjid',
+ alamat TEXT,
+ pic VARCHAR(150) NOT NULL,
+ no_wa VARCHAR(30) DEFAULT NULL,
+ radius INT NOT NULL DEFAULT 500, -- meter
+ lat DOUBLE NOT NULL,
+ lng DOUBLE NOT NULL,
+ foto_path VARCHAR(255) DEFAULT NULL,
+ surveyor_id INT DEFAULT NULL,
+ status ENUM('pending','verified','rejected') NOT NULL DEFAULT 'verified',
+ alasan_penolakan TEXT DEFAULT NULL,
+ kecamatan VARCHAR(100) DEFAULT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ CONSTRAINT fk_ri_surveyor FOREIGN KEY (surveyor_id) REFERENCES users(id) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE warga_miskin (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ nama_kk VARCHAR(200) NOT NULL,
+ nik VARCHAR(16) DEFAULT NULL,
+ jumlah_anggota INT NOT NULL DEFAULT 1,
+ keterangan TEXT,
+ alamat TEXT DEFAULT NULL,
+ kecamatan VARCHAR(100) DEFAULT NULL,
+ lat DOUBLE NOT NULL,
+ lng DOUBLE NOT NULL,
+ ibadah_id INT DEFAULT NULL, -- NULL = belum terjangkau
+ foto_path VARCHAR(255) DEFAULT NULL,
+ surveyor_id INT DEFAULT NULL,
+ status ENUM('pending','verified','rejected') NOT NULL DEFAULT 'verified',
+ alasan_penolakan TEXT DEFAULT NULL,
+ bantuan_diterima ENUM('sembako','beasiswa','modal','tunai','tidak_ada') NOT NULL DEFAULT 'tidak_ada',
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ CONSTRAINT uq_warga_nik UNIQUE (nik),
+ CONSTRAINT fk_wm_ibadah FOREIGN KEY (ibadah_id) REFERENCES rumah_ibadah(id) ON DELETE SET NULL,
+ CONSTRAINT fk_wm_surveyor FOREIGN KEY (surveyor_id) REFERENCES users(id) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE audit_logs (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ user_id INT NOT NULL,
+ aksi VARCHAR(100) NOT NULL,
+ target_type VARCHAR(50) DEFAULT NULL,
+ target_id INT DEFAULT NULL,
+ data_before JSON DEFAULT NULL,
+ data_after JSON DEFAULT NULL,
+ ip_address VARCHAR(45) DEFAULT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+CREATE INDEX idx_ri_status ON rumah_ibadah(status);
+CREATE INDEX idx_ri_kecamatan ON rumah_ibadah(kecamatan);
+CREATE INDEX idx_wm_status ON warga_miskin(status);
+CREATE INDEX idx_wm_kecamatan ON warga_miskin(kecamatan);
+CREATE INDEX idx_wm_ibadah ON warga_miskin(ibadah_id);
+CREATE INDEX idx_audit_user ON audit_logs(user_id);
+CREATE INDEX idx_audit_aksi ON audit_logs(aksi);
+CREATE INDEX idx_audit_created ON audit_logs(created_at);
\ No newline at end of file
diff --git a/db_init/02_spbu.sql b/db_init/02_spbu.sql
new file mode 100644
index 0000000..5a7a7dd
--- /dev/null
+++ b/db_init/02_spbu.sql
@@ -0,0 +1,23 @@
+-- ============================================
+-- WebGIS SPBU β Database Setup
+-- ============================================
+
+CREATE DATABASE IF NOT EXISTS webgis_spbu CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+
+USE webgis_spbu;
+
+CREATE TABLE IF NOT EXISTS spbu (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ nama VARCHAR(255) NOT NULL,
+ nomor_spbu VARCHAR(100) NOT NULL,
+ status VARCHAR(50) NOT NULL DEFAULT 'tidak',
+ latitude DOUBLE NOT NULL,
+ longitude DOUBLE NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+-- Contoh data awal
+INSERT INTO spbu (nama, nomor_spbu, status, latitude, longitude) VALUES
+('SPBU Pontianak Kota', '64.761.01', 'buka 24 jam', -0.0263, 109.3425),
+('SPBU Sungai Raya', '64.761.02', 'tidak', -0.0512, 109.3610),
+('SPBU Ahmad Yani', '64.761.03', 'buka 24 jam', -0.0198, 109.3580);
diff --git a/db_init/03_parsil.sql b/db_init/03_parsil.sql
new file mode 100644
index 0000000..e7ab2f2
--- /dev/null
+++ b/db_init/03_parsil.sql
@@ -0,0 +1,206 @@
+-- ============================================
+-- WebGIS Manajemen Jalan & Parsil Tanah
+-- Database Schema β Format GeoJSON
+-- ============================================
+
+CREATE DATABASE IF NOT EXISTS polyline_polygon CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+USE polyline_polygon;
+
+-- ============================================
+-- Tabel Data Jalan (LineString GeoJSON)
+-- ============================================
+CREATE TABLE IF NOT EXISTS jalan (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ nama_jalan VARCHAR(255) NOT NULL,
+ status_jalan ENUM('Jalan Nasional', 'Jalan Provinsi', 'Jalan Kabupaten') NOT NULL,
+ panjang_meter DOUBLE DEFAULT 0,
+ geojson LONGTEXT NOT NULL COMMENT 'GeoJSON Feature object with geometry type LineString',
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+
+-- ============================================
+-- Tabel Data Parsil Tanah (Polygon GeoJSON)
+-- ============================================
+CREATE TABLE IF NOT EXISTS parsil_tanah (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ nomor_sertifikat VARCHAR(100),
+ status_kepemilikan ENUM('SHM', 'HGB', 'HGU', 'HP') NOT NULL,
+ luas_meter2 DOUBLE DEFAULT 0,
+ geojson LONGTEXT NOT NULL COMMENT 'GeoJSON Feature object with geometry type Polygon',
+ nama_pemilik VARCHAR(255),
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
+);
+
+-- ============================================
+-- Tabel Laporan Kerusakan Jalan (Point GeoJSON)
+-- ============================================
+CREATE TABLE IF NOT EXISTS laporan_kerusakan (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ jalan_id INT DEFAULT 0 COMMENT 'FK ke tabel jalan (0 jika tidak terdeteksi)',
+ nama_jalan VARCHAR(255) DEFAULT 'Tidak Diketahui',
+ status_jalan VARCHAR(50) DEFAULT '',
+ nama_pelapor VARCHAR(255) DEFAULT 'Anonim',
+ kategori_rusak ENUM('Ringan', 'Sedang', 'Berat') NOT NULL,
+ tanggal_laporan DATE NOT NULL,
+ keterangan TEXT,
+ foto_url VARCHAR(500) DEFAULT NULL COMMENT 'Path foto kerusakan yang diupload',
+ geojson LONGTEXT NOT NULL COMMENT 'GeoJSON Feature Point [lng, lat]',
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ INDEX idx_jalan_id (jalan_id),
+ INDEX idx_tanggal (tanggal_laporan),
+ INDEX idx_kategori (kategori_rusak)
+);
+
+-- ============================================
+-- Sample Data Jalan
+-- Catatan: GeoJSON menggunakan [lng, lat] (bukan [lat, lng])
+-- ============================================
+INSERT INTO jalan (nama_jalan, status_jalan, panjang_meter, geojson) VALUES
+(
+ 'Jalan Ahmad Yani',
+ 'Jalan Nasional',
+ 1250.5,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nama_jalan": "Jalan Ahmad Yani",
+ "status_jalan": "Jalan Nasional",
+ "panjang_meter": 1250.5
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [109.3300, -0.0220],
+ [109.3340, -0.0235],
+ [109.3375, -0.0250],
+ [109.3410, -0.0263]
+ ]
+ }
+ }'
+),
+(
+ 'Jalan Gajah Mada',
+ 'Jalan Provinsi',
+ 870.3,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nama_jalan": "Jalan Gajah Mada",
+ "status_jalan": "Jalan Provinsi",
+ "panjang_meter": 870.3
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [109.3280, -0.0280],
+ [109.3330, -0.0270],
+ [109.3380, -0.0260]
+ ]
+ }
+ }'
+),
+(
+ 'Jalan Pahlawan',
+ 'Jalan Kabupaten',
+ 540.7,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nama_jalan": "Jalan Pahlawan",
+ "status_jalan": "Jalan Kabupaten",
+ "panjang_meter": 540.7
+ },
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [109.3420, -0.0300],
+ [109.3450, -0.0290],
+ [109.3480, -0.0280]
+ ]
+ }
+ }'
+);
+
+-- ============================================
+-- Sample Data Parsil Tanah
+-- Polygon: koordinat pertama dan terakhir harus sama (closed ring)
+-- ============================================
+INSERT INTO parsil_tanah (nomor_sertifikat, status_kepemilikan, luas_meter2, geojson, nama_pemilik) VALUES
+(
+ 'SHM-2024-001',
+ 'SHM',
+ 450.0,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nomor_sertifikat": "SHM-2024-001",
+ "status_kepemilikan": "SHM",
+ "luas_meter2": 450.0,
+ "nama_pemilik": "Budi Santoso"
+ },
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [109.3355, -0.0255],
+ [109.3370, -0.0255],
+ [109.3370, -0.0245],
+ [109.3355, -0.0245],
+ [109.3355, -0.0255]
+ ]]
+ }
+ }',
+ 'Budi Santoso'
+),
+(
+ 'HGB-2024-002',
+ 'HGB',
+ 620.5,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nomor_sertifikat": "HGB-2024-002",
+ "status_kepemilikan": "HGB",
+ "luas_meter2": 620.5,
+ "nama_pemilik": "PT. Maju Jaya"
+ },
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [109.3395, -0.0270],
+ [109.3415, -0.0270],
+ [109.3415, -0.0258],
+ [109.3395, -0.0258],
+ [109.3395, -0.0270]
+ ]]
+ }
+ }',
+ 'PT. Maju Jaya'
+),
+(
+ 'HGU-2024-003',
+ 'HGU',
+ 1200.0,
+ '{
+ "type": "Feature",
+ "properties": {
+ "nomor_sertifikat": "HGU-2024-003",
+ "status_kepemilikan": "HGU",
+ "luas_meter2": 1200.0,
+ "nama_pemilik": "CV. Agro Lestari"
+ },
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [[
+ [109.3310, -0.0285],
+ [109.3335, -0.0285],
+ [109.3335, -0.0268],
+ [109.3310, -0.0268],
+ [109.3310, -0.0285]
+ ]]
+ }
+ }',
+ 'CV. Agro Lestari'
+);
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..687542b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,31 @@
+services:
+ app:
+ build: .
+ restart: unless-stopped
+ ports:
+ - "8083:80"
+ environment:
+ DB_HOST: db
+ DB_USER: root
+ DB_PASS: cecilDatabase123
+ depends_on:
+ db:
+ condition: service_healthy
+
+ db:
+ image: mariadb:11.4
+ restart: unless-stopped
+ environment:
+ MARIADB_ROOT_PASSWORD: cecilDatabase123
+ volumes:
+ - db_data_cecil:/var/lib/mysql
+ - ./db_init:/docker-entrypoint-initdb.d:ro
+ healthcheck:
+ test: ["CMD-SHELL", "mariadb-admin ping -h localhost -uroot -pcecilDatabase123 --silent"]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+ start_period: 30s
+
+volumes:
+ db_data_cecil:
diff --git a/index.html b/index.html
index e49713b..3017a63 100644
--- a/index.html
+++ b/index.html
@@ -443,7 +443,7 @@