309 lines
17 KiB
PHP
309 lines
17 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';
|
||
|
||
// Konfigurasi Google OAuth (DUMMY/HARUS DIISI OLEH USER)
|
||
define('GOOGLE_CLIENT_ID', '575444350307-likfkam3fkppn8rjl8044uppdm4ovf35.apps.googleusercontent.com');
|
||
define('GOOGLE_CLIENT_SECRET', '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');
|
||
define('GOOGLE_REDIRECT_URI', 'http://localhost/webgis/register.php');
|
||
|
||
$sweetAlertScript = '';
|
||
|
||
// Proses Google OAuth Callback
|
||
if (isset($_GET['code'])) {
|
||
$code = $_GET['code'];
|
||
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, "https://oauth2.googleapis.com/token");
|
||
curl_setopt($ch, CURLOPT_POST, 1);
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||
'client_id' => GOOGLE_CLIENT_ID,
|
||
'client_secret' => GOOGLE_CLIENT_SECRET,
|
||
'redirect_uri' => GOOGLE_REDIRECT_URI,
|
||
'grant_type' => 'authorization_code',
|
||
'code' => $code
|
||
]));
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
$response = curl_exec($ch);
|
||
curl_close($ch);
|
||
|
||
$token_data = json_decode($response, true);
|
||
if (isset($token_data['access_token'])) {
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, "https://www.googleapis.com/oauth2/v3/userinfo");
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer " . $token_data['access_token']]);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
$user_data = json_decode(curl_exec($ch), true);
|
||
curl_close($ch);
|
||
|
||
if (isset($user_data['email'])) {
|
||
$email = $user_data['email'];
|
||
$name = $user_data['name'];
|
||
$state_role = $_GET['state'] ?? 'guest';
|
||
$role = in_array($state_role, ['guest', 'petugas']) ? $state_role : 'guest';
|
||
|
||
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ? OR username = ?");
|
||
$stmt->execute([$email, $email]);
|
||
$existing_user = $stmt->fetch();
|
||
|
||
if ($existing_user) {
|
||
if ($existing_user['status'] === 'pending') {
|
||
$sweetAlertScript = "Swal.fire({icon: 'warning', title: 'Menunggu Persetujuan', text: 'Akun Anda sedang menunggu persetujuan Admin.', confirmButtonColor: '#e11d48'});";
|
||
} else {
|
||
$_SESSION['user_id'] = $existing_user['id'];
|
||
$_SESSION['username'] = $existing_user['username'];
|
||
$_SESSION['role'] = $existing_user['role'];
|
||
header('Location: dashboard.php');
|
||
exit;
|
||
}
|
||
} else {
|
||
$status = ($role === 'petugas') ? 'pending' : 'active';
|
||
$username = explode('@', $email)[0] . rand(100,999);
|
||
$stmt = $pdo->prepare("INSERT INTO users (username, email, nama_lengkap, password, role, status, auth_provider) VALUES (?, ?, ?, ?, ?, ?, 'google')");
|
||
$stmt->execute([$username, $email, $name, password_hash(bin2hex(random_bytes(8)), PASSWORD_DEFAULT), $role, $status]);
|
||
|
||
if ($role === 'petugas') {
|
||
$sweetAlertScript = "Swal.fire({icon: 'success', title: 'Pendaftaran Berhasil', text: 'Pendaftaran via Google berhasil. Akun Anda menunggu persetujuan Admin.', confirmButtonColor: '#e11d48'}).then(() => { window.location.href = 'login.php'; });";
|
||
} else {
|
||
$_SESSION['user_id'] = $pdo->lastInsertId();
|
||
$_SESSION['username'] = $username;
|
||
$_SESSION['role'] = 'guest';
|
||
header('Location: dashboard.php');
|
||
exit;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
$sweetAlertScript = "Swal.fire({icon: 'error', title: 'Google Login Gagal', text: 'Terjadi kesalahan kredensial OAuth.', confirmButtonColor: '#e11d48'});";
|
||
}
|
||
}
|
||
|
||
// Proses Registrasi Lokal
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['register'])) {
|
||
$nama_lengkap = trim($_POST['nama_lengkap'] ?? '');
|
||
$email = trim($_POST['email'] ?? '');
|
||
$password = trim($_POST['password'] ?? '');
|
||
$role = trim($_POST['role'] ?? 'guest');
|
||
|
||
if ($nama_lengkap && $email && $password && in_array($role, ['guest', 'petugas'])) {
|
||
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ? OR username = ?");
|
||
$stmt->execute([$email, $email]);
|
||
if ($stmt->fetch()) {
|
||
$sweetAlertScript = "Swal.fire({icon: 'error', title: 'Registrasi Gagal', text: 'Email tersebut sudah terdaftar.', confirmButtonColor: '#e11d48'});";
|
||
} else {
|
||
$status = ($role === 'petugas') ? 'pending' : 'active';
|
||
$username = explode('@', $email)[0] . rand(100,999);
|
||
|
||
$stmt = $pdo->prepare("INSERT INTO users (username, email, nama_lengkap, password, role, status, auth_provider) VALUES (?, ?, ?, ?, ?, ?, 'local')");
|
||
if ($stmt->execute([$username, $email, $nama_lengkap, password_hash($password, PASSWORD_DEFAULT), $role, $status])) {
|
||
if ($role === 'petugas') {
|
||
$sweetAlertScript = "Swal.fire({icon: 'success', title: 'Pendaftaran Berhasil', text: 'Pendaftaran berhasil. Menunggu persetujuan Admin.', confirmButtonColor: '#e11d48'}).then(() => { window.location.href = 'login.php'; });";
|
||
} else {
|
||
$sweetAlertScript = "Swal.fire({icon: 'success', title: 'Pendaftaran Berhasil', text: 'Akun Anda aktif, silakan masuk ke sistem.', confirmButtonColor: '#e11d48'}).then(() => { window.location.href = 'login.php'; });";
|
||
}
|
||
} else {
|
||
$sweetAlertScript = "Swal.fire({icon: 'error', title: 'Gagal', text: 'Terjadi kesalahan sistem internal.', confirmButtonColor: '#e11d48'});";
|
||
}
|
||
}
|
||
} else {
|
||
$sweetAlertScript = "Swal.fire({icon: 'warning', title: 'Data Belum Lengkap', text: 'Harap lengkapi semua bidang yang tersedia.', confirmButtonColor: '#e11d48'});";
|
||
}
|
||
}
|
||
|
||
// URL OAuth Google
|
||
$google_auth_url = "https://accounts.google.com/o/oauth2/v2/auth?client_id=" . GOOGLE_CLIENT_ID . "&redirect_uri=" . urlencode(GOOGLE_REDIRECT_URI) . "&response_type=code&scope=email%20profile";
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="id">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Register – 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',
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</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; }
|
||
::-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 ($sweetAlertScript): ?>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
<?= $sweetAlertScript ?>
|
||
});
|
||
</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" 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">
|
||
Bergabung Bersama <br> Komunitas <span class="text-rose-200">Spasial</span>
|
||
</h2>
|
||
<p class="mt-4 max-w-md leading-relaxed text-rose-100/90 text-sm xl:text-base">
|
||
Jadilah bagian dari inisiatif digital pemetaan wilayah, dan ikut serta dalam evaluasi kemiskinan berbasis data geospasial.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Right: Register 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">
|
||
|
||
<!-- Header -->
|
||
<div class="mb-8 mt-10 lg:mt-0">
|
||
<h2 class="font-heading text-2xl font-bold tracking-tight text-foreground sm:text-3xl">Buat Akun Baru</h2>
|
||
<p class="mt-2 text-sm text-muted-foreground">Isi data di bawah ini untuk membuat akun WebGIS Anda.</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">
|
||
|
||
<!-- Google Auth Button -->
|
||
<button type="button" onclick="startGoogleAuth()" class="flex h-11 w-full items-center justify-center gap-3 rounded-xl border border-border bg-white text-sm font-semibold text-foreground shadow-sm hover:bg-gray-50 transition-colors mb-6">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
|
||
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
|
||
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/>
|
||
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
|
||
</svg>
|
||
Daftar dengan Google
|
||
</button>
|
||
|
||
<div class="relative flex items-center mb-6">
|
||
<div class="flex-grow border-t border-border"></div>
|
||
<span class="flex-shrink-0 mx-4 text-xs text-muted-foreground uppercase tracking-wider font-semibold">atau dengan email</span>
|
||
<div class="flex-grow border-t border-border"></div>
|
||
</div>
|
||
|
||
<form action="register.php" method="POST" class="flex flex-col gap-4">
|
||
<input type="hidden" name="register" value="1">
|
||
|
||
<!-- Input Nama -->
|
||
<div class="group">
|
||
<label for="nama_lengkap" class="mb-1.5 block text-sm font-semibold text-foreground group-focus-within:text-primary transition-colors">
|
||
Nama Lengkap
|
||
</label>
|
||
<div class="relative">
|
||
<input type="text" id="nama_lengkap" name="nama_lengkap" class="block w-full rounded-xl border border-border bg-white py-2.5 px-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="John Doe" required>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Input Email -->
|
||
<div class="group">
|
||
<label for="email" class="mb-1.5 block text-sm font-semibold text-foreground group-focus-within:text-primary transition-colors">
|
||
Alamat Email
|
||
</label>
|
||
<div class="relative">
|
||
<input type="email" id="email" name="email" class="block w-full rounded-xl border border-border bg-white py-2.5 px-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="john@example.com" required>
|
||
</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">
|
||
<input type="password" id="password" name="password" class="block w-full rounded-xl border border-border bg-white py-2.5 px-3 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>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Input Role -->
|
||
<div class="group">
|
||
<label for="role" class="mb-1.5 block text-sm font-semibold text-foreground group-focus-within:text-primary transition-colors">
|
||
Daftar Sebagai
|
||
</label>
|
||
<div class="relative">
|
||
<select id="role" name="role" class="block w-full rounded-xl border border-border bg-white py-2.5 px-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 appearance-none" required>
|
||
<option value="guest">Guest (Pengunjung Umum)</option>
|
||
<option value="petugas">Petugas (Verifikator Lapangan)</option>
|
||
</select>
|
||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-3 text-muted-foreground">
|
||
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Submit -->
|
||
<button type="submit" class="group mt-3 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">
|
||
Daftar Sekarang
|
||
</button>
|
||
</form>
|
||
|
||
<div class="mt-6 text-center text-sm text-muted-foreground">
|
||
Sudah punya akun? <a href="login.php" class="font-semibold text-primary hover:underline">Masuk di sini</a>
|
||
</div>
|
||
</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>
|
||
function startGoogleAuth() {
|
||
const role = document.getElementById('role').value;
|
||
window.location.href = "<?= $google_auth_url ?>" + "&state=" + encodeURIComponent(role);
|
||
}
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|