Upload files to "/"

This commit is contained in:
2026-06-05 03:09:29 +00:00
parent afcd403620
commit 0d1fe90613
5 changed files with 802 additions and 0 deletions
+377
View File
@@ -0,0 +1,377 @@
<?php
session_start();
if (!isset($_SESSION['login']) || $_SESSION['login'] !== true) {
header("Location: login.php");
exit;
}
include 'koneksi.php';
// ==================== HANDLE EXPORT CSV ====================
if (isset($_GET['export']) && $_GET['export'] == 'csv') {
$bulan = isset($_GET['bulan']) ? intval($_GET['bulan']) : 0;
$tahun = isset($_GET['tahun']) ? intval($_GET['tahun']) : date('Y');
$where = "WHERE b.tanggal_bantuan IS NOT NULL";
if ($bulan > 0) $where .= " AND MONTH(b.tanggal_bantuan) = $bulan";
if ($tahun > 0) $where .= " AND YEAR(b.tanggal_bantuan) = $tahun";
$query = mysqli_query($conn, "
SELECT
b.id,
b.tanggal_bantuan,
p.nama AS nama_penerima,
p.nik,
p.alamat,
p.kategori_kemiskinan,
b.jenis_bantuan,
b.jumlah_bantuan,
b.keterangan
FROM bantuan b
LEFT JOIN penduduk_miskin p ON b.penduduk_id = p.id
$where
ORDER BY b.tanggal_bantuan DESC
");
$nama_bulan_arr = ['','Januari','Februari','Maret','April','Mei','Juni','Juli','Agustus','September','Oktober','November','Desember'];
$label = ($bulan > 0 ? $nama_bulan_arr[$bulan] . '_' : 'Semua_Bulan_') . $tahun;
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="Laporan_Bantuan_' . $label . '.csv"');
header('Pragma: no-cache');
echo "\xEF\xBB\xBF"; // BOM UTF-8 agar Excel terbaca benar
$out = fopen('php://output', 'w');
fputcsv($out, ['No', 'Tanggal', 'Nama Penerima', 'NIK', 'Alamat', 'Kategori', 'Jenis Bantuan', 'Jumlah Bantuan', 'Keterangan'], ';');
$no = 1;
while ($row = mysqli_fetch_assoc($query)) {
fputcsv($out, [
$no++,
$row['tanggal_bantuan'],
$row['nama_penerima'] ?? '-',
$row['nik'] ?? '-',
$row['alamat'] ?? '-',
$row['kategori_kemiskinan'] ?? '-',
$row['jenis_bantuan'],
$row['jumlah_bantuan'],
$row['keterangan'] ?? '-',
], ';');
}
fclose($out);
exit;
}
// ==================== AMBIL DATA UNTUK PREVIEW ====================
$bulan_filter = isset($_GET['bulan']) ? intval($_GET['bulan']) : date('n');
$tahun_filter = isset($_GET['tahun']) ? intval($_GET['tahun']) : date('Y');
$where = "WHERE b.tanggal_bantuan IS NOT NULL";
if ($bulan_filter > 0) $where .= " AND MONTH(b.tanggal_bantuan) = $bulan_filter";
if ($tahun_filter > 0) $where .= " AND YEAR(b.tanggal_bantuan) = $tahun_filter";
$query = mysqli_query($conn, "
SELECT
b.id,
b.tanggal_bantuan,
p.nama AS nama_penerima,
p.nik,
p.alamat,
p.kategori_kemiskinan,
b.jenis_bantuan,
b.jumlah_bantuan,
b.keterangan
FROM bantuan b
LEFT JOIN penduduk_miskin p ON b.penduduk_id = p.id
$where
ORDER BY b.tanggal_bantuan DESC
");
// Statistik ringkasan
$stats = [];
$statQuery = mysqli_query($conn, "
SELECT jenis_bantuan, COUNT(*) as jumlah
FROM bantuan b
$where
GROUP BY jenis_bantuan
ORDER BY jumlah DESC
");
while ($r = mysqli_fetch_assoc($statQuery)) $stats[] = $r;
$totalQuery = mysqli_query($conn, "SELECT COUNT(*) as total FROM bantuan b $where");
$totalRow = mysqli_fetch_assoc($totalQuery);
$totalBantuan = $totalRow['total'];
$nama_bulan_arr = ['','Januari','Februari','Maret','April','Mei','Juni','Juli','Agustus','September','Oktober','November','Desember'];
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Laporan Bantuan - WebGIS Kemiskinan</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: Arial, sans-serif; background: #f0f2f5; color: #2c3e50; }
.topbar {
background: #2c3e50;
color: white;
padding: 12px 24px;
display: flex;
align-items: center;
justify-content: space-between;
}
.topbar h1 { font-size: 18px; margin: 0; }
.topbar a {
color: #bdc3c7;
text-decoration: none;
font-size: 13px;
padding: 6px 14px;
border: 1px solid #bdc3c7;
border-radius: 5px;
transition: all 0.2s;
}
.topbar a:hover { background: #3498db; border-color: #3498db; color: white; }
.container { max-width: 1100px; margin: 24px auto; padding: 0 16px; }
.filter-card {
background: white;
border-radius: 10px;
padding: 20px 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
margin-bottom: 20px;
display: flex;
align-items: flex-end;
gap: 16px;
flex-wrap: wrap;
}
.filter-card label { font-size: 12px; color: #666; display: block; margin-bottom: 4px; }
.filter-card select {
padding: 9px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
outline: none;
background: #fafafa;
min-width: 150px;
}
.filter-card select:focus { border-color: #3498db; }
.btn-filter {
padding: 9px 20px;
background: #3498db;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
transition: background 0.2s;
}
.btn-filter:hover { background: #2980b9; }
.btn-download {
padding: 9px 20px;
background: #27ae60;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
text-decoration: none;
display: inline-block;
transition: background 0.2s;
}
.btn-download:hover { background: #219a52; }
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 14px;
margin-bottom: 20px;
}
.stat-box {
background: white;
border-radius: 10px;
padding: 16px;
text-align: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
border-top: 4px solid #3498db;
}
.stat-box.green { border-top-color: #27ae60; }
.stat-box.orange { border-top-color: #e67e22; }
.stat-box.purple { border-top-color: #9b59b6; }
.stat-box .num { font-size: 28px; font-weight: bold; color: #2c3e50; }
.stat-box .label { font-size: 12px; color: #888; margin-top: 4px; }
.table-card {
background: white;
border-radius: 10px;
padding: 20px 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.table-card h3 { margin: 0 0 16px 0; font-size: 15px; color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 8px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
table th { background: #2c3e50; color: white; padding: 10px 12px; text-align: left; }
table td { padding: 9px 12px; border-bottom: 1px solid #f0f0f0; vertical-align: middle; }
table tr:hover td { background: #f8f9fa; }
table tr:last-child td { border-bottom: none; }
.badge {
display: inline-block;
padding: 3px 8px;
border-radius: 12px;
font-size: 11px;
font-weight: bold;
}
.badge-beras { background: #fff3cd; color: #856404; }
.badge-sembako { background: #d1ecf1; color: #0c5460; }
.badge-uang { background: #d4edda; color: #155724; }
.badge-pendidikan { background: #cce5ff; color: #004085; }
.badge-kesehatan { background: #f8d7da; color: #721c24; }
.badge-lain { background: #e2e3e5; color: #383d41; }
.empty-state {
text-align: center;
padding: 50px;
color: #aaa;
font-size: 15px;
}
.print-hint { font-size: 12px; color: #888; margin-top: 12px; text-align: right; }
@media print {
.topbar a, .filter-card button, .btn-download, .print-hint { display: none !important; }
.topbar { background: #2c3e50 !important; -webkit-print-color-adjust: exact; }
body { background: white; }
}
</style>
</head>
<body>
<div class="topbar">
<h1>📋 Laporan Bantuan — <?= $bulan_filter > 0 ? $nama_bulan_arr[$bulan_filter] . ' ' . $tahun_filter : 'Semua Bulan ' . $tahun_filter ?></h1>
<div style="display:flex;gap:8px;">
<a href="admin.php">🗺️ Kembali ke Dashboard</a>
<a href="javascript:window.print()" style="border-color:#f39c12;color:#f39c12;">🖨️ Cetak</a>
</div>
</div>
<div class="container">
<!-- FILTER -->
<div class="filter-card">
<div>
<label>Bulan</label>
<select id="selBulan">
<option value="0" <?= $bulan_filter==0?'selected':'' ?>>Semua Bulan</option>
<?php for($i=1;$i<=12;$i++): ?>
<option value="<?= $i ?>" <?= $bulan_filter==$i?'selected':'' ?>><?= $nama_bulan_arr[$i] ?></option>
<?php endfor; ?>
</select>
</div>
<div>
<label>Tahun</label>
<select id="selTahun">
<?php for($y=date('Y');$y>=date('Y')-5;$y--): ?>
<option value="<?= $y ?>" <?= $tahun_filter==$y?'selected':'' ?>><?= $y ?></option>
<?php endfor; ?>
</select>
</div>
<button class="btn-filter" onclick="terapkanFilter()">🔍 Tampilkan</button>
<a id="linkDownload" class="btn-download" href="laporan.php?export=csv&bulan=<?= $bulan_filter ?>&tahun=<?= $tahun_filter ?>">⬇️ Download CSV</a>
</div>
<!-- STATISTIK -->
<div class="stats-grid">
<div class="stat-box">
<div class="num"><?= $totalBantuan ?></div>
<div class="label">Total Penyaluran Bantuan</div>
</div>
<?php
$jenis_icon = ['Beras'=>'🌾','Sembako'=>'🛒','Uang Tunai'=>'💰','Pendidikan'=>'📚','Kesehatan'=>'🏥'];
$colors = ['green','orange','purple','green','orange'];
$ci = 0;
foreach($stats as $s):
$icon = $jenis_icon[$s['jenis_bantuan']] ?? '📦';
$cls = $colors[$ci % count($colors)]; $ci++;
?>
<div class="stat-box <?= $cls ?>">
<div class="num"><?= $s['jumlah'] ?></div>
<div class="label"><?= $icon ?> <?= htmlspecialchars($s['jenis_bantuan']) ?></div>
</div>
<?php endforeach; ?>
</div>
<!-- TABEL -->
<div class="table-card">
<h3>📄 Rincian Penyaluran Bantuan</h3>
<?php if ($totalBantuan == 0): ?>
<div class="empty-state">😕 Tidak ada data bantuan untuk periode ini.</div>
<?php else: ?>
<div style="overflow-x:auto;">
<table>
<thead>
<tr>
<th>No</th>
<th>Tanggal</th>
<th>Nama Penerima</th>
<th>NIK</th>
<th>Alamat</th>
<th>Kategori</th>
<th>Jenis Bantuan</th>
<th>Jumlah</th>
<th>Keterangan</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
while ($row = mysqli_fetch_assoc($query)):
$jenis = htmlspecialchars($row['jenis_bantuan'] ?? '');
$badgeClass = 'badge-lain';
if (strpos($jenis,'Beras') !== false) $badgeClass = 'badge-beras';
elseif (strpos($jenis,'Sembako') !== false) $badgeClass = 'badge-sembako';
elseif (strpos($jenis,'Uang') !== false) $badgeClass = 'badge-uang';
elseif (strpos($jenis,'Pendidikan') !== false) $badgeClass = 'badge-pendidikan';
elseif (strpos($jenis,'Kesehatan') !== false) $badgeClass = 'badge-kesehatan';
?>
<tr>
<td><?= $no++ ?></td>
<td><?= htmlspecialchars($row['tanggal_bantuan'] ?? '-') ?></td>
<td><strong><?= htmlspecialchars($row['nama_penerima'] ?? '-') ?></strong></td>
<td><?= htmlspecialchars($row['nik'] ?? '-') ?></td>
<td><?= htmlspecialchars($row['alamat'] ?? '-') ?></td>
<td><?= htmlspecialchars($row['kategori_kemiskinan'] ?? '-') ?></td>
<td><span class="badge <?= $badgeClass ?>"><?= $jenis ?></span></td>
<td><?= htmlspecialchars($row['jumlah_bantuan'] ?? '-') ?></td>
<td><?= htmlspecialchars($row['keterangan'] ?? '-') ?></td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
</div>
<p class="print-hint">Laporan dibuat pada: <?= date('d/m/Y H:i') ?> · Dibuat oleh: <?= htmlspecialchars($_SESSION['username']) ?></p>
<?php endif; ?>
</div>
</div>
<script>
function terapkanFilter() {
var bulan = document.getElementById('selBulan').value;
var tahun = document.getElementById('selTahun').value;
window.location.href = 'laporan.php?bulan=' + bulan + '&tahun=' + tahun;
}
// Update link download saat filter berubah
document.getElementById('selBulan').addEventListener('change', updateDownloadLink);
document.getElementById('selTahun').addEventListener('change', updateDownloadLink);
function updateDownloadLink() {
var bulan = document.getElementById('selBulan').value;
var tahun = document.getElementById('selTahun').value;
document.getElementById('linkDownload').href = 'laporan.php?export=csv&bulan=' + bulan + '&tahun=' + tahun;
}
</script>
</body>
</html>
+277
View File
@@ -0,0 +1,277 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Admin - WebGIS Kemiskinan</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Segoe UI', Arial, sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #1a252f 0%, #2c3e50 40%, #1a6b4a 100%);
position: relative;
overflow: hidden;
}
/* Lingkaran dekorasi background */
body::before {
content: '';
position: absolute;
width: 500px; height: 500px;
border-radius: 50%;
background: rgba(52, 152, 219, 0.08);
top: -150px; left: -150px;
}
body::after {
content: '';
position: absolute;
width: 400px; height: 400px;
border-radius: 50%;
background: rgba(39, 174, 96, 0.08);
bottom: -100px; right: -100px;
}
.wrapper {
display: flex;
width: 820px;
max-width: 96vw;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 25px 60px rgba(0,0,0,0.5);
position: relative;
z-index: 1;
}
/* Panel kiri - branding */
.panel-kiri {
flex: 1;
background: linear-gradient(160deg, #27ae60, #2c3e50);
padding: 50px 36px;
display: flex;
flex-direction: column;
justify-content: center;
color: white;
}
.panel-kiri .logo { font-size: 56px; margin-bottom: 18px; }
.panel-kiri h1 { font-size: 22px; font-weight: 700; margin-bottom: 10px; line-height: 1.3; }
.panel-kiri p { font-size: 13px; color: rgba(255,255,255,0.75); line-height: 1.7; }
.fitur-list { margin-top: 28px; list-style: none; }
.fitur-list li {
font-size: 13px;
color: rgba(255,255,255,0.85);
padding: 6px 0;
display: flex;
align-items: center;
gap: 10px;
}
.fitur-list li span.dot {
width: 8px; height: 8px;
background: #2ecc71;
border-radius: 50%;
flex-shrink: 0;
}
/* Panel kanan - form */
.panel-kanan {
width: 360px;
background: #ffffff;
padding: 48px 36px;
display: flex;
flex-direction: column;
justify-content: center;
}
.panel-kanan h2 {
font-size: 22px;
color: #2c3e50;
font-weight: 700;
margin-bottom: 6px;
}
.panel-kanan .sub {
font-size: 13px;
color: #999;
margin-bottom: 30px;
}
.field { margin-bottom: 18px; }
.field label {
display: block;
font-size: 12px;
font-weight: 700;
color: #555;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 7px;
}
.input-wrap {
position: relative;
}
.input-wrap .icon {
position: absolute;
left: 13px;
top: 50%;
transform: translateY(-50%);
font-size: 16px;
color: #aaa;
pointer-events: none;
}
.input-wrap input {
width: 100%;
padding: 12px 14px 12px 40px;
border: 2px solid #e8e8e8;
border-radius: 9px;
font-size: 14px;
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
color: #2c3e50;
background: #fafafa;
}
.input-wrap input:focus {
border-color: #27ae60;
box-shadow: 0 0 0 3px rgba(39,174,96,0.12);
background: white;
}
.input-wrap input::placeholder { color: #c0c0c0; }
/* Toggle password */
.toggle-pw {
position: absolute;
right: 13px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
font-size: 16px;
color: #aaa;
user-select: none;
}
.toggle-pw:hover { color: #27ae60; }
.btn-login {
width: 100%;
padding: 13px;
background: linear-gradient(135deg, #27ae60, #1e8449);
color: white;
border: none;
border-radius: 9px;
font-size: 15px;
font-weight: 700;
cursor: pointer;
transition: opacity 0.2s, transform 0.15s;
margin-top: 6px;
letter-spacing: 0.5px;
}
.btn-login:hover { opacity: 0.92; transform: translateY(-1px); }
.btn-login:active { transform: translateY(0); }
.error-msg {
background: #fdf0f0;
border: 1px solid #f5c6cb;
border-left: 4px solid #e74c3c;
color: #721c24;
padding: 10px 14px;
border-radius: 8px;
font-size: 13px;
margin-bottom: 20px;
}
.link {
text-align: center;
margin-top: 20px;
font-size: 13px;
color: #aaa;
}
.link a {
color: #27ae60;
text-decoration: none;
font-weight: 600;
}
.link a:hover { text-decoration: underline; }
/* Responsive - sembunyikan panel kiri di layar kecil */
@media (max-width: 600px) {
.panel-kiri { display: none; }
.panel-kanan { width: 100%; padding: 40px 28px; }
.wrapper { border-radius: 14px; }
}
</style>
</head>
<body>
<div class="wrapper">
<!-- PANEL KIRI -->
<div class="panel-kiri">
<div class="logo">🗺️</div>
<h1>WebGIS Kemiskinan<br>Kota Pontianak</h1>
<p>Sistem pemetaan rumah ibadah dan pendataan penduduk miskin berbasis geografis.</p>
<ul class="fitur-list">
<li><span class="dot"></span> Peta interaktif real-time</li>
<li><span class="dot"></span> Manajemen data penduduk miskin</li>
<li><span class="dot"></span> Pencatatan & laporan bantuan</li>
<li><span class="dot"></span> Analisis radius distribusi</li>
</ul>
</div>
<!-- PANEL KANAN -->
<div class="panel-kanan">
<h2>Selamat Datang 👋</h2>
<p class="sub">Masuk ke dashboard admin WebGIS</p>
<?php
if (isset($_GET['error'])) {
if ($_GET['error'] == 'empty') {
echo '<div class="error-msg">⚠️ Username dan password wajib diisi!</div>';
} elseif ($_GET['error'] == 'wrong') {
echo '<div class="error-msg">⚠️ Username atau password salah. Coba lagi.</div>';
}
}
?>
<form action="login_process.php" method="POST">
<div class="field">
<label>Username</label>
<div class="input-wrap">
<span class="icon">👤</span>
<input type="text" name="username" placeholder="Masukkan username" required autofocus autocomplete="username">
</div>
</div>
<div class="field">
<label>Password</label>
<div class="input-wrap">
<span class="icon">🔒</span>
<input type="password" name="password" id="inputPassword" placeholder="Masukkan password" required autocomplete="current-password">
<span class="toggle-pw" onclick="togglePassword()" id="toggleIcon">👁️</span>
</div>
</div>
<button type="submit" class="btn-login">🔐 LOGIN</button>
</form>
<div class="link">
<a href="lupa_password.html">Lupa password?</a>
</div>
</div>
</div>
<script>
function togglePassword() {
var input = document.getElementById('inputPassword');
var icon = document.getElementById('toggleIcon');
if (input.type === 'password') {
input.type = 'text';
icon.textContent = '🙈';
} else {
input.type = 'password';
icon.textContent = '👁️';
}
}
</script>
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
<?php
session_start();
include 'koneksi.php';
// Cek apakah form disubmit
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header("Location: login.php");
exit;
}
// Ambil data dari form
$username = trim($_POST['username'] ?? '');
$password = trim($_POST['password'] ?? '');
// Validasi tidak boleh kosong
if (empty($username) || empty($password)) {
header("Location: login.php?error=empty");
exit;
}
// Cek ke database
$stmt = $conn->prepare("SELECT * FROM admin WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$admin = $result->fetch_assoc();
// Cek password
if ($password === $admin['password']) {
$_SESSION['login'] = true;
$_SESSION['username'] = $username;
// Redirect ke admin.php
header("Location: admin.php");
exit;
}
}
// Login gagal
header("Location: login.php?error=wrong");
exit;
?>
+6
View File
@@ -0,0 +1,6 @@
<?php
session_start();
session_destroy();
header("Location: login.php"); // Ganti dari login.html ke login.php
exit;
?>
+98
View File
@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Lupa Password - WebGIS Kemiskinan</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #e67e22, #d35400);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.box {
width: 340px;
background: white;
padding: 35px 30px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}
.box h2 {
text-align: center;
color: #2c3e50;
margin-bottom: 8px;
}
.box p.sub {
text-align: center;
color: #888;
font-size: 13px;
margin-bottom: 25px;
}
label {
display: block;
font-size: 13px;
color: #555;
margin-bottom: 4px;
margin-top: 14px;
}
input {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
outline: none;
transition: border 0.2s;
}
input:focus { border-color: #e67e22; }
button {
width: 100%;
padding: 11px;
margin-top: 20px;
background: #e67e22;
color: white;
border: none;
border-radius: 6px;
font-size: 15px;
cursor: pointer;
transition: background 0.2s;
}
button:hover { background: #d35400; }
.link-bawah {
margin-top: 14px;
text-align: center;
font-size: 13px;
}
.link-bawah a {
color: #e67e22;
text-decoration: none;
}
.link-bawah a:hover { text-decoration: underline; }
</style>
</head>
<body>
<div class="box">
<h2>🔑 Reset Password</h2>
<p class="sub">Masukkan username dan password baru kamu</p>
<form action="reset_password.php" method="POST">
<label>Username</label>
<input type="text" name="username" placeholder="Masukkan username" required>
<label>Password Baru</label>
<input type="password" name="password_baru" placeholder="Masukkan password baru" required>
<button type="submit">RESET PASSWORD</button>
</form>
<div class="link-bawah">
<a href="login.php">← Kembali ke Login</a>
</div>
</div>
</body>
</html>