261 lines
14 KiB
PHP
261 lines
14 KiB
PHP
<?php
|
||
session_start();
|
||
// Jika sudah login, redirect ke dashboard.php
|
||
if (isset($_SESSION['user_id'])) {
|
||
header('Location: dashboard.php');
|
||
exit;
|
||
}
|
||
|
||
include 'koneksi.php';
|
||
|
||
// Ambil pengaturan show_demo_accounts
|
||
$show_demo = 1; // default
|
||
try {
|
||
$stmt = $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'show_demo_accounts'");
|
||
if ($row = $stmt->fetch()) {
|
||
$show_demo = (int)$row['setting_value'];
|
||
}
|
||
} catch (Exception $e) {}
|
||
|
||
$error = '';
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$username = trim($_POST['username'] ?? ''); // Bisa email atau username
|
||
$password = trim($_POST['password'] ?? '');
|
||
|
||
if ($username && $password) {
|
||
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? OR email = ?");
|
||
$stmt->execute([$username, $username]);
|
||
$user = $stmt->fetch();
|
||
|
||
if ($user && password_verify($password, $user['password'])) {
|
||
// Cek status pending
|
||
if ($user['status'] === 'pending') {
|
||
$error = 'Akun Anda sedang menunggu persetujuan Admin.';
|
||
} else {
|
||
$_SESSION['user_id'] = $user['id'];
|
||
$_SESSION['username'] = $user['username'];
|
||
$_SESSION['role'] = $user['role'];
|
||
header('Location: dashboard.php');
|
||
exit;
|
||
}
|
||
} else {
|
||
$error = 'Email/Username atau password salah.';
|
||
}
|
||
} else {
|
||
$error = 'Silakan isi Email/Username dan password.';
|
||
}
|
||
}
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="id">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Login – WebGIS Pengentasan Kemiskinan</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
fontFamily: {
|
||
sans: ['"Plus Jakarta Sans"', 'sans-serif'],
|
||
heading: ['"Plus Jakarta Sans"', 'sans-serif'],
|
||
mono: ['"JetBrains Mono"', 'monospace'],
|
||
},
|
||
colors: {
|
||
background: '#f8fafc',
|
||
foreground: '#0f172a',
|
||
primary: { DEFAULT: '#e11d48', foreground: '#ffffff' },
|
||
muted: { DEFAULT: '#f1f5f9', foreground: '#64748b' },
|
||
border: '#e2e8f0',
|
||
accent: '#e11d48',
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
.group-focus-within\:text-primary:focus-within { color: #e11d48; }
|
||
.focus-visible\:ring-primary\/20:focus-visible { --tw-ring-color: rgba(225, 29, 72, 0.2); }
|
||
.hover\:border-primary\/60:hover { border-color: rgba(225, 29, 72, 0.6); }
|
||
.focus-visible\:border-primary:focus-visible { border-color: #e11d48; }
|
||
/* Checkbox styling */
|
||
input[type="checkbox"]:checked {
|
||
background-color: #e11d48;
|
||
border-color: #e11d48;
|
||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||
}
|
||
/* Custom Pink Scrollbar */
|
||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||
::-webkit-scrollbar-track { background: transparent; }
|
||
::-webkit-scrollbar-thumb { background: #e11d48; border-radius: 4px; }
|
||
::-webkit-scrollbar-thumb:hover { background: #be123c; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<?php if ($error): ?>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Akses Ditolak',
|
||
text: '<?= htmlspecialchars($error) ?>',
|
||
confirmButtonColor: '#e11d48'
|
||
});
|
||
});
|
||
</script>
|
||
<?php endif; ?>
|
||
|
||
<main class="relative flex h-screen w-full items-center justify-center overflow-hidden font-sans text-foreground">
|
||
<!-- Full Screen Background Map -->
|
||
<img src="assets/img/map-bg.png" alt="Visualisasi peta analisis spasial" class="absolute inset-0 object-cover w-full h-full" onerror="this.src='https://images.unsplash.com/photo-1524661135-423995f22d0b?q=80&w=2074&auto=format&fit=crop'" />
|
||
<div aria-hidden="true" class="absolute inset-0 bg-gradient-to-br from-red-900/90 via-red-950/80 to-black/90"></div>
|
||
<div aria-hidden="true" class="absolute inset-0 opacity-10" style="background-image: linear-gradient(to right, white 1px, transparent 1px), linear-gradient(to bottom, white 1px, transparent 1px); background-size: 52px 52px;"></div>
|
||
|
||
<!-- Giant Card Container -->
|
||
<div class="relative z-10 flex w-[90%] max-w-5xl flex-col lg:flex-row overflow-hidden rounded-[2rem] border border-white/20 bg-white/10 shadow-2xl backdrop-blur-xl">
|
||
|
||
<!-- LEFT SECTION: Public Access -->
|
||
<div class="flex flex-col justify-between p-8 lg:w-1/2 lg:p-12">
|
||
<!-- Top / Brand -->
|
||
<div class="mb-8">
|
||
<div class="mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-white/15 ring-1 ring-white/30">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-6 w-6 text-white" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 21s-7-5.6-7-11a7 7 0 1 1 14 0c0 5.4-7 11-7 11Z" />
|
||
<circle cx="12" cy="10" r="2.5" />
|
||
</svg>
|
||
</div>
|
||
<h1 class="font-heading text-2xl font-bold tracking-tight text-white lg:text-3xl">WebGIS Geospasial</h1>
|
||
<p class="mt-2 text-sm leading-relaxed text-white/80">
|
||
Platform pemetaan cerdas untuk analisis spasial persebaran infrastruktur dan demografi kemiskinan.
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Bottom / Features Info -->
|
||
<div class="mt-8">
|
||
<h2 class="mb-4 flex items-center gap-2 text-sm font-bold text-white/90 uppercase tracking-wider">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-5 w-5 text-rose-300" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
|
||
</svg>
|
||
Sistem Pengamanan Tertutup
|
||
</h2>
|
||
<div class="flex flex-col gap-4 text-white/80 text-sm">
|
||
<div class="flex items-start gap-3">
|
||
<div class="mt-0.5 rounded-full bg-white/20 p-1"><svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path></svg></div>
|
||
<p><strong>Database Terpusat:</strong> Melacak data penduduk miskin berdasarkan NIK secara real-time.</p>
|
||
</div>
|
||
<div class="flex items-start gap-3">
|
||
<div class="mt-0.5 rounded-full bg-white/20 p-1"><svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path></svg></div>
|
||
<p><strong>Tracking Bantuan:</strong> Verifikasi silang penyaluran BLT dan PKH di berbagai wilayah.</p>
|
||
</div>
|
||
<div class="flex items-start gap-3">
|
||
<div class="mt-0.5 rounded-full bg-white/20 p-1"><svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"></path></svg></div>
|
||
<p><strong>Analisis Spasial:</strong> Pemetaan kantong kemiskinan untuk kebijakan tepat sasaran.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- RIGHT SECTION: Login Form -->
|
||
<div class="flex flex-col justify-center bg-white/95 p-8 lg:w-1/2 lg:p-12">
|
||
<div class="mb-6 text-center">
|
||
<h2 class="font-heading text-2xl font-bold tracking-tight text-foreground sm:text-3xl">Login Aplikasi Kemiskinan</h2>
|
||
<p class="mt-2 text-sm leading-relaxed text-muted-foreground">
|
||
Silakan masuk untuk mengakses pusat kendali data kemiskinan, memverifikasi bantuan, dan melihat statistik penduduk miskin.
|
||
</p>
|
||
</div>
|
||
|
||
<form action="login.php" method="POST" class="flex flex-col gap-4">
|
||
<!-- Input Email / Username -->
|
||
<div class="group">
|
||
<label for="username" class="mb-1 block text-xs font-semibold text-foreground group-focus-within:text-primary transition-colors">Email atau Username</label>
|
||
<div class="relative">
|
||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-muted-foreground group-focus-within:text-primary transition-colors">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-4.5 w-4.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
|
||
<circle cx="12" cy="7" r="4"></circle>
|
||
</svg>
|
||
</div>
|
||
<input type="text" id="username" name="username" class="block w-full rounded-lg border border-border bg-white py-2 pl-9 pr-3 text-sm transition-all focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 hover:border-primary/60" placeholder="contoh@email.com atau username" required autocomplete="username">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Input Password -->
|
||
<div class="group">
|
||
<label for="password" class="mb-1 block text-xs font-semibold text-foreground group-focus-within:text-primary transition-colors">Kata Sandi</label>
|
||
<div class="relative">
|
||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-muted-foreground group-focus-within:text-primary transition-colors">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-4.5 w-4.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
||
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
||
</svg>
|
||
</div>
|
||
<input type="password" id="password" name="password" class="block w-full rounded-lg border border-border bg-white py-2 pl-9 pr-9 text-sm transition-all focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 hover:border-primary/60" placeholder="••••••••" required autocomplete="current-password">
|
||
<button type="button" id="togglePassword" class="absolute inset-y-0 right-0 flex items-center pr-3 text-muted-foreground hover:text-foreground focus:outline-none">
|
||
<svg id="eyeIcon" viewBox="0 0 24 24" fill="none" class="h-4 w-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
||
<circle cx="12" cy="12" r="3"></circle>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Options -->
|
||
<div class="flex items-center justify-between mt-1">
|
||
<label class="flex items-center gap-2 cursor-pointer group">
|
||
<input type="checkbox" name="remember" class="h-3.5 w-3.5 rounded border-border text-primary shadow-sm focus:ring-primary focus:ring-offset-0">
|
||
<span class="text-xs font-medium text-muted-foreground group-hover:text-foreground transition-colors">Ingat saya</span>
|
||
</label>
|
||
<a href="#" class="text-xs font-semibold text-primary hover:text-primary/80">Lupa sandi?</a>
|
||
</div>
|
||
|
||
<!-- Submit -->
|
||
<button type="submit" class="group mt-2 flex h-10 items-center justify-center gap-2 rounded-lg bg-primary text-sm font-bold text-white shadow-md shadow-primary/25 transition-all hover:-translate-y-0.5 hover:bg-rose-700 hover:shadow-lg active:translate-y-0">
|
||
Masuk
|
||
<svg class="h-4 w-4 transition-transform group-hover:translate-x-1" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
||
</button>
|
||
</form>
|
||
|
||
<div class="mt-4 text-center text-xs text-muted-foreground">
|
||
Belum punya akun? <a href="register.php" class="font-semibold text-primary hover:underline">Daftar sekarang</a>
|
||
</div>
|
||
|
||
<!-- Akun demo telah dinonaktifkan -->
|
||
|
||
<p class="mt-8 text-center text-[10px] text-muted-foreground uppercase tracking-wider">
|
||
© <script>document.write(new Date().getFullYear())</script> Kementerian Analisis Spasial
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<script>
|
||
// Toggle Password Visibility
|
||
const toggleBtn = document.getElementById('togglePassword');
|
||
const passInput = document.getElementById('password');
|
||
const eyeIcon = document.getElementById('eyeIcon');
|
||
|
||
if (toggleBtn && passInput) {
|
||
toggleBtn.addEventListener('click', function() {
|
||
if (passInput.type === 'password') {
|
||
passInput.type = 'text';
|
||
eyeIcon.innerHTML = '<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line>';
|
||
} else {
|
||
passInput.type = 'password';
|
||
eyeIcon.innerHTML = '<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle>';
|
||
}
|
||
});
|
||
}
|
||
|
||
function fillDemo(user, pass) {
|
||
document.getElementById('username').value = user;
|
||
document.getElementById('password').value = pass;
|
||
}
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|