307 lines
16 KiB
PHP
307 lines
16 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="flex h-screen w-full overflow-hidden bg-background font-sans text-foreground">
|
||
<!-- Left: hero / map -->
|
||
<section class="relative hidden w-1/2 overflow-hidden lg:block">
|
||
<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/85 via-red-800/80 to-rose-900/90"></div>
|
||
<div aria-hidden="true" class="absolute inset-0 opacity-[0.06]" style="background-image: linear-gradient(to right, white 1px, transparent 1px), linear-gradient(to bottom, white 1px, transparent 1px); background-size: 52px 52px;"></div>
|
||
|
||
<div class="relative z-10 flex h-full flex-col justify-between p-12 xl:p-16">
|
||
<div class="flex items-center gap-2.5">
|
||
<div class="flex h-9 w-9 items-center justify-center rounded-xl bg-white/15 backdrop-blur-sm ring-1 ring-white/25">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-5 w-5 text-white" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<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>
|
||
<div>
|
||
<h1 class="font-heading text-sm font-bold tracking-wide text-white shadow-sm">WebGIS Geospasial</h1>
|
||
<p class="text-[11px] font-medium text-white/70 uppercase tracking-wider">Kementerian Analisis Spasial</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<h2 class="font-heading text-4xl font-bold leading-tight tracking-tight text-white xl:text-5xl">
|
||
Sistem Informasi <br> Geografis <span class="text-rose-200">Terpadu</span>
|
||
</h2>
|
||
<p class="mt-4 max-w-md leading-relaxed text-rose-100/90 text-sm xl:text-base">
|
||
Platform pemetaan cerdas untuk analisis spasial persebaran infrastruktur, demografi kemiskinan, dan evaluasi penyaluran bantuan secara real-time.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Right: Login Form -->
|
||
<section class="flex w-full lg:w-1/2 h-full overflow-y-auto p-6">
|
||
<div class="w-full max-w-sm sm:max-w-md m-auto">
|
||
<!-- Mobile branding -->
|
||
<div class="mb-10 flex flex-col items-center gap-3 lg:hidden">
|
||
<div class="flex h-12 w-12 items-center justify-center rounded-2xl bg-gradient-to-br from-primary to-rose-700 text-white shadow-md shadow-primary/20">
|
||
<svg viewBox="0 0 24 24" fill="none" class="h-6 w-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||
<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>
|
||
<div class="text-center">
|
||
<h1 class="font-heading text-lg font-bold text-foreground">WebGIS Geospasial</h1>
|
||
<p class="text-xs font-medium text-muted-foreground uppercase tracking-wider">Kementerian Analisis Spasial</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Header -->
|
||
<div class="mb-8">
|
||
<h2 class="font-heading text-2xl font-bold tracking-tight text-foreground sm:text-3xl">Selamat Datang Kembali</h2>
|
||
<p class="mt-2 text-sm text-muted-foreground">Silakan masuk menggunakan kredensial Anda untuk melanjutkan ke dashboard.</p>
|
||
</div>
|
||
|
||
<!-- Card -->
|
||
<div class="rounded-2xl border border-white/60 bg-white/70 p-6 shadow-[0_8px_30px_rgb(0,0,0,0.04)] backdrop-blur-xl sm:p-8">
|
||
<form action="login.php" method="POST" class="flex flex-col gap-5">
|
||
<!-- Input Email / Username -->
|
||
<div class="group">
|
||
<label for="username" class="mb-1.5 block text-sm 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.5 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" aria-hidden="true">
|
||
<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-xl border border-border bg-white py-2.5 pl-10 pr-3 text-sm text-foreground transition-all focus:outline-none focus-visible:border-primary focus-visible:ring-4 focus-visible:ring-primary/20 hover:border-primary/60" placeholder="admin@domain.com" required autocomplete="username">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Input Password -->
|
||
<div class="group">
|
||
<label for="password" class="mb-1.5 block text-sm 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.5 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" aria-hidden="true">
|
||
<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-xl border border-border bg-white py-2.5 pl-10 pr-10 text-sm text-foreground transition-all focus:outline-none focus-visible:border-primary focus-visible:ring-4 focus-visible: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.5 text-muted-foreground hover:text-foreground focus:outline-none" aria-label="Toggle password visibility">
|
||
<svg id="eyeIcon" 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="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-4 w-4 rounded border-border text-primary shadow-sm transition-all focus:ring-primary focus:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-50">
|
||
<span class="text-sm font-medium text-muted-foreground group-hover:text-foreground transition-colors">Ingat saya</span>
|
||
</label>
|
||
<a href="#" class="text-sm font-semibold text-primary transition-colors hover:text-primary/80">
|
||
Lupa sandi?
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Submit -->
|
||
<button type="submit" class="group mt-1 flex h-12 items-center justify-center gap-2 rounded-xl bg-primary text-sm font-semibold text-white shadow-lg shadow-primary/25 transition-all duration-300 hover:-translate-y-0.5 hover:bg-rose-700 hover:shadow-xl hover:shadow-primary/35 active:translate-y-0">
|
||
Masuk
|
||
<svg class="h-4 w-4 transition-transform duration-300 group-hover:translate-x-1 text-white" 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-6 text-center text-sm text-muted-foreground">
|
||
Belum punya akun? <a href="register.php" class="font-semibold text-primary hover:underline">Daftar sekarang</a>
|
||
</div>
|
||
|
||
<?php if ($show_demo === 1): ?>
|
||
<!-- Demo accounts helper -->
|
||
<div class="mt-7 rounded-xl border border-border/70 bg-gray-50 p-4">
|
||
<div class="mb-3 flex items-center gap-2">
|
||
<span class="h-1.5 w-1.5 rounded-full bg-primary"></span>
|
||
<p class="text-xs font-bold uppercase tracking-wide text-foreground">Info Akun Demo</p>
|
||
<span class="text-[11px] font-medium text-muted-foreground">· klik untuk mengisi</span>
|
||
</div>
|
||
<div class="flex flex-col gap-1.5">
|
||
<button type="button" onclick="fillDemo('admin', 'password')" class="group flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-transparent bg-white/60 px-3 py-2 text-left transition-all hover:border-primary/30 hover:bg-white hover:shadow-sm w-full">
|
||
<span class="flex items-center gap-2.5">
|
||
<span aria-hidden="true" class="text-sm leading-none">👑</span>
|
||
<span class="text-xs font-semibold text-foreground">Admin</span>
|
||
</span>
|
||
<span class="font-mono text-[11px] text-muted-foreground transition-colors group-hover:text-primary">
|
||
admin · password
|
||
</span>
|
||
</button>
|
||
<button type="button" onclick="fillDemo('petugas', 'password')" class="group flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-transparent bg-white/60 px-3 py-2 text-left transition-all hover:border-primary/30 hover:bg-white hover:shadow-sm w-full">
|
||
<span class="flex items-center gap-2.5">
|
||
<span aria-hidden="true" class="text-sm leading-none">📝</span>
|
||
<span class="text-xs font-semibold text-foreground">Petugas</span>
|
||
</span>
|
||
<span class="font-mono text-[11px] text-muted-foreground transition-colors group-hover:text-primary">
|
||
petugas · password
|
||
</span>
|
||
</button>
|
||
<button type="button" onclick="fillDemo('guest', 'password')" class="group flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-transparent bg-white/60 px-3 py-2 text-left transition-all hover:border-primary/30 hover:bg-white hover:shadow-sm w-full">
|
||
<span class="flex items-center gap-2.5">
|
||
<span aria-hidden="true" class="text-sm leading-none">👁️</span>
|
||
<span class="text-xs font-semibold text-foreground">Guest</span>
|
||
</span>
|
||
<span class="font-mono text-[11px] text-muted-foreground transition-colors group-hover:text-primary">
|
||
guest · password
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
</div>
|
||
|
||
<p class="mt-6 text-center text-xs text-muted-foreground">
|
||
© <script>document.write(new Date().getFullYear())</script> WebGIS Geospasial · Kementerian Analisis Spasial
|
||
</p>
|
||
</div>
|
||
</section>
|
||
</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>
|