Initial commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
DirectoryIndex index.php login.php
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^api/?$ api.php [L]
|
||||
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
require_once 'auth.php';
|
||||
requireApiLogin();
|
||||
// api.php — WebGIS Pemetaan Penduduk Miskin
|
||||
header("Content-Type: application/json");
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
||||
header("Access-Control-Allow-Headers: Content-Type");
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit(); }
|
||||
|
||||
// ── KONFIGURASI ──────────────────────────────────────────────
|
||||
$host = "localhost";
|
||||
$dbname = "webgis_spbu";
|
||||
$username = "root";
|
||||
$password = "";
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(["success" => false, "message" => "Koneksi gagal: " . $e->getMessage()]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$input = json_decode(file_get_contents("php://input"), true) ?? [];
|
||||
$resource = strtolower($_GET['resource'] ?? '');
|
||||
|
||||
switch ($resource) {
|
||||
case 'ibadah': handleIbadah($pdo, $method, $input); break;
|
||||
case 'miskin': handleMiskin($pdo, $method, $input); break;
|
||||
case 'bantuan': handleBantuan($pdo, $method, $input); break;
|
||||
default:
|
||||
http_response_code(404);
|
||||
echo json_encode(["success" => false, "message" => "Resource '$resource' tidak ditemukan. Gunakan: ibadah, miskin, bantuan"]);
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// RUMAH IBADAH
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
function handleIbadah($pdo, $method, $input) {
|
||||
$validKategori = ['Masjid', 'Gereja', 'Gereja Katolik', 'Pura', 'Vihara', 'Klenteng'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
$s = $pdo->query("SELECT * FROM rumah_ibadah ORDER BY kategori, nama_ibadah ASC");
|
||||
echo json_encode(["success" => true, "data" => $s->fetchAll()]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(["success" => true, "data" => [], "warning" => "Tabel belum ada: " . $e->getMessage()]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (['nama_ibadah', 'kategori', 'latitude', 'longitude', 'radius_meter'] as $f) {
|
||||
if (!isset($input[$f]) || $input[$f] === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Field '$f' wajib diisi"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!in_array($input['kategori'], $validKategori)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Kategori tidak valid. Pilih: " . implode(', ', $validKategori)]);
|
||||
return;
|
||||
}
|
||||
$s = $pdo->prepare(
|
||||
"INSERT INTO rumah_ibadah (nama_ibadah, kategori, radius_meter, keterangan, alamat, latitude, longitude)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$s->execute([
|
||||
trim($input['nama_ibadah']),
|
||||
$input['kategori'],
|
||||
(int)$input['radius_meter'],
|
||||
trim($input['keterangan'] ?? ''),
|
||||
trim($input['alamat'] ?? ''),
|
||||
(float)$input['latitude'],
|
||||
(float)$input['longitude'],
|
||||
]);
|
||||
echo json_encode(["success" => true, "message" => "Rumah ibadah disimpan", "id" => $pdo->lastInsertId()]);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if (!isset($input['id'])) {
|
||||
http_response_code(400); echo json_encode(["success" => false, "message" => "ID diperlukan"]); return;
|
||||
}
|
||||
if (!in_array($input['kategori'], $validKategori)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Kategori tidak valid"]);
|
||||
return;
|
||||
}
|
||||
$s = $pdo->prepare(
|
||||
"UPDATE rumah_ibadah SET nama_ibadah=?, kategori=?, radius_meter=?, keterangan=?, alamat=?, latitude=?, longitude=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$s->execute([
|
||||
trim($input['nama_ibadah']),
|
||||
$input['kategori'],
|
||||
(int)$input['radius_meter'],
|
||||
trim($input['keterangan'] ?? ''),
|
||||
trim($input['alamat'] ?? ''),
|
||||
(float)$input['latitude'],
|
||||
(float)$input['longitude'],
|
||||
(int)$input['id'],
|
||||
]);
|
||||
echo json_encode(["success" => true, "message" => "Rumah ibadah diperbarui"]);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? $input['id'] ?? null;
|
||||
if (!$id) { http_response_code(400); echo json_encode(["success" => false, "message" => "ID diperlukan"]); return; }
|
||||
$pdo->prepare("DELETE FROM rumah_ibadah WHERE id=?")->execute([(int)$id]);
|
||||
echo json_encode(["success" => true, "message" => "Rumah ibadah dihapus"]);
|
||||
break;
|
||||
|
||||
default:
|
||||
http_response_code(405);
|
||||
echo json_encode(["success" => false, "message" => "Method tidak diizinkan"]);
|
||||
}
|
||||
}
|
||||
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// PENDUDUK MISKIN
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
function handleMiskin($pdo, $method, $input) {
|
||||
$validKelas = ['Kelas I', 'Kelas II', 'Kelas III'];
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
// Urutkan: Kelas I dulu (prioritas tertinggi), lalu dalam jangkauan dulu
|
||||
$s = $pdo->query(
|
||||
"SELECT * FROM penduduk_miskin
|
||||
ORDER BY
|
||||
FIELD(kelas_kemiskinan, 'Kelas I', 'Kelas II', 'Kelas III'),
|
||||
nama_kk ASC"
|
||||
);
|
||||
echo json_encode(["success" => true, "data" => $s->fetchAll()]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(["success" => true, "data" => [], "warning" => "Tabel belum ada: " . $e->getMessage()]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (['nama_kk', 'latitude', 'longitude'] as $f) {
|
||||
if (!isset($input[$f]) || $input[$f] === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Field '$f' wajib diisi"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!empty($input['kelas_kemiskinan']) && !in_array($input['kelas_kemiskinan'], $validKelas)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Kelas kemiskinan tidak valid"]);
|
||||
return;
|
||||
}
|
||||
$s = $pdo->prepare(
|
||||
"INSERT INTO penduduk_miskin (nama_kk, jumlah_jiwa, kelas_kemiskinan, keterangan, alamat, dalam_jangkauan, latitude, longitude)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
$s->execute([
|
||||
trim($input['nama_kk']),
|
||||
(int)($input['jumlah_jiwa'] ?? 1),
|
||||
$input['kelas_kemiskinan'] ?? 'Kelas I',
|
||||
trim($input['keterangan'] ?? ''),
|
||||
trim($input['alamat'] ?? ''),
|
||||
(int)($input['dalam_jangkauan'] ?? 0),
|
||||
(float)$input['latitude'],
|
||||
(float)$input['longitude'],
|
||||
]);
|
||||
echo json_encode(["success" => true, "message" => "Data penduduk miskin disimpan", "id" => $pdo->lastInsertId()]);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if (!isset($input['id'])) {
|
||||
http_response_code(400); echo json_encode(["success" => false, "message" => "ID diperlukan"]); return;
|
||||
}
|
||||
$s = $pdo->prepare(
|
||||
"UPDATE penduduk_miskin SET nama_kk=?, jumlah_jiwa=?, kelas_kemiskinan=?, keterangan=?, alamat=?, dalam_jangkauan=?, latitude=?, longitude=?
|
||||
WHERE id=?"
|
||||
);
|
||||
$s->execute([
|
||||
trim($input['nama_kk']),
|
||||
(int)($input['jumlah_jiwa'] ?? 1),
|
||||
$input['kelas_kemiskinan'] ?? 'Kelas I',
|
||||
trim($input['keterangan'] ?? ''),
|
||||
trim($input['alamat'] ?? ''),
|
||||
(int)($input['dalam_jangkauan'] ?? 0),
|
||||
(float)$input['latitude'],
|
||||
(float)$input['longitude'],
|
||||
(int)$input['id'],
|
||||
]);
|
||||
echo json_encode(["success" => true, "message" => "Data penduduk miskin diperbarui"]);
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
if (isOperator()) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Operator tidak punya akses ini"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? $input['id'] ?? null;
|
||||
if (!$id) { http_response_code(400); echo json_encode(["success" => false, "message" => "ID diperlukan"]); return; }
|
||||
$pdo->prepare("DELETE FROM penduduk_miskin WHERE id=?")->execute([(int)$id]);
|
||||
echo json_encode(["success" => true, "message" => "Data penduduk miskin dihapus"]);
|
||||
break;
|
||||
|
||||
default:
|
||||
http_response_code(405);
|
||||
echo json_encode(["success" => false, "message" => "Method tidak diizinkan"]);
|
||||
}
|
||||
}
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
// RIWAYAT BANTUAN
|
||||
// ════════════════════════════════════════════════════════════════
|
||||
function handleBantuan($pdo, $method, $input) {
|
||||
switch ($method) {
|
||||
|
||||
// GET?resource=bantuan&id_miskin=N — ambil riwayat bantuan 1 KK
|
||||
case 'GET':
|
||||
$idMiskin = (int)($_GET['id_miskin'] ?? 0);
|
||||
if (!$idMiskin) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success"=>false,"message"=>"Parameter id_miskin diperlukan"]);
|
||||
return;
|
||||
}
|
||||
$s = $pdo->prepare(
|
||||
"SELECT *, DATEDIFF(CURDATE(), tanggal) AS hari_lalu
|
||||
FROM riwayat_bantuan
|
||||
WHERE id_miskin = ?
|
||||
ORDER BY tanggal DESC"
|
||||
);
|
||||
$s->execute([$idMiskin]);
|
||||
$rows = $s->fetchAll();
|
||||
|
||||
// Hitung apakah sudah dapat bantuan hari ini
|
||||
$sudahHariIni = false;
|
||||
if (!empty($rows) && $rows[0]['hari_lalu'] == 0) {
|
||||
$sudahHariIni = true;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
"success" => true,
|
||||
"data" => $rows,
|
||||
"sudah_hari_ini" => $sudahHariIni,
|
||||
]);
|
||||
break;
|
||||
|
||||
// POST — tambah riwayat bantuan baru
|
||||
case 'POST':
|
||||
if (isOperator()) {
|
||||
$idMiskin = (int)($input['id_miskin'] ?? 0);
|
||||
$idIbadah = myIbadahId();
|
||||
|
||||
$sMiskin = $pdo->prepare(
|
||||
"SELECT latitude, longitude
|
||||
FROM penduduk_miskin
|
||||
WHERE id=?"
|
||||
);
|
||||
$sMiskin->execute([$idMiskin]);
|
||||
$mk = $sMiskin->fetch();
|
||||
|
||||
$sIbadah = $pdo->prepare(
|
||||
"SELECT latitude, longitude, radius_meter
|
||||
FROM rumah_ibadah
|
||||
WHERE id=?"
|
||||
);
|
||||
$sIbadah->execute([$idIbadah]);
|
||||
$ib = $sIbadah->fetch();
|
||||
|
||||
if (!$mk || !$ib) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Akses ditolak"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$jarak = haversine(
|
||||
$mk['latitude'],
|
||||
$mk['longitude'],
|
||||
$ib['latitude'],
|
||||
$ib['longitude']
|
||||
);
|
||||
|
||||
if ($jarak > $ib['radius_meter']) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "KK ini di luar radius ibadah Anda"
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['id_miskin','jenis_bantuan'] as $f) {
|
||||
if (empty($input[$f])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success"=>false,"message"=>"Field '$f' wajib diisi"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$tanggal = $input['tanggal'] ?? date('Y-m-d'); // default hari ini
|
||||
$s = $pdo->prepare(
|
||||
"INSERT INTO riwayat_bantuan (id_miskin, tanggal, jenis_bantuan, keterangan, diberikan_oleh)
|
||||
VALUES (?, ?, ?, ?, ?)"
|
||||
);
|
||||
$s->execute([
|
||||
(int)$input['id_miskin'],
|
||||
$tanggal,
|
||||
trim($input['jenis_bantuan']),
|
||||
trim($input['keterangan'] ?? ''),
|
||||
trim($input['diberikan_oleh'] ?? ''),
|
||||
]);
|
||||
echo json_encode(["success"=>true,"message"=>"Riwayat bantuan disimpan","id"=>$pdo->lastInsertId()]);
|
||||
break;
|
||||
|
||||
// DELETE?id=N — hapus satu riwayat bantuan
|
||||
case 'DELETE':
|
||||
$id = $_GET['id'] ?? $input['id'] ?? null;
|
||||
if (!$id) { http_response_code(400); echo json_encode(["success"=>false,"message"=>"ID diperlukan"]); return; }
|
||||
$pdo->prepare("DELETE FROM riwayat_bantuan WHERE id=?")->execute([(int)$id]);
|
||||
echo json_encode(["success"=>true,"message"=>"Riwayat dihapus"]);
|
||||
break;
|
||||
|
||||
default:
|
||||
http_response_code(405);
|
||||
echo json_encode(["success"=>false,"message"=>"Method tidak diizinkan"]);
|
||||
}
|
||||
}
|
||||
function haversine($lat1, $lon1, $lat2, $lon2)
|
||||
{
|
||||
$R = 6371000; // meter
|
||||
|
||||
$dLat = deg2rad($lat2 - $lat1);
|
||||
$dLon = deg2rad($lon2 - $lon1);
|
||||
|
||||
$a =
|
||||
sin($dLat / 2) * sin($dLat / 2) +
|
||||
cos(deg2rad($lat1)) *
|
||||
cos(deg2rad($lat2)) *
|
||||
sin($dLon / 2) *
|
||||
sin($dLon / 2);
|
||||
|
||||
return $R * 2 * atan2(
|
||||
sqrt($a),
|
||||
sqrt(1 - $a)
|
||||
);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
function isLoggedIn() {
|
||||
return !empty($_SESSION['user_id']);
|
||||
}
|
||||
|
||||
function requireLogin() {
|
||||
if (!isLoggedIn()) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function requireApiLogin() {
|
||||
if (!isLoggedIn()) {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(401);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Belum login',
|
||||
'redirect' => 'login.php'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function isAdmin() { return ($_SESSION['role'] ?? '') === 'admin'; }
|
||||
function isOperator() { return ($_SESSION['role'] ?? '') === 'operator'; }
|
||||
function myIbadahId() { return (int)($_SESSION['id_ibadah'] ?? 0); }
|
||||
function myUserId() { return (int)($_SESSION['user_id'] ?? 0); }
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
session_start();
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$pdo = new PDO("mysql:host=localhost;dbname=webgis_spbu;charset=utf8mb4", "root", "");
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$username = trim($_POST['username'] ?? '');
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
$s = $pdo->prepare("SELECT * FROM users WHERE username=? AND aktif=1");
|
||||
$s->execute([$username]);
|
||||
$user = $s->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($user && password_verify($password, $user['password_hash'])) {
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['username'] = $user['username'];
|
||||
$_SESSION['role'] = $user['role'];
|
||||
$_SESSION['id_ibadah'] = $user['id_ibadah'];
|
||||
$_SESSION['nama'] = $user['nama_lengkap'];
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
} else {
|
||||
$error = 'Username atau password salah';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Login — WebGIS Kemiskinan</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600;700&display=swap" rel="stylesheet"/>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: 'Plus Jakarta Sans', sans-serif;
|
||||
background: #0d1117;
|
||||
color: #e6edf3;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
background: #161b22;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 16px;
|
||||
padding: 36px 32px;
|
||||
width: 360px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,.6);
|
||||
}
|
||||
.logo {
|
||||
width: 48px; height: 48px;
|
||||
background: linear-gradient(135deg,#10b981,#059669);
|
||||
border-radius: 12px;
|
||||
display: grid; place-items: center;
|
||||
font-size: 22px;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
h1 { text-align: center; font-size: 18px; font-weight: 700; margin-bottom: 4px; }
|
||||
.sub { text-align: center; font-size: 12px; color: #8b949e; margin-bottom: 28px; }
|
||||
label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: #8b949e; margin-bottom: 6px; }
|
||||
input {
|
||||
width: 100%; background: #21262d; border: 1px solid #30363d;
|
||||
border-radius: 8px; padding: 10px 13px; color: #e6edf3;
|
||||
font-size: 14px; font-family: inherit; outline: none;
|
||||
transition: border-color .2s; margin-bottom: 16px;
|
||||
}
|
||||
input:focus { border-color: #10b981; }
|
||||
button {
|
||||
width: 100%; background: #10b981; color: #fff;
|
||||
border: none; border-radius: 8px; padding: 11px;
|
||||
font-size: 14px; font-weight: 700; cursor: pointer;
|
||||
font-family: inherit; transition: background .2s;
|
||||
}
|
||||
button:hover { background: #0ea371; }
|
||||
.error {
|
||||
background: rgba(239,68,68,.12);
|
||||
border: 1px solid rgba(239,68,68,.3);
|
||||
border-radius: 8px; padding: 10px 13px;
|
||||
color: #ef4444; font-size: 13px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="logo">🗺</div>
|
||||
<h1>WebGIS Pemetaan Kemiskinan</h1>
|
||||
<p class="sub">Berbasis Partisipasi Rumah Ibadah</p>
|
||||
|
||||
<?php if (!empty($error)): ?>
|
||||
<div class="error">⚠ <?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" placeholder="Masukkan username" required autofocus/>
|
||||
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" placeholder="Masukkan password" required/>
|
||||
|
||||
<button type="submit">Masuk</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
// upload.php — Handler upload foto rumah & kartu keluarga
|
||||
header("Content-Type: application/json");
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Methods: POST, OPTIONS");
|
||||
header("Access-Control-Allow-Headers: Content-Type");
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit(); }
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(["success" => false, "message" => "Hanya menerima POST"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
// ── KONFIGURASI ──────────────────────────────────────────────
|
||||
$uploadDir = __DIR__ . '/uploads/';
|
||||
$uploadUrl = 'http://localhost/web_gis/01/uploads/';
|
||||
$maxSize = 5 * 1024 * 1024; // 5 MB
|
||||
$allowedExt = ['jpg', 'jpeg', 'png', 'webp'];
|
||||
|
||||
// Buat folder uploads jika belum ada
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
// ── VALIDASI ─────────────────────────────────────────────────
|
||||
$type = $_POST['type'] ?? ''; // 'rumah' atau 'kk'
|
||||
if (!in_array($type, ['rumah', 'kk'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Parameter 'type' harus 'rumah' atau 'kk'"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$idMiskin = (int)($_POST['id_miskin'] ?? 0);
|
||||
if ($idMiskin <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["success" => false, "message" => "Parameter 'id_miskin' tidak valid"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
if (empty($_FILES['foto']) || $_FILES['foto']['error'] !== UPLOAD_ERR_OK) {
|
||||
$errMsg = [
|
||||
UPLOAD_ERR_INI_SIZE => 'File terlalu besar (melebihi batas php.ini)',
|
||||
UPLOAD_ERR_FORM_SIZE => 'File terlalu besar',
|
||||
UPLOAD_ERR_PARTIAL => 'Upload tidak lengkap',
|
||||
UPLOAD_ERR_NO_FILE => 'Tidak ada file yang diupload',
|
||||
UPLOAD_ERR_NO_TMP_DIR => 'Folder temporary tidak ditemukan',
|
||||
UPLOAD_ERR_CANT_WRITE => 'Gagal menulis file',
|
||||
];
|
||||
$code = $_FILES['foto']['error'] ?? UPLOAD_ERR_NO_FILE;
|
||||
echo json_encode(["success" => false, "message" => $errMsg[$code] ?? 'Error upload tidak dikenal']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Validasi ukuran
|
||||
if ($_FILES['foto']['size'] > $maxSize) {
|
||||
echo json_encode(["success" => false, "message" => "Ukuran file maksimal 5 MB"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Validasi ekstensi
|
||||
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
|
||||
if (!in_array($ext, $allowedExt)) {
|
||||
echo json_encode(["success" => false, "message" => "Format file harus JPG, PNG, atau WebP"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Validasi MIME type (keamanan tambahan)
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimeType = finfo_file($finfo, $_FILES['foto']['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
$allowedMime = ['image/jpeg', 'image/png', 'image/webp'];
|
||||
if (!in_array($mimeType, $allowedMime)) {
|
||||
echo json_encode(["success" => false, "message" => "Tipe file tidak valid"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
// ── SIMPAN FILE ──────────────────────────────────────────────
|
||||
// Nama file: miskin_{id}_{type}_{timestamp}.{ext}
|
||||
$filename = "miskin_{$idMiskin}_{$type}_" . time() . ".{$ext}";
|
||||
$destPath = $uploadDir . $filename;
|
||||
|
||||
if (!move_uploaded_file($_FILES['foto']['tmp_name'], $destPath)) {
|
||||
echo json_encode(["success" => false, "message" => "Gagal menyimpan file"]);
|
||||
exit();
|
||||
}
|
||||
|
||||
// ── UPDATE DATABASE ──────────────────────────────────────────
|
||||
$host = "localhost";
|
||||
$dbname = "webgis_spbu";
|
||||
$username = "root";
|
||||
$password = "";
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
// Ambil foto lama untuk dihapus
|
||||
$s = $pdo->prepare("SELECT foto_rumah, foto_kk FROM penduduk_miskin WHERE id=?");
|
||||
$s->execute([$idMiskin]);
|
||||
$row = $s->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$col = $type === 'rumah' ? 'foto_rumah' : 'foto_kk';
|
||||
|
||||
// Hapus file lama jika ada
|
||||
if ($row && !empty($row[$col])) {
|
||||
$oldFile = $uploadDir . basename($row[$col]);
|
||||
if (file_exists($oldFile)) unlink($oldFile);
|
||||
}
|
||||
|
||||
// Simpan path baru ke DB
|
||||
$pdo->prepare("UPDATE penduduk_miskin SET {$col}=? WHERE id=?")->execute([$filename, $idMiskin]);
|
||||
|
||||
echo json_encode([
|
||||
"success" => true,
|
||||
"message" => "Foto berhasil diupload",
|
||||
"filename" => $filename,
|
||||
"url" => $uploadUrl . $filename,
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
// File sudah tersimpan tapi DB gagal — hapus file
|
||||
if (file_exists($destPath)) unlink($destPath);
|
||||
echo json_encode(["success" => false, "message" => "DB error: " . $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
Reference in New Issue
Block a user