Initial commit - Portal WebGIS Terpadu

This commit is contained in:
ocabacaa
2026-06-12 11:03:16 +07:00
commit 2cbdb83bce
74 changed files with 9846 additions and 0 deletions
+212
View File
@@ -0,0 +1,212 @@
# Portal WebGIS Terpadu
Portal WebGIS Terpadu merupakan sistem yang mengintegrasikan beberapa aplikasi WebGIS dalam satu platform untuk memudahkan pengguna dalam mengakses, memvisualisasikan, dan menganalisis data spasial secara interaktif.
## Identitas Pengembang
**Nama** : Clara Oxana Azalia
**NIM** : D1041231051
---
## Deskripsi Sistem
Portal ini berfungsi sebagai halaman utama (landing page) yang menghubungkan beberapa aplikasi WebGIS ke dalam satu sistem terintegrasi. Pengguna dapat memilih aplikasi yang ingin digunakan melalui antarmuka yang responsif dan mudah digunakan.
Aplikasi yang terintegrasi dalam portal ini meliputi:
1. **WebGIS Parsil Tanah**
2. **WebGIS Kemiskinan**
3. **WebGIS SPBU**
---
## Struktur Folder
```text
webgis-claraoxanaazalia/
├── gis-spbu/
├── webgis-parsiltanah/
├── webgis-poverty/
├── index.php
└── README.md
```
---
## Fitur Portal
* Landing page terintegrasi untuk seluruh aplikasi WebGIS.
* Tampilan modern dan responsif menggunakan Tailwind CSS.
* Navigasi mudah menuju masing-masing aplikasi.
* Desain bertema geospasial dan pemetaan.
* Mendukung tampilan desktop maupun perangkat mobile.
---
## Daftar Aplikasi
### 1. WebGIS Parsil Tanah
Aplikasi untuk menampilkan data bidang tanah (parsil) dalam bentuk peta interaktif beserta informasi atribut yang terkait.
#### Fitur
* Visualisasi data parsil tanah.
* Informasi atribut bidang tanah.
* Interaksi peta berbasis WebGIS.
* Popup informasi objek spasial.
---
### 2. WebGIS Kemiskinan
Aplikasi untuk menampilkan persebaran data kemiskinan wilayah menggunakan visualisasi peta tematik (choropleth).
#### Fitur
* Peta choropleth.
* Visualisasi tingkat kemiskinan.
* Analisis wilayah berbasis spasial.
* Informasi statistik wilayah.
---
### 3. WebGIS SPBU
Aplikasi untuk menampilkan lokasi SPBU pada peta interaktif beserta informasi pendukungnya.
#### Fitur
* Pemetaan lokasi SPBU.
* Marker interaktif.
* Informasi detail SPBU.
* Visualisasi lokasi berbasis peta.
---
## Cara Menjalankan Aplikasi
### 1. Clone Repository
```bash
git clone https://git.ifuntanhub.dev/claraoxza/webgis-claraoxanaazalia.git
```
### 2. Simpan pada Folder Web Server
**Laragon**
```text
C:\laragon\www\webgis-claraoxanaazalia
```
**XAMPP**
```text
C:\xampp\htdocs\webgis-claraoxanaazalia
```
### 3. Jalankan Web Server
* Start Laragon.
* Start MySQL.
* Pastikan database masing-masing aplikasi telah diimpor.
### 4. Buka Portal
Akses melalui browser:
```text
http://localhost/webgis-claraoxanaazalia/
```
---
## Cara Penggunaan
### Membuka Aplikasi
1. Buka Portal WebGIS Terpadu.
2. Pilih salah satu kartu aplikasi yang tersedia.
3. Klik tombol atau kartu aplikasi.
4. Sistem akan mengarahkan pengguna ke aplikasi WebGIS yang dipilih.
### Navigasi Peta
#### Zoom In
* Klik tombol (+)
* Scroll mouse ke atas
#### Zoom Out
* Klik tombol (-)
* Scroll mouse ke bawah
#### Geser Peta
* Klik dan tahan peta
* Geser ke arah yang diinginkan
#### Melihat Informasi Objek
* Klik marker, polygon, atau layer pada peta
* Informasi detail akan ditampilkan melalui popup
---
## Teknologi yang Digunakan
### Frontend
* HTML5
* CSS3
* Tailwind CSS
* JavaScript
### Backend
* PHP
### Database
* MySQL
### GIS & Mapping
* Leaflet JS
* GeoJSON
---
## Tujuan Pengembangan
Portal WebGIS Terpadu dikembangkan sebagai media integrasi berbagai aplikasi WebGIS yang mencakup pemetaan lokasi SPBU, data parsil tanah, dan visualisasi kemiskinan wilayah. Sistem ini dirancang untuk mempermudah pengguna dalam mengakses informasi geospasial secara terpusat dan interaktif.
---
## Tampilan Sistem
Portal menampilkan:
* Landing page utama.
* Informasi pengembang.
* Kartu aplikasi WebGIS.
* Panduan penggunaan.
* Navigasi menuju masing-masing sistem WebGIS.
---
## Lisensi
Project ini dibuat untuk keperluan pembelajaran, praktikum, dan pengembangan sistem informasi geospasial.
---
© 2026 Clara Oxana Azalia — D1041231051
+77
View File
@@ -0,0 +1,77 @@
# WebGIS SPBU
## Deskripsi
WebGIS SPBU merupakan Sistem Informasi Geografis berbasis web yang digunakan untuk memetakan, mengelola, dan mencari lokasi SPBU dengan rute terdekat dari titik lokasi user saat ini.
**Nama:** Clara Oxana Azalia
**NIM:** D1041231051
## Fitur
- CRUD Data SPBU
- Upload Foto SPBU
- Pencarian SPBU
- Lokasi Saya
- SPBU Terdekat
- Routing ke SPBU Terdekat
- Status Buka/Tutup Otomatis
- Filter SPBU
- Mode Admin dan View
- Digitasi Polygon
- Digitasi Polyline
- Edit dan Hapus Objek Spasial
- Penyimpanan GeoJSON ke Database
## Teknologi
- PHP Native
- MySQL
- JavaScript
- Leaflet.js
- Leaflet Draw
- Leaflet Routing Machine
- OpenStreetMap
- Tailwind CSS
## Instalasi
1. Clone repository
```bash
git clone https://github.com/USERNAME/webgis-spbu.git
```
2. Import database
```text
database.sql
```
3. Sesuaikan konfigurasi database pada:
```php
koneksi.php
```
4. Jalankan pada server lokal:
```text
http://localhost/webgis-spbu
```
## Struktur Project
```text
api/
assets/
uploads/
database.sql
koneksi.php
index.php
```
## Pengembang
Clara Oxana Azalia
D1041231051
+133
View File
@@ -0,0 +1,133 @@
<?php
include '../koneksi.php';
header('Content-Type: application/json');
$id = $_POST['id'];
$nama = $_POST['nama'];
$alamat = $_POST['alamat'];
$lat = $_POST['lat'];
$lng = $_POST['lng'];
$fotoLama = '';
$jam_buka = $_POST['jam_buka'];
$jam_tutup = $_POST['jam_tutup'];
$buka_24_jam = $_POST['buka_24_jam'];
$getData = mysqli_query(
$conn,
"SELECT foto
FROM spbu
WHERE id='$id'"
);
if($row = mysqli_fetch_assoc($getData)){
$fotoLama = $row['foto'];
}
$updateFoto = "";
$hapusFotoLama = false;
if(
isset($_FILES['foto']) &&
$_FILES['foto']['error'] == 0
){
$namaFile =
time().'_'.
$_FILES['foto']['name'];
$allowed = [
'jpg',
'jpeg',
'png',
'webp'
];
$fileType = strtolower(
pathinfo(
$_FILES['foto']['name'],
PATHINFO_EXTENSION
)
);
if(!in_array($fileType, $allowed)){
echo json_encode([
'status'=>'error',
'message'=>'File type not allowed'
]);
exit;
}
move_uploaded_file(
$_FILES['foto']['tmp_name'],
'../uploads/spbu/' .
$namaFile
);
$updateFoto =
", foto='$namaFile'";
$hapusFotoLama = true;
}
$query = mysqli_query(
$conn,
"UPDATE spbu SET
nama_spbu='$nama',
alamat='$alamat',
latitude='$lat',
longitude='$lng',
jam_buka='$jam_buka',
jam_tutup='$jam_tutup',
buka_24_jam='$buka_24_jam'
$updateFoto
WHERE id='$id'
"
);
if($query){
if(
$hapusFotoLama &&
!empty($fotoLama) &&
file_exists(
'../uploads/spbu/' .
$fotoLama
)
){
unlink(
'../uploads/spbu/' .
$fotoLama
);
}
echo json_encode([
'status'=>'success'
]);
} else{
echo json_encode([
'status'=>'error',
'message'=>mysqli_error($conn)
]);
}
+22
View File
@@ -0,0 +1,22 @@
<?php
include '../koneksi.php';
$query =
mysqli_query(
$conn,
"SELECT * FROM objek_peta"
);
$data = [];
while(
$row =
mysqli_fetch_assoc($query)
){
$data[] = $row;
}
echo json_encode($data);
+16
View File
@@ -0,0 +1,16 @@
<?php
include '../koneksi.php';
$query = mysqli_query(
$conn,
"SELECT * FROM spbu"
);
$data = [];
while($row = mysqli_fetch_assoc($query)){
$data[] = $row;
}
echo json_encode($data);
+15
View File
@@ -0,0 +1,15 @@
<?php
include '../koneksi.php';
$id = $_POST['id'];
mysqli_query(
$conn,
"DELETE FROM objek_peta
WHERE id='$id'"
);
+51
View File
@@ -0,0 +1,51 @@
<?php
include '../koneksi.php';
$data = json_decode(
file_get_contents("php://input"),
true
);
$id = $data['id'];
$foto = '';
$getData = mysqli_query(
$conn,
"SELECT foto
FROM spbu
WHERE id='$id'"
);
if($row = mysqli_fetch_assoc($getData)){
$foto = $row['foto'];
}
if(!empty($foto) && file_exists('../uploads/spbu/' . $foto)){
unlink('../uploads/spbu/' . $foto);
}
$query = mysqli_query(
$conn,
"DELETE FROM spbu WHERE id='$id'"
);
if($query){
echo json_encode([
'status'=>'success'
]);
}else{
echo json_encode([
'status'=>'error'
]);
}
+35
View File
@@ -0,0 +1,35 @@
<?php
include '../koneksi.php';
$nama = $_POST['nama'];
$deskripsi = $_POST['deskripsi'];
$tipe = $_POST['tipe'];
$geojson = $_POST['geojson'];
mysqli_query(
$conn,
"INSERT INTO objek_peta
(
nama,
deskripsi,
tipe,
geojson
)
VALUES
(
'$nama',
'$deskripsi',
'$tipe',
'$geojson'
)"
);
$id = mysqli_insert_id($conn);
echo json_encode([
'id'=>$id
]);
+104
View File
@@ -0,0 +1,104 @@
<?php
include '../koneksi.php';
$nama = $_POST['nama'];
$alamat = $_POST['alamat'];
$lat = $_POST['lat'];
$lng = $_POST['lng'];
$jam_buka = $_POST['jam_buka'] ?? null;
$jam_tutup = $_POST['jam_tutup'] ?? null;
$buka_24_jam = $_POST['buka_24_jam'] ?? 0;
$foto = '';
if(isset($_FILES['foto'])){
$namaFile =
time().'_'.
$_FILES['foto']['name'];
$allowed = [
'jpg',
'jpeg',
'png',
'webp'
];
$ext =
strtolower(
pathinfo(
$_FILES['foto']['name'],
PATHINFO_EXTENSION
)
);
if(
!in_array(
$ext,
$allowed
)
){
echo json_encode([
'status'=>'error',
'message'=>'Format file tidak valid'
]);
exit;
}
move_uploaded_file(
$_FILES['foto']['tmp_name'],
'../uploads/spbu/'.
$namaFile
);
$foto = $namaFile;
}
$query = mysqli_query(
$conn,
"INSERT INTO spbu
(
nama_spbu,
alamat,
latitude,
longitude,
foto,
jam_buka,
jam_tutup,
buka_24_jam
)
VALUES
(
'$nama',
'$alamat',
'$lat',
'$lng',
'$foto',
'$jam_buka',
'$jam_tutup',
'$buka_24_jam'
)"
);
if($query){
echo json_encode([
'status'=>'success'
]);
}else{
echo json_encode([
'status'=>'error',
'message'=>mysqli_error($conn)
]);
}
+43
View File
@@ -0,0 +1,43 @@
<?php
include '../koneksi.php';
$id = $_POST['id'];
$nama = $_POST['nama'] ?? '';
$deskripsi = $_POST['deskripsi'] ?? '';
if(isset($_POST['geojson'])){
$geojson = $_POST['geojson'];
mysqli_query(
$conn,
"UPDATE objek_peta
SET geojson='$geojson'
WHERE id='$id'"
);
}else{
mysqli_query(
$conn,
"UPDATE objek_peta
SET
nama='$nama',
deskripsi='$deskripsi'
WHERE id='$id'"
);
}
echo json_encode([
'status'=>'success'
]);
+3
View File
@@ -0,0 +1,3 @@
.leaflet-interactive{
cursor:pointer;
}
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
CREATE TABLE spbu (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_spbu VARCHAR(100),
alamat TEXT,
latitude DOUBLE,
longitude DOUBLE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE spbu
ADD foto VARCHAR(255);
ALTER TABLE spbu
ADD buka_24_jam TINYINT(1) DEFAULT 0,
ADD jam_buka TIME,
ADD jam_tutup TIME;
CREATE TABLE objek_peta (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100),
tipe VARCHAR(20),
geojson LONGTEXT
);
+306
View File
@@ -0,0 +1,306 @@
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw/dist/leaflet.draw.css" />
<style>
#map {
height: 100vh;
}
</style>
</head>
<body>
<div class="flex h-screen">
<div class="flex-1 relative">
<div style="
position:absolute;
top:15px;
left:60px;
z-index:9999;
background:white;
padding:10px;
border-radius:8px;
box-shadow:0 2px 8px rgba(0,0,0,.2);
">
<div style="margin-bottom:10px;">
<h1 style="
font-size:24px;
font-weight:bold;
color:#2563eb;
margin:0;
">
Dashboard WebGIS SPBU
</h1>
<p style="
margin:0;
color:#666;
font-size:14px;
">
Sistem Informasi Geografis Pemetaan dan Pencarian Lokasi SPBU
</p>
<p style="
margin:3px 0 0 0;
color:#999;
font-size:12px;
">
Clara Oxana Azalia | D1041231051
</p>
</div>
<!-- toolbar -->
<div class="flex gap-2">
<input type="text" id="search_spbu" placeholder="Cari SPBU..." class="border p-2 rounded">
<button onclick="cariSPBU()" class="bg-blue-500 text-white px-3 rounded">
Cari
</button>
<button onclick="lokasiSaya()" class="bg-green-500 text-white px-3 rounded">
Lokasi Saya
</button>
<button onclick="cariTerdekat()" class="bg-red-500 text-white px-3 rounded">
SPBU Terdekat
</button>
<button onclick="buatRuteTerdekat()" class="bg-purple-500 text-white px-3 rounded">
Rute
</button>
<select id="filter_spbu" onchange="filterSPBU()" class="border p-2 rounded">
<option value="all">
Semua SPBU
</option>
<option value="24">
SPBU 24 Jam
</option>
<option value="non24">
Non 24 Jam
</option>
<option value="buka">
Sedang Buka
</option>
<option value="tutup">
Sedang Tutup
</option>
</select>
<button onclick="toggleMode()" id="btnMode" class="bg-blue-600 text-white px-3 rounded">
Ganti Mode
</button>
<span id="statusMode" class="bg-blue-100 text-blue-700 px-3 py-2 rounded font-semibold">
🔓 ADMIN
</span>
</div>
</div>
<div style="
position:absolute;
bottom:20px;
left:20px;
z-index:9999;
background:white;
padding:12px;
border-radius:8px;
box-shadow:0 2px 8px rgba(0,0,0,.2);
">
<h3 class="font-bold mb-2">
Keterangan
</h3>
<div class="flex items-center gap-2 mb-1">
<span class="w-4 h-4 bg-green-500 rounded-full"></span>
SPBU 24 Jam
</div>
<div class="flex items-center gap-2">
<span class="w-4 h-4 bg-red-500 rounded-full"></span>
SPBU Non 24 Jam
</div>
</div>
<div id="bannerMode" class="hidden" style="
position:absolute;
top:120px;
left:50%;
transform:translateX(-50%);
z-index:99999;
">
</div>
<div id="map" class="h-full"></div>
</div>
<!-- edit -->
<div id="sidebar" class="w-96 bg-white shadow-lg p-5 hidden overflow-y-auto">
<h2 class="text-xl font-bold mb-4">
Edit SPBU
</h2>
<input type="hidden" id="edit_id">
<label class="block mb-1">
Nama SPBU
</label>
<input id="edit_nama" class="w-full border p-2 rounded mb-3">
<label class="block mb-1">
Alamat
</label>
<textarea id="edit_alamat" class="w-full border p-2 rounded mb-3"></textarea>
<label class="block mb-1">
Foto SPBU
</label>
<img id="preview_edit_foto" src="" class="w-full h-40 object-cover rounded mb-2 hidden">
<input type="file" id="edit_foto" class="w-full border p-2 rounded mb-3">
<label class="block mb-1">
Jam Buka
</label>
<input type="time" id="edit_jam_buka" class="w-full border p-2 rounded mb-3">
<label class="block mb-1">
Jam Tutup
</label>
<input type="time" id="edit_jam_tutup" class="w-full border p-2 rounded mb-3">
<label class="flex items-center gap-2 mb-3">
<input type="checkbox" id="edit_24jam">
Buka 24 Jam
</label>
<label class="block mb-1">
Latitude
</label>
<input id="edit_lat" class="w-full border p-2 rounded mb-3">
<label class="block mb-1">
Longitude
</label>
<input id="edit_lng" class="w-full border p-2 rounded mb-3">
<div class="flex gap-2">
<button onclick="updateSPBU()" class="bg-blue-500 text-white px-4 py-2 rounded">
Simpan
</button>
<button onclick="tutupSidebar()" class="bg-gray-500 text-white px-4 py-2 rounded">
Tutup
</button>
</div>
</div>
<div id="sidebarObjek" class="w-96 bg-white shadow-lg p-5 hidden overflow-y-auto">
<h2 class="text-xl font-bold mb-4">
Edit Objek Peta
</h2>
<input type="hidden" id="objek_id">
<label class="block mb-1">
Nama Objek
</label>
<input id="objek_nama" class="w-full border p-2 rounded mb-3">
<label class="block mb-1">
Deskripsi
</label>
<textarea id="objek_deskripsi" class="w-full border p-2 rounded mb-3"></textarea>
<label class="block mb-1">
Tipe
</label>
<input id="objek_tipe" readonly class="w-full border p-2 rounded mb-3 bg-gray-100">
<div class="flex gap-2">
<button onclick="updateObjek()" class="bg-blue-500 text-white px-4 py-2 rounded">
Simpan
</button>
<button onclick="tutupSidebarObjek()" class="bg-gray-500 text-white px-4 py-2 rounded">
Tutup
</button>
</div>
</div>
</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.js"></script>
<script src="https://unpkg.com/leaflet-draw/dist/leaflet.draw.js"></script>
<script src="assets/js/map.js"></script>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<?php
$conn = mysqli_connect(
"localhost",
"root",
"",
"gis_spbu"
);
if(!$conn){
die(mysqli_connect_error());
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

+321
View File
@@ -0,0 +1,321 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portal WebGIS Terpadu</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
rel="stylesheet">
<style>
body {
font-family: 'Poppins', sans-serif;
background:
linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px),
radial-gradient(circle at top right, #dbeafe 0%, transparent 30%),
radial-gradient(circle at bottom left, #e0f2fe 0%, transparent 30%),
#f8fafc;
background-size:
40px 40px,
40px 40px,
auto,
auto,
auto;
}
.card-hover {
transition: all .3s ease;
}
.card-hover:hover {
transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(0, 0, 0, .08);
}
</style>
</head>
<body>
<div class="min-h-screen">
<section class="py-14">
<div class="max-w-7xl mx-auto px-6">
<!-- Header -->
<div class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold text-slate-800">
Portal WebGIS Terpadu
</h1>
<p class="mt-4 text-slate-600 text-lg">
Pilih salah satu aplikasi WebGIS untuk membuka peta interaktif.
</p>
<div class="mt-6 flex justify-center">
<div class="bg-white px-6 py-3 rounded-2xl shadow border border-slate-200">
<p class="text-slate-700 font-medium">
Clara Oxana Azalia
</p>
<p class="text-slate-500 text-sm">
NIM D1041231051
</p>
</div>
</div>
</div>
<!-- Hero -->
<div class="bg-white rounded-3xl shadow-lg p-8 border border-slate-100 mb-10">
<div class="flex flex-col md:flex-row items-center gap-8">
<div class="flex-1">
<h2 class="text-2xl font-semibold text-slate-800 mb-3">
Sistem Informasi Geospasial Terintegrasi
</h2>
<p class="text-slate-600 leading-relaxed">
Portal WebGIS Terpadu merupakan sistem yang
mengintegrasikan beberapa aplikasi WebGIS dalam
satu platform untuk memudahkan akses,
visualisasi, dan analisis data spasial secara
interaktif.
</p>
<div class="mt-4 flex flex-wrap gap-2">
<span class="bg-blue-100 text-blue-700 px-3 py-1 rounded-full text-sm">
WebGIS
</span>
<span class="bg-green-100 text-green-700 px-3 py-1 rounded-full text-sm">
Spatial Analysis
</span>
<span class="bg-purple-100 text-purple-700 px-3 py-1 rounded-full text-sm">
Interactive Mapping
</span>
</div>
</div>
<div class="text-8xl">
🌎
</div>
</div>
</div>
<!-- Statistik -->
<div class="grid md:grid-cols-3 gap-6 mb-12">
<div class="bg-white p-6 rounded-2xl shadow border border-slate-100 text-center">
<h3 class="text-3xl font-bold text-blue-600">
3
</h3>
<p class="text-slate-600">
Aplikasi WebGIS
</p>
</div>
<div class="bg-white p-6 rounded-2xl shadow border border-slate-100 text-center">
<h3 class="text-3xl font-bold text-green-600">
3
</h3>
<p class="text-slate-600">
Tema Geospasial
</p>
</div>
<div class="bg-white p-6 rounded-2xl shadow border border-slate-100 text-center">
<h3 class="text-3xl font-bold text-purple-600">
1
</h3>
<p class="text-slate-600">
Portal Terintegrasi
</p>
</div>
</div>
<!-- Cards -->
<div class="grid md:grid-cols-2 xl:grid-cols-3 gap-8">
<!-- Parsil -->
<a href="webgis-parsiltanah/"
class="card-hover bg-white rounded-3xl shadow-lg p-7 border border-slate-100 hover:border-blue-400 flex flex-col">
<div class="text-5xl mb-4">🛣️</div>
<span class="inline-block mb-3 bg-blue-100 text-blue-700 text-xs px-3 py-1 rounded-full">
Spatial Layer
</span>
<h3 class="text-xl font-semibold text-slate-800 mb-2">
WebGIS Parsil Tanah
</h3>
<p class="text-slate-600">
Menampilkan data spasial bidang tanah dan informasi
parsil secara interaktif.
</p>
<div class="mt-auto pt-6 text-blue-600 font-medium">
Buka Aplikasi
</div>
</a>
<!-- Poverty -->
<a href="webgis-poverty/"
class="card-hover bg-white rounded-3xl shadow-lg p-7 border border-slate-100 hover:border-red-400 flex flex-col">
<div class="text-5xl mb-4">📊</div>
<span class="inline-block mb-3 bg-red-100 text-red-700 text-xs px-3 py-1 rounded-full">
Choropleth Map
</span>
<h3 class="text-xl font-semibold text-slate-800 mb-2">
WebGIS Kemiskinan
</h3>
<p class="text-slate-600">
Visualisasi data kemiskinan wilayah menggunakan
peta dan statistik spasial.
</p>
<div class="mt-auto pt-6 text-red-600 font-medium">
Buka Aplikasi
</div>
</a>
<!-- SPBU -->
<a href="gis-spbu/"
class="card-hover bg-white rounded-3xl shadow-lg p-7 border border-slate-100 hover:border-green-400 flex flex-col">
<div class="text-5xl mb-4"></div>
<span class="inline-block mb-3 bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full">
Point Location
</span>
<h3 class="text-xl font-semibold text-slate-800 mb-2">
WebGIS SPBU
</h3>
<p class="text-slate-600">
Menampilkan lokasi SPBU beserta informasi dan
layanan yang tersedia.
</p>
<div class="mt-auto pt-6 text-green-600 font-medium">
Buka Aplikasi
</div>
</a>
</div>
<!-- Cara Penggunaan -->
<div class="mt-16 bg-white rounded-3xl shadow-lg p-8 border border-slate-100">
<h2 class="text-2xl font-semibold text-slate-800 mb-6">
Cara Penggunaan
</h2>
<ol class="space-y-3 text-slate-600">
<li>
<b>1.</b> Pilih aplikasi WebGIS yang ingin digunakan.
</li>
<li>
<b>2.</b> Klik kartu aplikasi pada halaman utama.
</li>
<li>
<b>3.</b> Sistem akan membuka halaman peta interaktif.
</li>
<li>
<b>4.</b> Gunakan fitur zoom dan navigasi peta untuk menjelajahi data.
</li>
<li>
<b>5.</b> Klik objek peta untuk melihat informasi detail.
</li>
</ol>
</div>
<!-- Tentang -->
<div class="mt-12 bg-slate-800 text-white rounded-3xl p-8">
<h2 class="text-2xl font-semibold mb-4">
Tentang Portal
</h2>
<p class="text-slate-300 leading-relaxed">
Portal WebGIS Terpadu dikembangkan sebagai media
integrasi berbagai aplikasi WebGIS yang mencakup
pemetaan lokasi SPBU, data parsil tanah, dan
visualisasi kemiskinan wilayah. Sistem ini
dirancang untuk mempermudah pengguna dalam
mengakses informasi geospasial secara terpusat
dan interaktif.
</p>
</div>
</div>
</section>
</div>
<footer class="border-t border-slate-200 py-8">
<div class="max-w-7xl mx-auto px-6 text-center">
<h3 class="font-semibold text-slate-700">
Portal WebGIS Terpadu
</h3>
<p class="text-slate-500 mt-2">
Integrasi Aplikasi WebGIS untuk Visualisasi dan Analisis Data Spasial
</p>
<p class="text-slate-400 text-sm mt-4">
Clara Oxana Azalia (D1041231051)
</p>
</div>
</footer>
</body>
</html>
+71
View File
@@ -0,0 +1,71 @@
## Pengembang
**Clara Oxana Azalia**
**NIM:** D1041231051
---
## Tujuan Pengembangan
Proyek ini dibuat sebagai media pembelajaran dan implementasi Sistem Informasi Geografis (SIG) berbasis web untuk pengelolaan data jalan dan parsil tanah di Kota Pontianak.
---
## Cara Menjalankan Aplikasi
1. Jalankan Laragon atau XAMPP.
2. Buat database MySQL.
3. Import struktur tabel yang diperlukan.
4. Atur koneksi database pada file `config/koneksi.php`.
5. Simpan project pada folder web server.
6. Buka browser dan akses:
```text
http://localhost:3000
```
---
## Cara Menggunakan
### Menambah Data Jalan
1. Klik ikon **Draw Polyline**.
2. Gambar jalan pada peta.
3. Masukkan nama jalan dan status jalan.
4. Data akan tersimpan ke database.
### Menambah Data Parsil Tanah
1. Klik ikon **Draw Polygon**.
2. Gambar area parsil tanah pada peta.
3. Masukkan nomor parsil dan status kepemilikan.
4. Data akan tersimpan ke database.
### Mengedit Atribut Data
1. Klik objek jalan atau parsil pada peta.
2. Sidebar edit akan muncul.
3. Ubah atribut yang diperlukan.
4. Klik **Simpan Perubahan**.
### Mengedit Geometri
1. Klik tombol **Edit Layers**.
2. Pilih objek yang ingin diubah.
3. Geser titik geometri sesuai kebutuhan.
4. Klik **Save**.
5. Geometri akan diperbarui secara otomatis.
### Menghapus Data
1. Klik objek jalan atau parsil pada peta.
2. Buka sidebar.
3. Klik **Hapus Data**.
4. Data akan dihapus dari database.
---
## Lisensi
Proyek ini dibuat untuk keperluan pembelajaran, penelitian, dan pengembangan Sistem Informasi Geografis (SIG) berbasis web.
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
$db = "webgis_parsiltanah";
$conn = mysqli_connect($host, $user, $pass, $db);
if (!$conn) {
die("Koneksi gagal : " . mysqli_connect_error());
}
+30
View File
@@ -0,0 +1,30 @@
CREATE DATABASE webgis_parsiltanah;
USE webgis_parsiltanah;
CREATE TABLE jalan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(100) NOT NULL,
status_jalan ENUM(
'Jalan Nasional',
'Jalan Provinsi',
'Jalan Kabupaten'
) NOT NULL,
panjang DOUBLE NOT NULL,
geom JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE parsil_tanah (
id INT AUTO_INCREMENT PRIMARY KEY,
nomor_parsil VARCHAR(50) NOT NULL,
status_kepemilikan ENUM(
'SHM',
'HGB',
'HGU',
'HP'
) NOT NULL,
luas DOUBLE NOT NULL,
geom JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
+768
View File
@@ -0,0 +1,768 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGIS Jalan & Parsil Tanah</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css">
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
#map {
width: 100%;
height: 100vh;
}
#sidebar {
position: absolute;
top: 0;
right: -320px;
width: 300px;
height: 100%;
background: #fff;
border-left: 1px solid #ddd;
z-index: 9999;
padding: 20px;
transition: .3s;
overflow-y: auto;
box-shadow: -3px 0 10px rgba(0, 0, 0, .2);
}
#sidebar label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
#sidebar input,
#sidebar select {
box-sizing: border-box;
}
#sidebar button {
width: 100%;
}
#sidebar h3 {
margin-top: 10px;
}
#sidebar button {
padding: 10px;
cursor: pointer;
}
#sidebar.active {
right: 0;
}
#sidebar input,
#sidebar select {
width: 100%;
padding: 8px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
<div id="sidebar">
<button onclick="tutupSidebar()">
Tutup
</button>
<h3>Edit Data</h3>
<input type="hidden" id="edit_id">
<input type="hidden" id="edit_tipe">
<label>Nama / Nomor</label>
<input type="text" id="edit_nama">
<label>Status</label>
<select id="edit_status">
</select>
<br><br>
<button onclick="simpanEdit()" style="
background:#2563eb;
color:white;
border:none;
border-radius:5px;
">
Simpan Perubahan
</button>
<button onclick="hapusData()" style="
background:red;
color:white;
border:none;
border-radius:5px;
margin-top:10px;
">
Hapus Data
</button>
</div>
<script>
var map = L.map('map').setView([-0.0263, 109.3425], 13);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap'
}).addTo(map);
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: drawnItems
},
draw: {
marker: false,
circle: false,
rectangle: false,
circlemarker: false,
polyline: true,
polygon: true
}
});
map.addControl(drawControl);
var pontianak = [-0.0263, 109.3425];
var homeControl = L.control({
position: 'topleft'
});
homeControl.onAdd = function() {
var div = L.DomUtil.create('div');
div.innerHTML =
'<button style="padding:8px;">🏠 Home</button>';
div.onclick = function() {
map.setView(pontianak, 13);
};
return div;
};
homeControl.addTo(map);
function warnaJalan(status) {
if (status == "Jalan Nasional") return "red";
if (status == "Jalan Provinsi") return "blue";
if (status == "Jalan Kabupaten") return "green";
return "black";
}
function warnaParsil(status) {
if (status == "SHM") return "green";
if (status == "HGB") return "orange";
if (status == "HGU") return "blue";
if (status == "HP") return "purple";
return "gray";
}
//
// TAMPILKAN JALAN
fetch('jalan/tampil.php')
.then(response => response.json())
.then(data => {
data.forEach(item => {
var geojson = {
type: "Feature",
geometry: JSON.parse(item.geom),
properties: item
};
var layer = L.geoJSON(geojson, {
style: {
color: warnaJalan(item.status_jalan),
weight: 4
}
});
layer.eachLayer(function(l) {
l.id_data = item.id;
l.tipe_data = 'jalan';
l.bindPopup(
"<b>Nama Jalan :</b> " + item.nama_jalan +
"<br><b>Status :</b> " + item.status_jalan +
"<br><b>Panjang :</b> " +
parseFloat(item.panjang).toFixed(2) +
" Meter"
);
drawnItems.addLayer(l);
l.on('click', function() {
document
.getElementById('sidebar')
.classList.add('active');
document
.getElementById('edit_id')
.value = item.id;
document
.getElementById('edit_tipe')
.value = 'jalan';
document
.getElementById('edit_nama')
.value = item.nama_jalan;
document
.getElementById('edit_status')
.innerHTML =
'<option>Jalan Nasional</option>' +
'<option>Jalan Provinsi</option>' +
'<option>Jalan Kabupaten</option>';
document
.getElementById('edit_status')
.value = item.status_jalan;
});
});
});
});
// TAMPILKAN PARSIL
fetch('parsil/tampil.php')
.then(response => response.json())
.then(data => {
data.forEach(item => {
var geojson = {
type: "Feature",
geometry: JSON.parse(item.geom),
properties: item
};
var layer = L.geoJSON(geojson, {
style: {
color: warnaParsil(item.status_kepemilikan),
fillOpacity: 0.5
}
});
layer.eachLayer(function(l) {
l.id_data = item.id;
l.tipe_data = 'parsil';
l.bindPopup(
"<b>Nomor Parsil :</b> " +
item.nomor_parsil +
"<br><b>Status :</b> " +
item.status_kepemilikan +
"<br><b>Luas :</b> " +
parseFloat(item.luas).toFixed(2) +
""
);
drawnItems.addLayer(l);
l.on('click', function() {
document
.getElementById('sidebar')
.classList.add('active');
document
.getElementById('edit_id')
.value = item.id;
document
.getElementById('edit_tipe')
.value = 'parsil';
document
.getElementById('edit_nama')
.value = item.nomor_parsil;
document
.getElementById('edit_status')
.innerHTML =
'<option>SHM</option>' +
'<option>HGB</option>' +
'<option>HGU</option>' +
'<option>HP</option>';
document
.getElementById('edit_status')
.value = item.status_kepemilikan;
});
});
});
});
var layerKecamatan;
fetch('assets/geojson/pontianak.geojson')
.then(response => response.json())
.then(data => {
layerKecamatan = L.geoJSON(data, {
style: {
color: '#2563eb',
weight: 2,
fillColor: '#60a5fa',
fillOpacity: 0.3
},
interactive: false
});
layerKecamatan.addTo(map);
layerKecamatan.bringToBack();
});
// CREATE //
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
drawnItems.addLayer(layer);
var geojson = layer.toGeoJSON();
// JALAN
if (geojson.geometry.type === "LineString") {
var panjang =
turf.length(
geojson, {
units: 'kilometers'
}
) * 1000;
var namaJalan =
prompt("Masukkan Nama Jalan");
var statusJalan =
prompt(
"Masukkan Status Jalan:\n\nJalan Nasional\nJalan Provinsi\nJalan Kabupaten"
);
fetch('jalan/simpan.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'nama_jalan=' + encodeURIComponent(namaJalan) +
'&status_jalan=' + encodeURIComponent(statusJalan) +
'&panjang=' + encodeURIComponent(panjang) +
'&geom=' + encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Data Jalan Berhasil Disimpan");
location.reload();
} else {
alert(data.error);
}
});
}
// PARSIL
if (geojson.geometry.type === "Polygon") {
var luas =
turf.area(geojson);
var nomorParsil =
prompt("Masukkan Nomor Parsil");
var statusParsil =
prompt(
"Masukkan Status:\n\nSHM\nHGB\nHGU\nHP"
);
fetch('parsil/simpan.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'nomor_parsil=' + encodeURIComponent(nomorParsil) +
'&status=' + encodeURIComponent(statusParsil) +
'&luas=' + encodeURIComponent(luas) +
'&geom=' + encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert("Data Parsil Berhasil Disimpan");
location.reload();
} else {
alert(data.error);
}
});
}
});
map.on('draw:edited', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
var geojson = layer.toGeoJSON();
if (layer.tipe_data == 'jalan') {
var panjang =
turf.length(
geojson, {
units: 'kilometers'
}
) * 1000;
fetch(
'jalan/update_geom.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + layer.id_data +
'&panjang=' + panjang +
'&geom=' +
encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
}
);
}
if (layer.tipe_data == 'parsil') {
var luas =
turf.area(
geojson
);
fetch(
'parsil/update_geom.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + layer.id_data +
'&luas=' + luas +
'&geom=' +
encodeURIComponent(
JSON.stringify(
geojson.geometry
)
)
}
);
}
});
alert(
'Geometry berhasil diperbarui'
);
});
var legend = L.control({
position: 'bottomright'
});
function hapusJalan(id) {
if (!confirm('Hapus data jalan?')) {
return;
}
fetch(
'jalan/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Berhasil dihapus');
location.reload();
}
});
}
function hapusParsil(id) {
if (!confirm('Hapus data parsil?')) {
return;
}
fetch(
'parsil/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Berhasil dihapus');
location.reload();
}
});
}
function simpanEdit() {
var id =
document.getElementById('edit_id').value;
var tipe =
document.getElementById('edit_tipe').value;
var nama =
document.getElementById('edit_nama').value;
var status =
document.getElementById('edit_status').value;
if (tipe == 'jalan') {
fetch('jalan/update.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + id +
'&nama_jalan=' + encodeURIComponent(nama) +
'&status_jalan=' + encodeURIComponent(status)
})
.then(r => r.json())
.then(data => {
alert('Berhasil');
location.reload();
});
}
if (tipe == 'parsil') {
fetch('parsil/update.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + id +
'&nomor_parsil=' + encodeURIComponent(nama) +
'&status=' + encodeURIComponent(status)
})
.then(r => r.json())
.then(data => {
alert('Berhasil');
location.reload();
});
}
}
function tutupSidebar() {
document
.getElementById('sidebar')
.classList.remove('active');
}
function hapusData() {
var id =
document.getElementById('edit_id').value;
var tipe =
document.getElementById('edit_tipe').value;
if (!confirm('Yakin hapus data?')) {
return;
}
if (tipe == 'jalan') {
fetch(
'jalan/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Data berhasil dihapus');
location.reload();
}
});
}
if (tipe == 'parsil') {
fetch(
'parsil/hapus.php?id=' + id
)
.then(r => r.json())
.then(data => {
if (data.success) {
alert('Data berhasil dihapus');
location.reload();
}
});
}
}
legend.onAdd = function() {
var div = L.DomUtil.create('div');
div.style.background = 'white';
div.style.padding = '10px';
div.innerHTML =
'<b>Jalan</b><br>' +
'<span style="color:red">■</span> Nasional<br>' +
'<span style="color:blue">■</span> Provinsi<br>' +
'<span style="color:green">■</span> Kabupaten<br><br>' +
'<b>Parsil</b><br>' +
'<span style="color:green">■</span> SHM<br>' +
'<span style="color:orange">■</span> HGB<br>' +
'<span style="color:blue">■</span> HGU<br>' +
'<span style="color:purple">■</span> HP';
return div;
};
legend.addTo(map);
</script>
</body>
</html>
+17
View File
@@ -0,0 +1,17 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_GET['id'] ?? '';
$query = mysqli_query(
$conn,
"DELETE FROM jalan
WHERE id='$id'"
);
echo json_encode([
"success" => $query
]);
View File
+29
View File
@@ -0,0 +1,29 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$nama_jalan = $_POST['nama_jalan'] ?? '';
$status_jalan = $_POST['status_jalan'] ?? '';
$panjang = $_POST['panjang'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"INSERT INTO jalan (
nama_jalan,
status_jalan,
panjang,
geom
) VALUES (
'$nama_jalan',
'$status_jalan',
'$panjang',
'$geom'
)"
);
echo json_encode([
"success" => $query
]);
+20
View File
@@ -0,0 +1,20 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$query = mysqli_query(
$conn,
"SELECT * FROM jalan"
);
$data = [];
while($row = mysqli_fetch_assoc($query)){
$data[] = $row;
}
echo json_encode($data);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$nama_jalan = $_POST['nama_jalan'] ?? '';
$status_jalan = $_POST['status_jalan'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE jalan
SET
nama_jalan = '$nama_jalan',
status_jalan = '$status_jalan'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$panjang = $_POST['panjang'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE jalan
SET
panjang = '$panjang',
geom = '$geom'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
View File
+17
View File
@@ -0,0 +1,17 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_GET['id'] ?? '';
$query = mysqli_query(
$conn,
"DELETE FROM parsil_tanah
WHERE id='$id'"
);
echo json_encode([
"success" => $query
]);
View File
+29
View File
@@ -0,0 +1,29 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$nomor_parsil = $_POST['nomor_parsil'] ?? '';
$status = $_POST['status'] ?? '';
$luas = $_POST['luas'] ?? 0;
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"INSERT INTO parsil_tanah (
nomor_parsil,
status_kepemilikan,
luas,
geom
) VALUES (
'$nomor_parsil',
'$status',
'$luas',
'$geom'
)"
);
echo json_encode([
"success" => $query
]);
+20
View File
@@ -0,0 +1,20 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$query = mysqli_query(
$conn,
"SELECT * FROM parsil_tanah"
);
$data = [];
while($row = mysqli_fetch_assoc($query)){
$data[] = $row;
}
echo json_encode($data);
+22
View File
@@ -0,0 +1,22 @@
<?php
header('Content-Type: application/json');
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$nomor_parsil = $_POST['nomor_parsil'] ?? '';
$status = $_POST['status'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE parsil_tanah
SET
nomor_parsil = '$nomor_parsil',
status_kepemilikan = '$status'
WHERE id = '$id'"
);
echo json_encode([
"success" => $query
]);
+28
View File
@@ -0,0 +1,28 @@
<?php
header('Content-Type: application/json');
error_reporting(E_ALL);
ini_set('display_errors',1);
include '../config/koneksi.php';
$id = $_POST['id'] ?? '';
$luas = $_POST['luas'] ?? '';
$geom = $_POST['geom'] ?? '';
$query = mysqli_query(
$conn,
"UPDATE parsil_tanah
SET
luas='$luas',
geom='$geom'
WHERE id='$id'"
);
echo json_encode([
'success' => $query,
'affected_rows' => mysqli_affected_rows($conn),
'mysql_error' => mysqli_error($conn),
'id' => $id
]);
+518
View File
@@ -0,0 +1,518 @@
# WebGIS Pengentasan Kemiskinan Kalimantan Barat
Sistem Informasi Geografis (WebGIS) untuk Pelaporan, Validasi, dan Monitoring Bantuan Sosial Berbasis Lokasi di Kalimantan Barat.
## Informasi Pengembang
Nama : Clara Oxana Azalia
NIM : D1041231051
Program Studi Informatika
Universitas Tanjungpura
---
# Deskripsi Sistem
WebGIS Pengentasan Kemiskinan Kalimantan Barat merupakan sistem informasi geografis berbasis web yang digunakan untuk membantu proses pelaporan, validasi, penyaluran, dan monitoring bantuan sosial kepada masyarakat kurang mampu.
Sistem menyediakan tiga jenis pengguna, yaitu:
* Administrator
* Warga
* Customer Service (CS) Rumah Ibadah
Selain itu sistem dilengkapi dengan peta GIS berbasis Leaflet yang digunakan untuk memvisualisasikan lokasi laporan kemiskinan.
---
# Fitur Utama
- Login Multi Role (Admin, Warga, CS)
- Registrasi Warga
- Registrasi Customer Service (CS)
- Pelaporan Kemiskinan Berbasis Lokasi
- Upload Foto Laporan
- Validasi Laporan
- Assign Bantuan Sosial
- Monitoring Bantuan
- Upload Bukti Penyaluran Bantuan
- Dashboard Statistik
- Visualisasi GIS dengan Leaflet
- Marker Cluster
- Filter Status Laporan
- Integrasi Google Maps
# Teknologi yang Digunakan
## Backend
* PHP Native
* MySQL
## Frontend
* HTML
* CSS
* JavaScript
* Tailwind CSS
## GIS
* Leaflet JS
* OpenStreetMap
* Leaflet Marker Cluster
## Visualisasi Data
* Chart.js
---
# Cara Menjalankan Sistem di Localhost
## 1. Install XAMPP
Download dan install XAMPP:
https://www.apachefriends.org
Aktifkan:
* Apache
* MySQL
---
## 2. Salin Project
Letakkan folder project ke dalam:
```text
xampp/htdocs/
```
Contoh:
```text
xampp/htdocs/webgis_poverty
```
---
## 3. Buat Database
Buka browser:
```text
http://localhost/phpmyadmin
```
Buat database baru:
```sql
webgis_poverty
```
---
## 4. Import Database
Pilih database:
```text
webgis_poverty
```
Klik:
```text
Import
```
Lalu pilih file:
```text
database.sql
```
Kemudian klik:
```text
Go
```
---
## 5. Konfigurasi Koneksi Database
Edit file:
```text
config/koneksi.php
```
Contoh konfigurasi:
```php
<?php
$conn = mysqli_connect(
"localhost",
"root",
"",
"webgis_poverty"
);
?>
```
---
## 6. Jalankan Aplikasi
Buka browser:
```text
http://localhost/webgis_poverty
```
---
# Akun Login
## Administrator
```text
Username : admin
Password : admin
```
---
## Warga 1
```text
Username : andi
Password : 123456
```
---
## Warga 2
```text
Username : siti
Password : 123456
```
---
## Warga 3
```text
Username : rahmat
Password : 123456
```
---
## Customer Service (CS)
```text
Username : cs01
Password : cs123
```
```text
Username : cs02
Password : cs123
```
---
# Cara Penggunaan Sistem
## Sebagai Warga
### 1. Login
Masukkan username dan password warga.
### 2. Membuat Laporan
Pilih menu:
```text
Buat Laporan
```
Isi data:
* Nama Warga
* Alamat
* Kondisi Warga
* Lokasi pada peta
* Foto kondisi warga
Kemudian klik:
```text
Kirim Laporan
```
Status awal laporan:
```text
Pending
```
---
### 3. Melihat Status Laporan
Pilih menu:
```text
Status Laporan
```
Warga dapat melihat:
* Foto laporan
* Tanggal laporan
* Status laporan
Status yang tersedia:
```text
Pending
Disetujui
Ditolak
Diproses
Selesai
```
---
# Sebagai Administrator
### 1. Login
Gunakan akun administrator.
### 2. Dashboard
Administrator dapat melihat:
* Total laporan
* Statistik laporan
* Grafik laporan
* Data bantuan
* Data rumah ibadah
* Data CS
---
### 3. Validasi Laporan
Pilih menu:
```text
Validasi Laporan
```
Administrator dapat:
```text
Approve
Reject
```
Jika laporan disetujui maka status berubah menjadi:
```text
Disetujui
```
---
### 4. Assign Bantuan
Pilih tombol:
```text
Assign Bantuan
```
Administrator menentukan:
* Rumah Ibadah
* Customer Service
* Jenis Bantuan
Status laporan berubah menjadi:
```text
Diproses
```
---
### 5. Monitoring Bantuan
Pilih menu:
```text
Data Bantuan
```
Administrator dapat memantau:
* Nama warga
* Rumah ibadah
* CS penyalur
* Jenis bantuan
* Status bantuan
* Bukti foto bantuan
---
### 6. Kelola Rumah Ibadah
Pilih menu:
```text
Rumah Ibadah
```
Administrator dapat:
* Menambah rumah ibadah
* Menghapus rumah ibadah
* Menentukan lokasi rumah ibadah melalui peta
---
### 7. Peta GIS
Pilih menu:
```text
Peta GIS
```
Fitur yang tersedia:
* Marker lokasi laporan
* Cluster marker
* Filter status laporan
* Popup detail laporan
* Link Google Maps
Warna marker:
```text
Orange = Pending
Green = Disetujui
Red = Ditolak
Blue = Diproses
Purple = Selesai
```
---
# Sebagai Customer Service Rumah Ibadah (CS)
### 1. Login
Masukkan akun CS.
### 2. Lihat Tugas Bantuan
Pilih menu:
```text
Tugas Bantuan
```
CS dapat melihat:
* Nama warga
* Alamat
* Jenis bantuan
* Status bantuan
---
### 3. Lihat Lokasi Warga
Klik:
```text
Lihat Lokasi
```
Sistem akan membuka Google Maps berdasarkan koordinat laporan.
---
### 4. Upload Bukti Bantuan
Klik:
```text
Upload Bukti
```
Kemudian:
* Pilih foto dokumentasi bantuan
* Upload foto
Status bantuan otomatis menjadi:
```text
Selesai
```
Status laporan juga otomatis berubah menjadi:
```text
Selesai
```
---
# Struktur Status Sistem
## Status Laporan
```text
Pending
Disetujui
Ditolak
Diproses
Selesai
```
## Status Bantuan
```text
Proses
Selesai
```
---
# Penutup
WebGIS Pengentasan Kemiskinan Kalimantan Barat dikembangkan untuk membantu proses identifikasi, validasi, penyaluran, dan monitoring bantuan sosial berbasis lokasi secara lebih efektif dan terintegrasi.
© 2026
Clara Oxana Azalia
D1041231051
+38
View File
@@ -0,0 +1,38 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_GET['id']);
$cek = mysqli_query(
$conn,
"SELECT * FROM laporan
WHERE id='$id'"
);
if(mysqli_num_rows($cek)==0){
die("Data laporan tidak ditemukan");
}
mysqli_query($conn,
"UPDATE laporan
SET status='disetujui'
WHERE id='$id'");
header("Location: validasi.php");
?>
+344
View File
@@ -0,0 +1,344 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_GET['id']);
$laporan = mysqli_fetch_assoc(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE id='$id'")
);
if(!$laporan){
die("Data laporan tidak ditemukan");
}
$rumah_ibadah = mysqli_query($conn,
"SELECT * FROM rumah_ibadah");
$cs = mysqli_query($conn,
"SELECT * FROM cs_rumah_ibadah");
$cek_bantuan = mysqli_query(
$conn,
"SELECT * FROM bantuan
WHERE laporan_id='$id'"
);
if(mysqli_num_rows($cek_bantuan)>0){
echo "
<script>
alert('Laporan sudah pernah diassign');
window.location='validasi.php';
</script>
";
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Assign Bantuan</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="mb-6">
<h1 class="text-3xl font-bold text-gray-800">
Assign Bantuan
</h1>
<p class="text-gray-500 mt-2">
Tentukan rumah ibadah, CS penyalur, dan jenis bantuan untuk laporan yang telah disetujui.
</p>
</div>
<div class="grid lg:grid-cols-3 gap-6">
<!-- Informasi Warga -->
<div class="lg:col-span-1">
<div class="bg-white rounded-2xl shadow-lg overflow-hidden">
<div class="p-5 border-b bg-blue-50">
<h2 class="font-semibold text-lg flex items-center gap-2">
<i class="fas fa-user text-blue-600"></i>
Data Warga
</h2>
</div>
<div class="p-5">
<div class="mb-4">
<label class="text-gray-500 text-sm">
Nama Warga
</label>
<p class="font-semibold text-lg">
<?= htmlspecialchars($laporan['nama_warga']) ?>
</p>
</div>
<div class="mb-4">
<label class="text-gray-500 text-sm">
Alamat
</label>
<p>
<?= htmlspecialchars($laporan['alamat']) ?>
</p>
</div>
<div class="mb-4">
<label class="text-gray-500 text-sm">
Kondisi
</label>
<p>
<?= htmlspecialchars($laporan['kondisi']) ?>
</p>
</div>
<?php if(!empty($laporan['foto'])){ ?>
<img src="../assets/uploads/<?= htmlspecialchars($laporan['foto']) ?>"
class="w-full h-56 object-cover rounded-xl shadow">
<?php } ?>
</div>
</div>
</div>
<!-- Form Assign -->
<div class="lg:col-span-2">
<div class="bg-white rounded-2xl shadow-lg overflow-hidden">
<div class="p-5 border-b bg-gray-50">
<h2 class="font-semibold text-lg flex items-center gap-2">
<i class="fas fa-hand-holding-heart text-green-600"></i>
Form Penugasan Bantuan
</h2>
</div>
<form action="proses_assign.php" method="POST" class="p-6 space-y-5">
<input type="hidden" name="laporan_id" value="<?= $laporan['id'] ?>">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Nama Warga
</label>
<input type="text" readonly value="<?= htmlspecialchars($laporan['nama_warga']) ?>"
class="w-full border rounded-xl p-3 bg-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Rumah Ibadah
</label>
<select name="rumah_ibadah_id" required
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
<option value="">
-- Pilih Rumah Ibadah --
</option>
<?php while($r = mysqli_fetch_assoc($rumah_ibadah)){ ?>
<option value="<?= $r['id'] ?>">
<?= htmlspecialchars($r['nama']) ?>
</option>
<?php } ?>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
CS Penyalur
</label>
<select name="cs_id" required
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
<option value="">
-- Pilih CS --
</option>
<?php while($c = mysqli_fetch_assoc($cs)){ ?>
<option value="<?= $c['id'] ?>">
<?= htmlspecialchars($c['nama']) ?>
</option>
<?php } ?>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Jenis Bantuan
</label>
<select name="jenis_bantuan" required
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
<option value="">
-- Pilih Jenis Bantuan --
</option>
<option value="Sembako">
🍚 Sembako
</option>
<option value="Uang Tunai">
💵 Uang Tunai
</option>
<option value="Pendidikan">
🎓 Pendidikan
</option>
<option value="Kesehatan">
🏥 Kesehatan
</option>
<option value="Peralatan Sekolah">
🎒 Peralatan Sekolah
</option>
<option value="Perbaikan Rumah">
🏠 Perbaikan Rumah
</option>
<option value="Pakaian Layak">
👕 Pakaian Layak
</option>
<option value="Makanan Bergizi">
🍱 Makanan Bergizi
</option>
<option value="Modal Usaha">
💼 Modal Usaha
</option>
<option value="Lainnya">
📦 Lainnya
</option>
</select>
</div>
<div class="flex flex-wrap gap-3 pt-3">
<button type="submit"
class="px-6 py-3 bg-green-600 hover:bg-green-700 text-white rounded-xl shadow transition">
<i class="fas fa-check-circle mr-2"></i>
Assign Bantuan
</button>
<a href="validasi.php"
class="px-6 py-3 bg-gray-500 hover:bg-gray-600 text-white rounded-xl shadow transition">
<i class="fas fa-arrow-left mr-2"></i>
Kembali
</a>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
+391
View File
@@ -0,0 +1,391 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
/* TOTAL LAPORAN */
$total_laporan = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan")
);
/* PENDING */
$pending = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE status='pending'")
);
/* DISETUJUI */
$disetujui = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE status='disetujui'")
);
/* DITOLAK */
$ditolak = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE status='ditolak'")
);
$total_bantuan = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM bantuan")
);
$diproses = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE status='diproses'")
);
$selesai = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE status='selesai'")
);
$persentase = 0;
if($total_laporan > 0){
$persentase = round(
($selesai / $total_laporan) * 100
);
}
$cs_total = mysqli_num_rows(
mysqli_query(
$conn,
"SELECT * FROM cs_rumah_ibadah"
)
);
$rumah_ibadah_total = mysqli_num_rows(
mysqli_query(
$conn,
"SELECT * FROM rumah_ibadah"
)
);
?>
<!DOCTYPE html>
<html>
<head>
<title>Dashboard Admin</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="hero">
<h1 style="
font-size:32px;
margin-bottom:10px;
">
Dashboard Administrator
</h1>
<p>
Selamat datang,
<b><?= htmlspecialchars($_SESSION['nama']) ?></b>
</p>
<p style="
margin-top:10px;
opacity:.9;
">
Monitoring laporan kemiskinan,
validasi bantuan sosial,
dan distribusi bantuan.
</p>
<p style="
margin-top:15px;
font-size:14px;
">
<?= $total_laporan ?> laporan •
<?= $total_bantuan ?> bantuan •
<?= $persentase ?>% selesai
</p>
</div>
<div class="cards">
<div class="card">
<i class="fa-solid fa-file"></i>
<h3>Total Laporan</h3>
<h1><?= $total_laporan ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-clock"></i>
<h3>Pending</h3>
<h1><?= $pending ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-thumbs-up"></i>
<h3>Disetujui</h3>
<h1><?= $disetujui ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-hand-holding-heart"></i>
<h3>Total Bantuan</h3>
<h1><?= $total_bantuan ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-users"></i>
<h3>Total CS</h3>
<h1><?= $cs_total ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-building"></i>
<h3>Rumah Ibadah</h3>
<h1><?= $rumah_ibadah_total ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-spinner"></i>
<h3> Diproses</h3>
<h1><?= $diproses ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-hand-holding-heart"></i>
<h3>Selesai</h3>
<h1><?= $selesai ?></h1>
</div>
<div class="card">
<i class="fa-solid fa-ban"></i>
<h3>Ditolak</h3>
<h1><?= $ditolak ?></h1>
</div>
</div>
<div class="box" style="margin-top:25px;">
<h3>
Progress Penyelesaian Bantuan
</h3>
<br>
<div style="
width:100%;
height:20px;
background:#e2e8f0;
border-radius:20px;
overflow:hidden;
">
<div style="
width:<?= $persentase ?>%;
height:100%;
background:#16a34a;
">
</div>
</div>
<p style="
margin-top:10px;
color:#64748b;
">
<?= $persentase ?>%
laporan telah selesai ditangani
</p>
</div>
<div class="box" style="margin-top:25px;">
<h3>Statistik Laporan</h3>
<br>
<div style="max-width:500px;margin:auto;">
<canvas id="myChart"></canvas>
</div>
</div>
<div class="box" style="margin-top:25px;">
<h3>Ringkasan Sistem</h3>
<br>
<p>
Total laporan masuk:
<b><?= $total_laporan ?></b>
</p>
<p>
Bantuan yang telah dibuat:
<b><?= $total_bantuan ?></b>
</p>
<p>
CS aktif:
<b><?= $cs_total ?></b>
</p>
<p>
Rumah ibadah terdaftar:
<b><?= $rumah_ibadah_total ?></b>
</p>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
new Chart(ctx, {
type: 'doughnut',
data: {
labels: [
'Pending',
'Disetujui',
'Ditolak',
'Diproses',
'Selesai'
],
datasets: [{
label: 'Jumlah Laporan',
data: [
<?= $pending ?>,
<?= $disetujui ?>,
<?= $ditolak ?>,
<?= $diproses ?>,
<?= $selesai ?>
],
backgroundColor: [
'#f59e0b',
'#16a34a',
'#dc2626',
'#2563eb',
'#7c3aed'
]
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
</script>
</body>
</html>
+300
View File
@@ -0,0 +1,300 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$data = mysqli_query($conn,
"SELECT bantuan.*,
laporan.nama_warga,
rumah_ibadah.nama AS rumah_ibadah,
cs_rumah_ibadah.nama AS cs_nama
FROM bantuan
JOIN laporan
ON bantuan.laporan_id = laporan.id
JOIN rumah_ibadah
ON bantuan.rumah_ibadah_id = rumah_ibadah.id
JOIN cs_rumah_ibadah
ON bantuan.cs_id = cs_rumah_ibadah.id
ORDER BY bantuan.id DESC"
);
?>
<!DOCTYPE html>
<html>
<head>
<title>Data Bantuan</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="mb-6">
<h1 class="text-3xl font-bold text-gray-800">
Data Bantuan
</h1>
<p class="text-gray-500 mt-2">
Monitoring bantuan sosial yang sedang diproses dan telah selesai disalurkan.
</p>
</div>
<?php
$total = mysqli_num_rows($data);
mysqli_data_seek($data,0);
$proses = 0;
$selesai = 0;
while($r = mysqli_fetch_assoc($data)){
if($r['status']=='proses'){
$proses++;
}
if($r['status']=='selesai'){
$selesai++;
}
}
mysqli_data_seek($data,0);
?>
<div class="grid md:grid-cols-3 gap-5 mb-6">
<div class="bg-white rounded-2xl shadow p-5">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">
Total Bantuan
</p>
<h2 class="text-3xl font-bold text-blue-600">
<?= $total ?>
</h2>
</div>
<i class="fas fa-hand-holding-heart text-4xl text-blue-500"></i>
</div>
</div>
<div class="bg-white rounded-2xl shadow p-5">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">
Diproses
</p>
<h2 class="text-3xl font-bold text-orange-500">
<?= $proses ?>
</h2>
</div>
<i class="fas fa-spinner text-4xl text-orange-500"></i>
</div>
</div>
<div class="bg-white rounded-2xl shadow p-5">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">
Selesai
</p>
<h2 class="text-3xl font-bold text-green-600">
<?= $selesai ?>
</h2>
</div>
<i class="fas fa-check-circle text-4xl text-green-600"></i>
</div>
</div>
</div>
<div class="bg-white rounded-2xl shadow overflow-hidden">
<div class="p-5 border-b">
<h2 class="font-semibold text-lg">
Daftar Bantuan
</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-3 text-left">No</th>
<th class="px-4 py-3 text-left">Nama Warga</th>
<th class="px-4 py-3 text-left">Rumah Ibadah</th>
<th class="px-4 py-3 text-left">CS Penyalur</th>
<th class="px-4 py-3 text-left">Jenis Bantuan</th>
<th class="px-4 py-3 text-center">Status</th>
<th class="px-4 py-3 text-center">Bukti</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
if(mysqli_num_rows($data) > 0){
while($row = mysqli_fetch_assoc($data)){
?>
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<?= $no++ ?>
</td>
<td class="px-4 py-3 font-medium">
<?= htmlspecialchars($row['nama_warga']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['rumah_ibadah']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['cs_nama']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['jenis_bantuan']) ?>
</td>
<td class="px-4 py-3 text-center">
<?php if($row['status']=='proses'){ ?>
<span
class="px-3 py-1 rounded-full text-xs font-semibold bg-orange-100 text-orange-700">
Diproses
</span>
<?php } elseif($row['status']=='selesai'){ ?>
<span class="px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-700">
Selesai
</span>
<?php } ?>
</td>
<td class="px-4 py-3 text-center">
<?php if(!empty($row['bukti_foto'])){ ?>
<img src="../assets/uploads/<?= htmlspecialchars($row['bukti_foto']) ?>"
class="w-24 h-24 object-cover rounded-xl shadow mx-auto hover:scale-105 transition cursor-pointer">
<?php } else { ?>
<span class="text-gray-400 italic">
Belum Ada
</span>
<?php } ?>
</td>
</tr>
<?php } } else { ?>
<tr>
<td colspan="7" class="py-10 text-center text-gray-500">
<i class="fas fa-box-open text-4xl mb-3 block"></i>
Belum ada data bantuan
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
+27
View File
@@ -0,0 +1,27 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_GET['id']);
mysqli_query($conn,
"DELETE FROM laporan
WHERE id='$id'");
header("Location: validasi.php");
?>
@@ -0,0 +1,27 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_GET['id']);
mysqli_query($conn,
"DELETE FROM rumah_ibadah
WHERE id='$id'");
header("Location: rumah_ibadah.php");
?>
+29
View File
@@ -0,0 +1,29 @@
<div class="navbar">
<div class="logo-area">
<i class="fa-solid fa-map-location-dot"></i>
<div>
<h2>WEBGIS KEMISKINAN</h2>
<small>Sistem Pengentasan Kemiskinan</small>
</div>
</div>
<div class="admin-profile">
<div class="avatar">
<i class="fa-solid fa-user"></i>
</div>
<div>
<strong><?= htmlspecialchars($_SESSION['nama']); ?></strong>
<br>
<small>Administrator</small>
</div>
</div>
</div>
+45
View File
@@ -0,0 +1,45 @@
<div class="sidebar">
<div class="sidebar-title">
MENU ADMIN
</div>
<a class="<?php if(basename($_SERVER['PHP_SELF'])=='dashboard.php') echo 'active'; ?>" href="dashboard.php">
<i class="fa-solid fa-house"></i>
Dashboard
</a>
<a class="<?php if(basename($_SERVER['PHP_SELF'])=='peta.php') echo 'active'; ?>" href="peta.php">
<i class="fa-solid fa-map-location-dot"></i>
Peta GIS
</a>
<a class="<?php if(basename($_SERVER['PHP_SELF'])=='validasi.php') echo 'active'; ?>" href="validasi.php">
<i class="fa-solid fa-circle-check"></i>
Validasi Laporan
</a>
<a class="<?php if(basename($_SERVER['PHP_SELF'])=='data_bantuan.php') echo 'active'; ?>" href="data_bantuan.php">
<i class="fa-solid fa-hand-holding-heart"></i>
Data Bantuan
</a>
<a class="<?php if(basename($_SERVER['PHP_SELF'])=='rumah_ibadah.php') echo 'active'; ?>" href="rumah_ibadah.php">
<i class="fa-solid fa-building"></i>
Rumah Ibadah
</a>
<div class="sidebar-footer">
<a href="../logout.php" onclick="return confirm('Logout sekarang?')">
<i class="fa-solid fa-right-from-bracket"></i>
Logout
</a>
</div>
</div>
+379
View File
@@ -0,0 +1,379 @@
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #f8fafc;
font-family: 'Segoe UI', sans-serif;
}
.content {
padding: 30px;
}
/* NAVBAR */
.navbar {
position: fixed;
top: 0;
left: 260px;
right: 0;
height: 70px;
background: white;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30px;
box-shadow:
0 2px 15px rgba(0, 0, 0, .08);
z-index: 1000;
}
.logo-area {
display: flex;
align-items: center;
gap: 12px;
}
.logo-area i {
font-size: 28px;
color: #2563eb;
}
.logo-area h2 {
font-size: 18px;
margin: 0;
}
.logo-area small {
color: #64748b;
}
.admin-profile {
display: flex;
align-items: center;
gap: 12px;
}
.avatar {
width: 45px;
height: 45px;
border-radius: 50%;
background: #2563eb;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
/* SIDEBAR */
.sidebar {
position: fixed;
left: 0;
top: 0;
width: 260px;
height: 100vh;
background: #1e293b;
padding-top: 20px;
display: flex;
flex-direction: column;
}
.sidebar-title {
color: #94a3b8;
font-size: 12px;
padding: 15px 25px;
}
.sidebar a {
color: #e2e8f0;
text-decoration: none;
padding: 15px 25px;
display: flex;
align-items: center;
gap: 12px;
transition: .3s;
}
.sidebar a:hover {
background: #334155;
}
.sidebar a.active {
background: #2563eb;
border-left: 4px solid white;
}
.sidebar-footer {
margin-top: auto;
border-top: 1px solid #334155;
padding-top: 10px;
}
/* CONTENT */
.content {
margin-left: 260px;
margin-top: 70px;
padding: 30px;
}
/* CARD */
.card {
background: white;
border-radius: 16px;
padding: 25px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
transition: .3s;
}
.card:hover {
transform: translateY(-5px);
}
/* TABLE */
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
th {
background: #2563eb;
color: white;
}
th,
td {
padding: 14px;
border-bottom: 1px solid #eee;
}
/* BUTTON */
.btn {
padding: 10px 16px;
border-radius: 10px;
text-decoration: none;
color: white;
display: inline-block;
}
.approve {
background: #16a34a;
}
.reject {
background: #dc2626;
}
.delete {
background: #64748b;
}
.warning {
background: #f59e0b;
}
/* INPUT */
input,
select,
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 10px;
margin-top: 8px;
}
/* BOX */
.box {
background: white;
padding: 25px;
border-radius: 20px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
.cards {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.card i {
font-size: 40px;
color: #2563eb;
margin-bottom: 15px;
}
.card h3 {
color: #64748b;
font-size: 14px;
}
.card h1 {
font-size: 35px;
margin-top: 10px;
}
.badge {
padding: 6px 12px;
border-radius: 30px;
color: white;
font-size: 13px;
}
.pending {
background: #f59e0b;
}
.approved {
background: #16a34a;
}
.rejected {
background: #dc2626;
}
.process {
background: #2563eb;
}
.done {
background: #7c3aed;
}
#legend {
position: absolute;
top: 20px;
right: 20px;
z-index: 1000;
background: white;
padding: 15px;
border-radius: 10px;
box-shadow:
0 2px 10px rgba(0, 0, 0, .2);
}
.photo {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 12px;
border: 3px solid white;
box-shadow:
0 2px 10px rgba(0, 0, 0, .2);
}
.hero {
background:
linear-gradient(135deg,
#2563eb,
#06b6d4);
color: white;
padding: 30px;
border-radius: 20px;
margin-bottom: 30px;
}
</style>
+380
View File
@@ -0,0 +1,380 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$status = isset($_GET['status'])
? mysqli_real_escape_string($conn,$_GET['status'])
: '';
$query = "SELECT * FROM laporan";
if($status != ''){
$query .= " WHERE status='$status'";
}
$query .= " ORDER BY id DESC";
$data = mysqli_query($conn,$query);
if(!$data){
die("Query Error: " . mysqli_error($conn));
}
$total_data = mysqli_num_rows($data);
?>
<!DOCTYPE html>
<html>
<head>
<title>Peta Kemiskinan</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
<style>
#map {
height: 80vh;
width: 100%;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, .1);
}
</style>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="hero">
<h1>Peta Kemiskinan</h1>
<p style="margin-top:10px;">
Visualisasi lokasi laporan kemiskinan berdasarkan status laporan.
</p>
</div>
<div class="box">
<div style="
display:flex;
justify-content:space-between;
align-items:center;
flex-wrap:wrap;
gap:15px;
">
<div>
<h3>Total Data Ditampilkan</h3>
<h1 style="
color:#2563eb;
margin-top:5px;
">
<?= $total_data ?>
</h1>
</div>
<form method="GET">
<select name="status" style="
width:auto;
display:inline-block;
">
<option value="">
Semua Status
</option>
<option value="pending" <?= $status=='pending' ? 'selected' : '' ?>>
Pending
</option>
<option value="disetujui" <?= $status=='disetujui' ? 'selected' : '' ?>>
Disetujui
</option>
<option value="ditolak" <?= $status=='ditolak' ? 'selected' : '' ?>>
Ditolak
</option>
<option value="diproses" <?= $status=='diproses' ? 'selected' : '' ?>>
Diproses
</option>
<option value="selesai" <?= $status=='selesai' ? 'selected' : '' ?>>
Selesai
</option>
</select>
<button type="submit" class="btn approve">
Filter
</button>
<a href="peta.php" class="btn delete">
Reset
</a>
</form>
</div>
</div>
<br>
<div id="legend">
<b>Status Marker</b>
<hr style="margin:10px 0;">
🟡 Pending <br>
🟢 Disetujui <br>
🔴 Ditolak <br>
🔵 Diproses <br>
🟣 Selesai
</div>
<div id="map"></div>
</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script>
<script>
var map = L.map('map').setView(
[-0.0263, 109.3425],
11
);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap'
}
).addTo(map);
var markers = L.markerClusterGroup();
<?php
mysqli_data_seek($data,0);
while($row = mysqli_fetch_assoc($data)){
if(
empty($row['latitude']) ||
empty($row['longitude'])
){
continue;
}
$warna = "orange";
if($row['status']=="disetujui"){
$warna = "green";
}
elseif($row['status']=="ditolak"){
$warna = "red";
}
elseif($row['status']=="diproses"){
$warna = "blue";
}
elseif($row['status']=="selesai"){
$warna = "purple";
}
$nama =
addslashes(
htmlspecialchars(
$row['nama_warga']
));
$alamat =
addslashes(
htmlspecialchars(
$row['alamat']
));
$kondisi =
addslashes(
htmlspecialchars(
$row['kondisi']
));
$foto =
addslashes(
htmlspecialchars(
$row['foto']
));
if(empty($row['foto'])){
$foto = 'no-image.png';
}
$statusBadge = '';
if($row['status']=='pending'){
$statusBadge = '🟡 Pending';
}
elseif($row['status']=='disetujui'){
$statusBadge = '🟢 Disetujui';
}
elseif($row['status']=='ditolak'){
$statusBadge = '🔴 Ditolak';
}
elseif($row['status']=='diproses'){
$statusBadge = '🔵 Diproses';
}
elseif($row['status']=='selesai'){
$statusBadge = '🟣 Selesai';
}
?>
L.circleMarker(
[
<?= $row['latitude'] ?>,
<?= $row['longitude'] ?>
], {
radius: 12,
weight: 2,
color: '<?= $warna ?>',
fillColor: '<?= $warna ?>',
fillOpacity: 0.8
}
)
.bindPopup(`
<div style="width:250px;">
<img
src="../assets/uploads/<?= $foto ?>"
onerror="this.src='../assets/uploads/no-image.png'"
style="
width:100%;
height:150px;
object-fit:cover;
border-radius:10px;
margin-bottom:10px;
">
<b style="
font-size:16px;
">
<?= $nama ?>
</b>
<hr style="margin:8px 0;">
<b>Alamat</b>
<br>
<?= $alamat ?>
<br><br>
<b>Kondisi</b>
<br>
<?= $kondisi ?>
<br><br>
<b>Status</b>
<br>
<?= $statusBadge ?>
<br><br>
<b>Tanggal</b>
<br>
<?= !empty($row['created_at'])
? date('d-m-Y H:i', strtotime($row['created_at']))
: '-' ?>
<br><br>
<a
href="https://www.google.com/maps?q=<?= $row['latitude'] ?>,<?= $row['longitude'] ?>"
target="_blank"
style="
display:inline-block;
background:#2563eb;
color:white;
padding:8px 12px;
border-radius:8px;
text-decoration:none;
">
📍 Buka Google Maps
</a>
</div>
`)
.addTo(markers);
<?php } ?>
map.addLayer(markers);
if (markers.getLayers().length > 0) {
map.fitBounds(
markers.getBounds()
);
}
</script>
</body>
</html>
+86
View File
@@ -0,0 +1,86 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$laporan_id = intval($_POST['laporan_id']);
$rumah_ibadah_id = intval($_POST['rumah_ibadah_id']);
$cs_id = intval($_POST['cs_id']);
$jenis_bantuan =
mysqli_real_escape_string(
$conn,
$_POST['jenis_bantuan']
);
$cek = mysqli_query(
$conn,
"SELECT * FROM bantuan
WHERE laporan_id='$laporan_id'"
);
if(mysqli_num_rows($cek) > 0){
echo "
<script>
alert('Bantuan sudah pernah diassign');
window.location='validasi.php';
</script>
";
exit;
}
mysqli_query($conn,
"INSERT INTO bantuan
(laporan_id,rumah_ibadah_id,cs_id,jenis_bantuan,status)
VALUES
(
'$laporan_id',
'$rumah_ibadah_id',
'$cs_id',
'$jenis_bantuan',
'proses'
)"
);
$cek_laporan = mysqli_query(
$conn,
"SELECT * FROM laporan
WHERE id='$laporan_id'"
);
if(mysqli_num_rows($cek_laporan)==0){
die("Laporan tidak ditemukan");
}
/* UPDATE STATUS */
mysqli_query($conn,
"UPDATE laporan
SET status='diproses'
WHERE id='$laporan_id'"
);
header("Location: validasi.php");
?>
+38
View File
@@ -0,0 +1,38 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_GET['id']);
$cek = mysqli_query(
$conn,
"SELECT * FROM laporan
WHERE id='$id'"
);
if(mysqli_num_rows($cek)==0){
die("Data laporan tidak ditemukan");
}
mysqli_query($conn,
"UPDATE laporan
SET status='ditolak'
WHERE id='$id'");
header("Location: validasi.php");
?>
+227
View File
@@ -0,0 +1,227 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$data = mysqli_query($conn,
"SELECT * FROM rumah_ibadah");
?>
<!DOCTYPE html>
<html>
<head>
<title>Rumah Ibadah</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-6">
<div>
<h1 class="text-3xl font-bold text-gray-800">
Data Rumah Ibadah
</h1>
<p class="text-gray-500 mt-2">
Kelola data rumah ibadah yang berpartisipasi dalam program bantuan sosial.
</p>
</div>
<a href="tambah_rumah_ibadah.php"
class="inline-flex items-center gap-2 px-5 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-xl shadow transition">
<i class="fas fa-plus"></i>
Tambah Rumah Ibadah
</a>
</div>
<?php
$total_rumah_ibadah = mysqli_num_rows($data);
mysqli_data_seek($data,0);
?>
<div class="grid md:grid-cols-3 gap-5 mb-6">
<div class="bg-white rounded-2xl shadow p-5">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">
Total Rumah Ibadah
</p>
<h2 class="text-3xl font-bold text-blue-600">
<?= $total_rumah_ibadah ?>
</h2>
</div>
<i class="fas fa-place-of-worship text-4xl text-blue-500"></i>
</div>
</div>
</div>
<div class="bg-white rounded-2xl shadow overflow-hidden">
<div class="p-5 border-b">
<h2 class="font-semibold text-lg">
Daftar Rumah Ibadah
</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-3 text-left">No</th>
<th class="px-4 py-3 text-left">Nama</th>
<th class="px-4 py-3 text-left">Alamat</th>
<th class="px-4 py-3 text-left">Latitude</th>
<th class="px-4 py-3 text-left">Longitude</th>
<th class="px-4 py-3 text-center">Aksi</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
mysqli_data_seek($data,0);
if(mysqli_num_rows($data) > 0){
while($row = mysqli_fetch_assoc($data)){
?>
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<?= $no++ ?>
</td>
<td class="px-4 py-3 font-medium">
<?= htmlspecialchars($row['nama']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['alamat']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['latitude']) ?>
</td>
<td class="px-4 py-3">
<?= htmlspecialchars($row['longitude']) ?>
</td>
<td class="px-4 py-3 text-center">
<div class="flex flex-wrap justify-center gap-2">
<a href="https://www.google.com/maps?q=<?= $row['latitude'] ?>,<?= $row['longitude'] ?>"
target="_blank"
class="px-3 py-2 bg-green-600 hover:bg-green-700 text-white rounded-lg transition">
<i class="fas fa-map-marker-alt"></i>
</a>
<a href="hapus_rumah_ibadah.php?id=<?= $row['id'] ?>"
onclick="return confirm('Yakin hapus data?')"
class="px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg transition">
<i class="fas fa-trash"></i>
</a>
</div>
</td>
</tr>
<?php } } else { ?>
<tr>
<td colspan="6" class="py-10 text-center text-gray-500">
<i class="fas fa-place-of-worship text-4xl mb-3 block"></i>
Belum ada data rumah ibadah
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,47 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$nama =
mysqli_real_escape_string(
$conn,
$_POST['nama']
);
$alamat =
mysqli_real_escape_string(
$conn,
$_POST['alamat']
);
$latitude = $_POST['latitude'];
$longitude = $_POST['longitude'];
mysqli_query($conn,
"INSERT INTO rumah_ibadah
(nama,alamat,latitude,longitude)
VALUES
('$nama','$alamat','$latitude','$longitude')"
);
header("Location: rumah_ibadah.php");
?>
@@ -0,0 +1,345 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
?>
<!DOCTYPE html>
<html>
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Tambah Rumah Ibadah</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<?php include 'layout/style.php'; ?>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="mb-6">
<h1 class="text-3xl font-bold text-gray-800">
Tambah Rumah Ibadah
</h1>
<p class="text-gray-500 mt-2">
Tambahkan data rumah ibadah yang akan menjadi mitra penyaluran bantuan sosial.
</p>
</div>
<div class="bg-white rounded-2xl shadow-lg overflow-hidden max-w-5xl">
<div class="p-5 border-b bg-gray-50">
<h2 class="font-semibold text-lg flex items-center gap-2">
<i class="fas fa-place-of-worship text-blue-600"></i>
Form Rumah Ibadah
</h2>
</div>
<form action="simpan_rumah_ibadah.php" method="POST" class="p-6 space-y-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Nama Rumah Ibadah
</label>
<div class="relative">
<i class="fas fa-building absolute left-4 top-4 text-gray-400"></i>
<input type="text" name="nama" required placeholder="Masukkan nama rumah ibadah"
class="w-full border rounded-xl pl-11 pr-4 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Alamat
</label>
<textarea id="alamat" name="alamat" required rows="4"
placeholder="Alamat akan terisi otomatis saat memilih lokasi"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Cari Lokasi
</label>
<input type="text" id="searchLocation" placeholder="Contoh: Masjid Raya Mujahidin Pontianak"
class="w-full border rounded-xl p-3">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Pilih Lokasi di Peta
</label>
<div id="map" class="rounded-xl border" style="height:450px;">
</div>
</div>
<div class="grid md:grid-cols-2 gap-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Latitude
</label>
<input type="text" id="latitude" name="latitude" readonly required
class="w-full border rounded-xl p-3 bg-gray-100">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Longitude
</label>
<input type="text" id="longitude" name="longitude" readonly required
class="w-full border rounded-xl p-3 bg-gray-100">
</div>
</div>
<div class="flex flex-wrap gap-3 pt-4">
<button type="submit"
class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-xl shadow transition">
<i class="fas fa-save mr-2"></i>
Simpan Data
</button>
<a href="rumah_ibadah.php"
class="px-6 py-3 bg-gray-500 hover:bg-gray-600 text-white rounded-xl shadow transition">
<i class="fas fa-arrow-left mr-2"></i>
Kembali
</a>
</div>
</form>
</div>
</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
var map = L.map('map').setView(
[-0.0263, 109.3425],
11
);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap'
}
).addTo(map);
var marker = L.marker(
[-0.0263, 109.3425], {
draggable: true
}
).addTo(map);
function updateLatLng(lat, lng) {
document.getElementById('latitude').value =
lat.toFixed(6);
document.getElementById('longitude').value =
lng.toFixed(6);
}
updateLatLng(
marker.getLatLng().lat,
marker.getLatLng().lng
);
function updateAddress(lat, lng) {
fetch(
'https://nominatim.openstreetmap.org/reverse?format=json&lat=' +
lat +
'&lon=' +
lng
)
.then(response => response.json())
.then(data => {
if (data.display_name) {
document.getElementById('alamat').value =
data.display_name;
}
});
}
map.on('click', function(e) {
marker.setLatLng(e.latlng);
updateLatLng(
e.latlng.lat,
e.latlng.lng
);
updateAddress(
e.latlng.lat,
e.latlng.lng
);
});
marker.on('dragend', function() {
var pos = marker.getLatLng();
updateLatLng(
pos.lat,
pos.lng
);
updateAddress(
pos.lat,
pos.lng
);
});
document
.getElementById('searchLocation')
.addEventListener('keypress', async function(e) {
if (e.key !== 'Enter') {
return;
}
e.preventDefault();
let keyword = this.value;
let response = await fetch(
'https://nominatim.openstreetmap.org/search?format=json&q=' +
encodeURIComponent(keyword)
);
let data = await response.json();
if (data.length > 0) {
let lat = parseFloat(data[0].lat);
let lng = parseFloat(data[0].lon);
map.setView(
[lat, lng],
15
);
marker.setLatLng(
[lat, lng]
);
updateLatLng(
lat,
lng
);
updateAddress(
lat,
lng
);
} else {
alert('Lokasi tidak ditemukan');
}
});
setTimeout(function() {
map.invalidateSize();
}, 500);
</script>
</body>
</html>
</html>
+230
View File
@@ -0,0 +1,230 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'admin'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$data = mysqli_query($conn,
"SELECT * FROM laporan");
if(!$data){
die(mysqli_error($conn));
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Validasi</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<?php include 'layout/style.php'; ?>
</head>
<body>
<?php include 'layout/navbar.php'; ?>
<?php include 'layout/sidebar.php'; ?>
<div class="content">
<div class="mb-6">
<h1 class="text-3xl font-bold text-gray-800">
Validasi Laporan
</h1>
<p class="text-gray-500 mt-1">
Kelola laporan kemiskinan yang masuk dari masyarakat.
</p>
</div>
<div class="bg-white rounded-2xl shadow-lg overflow-hidden">
<div class="p-5 border-b bg-gray-50">
<h2 class="font-semibold text-lg">
Data Laporan
</h2>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-3 text-left">No</th>
<th class="px-4 py-3 text-left">Nama</th>
<th class="px-4 py-3 text-left">Alamat</th>
<th class="px-4 py-3 text-left">Foto</th>
<th class="px-4 py-3 text-left">Status</th>
<th class="px-4 py-3 text-center">Aksi</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
while($row = mysqli_fetch_assoc($data)){
?>
<tr class="border-b hover:bg-gray-50 transition">
<td class="px-4 py-3">
<?= $no++ ?>
</td>
<td class="px-4 py-3 font-medium">
<?= $row['nama_warga'] ?>
</td>
<td class="px-4 py-3">
<?= $row['alamat'] ?>
</td>
<td class="px-4 py-3">
<?php if(!empty($row['foto'])){ ?>
<img src="../assets/uploads/<?= htmlspecialchars($row['foto']) ?>"
onerror="this.src='../assets/uploads/no-image.png'"
class="w-20 h-20 object-cover rounded-xl shadow">
<?php } else { ?>
<span class="text-gray-400 italic">
Tidak ada foto
</span>
<?php } ?>
</td>
<td class="px-4 py-3">
<?php
if($row['status']=='pending'){
echo '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-700">
Pending
</span>';
}
elseif($row['status']=='disetujui'){
echo '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-700">
Disetujui
</span>';
}
elseif($row['status']=='ditolak'){
echo '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-red-100 text-red-700">
Ditolak
</span>';
}
elseif($row['status']=='diproses'){
echo '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 text-blue-700">
Diproses
</span>';
}
elseif($row['status']=='selesai'){
echo '<span class="px-3 py-1 rounded-full text-xs font-semibold bg-purple-100 text-purple-700">
Selesai
</span>';
}
?>
</td>
<td class="px-4 py-3">
<div class="flex flex-wrap gap-2 justify-center">
<?php if($row['status']=='pending'){ ?>
<a href="approve.php?id=<?= $row['id'] ?>"
onclick="return confirm('Setujui laporan ini?')"
class="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-lg text-sm transition">
<i class="fas fa-check mr-1"></i>
Approve
</a>
<a href="reject.php?id=<?= $row['id'] ?>"
onclick="return confirm('Tolak laporan ini?')"
class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-sm transition">
<i class="fas fa-times mr-1"></i>
Reject
</a>
<?php } ?>
<?php if($row['status']=='disetujui'){ ?>
<a href="assign_bantuan.php?id=<?= $row['id'] ?>"
class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm transition">
<i class="fas fa-hand-holding-heart mr-1"></i>
Assign Bantuan
</a>
<?php } ?>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

+19
View File
@@ -0,0 +1,19 @@
<?php
$host = getenv('DB_HOST') ?: 'localhost';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASS') ?: '';
$db = getenv('DB_NAME') ?: 'webgis_poverty';
$conn = mysqli_connect(
$host,
$user,
$pass,
$db
);
if (!$conn) {
die("Koneksi database gagal: " . mysqli_connect_error());
}
?>
+223
View File
@@ -0,0 +1,223 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'cs'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$user_id = $_SESSION['id'];
$cs = mysqli_fetch_assoc(
mysqli_query(
$conn,
"SELECT * FROM cs_rumah_ibadah
WHERE user_id='$user_id'"
)
);
$cs_id = $cs['id'];
/* TOTAL */
$total = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM bantuan
WHERE cs_id='$cs_id'")
);
/* PROSES */
$proses = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM bantuan
WHERE cs_id='$cs_id'
AND status='proses'")
);
/* SELESAI */
$selesai = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM bantuan
WHERE cs_id='$cs_id'
AND status='selesai'")
);
$persentase = 0;
if($total > 0){
$persentase = round(($selesai / $total) * 100);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Dashboard CS</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
</head>
<body class="bg-slate-100 min-h-screen">
<!-- NAVBAR -->
<nav class="bg-slate-800 text-white shadow">
<div class="max-w-7xl mx-auto px-4 py-4 flex flex-col md:flex-row justify-between items-center gap-3">
<h2 class="font-bold text-xl">
Dashboard CS
</h2>
<div class="flex flex-col sm:flex-row items-center gap-3">
<span>
Halo,
<?= htmlspecialchars($_SESSION['nama']) ?>
</span>
<a href="../logout.php" onclick="return confirm('Logout sekarang?')"
class="bg-red-500 hover:bg-red-600 px-4 py-2 rounded-lg transition">
Logout
</a>
</div>
</div>
</nav>
<!-- CONTENT -->
<div class="max-w-7xl mx-auto p-6">
<!-- HERO -->
<div class="bg-gradient-to-r from-emerald-600 to-teal-600 text-white rounded-3xl p-8 shadow-lg">
<h1 class="text-3xl font-bold">
Selamat Datang 👋
<?= htmlspecialchars($_SESSION['nama']) ?>
</h1>
<p class="mt-3 text-emerald-100">
Kelola tugas bantuan sosial yang telah diberikan oleh admin.
</p>
<div class="flex flex-col sm:flex-row gap-3 mt-6">
<a href="tugas.php"
class="bg-white text-emerald-600 font-semibold px-6 py-3 rounded-xl shadow hover:shadow-lg transition">
<i class="fa-solid fa-list-check mr-2"></i>
Lihat Tugas
</a>
</div>
</div>
<!-- CARDS -->
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 mt-8">
<!-- Total -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-list text-4xl text-emerald-600"></i>
<p class="text-slate-500 mt-3">
Total Tugas
</p>
<h2 class="text-4xl font-bold">
<?= $total ?>
</h2>
</div>
<!-- Diproses -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-spinner animate-spin text-4xl text-blue-500"></i>
<p class="text-slate-500 mt-3">
Diproses
</p>
<h2 class="text-4xl font-bold">
<?= $proses ?>
</h2>
</div>
<!-- Selesai -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-circle-check text-4xl text-green-500"></i>
<p class="text-slate-500 mt-3">
Selesai
</p>
<h2 class="text-4xl font-bold">
<?= $selesai ?>
</h2>
</div>
</div>
<div class="bg-white rounded-2xl shadow p-6 mt-8">
<h3 class="font-semibold text-slate-700">
Progress Penyelesaian Bantuan
</h3>
<div class="w-full bg-slate-200 rounded-full h-4 mt-4">
<div class="bg-green-500 h-4 rounded-full" style="width: <?= $persentase ?>%">
</div>
</div>
<p class="mt-3 text-slate-500">
<?= $persentase ?>% tugas bantuan telah selesai disalurkan
</p>
</div>
</div>
</body>
</html>
+106
View File
@@ -0,0 +1,106 @@
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #f8fafc;
font-family: 'Segoe UI', sans-serif;
}
.content {
padding: 30px;
}
/* CARD */
.card {
background: white;
border-radius: 16px;
padding: 25px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
transition: .3s;
}
.card:hover {
transform: translateY(-5px);
}
/* TABLE */
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
th {
background: #2563eb;
color: white;
}
th,
td {
padding: 14px;
border-bottom: 1px solid #eee;
}
/* BUTTON */
.btn {
padding: 10px 16px;
border-radius: 10px;
text-decoration: none;
color: white;
display: inline-block;
}
.approve {
background: #16a34a;
}
.reject {
background: #dc2626;
}
.delete {
background: #64748b;
}
.warning {
background: #f59e0b;
}
/* INPUT */
input,
select,
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 10px;
margin-top: 8px;
}
/* BOX */
.box {
background: white;
padding: 25px;
border-radius: 20px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
</style>
+158
View File
@@ -0,0 +1,158 @@
<?php
session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
include '../config/koneksi.php';
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'cs'){
header("Location: ../index.php");
exit;
}
$user_id = $_SESSION['id'];
$cs_query = mysqli_query(
$conn,
"SELECT * FROM cs_rumah_ibadah
WHERE user_id='$user_id'"
);
if(!$cs_query){
die(mysqli_error($conn));
}
$cs = mysqli_fetch_assoc($cs_query);
if(!$cs){
die("Data CS tidak ditemukan");
}
$cs_id = $cs['id'];
if(!isset($_POST['id'])){
die("ID bantuan tidak ditemukan");
}
$id = intval($_POST['id']);
if(
!isset($_FILES['foto']) ||
$_FILES['foto']['error'] != 0
){
die("Silakan pilih foto");
}
$tmp = $_FILES['foto']['tmp_name'];
$nama_asli = $_FILES['foto']['name'];
$ext = strtolower(
pathinfo(
$nama_asli,
PATHINFO_EXTENSION
)
);
$allowed = [
'jpg',
'jpeg',
'png',
'webp'
];
if(!in_array($ext,$allowed)){
die("Format file tidak didukung");
}
if(getimagesize($tmp) === false){
die("File harus berupa gambar");
}
$foto =
time() . '_' .
preg_replace(
'/[^a-zA-Z0-9._-]/',
'',
basename($nama_asli)
);
$cek_query = mysqli_query(
$conn,
"SELECT *
FROM bantuan
WHERE id='$id'
AND cs_id='$cs_id'"
);
if(!$cek_query){
die(mysqli_error($conn));
}
$cek = mysqli_fetch_assoc($cek_query);
if(!$cek){
die("Akses ditolak");
}
if(!is_dir("../assets/uploads")){
mkdir("../assets/uploads",0777,true);
}
if(
!move_uploaded_file(
$tmp,
"../assets/uploads/".$foto
)
){
die("Upload foto gagal");
}
$update = mysqli_query(
$conn,
"UPDATE bantuan
SET
bukti_foto='$foto',
status='selesai'
WHERE id='$id'"
);
if(!$update){
die(mysqli_error($conn));
}
$data_query = mysqli_query(
$conn,
"SELECT laporan_id
FROM bantuan
WHERE id='$id'"
);
if(!$data_query){
die(mysqli_error($conn));
}
$data = mysqli_fetch_assoc($data_query);
if(!$data){
die("Data bantuan tidak ditemukan");
}
$laporan_id = $data['laporan_id'];
mysqli_query(
$conn,
"UPDATE laporan
SET status='selesai'
WHERE id='$laporan_id'"
);
header("Location: tugas.php");
exit;
?>
+249
View File
@@ -0,0 +1,249 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'cs'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$user_id = $_SESSION['id'];
$cs = mysqli_fetch_assoc(
mysqli_query($conn,
"SELECT * FROM cs_rumah_ibadah
WHERE user_id='$user_id'")
);
$cs_id = $cs['id'];
$data = mysqli_query($conn,
"SELECT bantuan.*,
laporan.nama_warga,
laporan.alamat,
laporan.latitude,
laporan.longitude
FROM bantuan
JOIN laporan
ON bantuan.laporan_id = laporan.id
WHERE bantuan.cs_id='$cs_id'
ORDER BY bantuan.id DESC"
);
?>
<!DOCTYPE html>
<html>
<head>
<title>Tugas Bantuan</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-slate-100 min-h-screen">
<div class="max-w-7xl mx-auto p-6">
<!-- HEADER -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-6">
<div>
<h1 class="text-3xl font-bold text-slate-800">
Tugas Bantuan Saya
</h1>
<p class="text-slate-500 mt-2">
Daftar bantuan sosial yang harus disalurkan.
</p>
</div>
<a href="dashboard.php"
class="bg-slate-800 hover:bg-slate-900 text-white px-5 py-3 rounded-xl shadow transition">
← Dashboard
</a>
</div>
<!-- CARD -->
<div class="bg-white rounded-3xl shadow-lg overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="bg-emerald-600 text-white">
<th class="px-4 py-4 text-left">No</th>
<th class="px-4 py-4 text-left">Nama Warga</th>
<th class="px-4 py-4 text-left">Alamat</th>
<th class="px-4 py-4 text-left">Lokasi</th>
<th class="px-4 py-4 text-left">Jenis Bantuan</th>
<th class="px-4 py-4 text-left">Status</th>
<th class="px-4 py-4 text-left">Aksi</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
if(mysqli_num_rows($data) == 0){
?>
<tr>
<td colspan="7" class="text-center py-10 text-slate-500">
Belum ada tugas bantuan
</td>
</tr>
<?php
}
while($row = mysqli_fetch_assoc($data)){
?>
<tr class="border-b hover:bg-slate-50 transition">
<td class="px-4 py-4">
<?= $no++ ?>
</td>
<td class="px-4 py-4 font-medium text-slate-800">
<?= htmlspecialchars($row['nama_warga']) ?>
</td>
<td class="px-4 py-4 text-slate-600">
<?= htmlspecialchars($row['alamat']) ?>
</td>
<td class="px-4 py-4">
<a target="_blank"
href="https://www.google.com/maps?q=<?= $row['latitude'] ?>,<?= $row['longitude'] ?>"
class="text-blue-600 hover:underline font-medium">
Lihat Lokasi
</a>
</td>
<td class="px-4 py-4">
<?= htmlspecialchars($row['jenis_bantuan']) ?>
</td>
<td class="px-4 py-4">
<?php if($row['status']=='proses'){ ?>
<span class="
bg-amber-500
text-white
px-3 py-1
rounded-full
text-sm">
Diproses
</span>
<?php } ?>
<?php if($row['status']=='selesai'){ ?>
<span class="
bg-green-600
text-white
px-3 py-1
rounded-full
text-sm">
Selesai
</span>
<?php } ?>
</td>
<td class="px-4 py-4">
<?php if($row['status']=='proses'){ ?>
<a href="upload_bukti.php?id=<?= $row['id'] ?>" class="
bg-emerald-600
hover:bg-emerald-700
text-white
px-4 py-2
rounded-lg
shadow
transition">
Upload Bukti
</a>
<?php } else { ?>
<span class="text-green-600 font-semibold">
✓ Selesai
</span>
<?php } ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
+209
View File
@@ -0,0 +1,209 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'cs'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$user_id = $_SESSION['id'];
$cs = mysqli_fetch_assoc(
mysqli_query(
$conn,
"SELECT * FROM cs_rumah_ibadah
WHERE user_id='$user_id'"
)
);
if(!$cs){
die("Data CS tidak ditemukan");
}
$cs_id = $cs['id'];
$id = intval($_GET['id']);
$data = mysqli_fetch_assoc(
mysqli_query($conn,
"SELECT bantuan.*,
laporan.nama_warga,
laporan.alamat
FROM bantuan
JOIN laporan
ON bantuan.laporan_id = laporan.id
WHERE bantuan.id='$id'
AND bantuan.cs_id='$cs_id'")
);
if(!$data){
die("Tugas tidak ditemukan");
}
?>
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<title>Upload Bukti Bantuan</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>
<body class="bg-gray-100 min-h-screen">
<div class="max-w-4xl mx-auto p-6">
<a href="tugas.php"
class="inline-flex items-center gap-2 px-4 py-2 bg-gray-700 hover:bg-gray-800 text-white rounded-xl mb-6 transition">
<i class="fas fa-arrow-left"></i>
Kembali
</a>
<div class="bg-white rounded-2xl shadow-lg overflow-hidden">
<div class="bg-green-600 text-white p-6">
<h1 class="text-2xl font-bold flex items-center gap-3">
<i class="fas fa-camera"></i>
Upload Bukti Bantuan
</h1>
<p class="mt-2 text-green-100">
Upload dokumentasi penyaluran bantuan kepada warga.
</p>
</div>
<div class="p-6">
<div class="grid md:grid-cols-2 gap-5 mb-6">
<div class="bg-gray-50 rounded-xl p-4">
<p class="text-gray-500 text-sm">
Nama Warga
</p>
<h3 class="font-semibold text-lg mt-1">
<?= htmlspecialchars($data['nama_warga']) ?>
</h3>
</div>
<div class="bg-gray-50 rounded-xl p-4">
<p class="text-gray-500 text-sm">
Alamat
</p>
<h3 class="font-medium mt-1">
<?= htmlspecialchars($data['alamat']) ?>
</h3>
</div>
</div>
<form action="proses_upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?= $data['id'] ?>">
<div class="mb-5">
<label class="block text-sm font-medium text-gray-700 mb-2">
Foto Bukti Bantuan
</label>
<input type="file" id="foto" name="foto" accept="image/*" required
class="w-full border rounded-xl p-3">
</div>
<div class="mb-6">
<img id="preview" class="hidden w-full max-w-md h-64 object-cover rounded-xl border shadow">
</div>
<button type="submit"
class="px-6 py-3 bg-green-600 hover:bg-green-700 text-white rounded-xl shadow transition">
<i class="fas fa-upload mr-2"></i>
Upload Bukti
</button>
</form>
</div>
</div>
</div>
<script>
document
.getElementById('foto')
.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(ev) {
const preview =
document.getElementById('preview');
preview.src = ev.target.result;
preview.classList.remove('hidden');
};
reader.readAsDataURL(file);
});
</script>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
CREATE DATABASE IF NOT EXISTS webgis_poverty
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
USE webgis_poverty;
DROP TABLE IF EXISTS bantuan;
DROP TABLE IF EXISTS cs_rumah_ibadah;
DROP TABLE IF EXISTS laporan;
DROP TABLE IF EXISTS rumah_ibadah;
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
nama VARCHAR(100),
username VARCHAR(50),
password VARCHAR(255),
role ENUM('admin','warga','cs'),
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE laporan (
id INT NOT NULL AUTO_INCREMENT,
pelapor_id INT,
nama_warga VARCHAR(100),
alamat TEXT,
latitude DOUBLE,
longitude DOUBLE,
kondisi TEXT,
foto VARCHAR(255),
status ENUM(
'pending',
'disetujui',
'ditolak',
'diproses',
'selesai'
) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE rumah_ibadah (
id INT NOT NULL AUTO_INCREMENT,
nama VARCHAR(100),
alamat TEXT,
latitude DOUBLE,
longitude DOUBLE,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE cs_rumah_ibadah (
id INT NOT NULL AUTO_INCREMENT,
nama VARCHAR(100),
rumah_ibadah_id INT,
no_hp VARCHAR(20),
user_id INT,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE bantuan (
id INT NOT NULL AUTO_INCREMENT,
laporan_id INT,
cs_id INT,
jenis_bantuan VARCHAR(100),
status ENUM(
'belum',
'proses',
'selesai'
) DEFAULT 'belum',
bukti_foto VARCHAR(255),
tanggal TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
rumah_ibadah_id INT,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO users
(nama, username, password, role)
VALUES
('Administrator','admin','0192023a7bbd73250516f069df18b500','admin'),
('Andi Saputra','andi','e10adc3949ba59abbe56e057f20f883e','warga'),
('Siti Nurhaliza','siti','e10adc3949ba59abbe56e057f20f883e','warga'),
('Rahmat Hidayat','rahmat','e10adc3949ba59abbe56e057f20f883e','warga'),
('Budi Santoso','cs01','8551e0027ff3a8de9662eb3b8a16c23e','cs'),
('Santoso','cs02','8551e0027ff3a8de9662eb3b8a16c23e','cs');
INSERT INTO rumah_ibadah
(nama, alamat, latitude, longitude)
VALUES
(
'Gereja Katolik Paroki Bunda Maria',
'Pontianak Barat, Kalimantan Barat',
-0.005640,
109.295179
),
(
'Masjid Nurul Hamid',
'Pontianak Barat, Kalimantan Barat',
-0.008226,
109.296014
),
(
'Masjid Jannatun Naim',
'Kendari, Sulawesi Tenggara',
-3.997242,
122.521983
),
(
'GPIB Siloam Pontianak',
'Pontianak Kota, Kalimantan Barat',
-0.025091,
109.337375
);
INSERT INTO cs_rumah_ibadah
(nama, rumah_ibadah_id, no_hp, user_id)
VALUES
(
'Santoso',
1,
'081234567890',
6
);
+116
View File
@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>Login WebGIS</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: Arial;
background: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.login-box {
background: white;
padding: 30px;
border-radius: 10px;
width: 300px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
input {
width: 100%;
padding: 10px;
margin-top: 10px;
}
button {
width: 100%;
padding: 10px;
margin-top: 15px;
background: #3498db;
color: white;
border: none;
}
</style>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen">
<div class="bg-white p-8 rounded-2xl shadow-xl w-full max-w-md">
<div class="text-center mb-6">
<h1 class="text-3xl font-bold text-blue-600">
WebGIS Kemiskinan
</h1>
<p class="text-gray-500 mt-2">
Sistem Pengentasan Kemiskinan Kalimantan Barat
</p>
</div>
<form action="login.php" method="POST" class="space-y-4">
<input type="text" name="username" placeholder="Username"
class="w-full border rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-500" required>
<input type="password" name="password" placeholder="Password"
class="w-full border rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-500" required>
<button type="submit"
class="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-xl font-semibold transition">
Login
</button>
</form>
<div class="mt-6 text-center space-y-2">
<a href="register.php" class="block text-blue-600 hover:underline">
Daftar sebagai Warga
</a>
<a href="register_cs.php" class="block text-green-600 hover:underline">
Daftar sebagai CS Rumah Ibadah
</a>
</div>
</div>
</body>
</html>
+72
View File
@@ -0,0 +1,72 @@
<?php
session_start();
include 'config/koneksi.php';
$username =
mysqli_real_escape_string(
$conn,
$_POST['username']
);
$password = md5($_POST['password']);
$query = mysqli_query($conn,
"SELECT * FROM users
WHERE username='$username'
AND password='$password'"
);
$data = mysqli_fetch_assoc($query);
if($data){
$_SESSION['id'] = $data['id'];
$_SESSION['nama'] = $data['nama'];
$_SESSION['role'] = $data['role'];
/* ADMIN */
if($data['role']=='admin'){
header("Location: admin/dashboard.php");
exit;
}
/* WARGA */
elseif($data['role']=='warga'){
header("Location: warga/dashboard.php");
exit;
}
/* CS */
elseif($data['role']=='cs'){
header("Location: cs/dashboard.php");
exit;
}
}else{
echo "
<script>
alert('Login gagal');
window.location='index.php';
</script>
";
}
?>
+9
View File
@@ -0,0 +1,9 @@
<?php
session_start();
session_destroy();
header("Location: index.php");
?>
+280
View File
@@ -0,0 +1,280 @@
<?php
include 'config/koneksi.php';
if(isset($_POST['register'])){
$nama =
mysqli_real_escape_string(
$conn,
$_POST['nama']
);
$username =
mysqli_real_escape_string(
$conn,
$_POST['username']
);
$password = md5($_POST['password']);
$cek = mysqli_query($conn,
"SELECT * FROM users WHERE username='$username'");
if(mysqli_num_rows($cek) > 0){
echo "<script>
alert('Username sudah digunakan');
window.location='register.php';
</script>";
exit;
}
mysqli_query($conn,
"INSERT INTO users
(nama,username,password,role)
VALUES
(
'$nama',
'$username',
'$password',
'warga'
)"
);
header("Location: index.php");
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Register Warga</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<?php
include 'config/koneksi.php';
if(isset($_POST['register'])){
$nama = mysqli_real_escape_string(
$conn,
trim($_POST['nama'])
);
$username = mysqli_real_escape_string(
$conn,
trim($_POST['username'])
);
$password = $_POST['password'];
$konfirmasi = $_POST['konfirmasi_password'];
if(strlen($password) < 6){
echo "
<script>
alert('Password minimal 6 karakter');
window.location='register.php';
</script>
";
exit;
}
if($password != $konfirmasi){
echo "
<script>
alert('Konfirmasi password tidak sesuai');
window.location='register.php';
</script>
";
exit;
}
$cek = mysqli_query(
$conn,
"SELECT * FROM users WHERE username='$username'"
);
if(mysqli_num_rows($cek) > 0){
echo "
<script>
alert('Username sudah digunakan');
window.location='register.php';
</script>
";
exit;
}
$password_hash = password_hash(
$password,
PASSWORD_DEFAULT
);
mysqli_query(
$conn,
"INSERT INTO users
(
nama,
username,
password,
role
)
VALUES
(
'$nama',
'$username',
'$password_hash',
'warga'
)"
);
echo "
<script>
alert('Registrasi berhasil');
window.location='index.php';
</script>
";
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Register Warga</title>
<meta charset="utf-8">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>
<body
class="min-h-screen bg-gradient-to-br from-blue-600 via-blue-500 to-cyan-500 flex items-center justify-center p-5">
<div class="w-full max-w-md">
<div class="bg-white rounded-3xl shadow-2xl overflow-hidden">
<div class="bg-blue-600 text-white p-8 text-center">
<i class="fas fa-user-plus text-5xl mb-4"></i>
<h1 class="text-3xl font-bold">
Register Warga
</h1>
<p class="mt-2 text-blue-100">
Buat akun untuk mengirim laporan kemiskinan
</p>
</div>
<form method="POST" class="p-8 space-y-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Nama Lengkap
</label>
<input type="text" name="nama" required placeholder="Masukkan nama lengkap"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Username
</label>
<input type="text" name="username" required placeholder="Masukkan username"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Password
</label>
<input type="password" id="password" name="password" required placeholder="Minimal 6 karakter"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Konfirmasi Password
</label>
<input type="password" id="konfirmasi" name="konfirmasi_password" required
placeholder="Ulangi password"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
<button type="submit" name="register"
class="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-xl font-semibold transition">
<i class="fas fa-user-plus mr-2"></i>
Register
</button>
</form>
<div class="px-8 pb-8 text-center">
<a href="index.php" class="text-blue-600 hover:text-blue-800 font-medium">
<i class="fas fa-arrow-left mr-1"></i>
Sudah punya akun? Login di sini
</a>
</div>
</div>
</div>
</body>
</html>
?>
+390
View File
@@ -0,0 +1,390 @@
<?php
include 'config/koneksi.php';
/* AMBIL RUMAH IBADAH */
$rumah_ibadah = mysqli_query($conn,
"SELECT * FROM rumah_ibadah");
if(isset($_POST['register'])){
$nama =
mysqli_real_escape_string(
$conn,
$_POST['nama']
);
$username =
mysqli_real_escape_string(
$conn,
$_POST['username']
);
$no_hp =
mysqli_real_escape_string(
$conn,
$_POST['no_hp']
);
$rumah_ibadah_id =
$_POST['rumah_ibadah_id'];
$password = md5($_POST['password']);
$cek = mysqli_query($conn,
"SELECT * FROM users WHERE username='$username'");
if(mysqli_num_rows($cek) > 0){
echo "<script>
alert('Username sudah digunakan');
window.location='register_cs.php';
</script>";
exit;
}
/* INSERT USERS */
mysqli_query($conn,
"INSERT INTO users
(
nama,
username,
password,
role
)
VALUES
(
'$nama',
'$username',
'$password',
'cs'
)"
);
/* AMBIL USER ID */
$user_id = mysqli_insert_id($conn);
/* INSERT CS */
mysqli_query($conn,
"INSERT INTO cs_rumah_ibadah
(
nama,
rumah_ibadah_id,
no_hp,
user_id
)
VALUES
(
'$nama',
'$rumah_ibadah_id',
'$no_hp',
'$user_id'
)"
);
header("Location: index.php");
}
?>
<!DOCTYPE html>
<?php
include 'config/koneksi.php';
$rumah_ibadah = mysqli_query(
$conn,
"SELECT * FROM rumah_ibadah ORDER BY nama ASC"
);
if(isset($_POST['register'])){
$nama = mysqli_real_escape_string(
$conn,
trim($_POST['nama'])
);
$username = mysqli_real_escape_string(
$conn,
trim($_POST['username'])
);
$no_hp = mysqli_real_escape_string(
$conn,
trim($_POST['no_hp'])
);
$rumah_ibadah_id = intval(
$_POST['rumah_ibadah_id']
);
$password = $_POST['password'];
$konfirmasi = $_POST['konfirmasi_password'];
if(strlen($password) < 6){
echo "
<script>
alert('Password minimal 6 karakter');
window.location='register_cs.php';
</script>
";
exit;
}
if($password != $konfirmasi){
echo "
<script>
alert('Konfirmasi password tidak sesuai');
window.location='register_cs.php';
</script>
";
exit;
}
$cek = mysqli_query(
$conn,
"SELECT * FROM users
WHERE username='$username'"
);
if(mysqli_num_rows($cek) > 0){
echo "
<script>
alert('Username sudah digunakan');
window.location='register_cs.php';
</script>
";
exit;
}
$password_hash = password_hash(
$password,
PASSWORD_DEFAULT
);
mysqli_query(
$conn,
"INSERT INTO users
(
nama,
username,
password,
role
)
VALUES
(
'$nama',
'$username',
'$password_hash',
'cs'
)"
);
$user_id = mysqli_insert_id($conn);
mysqli_query(
$conn,
"INSERT INTO cs_rumah_ibadah
(
nama,
rumah_ibadah_id,
no_hp,
user_id
)
VALUES
(
'$nama',
'$rumah_ibadah_id',
'$no_hp',
'$user_id'
)"
);
echo "
<script>
alert('Registrasi CS berhasil');
window.location='index.php';
</script>
";
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Register CS Rumah Ibadah</title>
<meta charset="utf-8">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>
<body
class="min-h-screen bg-gradient-to-br from-green-600 via-emerald-500 to-teal-500 flex items-center justify-center p-5">
<div class="w-full max-w-lg">
<div class="bg-white rounded-3xl shadow-2xl overflow-hidden">
<div class="bg-green-600 text-white p-8 text-center">
<i class="fas fa-hand-holding-heart text-5xl mb-4"></i>
<h1 class="text-3xl font-bold">
Register CS
</h1>
<p class="mt-2 text-green-100">
Daftarkan Customer Service Rumah Ibadah
</p>
</div>
<form method="POST" class="p-8 space-y-5">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Nama Lengkap
</label>
<input type="text" name="nama" required placeholder="Masukkan nama lengkap"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Rumah Ibadah
</label>
<select name="rumah_ibadah_id" required
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
<option value="">
-- Pilih Rumah Ibadah --
</option>
<?php while($r = mysqli_fetch_assoc($rumah_ibadah)){ ?>
<option value="<?= $r['id'] ?>">
<?= htmlspecialchars($r['nama']) ?>
</option>
<?php } ?>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Nomor HP
</label>
<input type="text" name="no_hp" required placeholder="08xxxxxxxxxx"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Username
</label>
<input type="text" name="username" required placeholder="Masukkan username"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Password
</label>
<input type="password" name="password" required placeholder="Minimal 6 karakter"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Konfirmasi Password
</label>
<input type="password" name="konfirmasi_password" required placeholder="Ulangi password"
class="w-full border rounded-xl p-3 focus:ring-2 focus:ring-green-500 focus:outline-none">
</div>
<button type="submit" name="register"
class="w-full bg-green-600 hover:bg-green-700 text-white py-3 rounded-xl font-semibold transition">
<i class="fas fa-user-plus mr-2"></i>
Daftar CS
</button>
</form>
<div class="px-8 pb-8 text-center">
<a href="index.php" class="text-green-600 hover:text-green-800 font-medium">
<i class="fas fa-arrow-left mr-1"></i>
Kembali ke Login
</a>
</div>
</div>
</div>
</body>
</html>
+242
View File
@@ -0,0 +1,242 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'warga'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = intval($_SESSION['id']);
$total = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'")
);
$pending = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
AND status='pending'")
);
$disetujui = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
AND status='disetujui'")
);
$diproses = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
AND status='diproses'")
);
$selesai = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
AND status='selesai'")
);
$ditolak = mysqli_num_rows(
mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
AND status='ditolak'")
);
$persentase = 0;
if($total > 0){
$persentase = round(($selesai/$total)*100);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Dashboard Warga</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
</head>
<body class="bg-slate-100 min-h-screen">
<!-- NAVBAR -->
<nav class="bg-slate-800 text-white shadow">
<div class="max-w-7xl mx-auto px-4 py-4 flex flex-col md:flex-row justify-between items-center gap-3">
<h2 class="font-bold text-xl">
WebGIS Kemiskinan
</h2>
<div class="flex flex-col sm:flex-row items-center gap-3">
<span>
Halo,
<?= htmlspecialchars($_SESSION['nama']) ?>
</span>
<a href="../logout.php" onclick="return confirm('Logout sekarang?');"
class="bg-red-500 hover:bg-red-600 px-4 py-2 rounded-lg transition">
Logout
</a>
</div>
</div>
</nav>
<!-- CONTENT -->
<div class="max-w-7xl mx-auto p-6">
<!-- HERO -->
<div class="bg-gradient-to-r from-cyan-600 to-blue-600 text-white rounded-3xl p-8 shadow-lg">
<h1 class="text-3xl font-bold">
Selamat Datang 👋
<?= htmlspecialchars($_SESSION['nama']) ?>
</h1>
<p class="mt-3 text-cyan-100">
Laporkan kondisi warga yang membutuhkan bantuan sosial
di sekitar lingkungan Anda.
</p>
<div class="flex flex-col sm:flex-row gap-3 mt-6">
<a href="laporan.php"
class="bg-white text-blue-600 font-semibold px-6 py-3 rounded-xl shadow hover:shadow-lg transition">
<i class="fa-solid fa-plus mr-2"></i>
Buat Laporan
</a>
<a href="status.php"
class="bg-slate-800 text-white font-semibold px-6 py-3 rounded-xl shadow hover:bg-slate-900 transition">
<i class="fa-solid fa-list-check mr-2"></i>
Lihat Laporan
</a>
</div>
<div class="bg-white rounded-2xl shadow p-6 mt-6">
<p class="font-semibold">
Progress Bantuan
</p>
<div class="w-full bg-slate-200 rounded-full h-4 mt-3">
<div class="bg-green-500 h-4 rounded-full" style="width: <?= $persentase ?>%">
</div>
</div>
<p class="mt-2 text-sm text-slate-500">
<?= $persentase ?>% laporan telah selesai
</p>
</div>
</div>
<!-- CARDS -->
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 mt-8">
<!-- Total -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-file text-4xl text-blue-600"></i>
<p class="text-slate-500 mt-3">Total Laporan</p>
<h2 class="text-4xl font-bold"><?= $total ?></h2>
</div>
<!-- Pending -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-clock text-4xl text-yellow-500"></i>
<p class="text-slate-500 mt-3">Pending</p>
<h2 class="text-4xl font-bold"><?= $pending ?></h2>
</div>
<!-- Disetujui -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-circle-check text-4xl text-green-500"></i>
<p class="text-slate-500 mt-3">Disetujui</p>
<h2 class="text-4xl font-bold"><?= $disetujui ?></h2>
</div>
<!-- Diproses -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-spinner animate-spin text-4xl text-blue-500"></i>
<p class="text-slate-500 mt-3">Diproses</p>
<h2 class="text-4xl font-bold"><?= $diproses ?></h2>
</div>
<!-- Selesai -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-hand-holding-heart text-4xl text-purple-500"></i>
<p class="text-slate-500 mt-3">Selesai</p>
<h2 class="text-4xl font-bold"><?= $selesai ?></h2>
</div>
<!-- Ditolak -->
<div class="bg-white rounded-2xl shadow p-6">
<i class="fa-solid fa-circle-xmark text-4xl text-red-500"></i>
<p class="text-slate-500 mt-3">Ditolak</p>
<h2 class="text-4xl font-bold"><?= $ditolak ?></h2>
</div>
</div>
</div>
</body>
</html>
+201
View File
@@ -0,0 +1,201 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'warga'){
header("Location: ../index.php");
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Buat Laporan</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
</head>
<body class="bg-slate-100 min-h-screen">
<div class="max-w-5xl mx-auto p-6">
<a href="dashboard.php"
class="inline-flex items-center gap-2 bg-slate-800 hover:bg-slate-900 text-white px-4 py-3 rounded-xl shadow">
← Kembali ke Dashboard
</a>
<div class="bg-white rounded-3xl shadow-lg p-8 mt-6">
<div class="mb-8">
<h1 class="text-3xl font-bold text-slate-800">
Buat Laporan Warga
</h1>
<p class="text-slate-500 mt-2">
Isi data warga yang membutuhkan bantuan sosial dan pilih lokasi pada peta.
</p>
</div>
<form action="simpan_laporan.php" method="POST" enctype="multipart/form-data" class="space-y-5">
<div>
<label class="block mb-2 font-medium text-slate-700">
Nama Warga
</label>
<input type="text" name="nama_warga" required
class="w-full border rounded-xl px-4 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none">
</div>
<div>
<label class="block mb-2 font-medium text-slate-700">
Alamat
</label>
<textarea name="alamat" rows="3" required
class="w-full border rounded-xl px-4 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none"></textarea>
</div>
<div>
<label class="block mb-2 font-medium text-slate-700">
Kondisi Warga
</label>
<textarea name="kondisi" rows="4" required
class="w-full border rounded-xl px-4 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none"></textarea>
</div>
<div>
<label class="block mb-2 font-medium text-slate-700">
Foto Kondisi Warga
</label>
<input type="file" name="foto" accept="image/*" required class="w-full border rounded-xl px-4 py-3">
</div>
<div class="grid md:grid-cols-2 gap-4">
<div>
<label class="block mb-2 font-medium text-slate-700">
Latitude
</label>
<input type="text" name="latitude" id="latitude" readonly required
class="w-full border rounded-xl px-4 py-3 bg-slate-100">
</div>
<div>
<label class="block mb-2 font-medium text-slate-700">
Longitude
</label>
<input type="text" name="longitude" id="longitude" readonly required
class="w-full border rounded-xl px-4 py-3 bg-slate-100">
</div>
</div>
<div>
<label class="block mb-3 font-medium text-slate-700">
Pilih Lokasi Pada Peta
</label>
<p class="text-sm text-slate-500 mb-3">
Klik pada peta untuk menentukan lokasi warga.
</p>
<div id="map" style="height:450px;" class="rounded-2xl border">
</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
var map = L.map('map').setView(
[-0.0263, 109.3425],
11
);
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19
}
).addTo(map);
var marker;
map.on('click', function(e) {
var lat = e.latlng.lat.toFixed(6);
var lng = e.latlng.lng.toFixed(6);
document.getElementById('latitude').value = lat;
document.getElementById('longitude').value = lng;
if (marker) {
map.removeLayer(marker);
}
marker = L.marker([lat, lng])
.addTo(map)
.bindPopup(
"Lat: " + lat +
"<br>Lng: " + lng
)
.openPopup();
});
setTimeout(function() {
map.invalidateSize();
}, 200);
</script>
</div>
<button type="submit"
class="w-full md:w-auto bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-xl font-semibold shadow">
Kirim Laporan
</button>
</form>
</div>
</div>
</body>
</html>
+106
View File
@@ -0,0 +1,106 @@
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #f8fafc;
font-family: 'Segoe UI', sans-serif;
}
.content {
padding: 30px;
}
/* CARD */
.card {
background: white;
border-radius: 16px;
padding: 25px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
transition: .3s;
}
.card:hover {
transform: translateY(-5px);
}
/* TABLE */
table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
th {
background: #2563eb;
color: white;
}
th,
td {
padding: 14px;
border-bottom: 1px solid #eee;
}
/* BUTTON */
.btn {
padding: 10px 16px;
border-radius: 10px;
text-decoration: none;
color: white;
display: inline-block;
}
.approve {
background: #16a34a;
}
.reject {
background: #dc2626;
}
.delete {
background: #64748b;
}
.warning {
background: #f59e0b;
}
/* INPUT */
input,
select,
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 10px;
margin-top: 8px;
}
/* BOX */
.box {
background: white;
padding: 25px;
border-radius: 20px;
box-shadow:
0 4px 20px rgba(0, 0, 0, .08);
}
</style>
+105
View File
@@ -0,0 +1,105 @@
<?php
session_start();
include '../config/koneksi.php';
$pelapor_id = $_SESSION['id'];
$nama_warga = mysqli_real_escape_string(
$conn,
$_POST['nama_warga']
);
$alamat = mysqli_real_escape_string(
$conn,
$_POST['alamat']
);
$kondisi = mysqli_real_escape_string(
$conn,
$_POST['kondisi']
);
$latitude = floatval($_POST['latitude']);
$longitude = floatval($_POST['longitude']);
/* FOTO */
$foto =
time().'_'.
basename($_FILES['foto']['name']);
$tmp = $_FILES['foto']['tmp_name'];
$ext = strtolower(
pathinfo(
$foto,
PATHINFO_EXTENSION
)
);
$allowed = [
'jpg',
'jpeg',
'png',
'webp'
];
if(!in_array($ext,$allowed)){
echo "
<script>
alert('Format foto harus JPG, PNG, atau WEBP');
history.back();
</script>
";
exit;
}
if(!move_uploaded_file(
$tmp,
"../assets/uploads/".$foto
)){
die("Upload foto gagal");
}
/* INSERT */
mysqli_query($conn,
"INSERT INTO laporan
(
pelapor_id,
nama_warga,
alamat,
latitude,
longitude,
kondisi,
foto,
status
)
VALUES
(
'$pelapor_id',
'$nama_warga',
'$alamat',
'$latitude',
'$longitude',
'$kondisi',
'$foto',
'pending'
)"
);
echo "
<script>
alert('Laporan berhasil dikirim');
window.location='dashboard.php';
</script>
";
?>
+224
View File
@@ -0,0 +1,224 @@
<?php
session_start();
if(!isset($_SESSION['role'])){
header("Location: ../index.php");
exit;
}
if($_SESSION['role'] != 'warga'){
header("Location: ../index.php");
exit;
}
include '../config/koneksi.php';
$id = $_SESSION['id'];
$data = mysqli_query($conn,
"SELECT * FROM laporan
WHERE pelapor_id='$id'
ORDER BY id DESC"
);
?>
<!DOCTYPE html>
<html>
<head>
<title>Status Laporan</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: Arial;
background: #f4f4f4;
padding: 20px;
}
table {
width: 100%;
background: white;
border-collapse: collapse;
}
th,
td {
padding: 12px;
border: 1px solid #ddd;
}
th {
background: #3498db;
color: white;
}
</style>
</head>
<body class="bg-slate-100 min-h-screen">
<div class="max-w-7xl mx-auto p-6">
<a href="dashboard.php"
class="inline-flex items-center gap-2 bg-slate-800 hover:bg-slate-900 text-white px-5 py-3 rounded-xl shadow transition">
← Kembali ke Dashboard
</a>
<div class="bg-white rounded-3xl shadow-lg p-6 md:p-8 mt-6">
<div class="mb-6">
<h1 class="text-3xl font-bold text-slate-800">
Status Laporan Saya
</h1>
<p class="text-slate-500 mt-2">
Pantau perkembangan laporan yang telah Anda kirim.
</p>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="bg-blue-600 text-white">
<th class="px-4 py-3 text-left">No</th>
<th class="px-4 py-3 text-left">Nama Warga</th>
<th class="px-4 py-3 text-left">Foto</th>
<th class="px-4 py-3 text-left">Tanggal</th>
<th class="px-4 py-3 text-left">Status</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
if(mysqli_num_rows($data) == 0){
?>
<tr>
<td colspan="5" class="text-center py-8 text-slate-500">
Belum ada laporan
</td>
</tr>
<?php
} else {
while($row = mysqli_fetch_assoc($data)){
?>
<tr class="border-b hover:bg-slate-50">
<td class="px-4 py-4">
<?= $no++ ?>
</td>
<td class="px-4 py-4 font-medium">
<?= htmlspecialchars($row['nama_warga']) ?>
</td>
<td class="px-4 py-4">
<?php if($row['foto']!=''){ ?>
<img src="../assets/uploads/<?= htmlspecialchars($row['foto']) ?>"
class="w-20 h-20 object-cover rounded-xl shadow">
<?php } else { ?>
<span class="text-slate-400">
Tidak ada foto
</span>
<?php } ?>
</td>
<td class="px-4 py-4 text-slate-600">
<?= date('d-m-Y H:i', strtotime($row['created_at'])) ?>
</td>
<td class="px-4 py-4">
<?php
if($row['status']=='pending'){
echo "<span class='bg-amber-500 text-white px-3 py-1 rounded-full text-sm'>Pending</span>";
}
elseif($row['status']=='disetujui'){
echo "<span class='bg-green-600 text-white px-3 py-1 rounded-full text-sm'>Disetujui</span>";
}
elseif($row['status']=='ditolak'){
echo "<span class='bg-red-600 text-white px-3 py-1 rounded-full text-sm'>Ditolak</span>";
}
elseif($row['status']=='diproses'){
echo "<span class='bg-blue-600 text-white px-3 py-1 rounded-full text-sm'>Diproses</span>";
}
elseif($row['status']=='selesai'){
echo "<span class='bg-purple-600 text-white px-3 py-1 rounded-full text-sm'>Selesai</span>";
}
?>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>