first commit

This commit is contained in:
Anderi Saputra
2026-06-10 17:00:19 +07:00
commit adec71e763
38 changed files with 9278 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
.DS_Store
Thumbs.db
.idea/
.vscode/
*.log
*.zip
.env
+21
View File
@@ -0,0 +1,21 @@
# UAS WebGIS
Project UAS WebGIS yang terdiri dari:
- WebGIS Infrastruktur Kota Pontianak
- WebGIS Pemetaan Kemiskinan
- Landing page untuk mengakses kedua project
## Menjalankan Project
1. Letakkan folder project di `C:\xampp\htdocs\webgis\pertemuan01`.
2. Jalankan Apache dan MySQL melalui XAMPP.
3. Buka `http://localhost/webgis/pertemuan01/`.
Database dan tabel akan dibuat otomatis ketika project dijalankan.
## Login Admin
- Username: `admin`
- Password: `password`
+1060
View File
File diff suppressed because it is too large Load Diff
+738
View File
@@ -0,0 +1,738 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Portal WebGIS yang memuat Project Infrastruktur dan Project Kemiskinan Kota Pontianak.">
<title>Portal Project WebGIS</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Manrope:wght@600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--navy: #0b2545;
--navy-light: #163b67;
--blue: #246bfd;
--blue-soft: #eaf1ff;
--orange: #f97316;
--orange-soft: #fff0e6;
--ink: #10233f;
--muted: #65758b;
--line: #dfe7f1;
--surface: #ffffff;
--background: #f4f7fb;
--shadow: 0 22px 55px rgba(13, 43, 78, .12);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
min-height: 100vh;
color: var(--ink);
background:
radial-gradient(circle at 8% 5%, rgba(36, 107, 253, .09), transparent 25rem),
radial-gradient(circle at 92% 42%, rgba(249, 115, 22, .08), transparent 24rem),
var(--background);
font-family: "DM Sans", sans-serif;
overflow-x: hidden;
}
a {
color: inherit;
text-decoration: none;
}
.page-shell {
width: min(1180px, calc(100% - 40px));
margin: 0 auto;
}
.site-header {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 84px;
gap: 24px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 12px;
font-family: "Manrope", sans-serif;
font-size: 17px;
font-weight: 800;
letter-spacing: -.02em;
}
.brand-mark {
display: grid;
place-items: center;
width: 42px;
height: 42px;
color: #fff;
background: var(--navy);
border-radius: 13px;
box-shadow: 0 8px 18px rgba(11, 37, 69, .18);
}
.brand-mark svg {
width: 23px;
height: 23px;
}
.header-note {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-size: 13px;
font-weight: 600;
}
.status-dot {
width: 8px;
height: 8px;
background: var(--orange);
border-radius: 50%;
box-shadow: 0 0 0 5px rgba(249, 115, 22, .12);
}
.hero {
display: grid;
grid-template-columns: 1.15fr .85fr;
align-items: center;
min-height: 430px;
padding: 58px 0 68px;
gap: 70px;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 9px;
margin-bottom: 20px;
padding: 8px 12px;
color: var(--blue);
background: var(--blue-soft);
border-radius: 999px;
font-size: 12px;
font-weight: 700;
letter-spacing: .08em;
text-transform: uppercase;
}
.eyebrow svg {
width: 16px;
height: 16px;
}
h1 {
max-width: 720px;
color: var(--navy);
font-family: "Manrope", sans-serif;
font-size: clamp(42px, 6vw, 70px);
font-weight: 800;
line-height: 1.05;
letter-spacing: -.055em;
}
h1 span {
color: var(--blue);
}
.hero-copy {
max-width: 650px;
margin-top: 24px;
color: var(--muted);
font-size: 18px;
line-height: 1.75;
}
.hero-action {
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 30px;
padding: 13px 19px;
color: #fff;
background: var(--navy);
border-radius: 12px;
font-size: 14px;
font-weight: 700;
transition: transform .2s ease, background .2s ease;
}
.hero-action:hover {
background: var(--navy-light);
transform: translateY(-2px);
}
.hero-action svg {
width: 17px;
height: 17px;
}
.map-visual {
position: relative;
min-height: 330px;
border: 1px solid rgba(255, 255, 255, .5);
border-radius: 32px;
background:
linear-gradient(rgba(255, 255, 255, .78), rgba(255, 255, 255, .78)),
repeating-linear-gradient(35deg, transparent 0 28px, rgba(36, 107, 253, .2) 29px 31px),
repeating-linear-gradient(125deg, transparent 0 38px, rgba(249, 115, 22, .18) 39px 41px);
box-shadow: var(--shadow);
overflow: hidden;
}
.map-visual::before,
.map-visual::after {
content: "";
position: absolute;
border-radius: 50%;
filter: blur(2px);
}
.map-visual::before {
width: 210px;
height: 210px;
top: -65px;
right: -45px;
background: rgba(36, 107, 253, .12);
}
.map-visual::after {
width: 180px;
height: 180px;
bottom: -60px;
left: -40px;
background: rgba(249, 115, 22, .13);
}
.visual-center {
position: absolute;
inset: 0;
z-index: 1;
display: grid;
place-items: center;
}
.pin {
display: grid;
place-items: center;
width: 92px;
height: 92px;
color: #fff;
background: var(--blue);
border: 12px solid rgba(255, 255, 255, .96);
border-radius: 50% 50% 50% 12px;
box-shadow: 0 18px 35px rgba(36, 107, 253, .32);
transform: rotate(-45deg);
}
.pin svg {
width: 37px;
height: 37px;
transform: rotate(45deg);
}
.map-label {
position: absolute;
z-index: 2;
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
background: rgba(255, 255, 255, .95);
border: 1px solid var(--line);
border-radius: 12px;
box-shadow: 0 10px 25px rgba(16, 35, 63, .1);
font-size: 12px;
font-weight: 700;
}
.map-label.one {
top: 50px;
left: 28px;
}
.map-label.two {
right: 24px;
bottom: 42px;
}
.label-icon {
display: grid;
place-items: center;
width: 28px;
height: 28px;
color: var(--blue);
background: var(--blue-soft);
border-radius: 8px;
}
.map-label.two .label-icon {
color: var(--blue);
background: var(--blue-soft);
}
.label-icon svg {
width: 15px;
height: 15px;
}
.map-label.one .label-icon {
color: var(--orange);
background: var(--orange-soft);
}
.projects-section {
padding: 30px 0 84px;
}
.section-heading {
display: flex;
align-items: end;
justify-content: space-between;
margin-bottom: 28px;
gap: 20px;
}
.section-kicker {
margin-bottom: 7px;
color: var(--blue);
font-size: 12px;
font-weight: 800;
letter-spacing: .12em;
text-transform: uppercase;
}
h2 {
color: var(--navy);
font-family: "Manrope", sans-serif;
font-size: clamp(28px, 4vw, 38px);
letter-spacing: -.035em;
}
.project-count {
color: var(--muted);
font-size: 14px;
font-weight: 600;
}
.project-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px;
}
.project-card {
position: relative;
display: flex;
flex-direction: column;
min-height: 375px;
padding: 32px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: 22px;
box-shadow: 0 12px 35px rgba(16, 35, 63, .06);
overflow: hidden;
transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.project-card::after {
content: "";
position: absolute;
width: 160px;
height: 160px;
top: -70px;
right: -55px;
background: var(--orange-soft);
border-radius: 50%;
transition: transform .3s ease;
}
.project-card.blue::after {
background: var(--blue-soft);
}
.project-card:hover {
border-color: #c9d8ec;
box-shadow: 0 20px 45px rgba(16, 35, 63, .12);
transform: translateY(-6px);
}
.project-card:hover::after {
transform: scale(1.18);
}
.card-top {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 28px;
}
.project-icon {
display: grid;
place-items: center;
width: 58px;
height: 58px;
color: var(--orange);
background: var(--orange-soft);
border-radius: 16px;
}
.blue .project-icon {
color: var(--blue);
background: var(--blue-soft);
}
.project-icon svg {
width: 29px;
height: 29px;
}
.project-number {
color: #a9b5c5;
font-family: "Manrope", sans-serif;
font-size: 13px;
font-weight: 800;
letter-spacing: .12em;
}
.project-card h3 {
color: var(--navy);
font-family: "Manrope", sans-serif;
font-size: 25px;
letter-spacing: -.025em;
}
.project-card p {
margin-top: 13px;
color: var(--muted);
font-size: 15px;
line-height: 1.7;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 22px 0 26px;
}
.tag {
padding: 6px 10px;
color: #4f6178;
background: #f1f5f9;
border-radius: 8px;
font-size: 11px;
font-weight: 700;
}
.project-link {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin-top: auto;
padding: 14px 16px;
color: var(--orange);
background: var(--orange-soft);
border-radius: 12px;
font-size: 14px;
font-weight: 800;
transition: color .2s ease, background .2s ease;
}
.blue .project-link {
color: var(--blue);
background: var(--blue-soft);
}
.project-link:hover {
color: #fff;
background: var(--orange);
}
.blue .project-link:hover {
background: var(--blue);
}
.project-link svg {
width: 18px;
height: 18px;
transition: transform .2s ease;
}
.project-link:hover svg {
transform: translateX(4px);
}
footer {
border-top: 1px solid var(--line);
}
.footer-inner {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 82px;
color: var(--muted);
font-size: 13px;
gap: 20px;
}
.footer-inner strong {
color: var(--navy);
}
@media (max-width: 860px) {
.hero {
grid-template-columns: 1fr;
gap: 44px;
padding-top: 48px;
}
.hero-copy {
max-width: 720px;
}
.map-visual {
min-height: 300px;
}
}
@media (max-width: 680px) {
.page-shell {
width: min(100% - 28px, 1180px);
}
.site-header {
min-height: 74px;
}
.header-note {
display: none;
}
.hero {
min-height: auto;
padding: 40px 0 58px;
}
h1 {
font-size: clamp(39px, 13vw, 56px);
}
.hero-copy {
font-size: 16px;
}
.map-visual {
min-height: 260px;
border-radius: 24px;
}
.pin {
width: 76px;
height: 76px;
}
.map-label.one {
top: 28px;
left: 16px;
}
.map-label.two {
right: 16px;
bottom: 28px;
}
.section-heading {
align-items: start;
flex-direction: column;
}
.project-grid {
grid-template-columns: 1fr;
}
.project-card {
min-height: 360px;
padding: 26px;
}
.footer-inner {
align-items: flex-start;
flex-direction: column;
justify-content: center;
padding: 22px 0;
gap: 7px;
}
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*,
*::before,
*::after {
transition-duration: .01ms !important;
}
}
</style>
</head>
<body>
<header class="page-shell site-header">
<a class="brand" href="./" aria-label="Portal Project WebGIS">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M4 6.5 9 4l6 2.5L20 4v13.5L15 20l-6-2.5L4 20V6.5Z"/>
<path d="M9 4v13.5M15 6.5V20"/>
</svg>
</span>
<span>Portal WebGIS</span>
</a>
<div class="header-note">
<span class="status-dot" aria-hidden="true"></span>
Dua project tersedia
</div>
</header>
<main>
<section class="page-shell hero">
<div>
<div class="eyebrow">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 21s7-4.35 7-11A7 7 0 1 0 5 10c0 6.65 7 11 7 11Z"/>
<circle cx="12" cy="10" r="2.5"/>
</svg>
Sistem Informasi Geografis
</div>
<h1>Jelajahi data melalui <span>peta interaktif.</span></h1>
<p class="hero-copy">
Portal terintegrasi untuk mengakses seluruh project WebGIS. Pilih project di bawah untuk melihat informasi spasial, data, dan analisis pada wilayah Kota Pontianak.
</p>
<a class="hero-action" href="#daftar-project">
Lihat daftar project
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="m6 9 6 6 6-6"/>
</svg>
</a>
</div>
<div class="map-visual" aria-hidden="true">
<div class="map-label one">
<span class="label-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 20V10l8-6 8 6v10"/>
<path d="M8 20v-6h8v6M3 20h18"/>
</svg>
</span>
Infrastruktur
</div>
<div class="visual-center">
<div class="pin">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M4 6.5 9 4l6 2.5L20 4v13.5L15 20l-6-2.5L4 20V6.5Z"/>
<path d="M9 4v13.5M15 6.5V20"/>
</svg>
</div>
</div>
<div class="map-label two">
<span class="label-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
</span>
Kemiskinan
</div>
</div>
</section>
<section class="page-shell projects-section" id="daftar-project">
<div class="section-heading">
<div>
<div class="section-kicker">Daftar Project</div>
<h2>Pilih project untuk dibuka</h2>
</div>
<div class="project-count">2 project WebGIS</div>
</div>
<div class="project-grid">
<article class="project-card">
<div class="card-top">
<div class="project-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M3 21h18M5 21V8l7-5 7 5v13M9 21v-5h6v5"/>
<path d="M8 10h2M14 10h2M8 13h2M14 13h2"/>
</svg>
</div>
<span class="project-number">PROJECT 01</span>
</div>
<h3>WebGIS Infrastruktur</h3>
<p>
Pemetaan fasilitas dan infrastruktur Kota Pontianak untuk membantu visualisasi lokasi serta pengelolaan data spasial.
</p>
<div class="tags" aria-label="Cakupan data">
<span class="tag">SPBU</span>
<span class="tag">Jalan</span>
<span class="tag">Kavling</span>
</div>
<a class="project-link" href="infrastruktur/">
Buka Project Infrastruktur
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M13 6l6 6-6 6"/>
</svg>
</a>
</article>
<article class="project-card blue">
<div class="card-top">
<div class="project-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M19 8v6M16 11h6"/>
</svg>
</div>
<span class="project-number">PROJECT 02</span>
</div>
<h3>WebGIS Kemiskinan</h3>
<p>
Pemetaan kemiskinan berbasis partisipasi rumah ibadah untuk mendukung pendataan rumah, bantuan, dan analisis sosial.
</p>
<div class="tags" aria-label="Cakupan data">
<span class="tag">Data Rumah</span>
<span class="tag">Rumah Ibadah</span>
<span class="tag">Bantuan</span>
</div>
<a class="project-link" href="kemiskinan/">
Buka Project Kemiskinan
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M13 6l6 6-6 6"/>
</svg>
</a>
</article>
</div>
</section>
</main>
</body>
</html>
File diff suppressed because one or more lines are too long
+10
View File
@@ -0,0 +1,10 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_GET['id']);
$conn->query("DELETE FROM tb_jalan WHERE id='$id'");
?>
+9
View File
@@ -0,0 +1,9 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_GET['id']);
$conn->query("DELETE FROM tb_kavling WHERE id='$id'");
?>
+10
View File
@@ -0,0 +1,10 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_GET['id']);
$conn->query("DELETE FROM tb_spbu WHERE id='$id'");
?>
File diff suppressed because it is too large Load Diff
+62
View File
@@ -0,0 +1,62 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
$dbname = "db_infrastruktur";
// Auto-create database if not exists
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die(json_encode(['error' => 'Koneksi MySQL gagal: ' . $conn->connect_error]));
}
// Create database if not exist
$conn->query("CREATE DATABASE IF NOT EXISTS `$dbname`");
$conn->select_db($dbname);
// Auto-create tables if not exist
$conn->query("CREATE TABLE IF NOT EXISTS tb_admin (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'infrastruktur'
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_spbu (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_spbu VARCHAR(150) NOT NULL,
no_wa VARCHAR(20) DEFAULT NULL,
buka_24jam ENUM('Ya','Tidak') DEFAULT 'Tidak',
latitude DECIMAL(11,8) NOT NULL,
longitude DECIMAL(11,8) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_jalan (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(200) NOT NULL,
status_jalan ENUM('Nasional','Provinsi','Kabupaten') NOT NULL,
panjang_jalan VARCHAR(50) DEFAULT NULL,
geojson LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_kavling (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_kavling VARCHAR(200) NOT NULL,
status_kepemilikan ENUM('SHM','HGB','HGU','HP') NOT NULL,
luas_tanah VARCHAR(50) DEFAULT NULL,
geojson LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)");
// Insert default admin if not exist
$check = $conn->query("SELECT id FROM tb_admin WHERE username='admin'");
if ($check && $check->num_rows == 0) {
$pw = password_hash("password", PASSWORD_DEFAULT);
$conn->query("INSERT INTO tb_admin (username, password, role) VALUES ('admin', '$pw', 'infrastruktur')");
}
?>
+12
View File
@@ -0,0 +1,12 @@
<?php
include "koneksi.php";
$data = [];
$q = $conn->query("SELECT * FROM tb_jalan");
while($row = $q->fetch_assoc()){
$data[] = $row;
}
echo json_encode($data);
?>
+12
View File
@@ -0,0 +1,12 @@
<?php
include "koneksi.php";
$data = [];
$q = $conn->query("SELECT * FROM tb_kavling");
while($row = $q->fetch_assoc()){
$data[] = $row;
}
echo json_encode($data);
?>
+12
View File
@@ -0,0 +1,12 @@
<?php
include "koneksi.php";
$data = [];
$q = $conn->query("SELECT * FROM tb_spbu");
while($row = $q->fetch_assoc()){
$data[] = $row;
}
echo json_encode($data);
?>
+310
View File
@@ -0,0 +1,310 @@
<?php
session_start();
if(isset($_SESSION['username'])){
header("Location: index.php");
exit;
}
include "koneksi.php";
$error = false;
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$username = $conn->real_escape_string($_POST['username']);
$password = $_POST['password'];
$sql = "SELECT * FROM tb_admin WHERE username='$username'";
$result = $conn->query($sql);
if($result && $result->num_rows > 0){
$row = $result->fetch_assoc();
if(password_verify($password, $row['password'])){
$_SESSION['username'] = $username;
$_SESSION['role'] = $row['role'];
header("Location: index.php");
exit;
} else {
$error = true;
}
} else {
$error = true;
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Login — WebGIS Infrastruktur</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--primary: #ea580c;
--primary-hover: #c2410c;
--primary-light: #fff7ed;
--radius: 14px;
}
body {
font-family: 'Plus Jakarta Sans', sans-serif;
min-height: 100vh;
background: linear-gradient(135deg, #1c1917 0%, #292524 40%, #1a1207 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow: hidden;
}
/* Decorative background blobs */
body::before {
content: '';
position: absolute;
top: -200px;
right: -200px;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(234,88,12,0.15) 0%, transparent 70%);
border-radius: 50%;
pointer-events: none;
}
body::after {
content: '';
position: absolute;
bottom: -200px;
left: -200px;
width: 500px;
height: 500px;
background: radial-gradient(circle, rgba(234,88,12,0.1) 0%, transparent 70%);
border-radius: 50%;
pointer-events: none;
}
.login-wrapper {
width: 100%;
max-width: 420px;
position: relative;
z-index: 1;
}
/* Brand header */
.brand-header {
text-align: center;
margin-bottom: 24px;
}
.brand-icon {
width: 72px;
height: 72px;
background: linear-gradient(135deg, #ea580c, #f97316);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
margin: 0 auto 16px;
box-shadow: 0 8px 32px rgba(234,88,12,0.4);
}
.brand-title {
font-size: 24px;
font-weight: 800;
color: #fff;
margin-bottom: 4px;
}
.brand-sub {
font-size: 13px;
color: rgba(255,255,255,0.5);
}
/* Card */
.login-card {
background: rgba(255,255,255,0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255,255,255,0.1);
border-radius: var(--radius);
padding: 32px;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.card-title {
font-size: 16px;
font-weight: 700;
color: #fff;
margin-bottom: 4px;
}
.card-sub {
font-size: 13px;
color: rgba(255,255,255,0.5);
margin-bottom: 24px;
}
/* Error */
.error-box {
background: rgba(239,68,68,0.15);
border: 1px solid rgba(239,68,68,0.3);
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: #fca5a5;
font-weight: 500;
}
/* Form */
.form-group {
margin-bottom: 16px;
}
label {
display: block;
font-size: 12px;
font-weight: 600;
color: rgba(255,255,255,0.7);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 6px;
}
input[type="text"], input[type="password"] {
width: 100%;
background: rgba(255,255,255,0.07);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 8px;
padding: 12px 14px;
font-size: 14px;
font-family: 'Plus Jakarta Sans', sans-serif;
color: #fff;
outline: none;
transition: all 0.2s;
}
input[type="text"]:focus, input[type="password"]:focus {
border-color: var(--primary);
background: rgba(234,88,12,0.08);
box-shadow: 0 0 0 3px rgba(234,88,12,0.2);
}
input::placeholder { color: rgba(255,255,255,0.3); }
.btn-login {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #ea580c, #f97316);
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 700;
font-family: 'Plus Jakarta Sans', sans-serif;
color: #fff;
cursor: pointer;
margin-top: 8px;
transition: all 0.2s;
box-shadow: 0 4px 20px rgba(234,88,12,0.4);
}
.btn-login:hover {
transform: translateY(-1px);
box-shadow: 0 6px 28px rgba(234,88,12,0.55);
}
.btn-login:active { transform: translateY(0); }
/* Info chips at bottom */
.info-chips {
display: flex;
gap: 8px;
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
}
.chip {
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
flex: 1;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 20px;
padding: 5px 10px;
font-size: 11px;
color: rgba(255,255,255,0.5);
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: #f97316; }
/* Footer */
.footer-link {
text-align: center;
margin-top: 20px;
font-size: 12.5px;
color: rgba(255,255,255,0.35);
}
.footer-link a {
color: rgba(234,88,12,0.8);
text-decoration: none;
font-weight: 600;
transition: color 0.15s;
}
.footer-link a:hover { color: #f97316; }
</style>
</head>
<body>
<div class="login-wrapper">
<div class="brand-header">
<div class="brand-icon">🏗️</div>
<div class="brand-title">WebGIS Infrastruktur</div>
<div class="brand-sub">Sistem Informasi Geografis — SPBU, Jalan & Kavling</div>
</div>
<div class="login-card">
<div class="card-title">Masuk ke Sistem</div>
<div class="card-sub">Gunakan akun Admin Infrastruktur untuk mengakses peta</div>
<?php if($error): ?>
<div class="error-box">
⚠️ Username atau password salah. Silakan coba lagi.
</div>
<?php endif; ?>
<form method="POST" action="login.php">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" placeholder="Masukkan username" required autofocus>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" placeholder="Masukkan password" required>
</div>
<button type="submit" class="btn-login">🔑 Masuk ke Sistem Infrastruktur</button>
</form>
<div class="info-chips">
<div class="chip"><span class="dot"></span> SPBU</div>
<div class="chip"><span class="dot"></span> Jalan</div>
<div class="chip"><span class="dot"></span> Kavling</div>
</div>
</div>
<div class="footer-link">
<a href="index.php">← Kembali ke Peta Infrastruktur</a>
</div>
</div>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
<?php
session_start();
session_destroy();
header("Location: index.php");
exit();
?>
+96
View File
@@ -0,0 +1,96 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
// Koneksi tanpa DB dulu untuk buat DB jika belum ada
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die("Koneksi gagal: " . $conn->connect_error);
}
// 1. Buat Database
$sql_db = "CREATE DATABASE IF NOT EXISTS db_infrastruktur";
if ($conn->query($sql_db) === TRUE) {
echo "Database db_infrastruktur siap.<br>";
} else {
echo "Error membuat database: " . $conn->error . "<br>";
}
// Gunakan database tersebut
$conn->select_db("db_infrastruktur");
// 2. Buat Tabel tb_admin
$sql_admin = "CREATE TABLE IF NOT EXISTS tb_admin (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'infrastruktur'
)";
if ($conn->query($sql_admin) === TRUE) {
echo "Tabel tb_admin siap.<br>";
} else {
echo "Error membuat tb_admin: " . $conn->error . "<br>";
}
// Insert admin infrastruktur if not exist
$check_admin = $conn->query("SELECT id FROM tb_admin WHERE username='admin'");
if ($check_admin->num_rows == 0) {
// Password "password"
$pw = password_hash("password", PASSWORD_DEFAULT);
$conn->query("INSERT INTO tb_admin (username, password, role) VALUES ('admin', '$pw', 'infrastruktur')");
echo "Akun 'admin' ditambahkan.<br>";
}
// 3. Buat Tabel tb_spbu
$sql_spbu = "CREATE TABLE IF NOT EXISTS tb_spbu (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_spbu VARCHAR(150) NOT NULL,
no_wa VARCHAR(20) DEFAULT NULL,
buka_24jam ENUM('Ya','Tidak') DEFAULT 'Tidak',
latitude DECIMAL(11,8) NOT NULL,
longitude DECIMAL(11,8) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)";
if ($conn->query($sql_spbu) === TRUE) {
echo "Tabel tb_spbu siap.<br>";
} else {
echo "Error membuat tb_spbu: " . $conn->error . "<br>";
}
// 4. Buat Tabel tb_jalan
$sql_jalan = "CREATE TABLE IF NOT EXISTS tb_jalan (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_jalan VARCHAR(200) NOT NULL,
status_jalan ENUM('Nasional','Provinsi','Kabupaten') NOT NULL,
panjang_jalan VARCHAR(50) DEFAULT NULL,
geojson LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)";
if ($conn->query($sql_jalan) === TRUE) {
echo "Tabel tb_jalan siap.<br>";
} else {
echo "Error membuat tb_jalan: " . $conn->error . "<br>";
}
// 5. Buat Tabel tb_kavling
$sql_kavling = "CREATE TABLE IF NOT EXISTS tb_kavling (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama_kavling VARCHAR(200) NOT NULL,
status_kepemilikan ENUM('SHM','HGB','HGU','HP') NOT NULL,
luas_tanah VARCHAR(50) DEFAULT NULL,
geojson LONGTEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)";
if ($conn->query($sql_kavling) === TRUE) {
echo "Tabel tb_kavling siap.<br>";
} else {
echo "Error membuat tb_kavling: " . $conn->error . "<br>";
}
echo "<br><h3>Migrasi Selesai!</h3>";
echo "<a href='index.php'>Kembali ke Halaman Utama</a>";
?>
+21
View File
@@ -0,0 +1,21 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$nama = $conn->real_escape_string($_POST['nama']);
$status = $conn->real_escape_string($_POST['status']);
$panjang = $conn->real_escape_string($_POST['panjang']);
$geojson = $conn->real_escape_string($_POST['geojson']);
$sql = "INSERT INTO tb_jalan (nama_jalan,status_jalan,panjang_jalan,geojson)
VALUES ('$nama','$status','$panjang','$geojson')";
if($conn->query($sql)){
echo "success|".$conn->insert_id;
}else{
echo "error";
}
?>
+21
View File
@@ -0,0 +1,21 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$nama = $conn->real_escape_string($_POST['nama']);
$status = $conn->real_escape_string($_POST['status']);
$luas = $conn->real_escape_string($_POST['luas']);
$geojson = $conn->real_escape_string($_POST['geojson']);
$sql = "INSERT INTO tb_kavling (nama_kavling,status_kepemilikan,luas_tanah,geojson)
VALUES ('$nama','$status','$luas','$geojson')";
if($conn->query($sql)){
echo "success|".$conn->insert_id;
}else{
echo "error";
}
?>
+22
View File
@@ -0,0 +1,22 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$nama = $conn->real_escape_string($_POST['nama']);
$wa = $conn->real_escape_string($_POST['wa']);
$buka = $conn->real_escape_string($_POST['buka']);
$lat = doubleval($_POST['lat']);
$lng = doubleval($_POST['lng']);
$sql = "INSERT INTO tb_spbu (nama_spbu,no_wa,buka_24jam,latitude,longitude)
VALUES ('$nama','$wa','$buka','$lat','$lng')";
if($conn->query($sql)){
echo "success|".$conn->insert_id;
}else{
echo "error";
}
?>
+26
View File
@@ -0,0 +1,26 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_POST['id']);
$nama = $conn->real_escape_string($_POST['nama']);
$status = $conn->real_escape_string($_POST['status']);
$panjang = $conn->real_escape_string($_POST['panjang']);
$geojson = $conn->real_escape_string($_POST['geojson']);
$sql = "UPDATE tb_jalan SET
nama_jalan = '$nama',
status_jalan = '$status',
panjang_jalan = '$panjang',
geojson = '$geojson'
WHERE id = '$id'";
if($conn->query($sql)){
echo "success";
}else{
echo "error";
}
?>
+26
View File
@@ -0,0 +1,26 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_POST['id']);
$nama = $conn->real_escape_string($_POST['nama']);
$status = $conn->real_escape_string($_POST['status']);
$luas = $conn->real_escape_string($_POST['luas']);
$geojson = $conn->real_escape_string($_POST['geojson']);
$sql = "UPDATE tb_kavling SET
nama_kavling = '$nama',
status_kepemilikan = '$status',
luas_tanah = '$luas',
geojson = '$geojson'
WHERE id = '$id'";
if($conn->query($sql)){
echo "success";
}else{
echo "error";
}
?>
+13
View File
@@ -0,0 +1,13 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'infrastruktur') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_POST['id']);
$lat = doubleval($_POST['lat']);
$lng = doubleval($_POST['lng']);
$conn->query("UPDATE tb_spbu SET latitude='$lat', longitude='$lng' WHERE id='$id'");
?>
File diff suppressed because one or more lines are too long
+11
View File
@@ -0,0 +1,11 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_GET['id']);
$id = $conn->real_escape_string($id);
$conn->query("DELETE FROM tb_rumah WHERE id = '$id'");
?>
+10
View File
@@ -0,0 +1,10 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = intval($_GET['id']);
$conn->query("DELETE FROM tb_tempat_ibadah WHERE id='$id'");
?>
+58
View File
@@ -0,0 +1,58 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') {
echo json_encode(['status'=>'error','message'=>'Tidak diizinkan']);
exit;
}
include "koneksi.php";
if (!isset($_FILES['csvfile']) || $_FILES['csvfile']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['status'=>'error','message'=>'File tidak ditemukan atau gagal upload']);
exit;
}
$tmpPath = $_FILES['csvfile']['tmp_name'];
$handle = fopen($tmpPath, 'r');
if (!$handle) {
echo json_encode(['status'=>'error','message'=>'Gagal membaca file CSV']);
exit;
}
$inserted = 0;
$skipped = 0;
$rowNum = 0;
while (($row = fgetcsv($handle, 1000, ',')) !== false) {
$rowNum++;
if ($rowNum === 1) continue; // skip header
// Expected columns: nama, alamat, keterangan, latitude, longitude
if (count($row) < 5) { $skipped++; continue; }
$nama = $conn->real_escape_string(trim($row[0]));
$alamat = $conn->real_escape_string(trim($row[1]));
$ket = $conn->real_escape_string(trim($row[2]));
$lat = doubleval($row[3]);
$lng = doubleval($row[4]);
if (!$nama || !$lat || !$lng) { $skipped++; continue; }
$sql = "INSERT INTO tb_rumah (nama, alamat, keterangan, latitude, longitude)
VALUES ('$nama', '$alamat', '$ket', $lat, $lng)";
if ($conn->query($sql)) {
$inserted++;
} else {
$skipped++;
}
}
fclose($handle);
echo json_encode([
'status' => 'success',
'inserted' => $inserted,
'skipped' => $skipped
]);
?>
+3017
View File
File diff suppressed because it is too large Load Diff
+74
View File
@@ -0,0 +1,74 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
$dbname = "db_kemiskinan";
// Auto-create database if not exists
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die(json_encode(['error' => 'Koneksi MySQL gagal: ' . $conn->connect_error]));
}
// Create database if not exist
$conn->query("CREATE DATABASE IF NOT EXISTS `$dbname`");
$conn->select_db($dbname);
// Auto-create tables if not exist
$conn->query("CREATE TABLE IF NOT EXISTS tb_admin (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'kemiskinan'
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_tempat_ibadah (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) DEFAULT NULL,
tipe_ibadah VARCHAR(50) DEFAULT 'Masjid',
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
radius_meter INT(11) NOT NULL,
kecamatan VARCHAR(100) DEFAULT NULL,
alamat TEXT DEFAULT NULL
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_rumah (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) NOT NULL,
alamat TEXT DEFAULT NULL,
keterangan TEXT DEFAULT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
jumlah_anggota INT(11) DEFAULT 1,
penghasilan VARCHAR(60) DEFAULT NULL,
status_kepemilikan VARCHAR(50) DEFAULT NULL,
kategori_kemiskinan VARCHAR(50) DEFAULT 'Miskin',
status_bantuan VARCHAR(20) DEFAULT 'belum',
jenis_bantuan VARCHAR(200) DEFAULT NULL,
foto_rumah VARCHAR(255) DEFAULT NULL,
kecamatan VARCHAR(100) DEFAULT NULL,
tahun INT(11) DEFAULT 2026,
umur_kk INT(11) DEFAULT NULL,
pekerjaan VARCHAR(100) DEFAULT NULL,
status_rumah VARCHAR(100) DEFAULT NULL
)");
$conn->query("CREATE TABLE IF NOT EXISTS tb_bantuan_history (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
rumah_id INT(11) NOT NULL,
tanggal DATE NOT NULL,
jenis_bantuan VARCHAR(200) DEFAULT NULL,
keterangan TEXT DEFAULT NULL,
petugas VARCHAR(100) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (rumah_id) REFERENCES tb_rumah(id) ON DELETE CASCADE
)");
// Insert default admin if not exist
$check = $conn->query("SELECT id FROM tb_admin WHERE username='admin'");
if ($check && $check->num_rows == 0) {
$pw = password_hash("password", PASSWORD_DEFAULT);
$conn->query("INSERT INTO tb_admin (username, password, role) VALUES ('admin', '$pw', 'kemiskinan')");
}
?>
+10
View File
@@ -0,0 +1,10 @@
<?php
include "koneksi.php";
$rumah_id = intval($_GET['rumah_id'] ?? 0);
$sql = "SELECT * FROM tb_bantuan_history WHERE rumah_id=$rumah_id ORDER BY tanggal DESC LIMIT 20";
$result = $conn->query($sql);
$data = [];
if ($result) { while ($row = $result->fetch_assoc()) { $data[] = $row; } }
header('Content-Type: application/json');
echo json_encode($data);
?>
+12
View File
@@ -0,0 +1,12 @@
<?php
include "koneksi.php";
$data = [];
$q = $conn->query("SELECT * FROM tb_rumah");
if ($q) {
while($row = $q->fetch_assoc()){
$data[] = $row;
}
}
header('Content-Type: application/json');
echo json_encode($data);
?>
+12
View File
@@ -0,0 +1,12 @@
<?php
include "koneksi.php";
$data = [];
$q = $conn->query("SELECT * FROM tb_tempat_ibadah");
if ($q) {
while($row = $q->fetch_assoc()){
$data[] = $row;
}
}
header('Content-Type: application/json');
echo json_encode($data);
?>
+308
View File
@@ -0,0 +1,308 @@
<?php
session_start();
if(isset($_SESSION['username'])){
header("Location: index.php");
exit;
}
include "koneksi.php";
$error = false;
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$username = $conn->real_escape_string($_POST['username']);
$password = $_POST['password'];
$sql = "SELECT * FROM tb_admin WHERE username='$username'";
$result = $conn->query($sql);
if($result && $result->num_rows > 0){
$row = $result->fetch_assoc();
if(password_verify($password, $row['password'])){
$_SESSION['username'] = $username;
$_SESSION['role'] = $row['role'];
header("Location: index.php");
exit;
} else {
$error = true;
}
} else {
$error = true;
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Login — WebGIS Kemiskinan</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--primary: #0891b2;
--primary-hover: #0e7490;
--primary-light: #ecfeff;
--radius: 14px;
}
body {
font-family: 'Plus Jakarta Sans', sans-serif;
min-height: 100vh;
background: linear-gradient(135deg, #0c1a2e 0%, #0f2744 40%, #071525 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow: hidden;
}
/* Decorative background blobs */
body::before {
content: '';
position: absolute;
top: -200px;
right: -200px;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(8,145,178,0.15) 0%, transparent 70%);
border-radius: 50%;
pointer-events: none;
}
body::after {
content: '';
position: absolute;
bottom: -200px;
left: -200px;
width: 500px;
height: 500px;
background: radial-gradient(circle, rgba(8,145,178,0.1) 0%, transparent 70%);
border-radius: 50%;
pointer-events: none;
}
.login-wrapper {
width: 100%;
max-width: 420px;
position: relative;
z-index: 1;
}
/* Brand header */
.brand-header {
text-align: center;
margin-bottom: 24px;
}
.brand-icon {
width: 72px;
height: 72px;
background: linear-gradient(135deg, #0891b2, #06b6d4);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
margin: 0 auto 16px;
box-shadow: 0 8px 32px rgba(8,145,178,0.4);
}
.brand-title {
font-size: 24px;
font-weight: 800;
color: #fff;
margin-bottom: 4px;
}
.brand-sub {
font-size: 13px;
color: rgba(255,255,255,0.5);
}
/* Card */
.login-card {
background: rgba(255,255,255,0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255,255,255,0.1);
border-radius: var(--radius);
padding: 32px;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.card-title {
font-size: 16px;
font-weight: 700;
color: #fff;
margin-bottom: 4px;
}
.card-sub {
font-size: 13px;
color: rgba(255,255,255,0.5);
margin-bottom: 24px;
}
/* Error */
.error-box {
background: rgba(239,68,68,0.15);
border: 1px solid rgba(239,68,68,0.3);
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: #fca5a5;
font-weight: 500;
}
/* Form */
.form-group {
margin-bottom: 16px;
}
label {
display: block;
font-size: 12px;
font-weight: 600;
color: rgba(255,255,255,0.7);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 6px;
}
input[type="text"], input[type="password"] {
width: 100%;
background: rgba(255,255,255,0.07);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 8px;
padding: 12px 14px;
font-size: 14px;
font-family: 'Plus Jakarta Sans', sans-serif;
color: #fff;
outline: none;
transition: all 0.2s;
}
input[type="text"]:focus, input[type="password"]:focus {
border-color: var(--primary);
background: rgba(8,145,178,0.08);
box-shadow: 0 0 0 3px rgba(8,145,178,0.2);
}
input::placeholder { color: rgba(255,255,255,0.3); }
.btn-login {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #0891b2, #06b6d4);
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 700;
font-family: 'Plus Jakarta Sans', sans-serif;
color: #fff;
cursor: pointer;
margin-top: 8px;
transition: all 0.2s;
box-shadow: 0 4px 20px rgba(8,145,178,0.4);
}
.btn-login:hover {
transform: translateY(-1px);
box-shadow: 0 6px 28px rgba(8,145,178,0.55);
}
.btn-login:active { transform: translateY(0); }
/* Info chips at bottom */
.info-chips {
display: flex;
gap: 8px;
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
}
.chip {
display: flex;
align-items: center;
gap: 5px;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 20px;
padding: 5px 10px;
font-size: 11px;
color: rgba(255,255,255,0.5);
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: #22d3ee; }
/* Footer */
.footer-link {
text-align: center;
margin-top: 20px;
font-size: 12.5px;
color: rgba(255,255,255,0.35);
}
.footer-link a {
color: rgba(8,145,178,0.9);
text-decoration: none;
font-weight: 600;
transition: color 0.15s;
}
.footer-link a:hover { color: #06b6d4; }
</style>
</head>
<body>
<div class="login-wrapper">
<div class="brand-header">
<div class="brand-icon">🏠</div>
<div class="brand-title">WebGIS Kemiskinan</div>
<div class="brand-sub">Pemetaan Kemiskinan Berbasis Partisipasi Rumah Ibadah</div>
</div>
<div class="login-card">
<div class="card-title">Masuk ke Sistem</div>
<div class="card-sub">Gunakan akun Admin Kemiskinan untuk mengakses peta</div>
<?php if($error): ?>
<div class="error-box">
⚠️ Username atau password salah. Silakan coba lagi.
</div>
<?php endif; ?>
<form method="POST" action="login.php">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" placeholder="Masukkan username" required autofocus>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" placeholder="Masukkan password" required>
</div>
<button type="submit" class="btn-login">🔑 Masuk ke Sistem Kemiskinan</button>
</form>
<div class="info-chips">
<div class="chip"><span class="dot"></span> Tempat Ibadah</div>
<div class="chip"><span class="dot"></span> Rumah Warga</div>
<div class="chip"><span class="dot"></span> Radius Bantuan</div>
</div>
</div>
<div class="footer-link">
<a href="index.php">← Kembali ke Peta Kemiskinan</a>
</div>
</div>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
<?php
session_start();
session_destroy();
header("Location: index.php");
exit();
?>
+108
View File
@@ -0,0 +1,108 @@
<?php
$host = "localhost";
$user = "root";
$pass = "";
// Koneksi tanpa DB dulu untuk buat DB jika belum ada
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die("Koneksi gagal: " . $conn->connect_error);
}
// 1. Buat Database
$sql_db = "CREATE DATABASE IF NOT EXISTS db_kemiskinan";
if ($conn->query($sql_db) === TRUE) {
echo "Database db_kemiskinan siap.<br>";
} else {
echo "Error membuat database: " . $conn->error . "<br>";
}
// Gunakan database tersebut
$conn->select_db("db_kemiskinan");
// 2. Buat Tabel tb_admin
$sql_admin = "CREATE TABLE IF NOT EXISTS tb_admin (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'kemiskinan'
)";
if ($conn->query($sql_admin) === TRUE) {
echo "Tabel tb_admin siap.<br>";
} else {
echo "Error membuat tb_admin: " . $conn->error . "<br>";
}
// Insert admin kemiskinan if not exist
$check_admin = $conn->query("SELECT id FROM tb_admin WHERE username='admin'");
if ($check_admin->num_rows == 0) {
// Password "password"
$pw = password_hash("password", PASSWORD_DEFAULT);
$conn->query("INSERT INTO tb_admin (username, password, role) VALUES ('admin', '$pw', 'kemiskinan')");
echo "Akun 'admin' ditambahkan.<br>";
}
// 3. Buat Tabel tb_tempat_ibadah
$sql_ibadah = "CREATE TABLE IF NOT EXISTS tb_tempat_ibadah (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) DEFAULT NULL,
tipe_ibadah VARCHAR(50) DEFAULT 'Masjid',
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
radius_meter INT(11) NOT NULL,
kecamatan VARCHAR(100) DEFAULT NULL,
alamat TEXT DEFAULT NULL
)";
if ($conn->query($sql_ibadah) === TRUE) {
echo "Tabel tb_tempat_ibadah siap.<br>";
} else {
echo "Error membuat tb_tempat_ibadah: " . $conn->error . "<br>";
}
// 4. Buat Tabel tb_rumah
$sql_rumah = "CREATE TABLE IF NOT EXISTS tb_rumah (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(255) NOT NULL,
alamat TEXT DEFAULT NULL,
keterangan TEXT DEFAULT NULL,
latitude DOUBLE NOT NULL,
longitude DOUBLE NOT NULL,
jumlah_anggota INT(11) DEFAULT 1,
penghasilan VARCHAR(60) DEFAULT NULL,
status_kepemilikan VARCHAR(50) DEFAULT NULL,
kategori_kemiskinan VARCHAR(50) DEFAULT 'Miskin',
status_bantuan VARCHAR(20) DEFAULT 'belum',
jenis_bantuan VARCHAR(200) DEFAULT NULL,
foto_rumah VARCHAR(255) DEFAULT NULL,
kecamatan VARCHAR(100) DEFAULT NULL,
tahun INT(11) DEFAULT 2026,
umur_kk INT(11) DEFAULT NULL,
pekerjaan VARCHAR(100) DEFAULT NULL,
status_rumah VARCHAR(100) DEFAULT NULL
)";
if ($conn->query($sql_rumah) === TRUE) {
echo "Tabel tb_rumah siap.<br>";
} else {
echo "Error membuat tb_rumah: " . $conn->error . "<br>";
}
// 5. Buat Tabel tb_bantuan_history
$sql_bantuan = "CREATE TABLE IF NOT EXISTS tb_bantuan_history (
id INT(11) AUTO_INCREMENT PRIMARY KEY,
rumah_id INT(11) NOT NULL,
tanggal DATE NOT NULL,
jenis_bantuan VARCHAR(200) DEFAULT NULL,
keterangan TEXT DEFAULT NULL,
petugas VARCHAR(100) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (rumah_id) REFERENCES tb_rumah(id) ON DELETE CASCADE
)";
if ($conn->query($sql_bantuan) === TRUE) {
echo "Tabel tb_bantuan_history siap.<br>";
} else {
echo "Error membuat tb_bantuan_history: " . $conn->error . "<br>";
}
echo "<br><h3>Migrasi Selesai!</h3>";
echo "<a href='index.php'>Kembali ke Halaman Utama</a>";
?>
+24
View File
@@ -0,0 +1,24 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$rumah_id = isset($_POST['rumah_id']) ? intval($_POST['rumah_id']) : 0;
$tanggal = isset($_POST['tanggal']) ? $conn->real_escape_string($_POST['tanggal']) : date('Y-m-d');
$jenis = isset($_POST['jenis']) ? $conn->real_escape_string($_POST['jenis']) : '';
$keterangan = isset($_POST['keterangan']) ? $conn->real_escape_string($_POST['keterangan']) : '';
$petugas = isset($_POST['petugas']) ? $conn->real_escape_string($_POST['petugas']) : '';
if ($rumah_id <= 0) { echo "error|rumah_id kosong"; exit; }
$sql = "INSERT INTO tb_bantuan_history (rumah_id, tanggal, jenis_bantuan, keterangan, petugas)
VALUES ($rumah_id, '$tanggal', '$jenis', '$keterangan', '$petugas')";
if ($conn->query($sql)) {
echo "success|" . $conn->insert_id;
} else {
echo "error|" . $conn->error;
}
?>
+29
View File
@@ -0,0 +1,29 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$nama = $conn->real_escape_string($_POST['nama']);
$alamat = $conn->real_escape_string($_POST['alamat']);
$ket = $conn->real_escape_string($_POST['keterangan']);
$lat = doubleval($_POST['lat']);
$lng = doubleval($_POST['lng']);
$umur_kk = isset($_POST['umur_kk']) ? intval($_POST['umur_kk']) : null;
$pekerjaan = $conn->real_escape_string(isset($_POST['pekerjaan']) ? $_POST['pekerjaan'] : '');
$penghasilan = $conn->real_escape_string(isset($_POST['penghasilan']) ? $_POST['penghasilan'] : '');
$jumlah_anggota = isset($_POST['jumlah_anggota']) ? intval($_POST['jumlah_anggota']) : 1;
$status_rumah = $conn->real_escape_string(isset($_POST['status_rumah']) ? $_POST['status_rumah'] : '');
$umur_kk_val = ($umur_kk !== null && $umur_kk >= 0) ? $umur_kk : "NULL";
$sql = "INSERT INTO tb_rumah (nama, alamat, keterangan, latitude, longitude, umur_kk, pekerjaan, penghasilan, jumlah_anggota, status_rumah)
VALUES ('$nama', '$alamat', '$ket', $lat, $lng, $umur_kk_val, '$pekerjaan', '$penghasilan', $jumlah_anggota, '$status_rumah')";
if ($conn->query($sql)) {
echo "success|" . $conn->insert_id;
} else {
echo "error";
}
?>
+41
View File
@@ -0,0 +1,41 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = isset($_POST['id']) ? $conn->real_escape_string($_POST['id']) : '';
$nama = $conn->real_escape_string($_POST['nama']);
$tipe = $conn->real_escape_string($_POST['tipe']);
$alamat = $conn->real_escape_string($_POST['alamat']);
$lat = doubleval($_POST['lat']);
$lng = doubleval($_POST['lng']);
$radius = intval($_POST['radius']);
if (!empty($id)) {
$sql = "UPDATE tb_tempat_ibadah SET
nama = '$nama',
tipe_ibadah = '$tipe',
alamat = '$alamat',
latitude = $lat,
longitude = $lng,
radius_meter = $radius
WHERE id = '$id'";
if ($conn->query($sql)) {
echo "ok|" . $id;
} else {
echo "error";
}
} else {
$sql = "INSERT INTO tb_tempat_ibadah
(nama, tipe_ibadah, alamat, latitude, longitude, radius_meter)
VALUES
('$nama', '$tipe', '$alamat', $lat, $lng, $radius)";
if ($conn->query($sql)) {
echo "ok|" . $conn->insert_id;
} else {
echo "error";
}
}
?>
+21
View File
@@ -0,0 +1,21 @@
<?php
session_start();
$role = isset($_SESSION['role']) ? $_SESSION['role'] : '';
if ($role !== 'kemiskinan') { echo "unauthorized"; exit; }
include "koneksi.php";
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$status = isset($_POST['status']) ? $conn->real_escape_string($_POST['status']) : 'belum';
$jenis_bantuan = isset($_POST['jenis_bantuan']) ? $conn->real_escape_string($_POST['jenis_bantuan']) : '';
if ($id <= 0) { echo "error|id kosong"; exit; }
$sql = "UPDATE tb_rumah SET status_bantuan='$status', jenis_bantuan='$jenis_bantuan' WHERE id=$id";
if ($conn->query($sql)) {
echo "success";
} else {
echo "error|" . $conn->error;
}
?>