437 lines
13 KiB
PHP
437 lines
13 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Masuk — WebGIS Pontianak</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--bg: #080c14;
|
|
--surface: #0f1522;
|
|
--card: #141b2d;
|
|
--border: rgba(99,179,237,0.12);
|
|
--accent: #3b82f6;
|
|
--accent2: #06b6d4;
|
|
--gold: #f59e0b;
|
|
--green: #10b981;
|
|
--red: #ef4444;
|
|
--text: #e2e8f0;
|
|
--text2: #7c93b5;
|
|
--glow: rgba(59,130,246,0.25);
|
|
}
|
|
*{box-sizing:border-box;margin:0;padding:0}
|
|
body{
|
|
font-family:'Sora',sans-serif;
|
|
background:var(--bg);
|
|
color:var(--text);
|
|
min-height:100vh;
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:center;
|
|
overflow:hidden;
|
|
position:relative;
|
|
}
|
|
|
|
/* Animated background */
|
|
.bg-grid{
|
|
position:fixed;inset:0;
|
|
background-image:
|
|
linear-gradient(rgba(59,130,246,0.04) 1px,transparent 1px),
|
|
linear-gradient(90deg,rgba(59,130,246,0.04) 1px,transparent 1px);
|
|
background-size:40px 40px;
|
|
animation:gridMove 20s linear infinite;
|
|
}
|
|
@keyframes gridMove{ to{background-position:40px 40px} }
|
|
|
|
.bg-orb{
|
|
position:fixed;
|
|
border-radius:50%;
|
|
filter:blur(80px);
|
|
pointer-events:none;
|
|
}
|
|
.orb1{width:600px;height:600px;background:rgba(59,130,246,0.08);top:-200px;right:-100px;animation:orbFloat 12s ease-in-out infinite;}
|
|
.orb2{width:400px;height:400px;background:rgba(6,182,212,0.06);bottom:-100px;left:-100px;animation:orbFloat 15s ease-in-out infinite reverse;}
|
|
.orb3{width:300px;height:300px;background:rgba(245,158,11,0.04);top:50%;left:50%;transform:translate(-50%,-50%);animation:orbFloat 18s ease-in-out infinite 3s;}
|
|
@keyframes orbFloat{0%,100%{transform:translate(0,0)}50%{transform:translate(30px,-30px)}}
|
|
|
|
/* Floating particles */
|
|
.particles{position:fixed;inset:0;pointer-events:none}
|
|
.particle{
|
|
position:absolute;
|
|
width:2px;height:2px;
|
|
background:var(--accent);
|
|
border-radius:50%;
|
|
opacity:0;
|
|
animation:particleFly 8s ease-in infinite;
|
|
}
|
|
@keyframes particleFly{
|
|
0%{opacity:0;transform:translateY(100vh) scale(0)}
|
|
10%{opacity:0.6}
|
|
90%{opacity:0.2}
|
|
100%{opacity:0;transform:translateY(-20px) scale(1)}
|
|
}
|
|
|
|
/* Main container */
|
|
.login-wrap{
|
|
position:relative;z-index:10;
|
|
display:grid;
|
|
grid-template-columns:1fr 1fr;
|
|
max-width:900px;width:95%;
|
|
min-height:560px;
|
|
border-radius:24px;
|
|
overflow:hidden;
|
|
box-shadow:0 40px 80px rgba(0,0,0,0.6), 0 0 0 1px var(--border);
|
|
animation:wrapIn 0.8s cubic-bezier(0.23,1,0.32,1) both;
|
|
}
|
|
@keyframes wrapIn{from{opacity:0;transform:translateY(30px) scale(0.97)}to{opacity:1;transform:none}}
|
|
|
|
/* Left panel */
|
|
.login-hero{
|
|
background:linear-gradient(135deg,#0d1929 0%,#0a1628 50%,#060e1a 100%);
|
|
padding:52px 48px;
|
|
display:flex;flex-direction:column;justify-content:space-between;
|
|
position:relative;overflow:hidden;
|
|
}
|
|
.hero-map{
|
|
position:absolute;inset:0;opacity:0.15;
|
|
background-image:radial-gradient(circle at 30% 60%, var(--accent) 0%, transparent 50%);
|
|
}
|
|
.hero-dots{
|
|
position:absolute;inset:0;
|
|
background-image:radial-gradient(circle,rgba(59,130,246,0.4) 1px,transparent 1px);
|
|
background-size:24px 24px;
|
|
opacity:0.3;
|
|
}
|
|
.brand{position:relative;z-index:2}
|
|
.brand-icon{
|
|
width:56px;height:56px;
|
|
background:linear-gradient(135deg,var(--accent),var(--accent2));
|
|
border-radius:16px;
|
|
display:flex;align-items:center;justify-content:center;
|
|
font-size:26px;
|
|
margin-bottom:20px;
|
|
box-shadow:0 8px 32px var(--glow);
|
|
}
|
|
.brand-name{font-size:22px;font-weight:800;letter-spacing:-0.5px;line-height:1.2}
|
|
.brand-sub{font-size:12px;color:var(--text2);margin-top:4px;letter-spacing:0.5px}
|
|
|
|
.hero-stats{
|
|
position:relative;z-index:2;
|
|
display:flex;flex-direction:column;gap:12px;
|
|
}
|
|
.hero-stat{
|
|
display:flex;align-items:center;gap:12px;
|
|
padding:12px 16px;
|
|
background:rgba(255,255,255,0.04);
|
|
border:1px solid rgba(255,255,255,0.06);
|
|
border-radius:12px;
|
|
backdrop-filter:blur(8px);
|
|
}
|
|
.hs-icon{font-size:20px}
|
|
.hs-num{font-size:18px;font-weight:700;color:var(--accent)}
|
|
.hs-label{font-size:11px;color:var(--text2);margin-top:1px}
|
|
|
|
.hero-footer{
|
|
position:relative;z-index:2;
|
|
font-size:11px;color:rgba(124,147,181,0.6);
|
|
}
|
|
|
|
/* Right panel */
|
|
.login-form-wrap{
|
|
background:var(--card);
|
|
padding:52px 48px;
|
|
display:flex;flex-direction:column;justify-content:center;
|
|
}
|
|
.form-title{font-size:26px;font-weight:800;letter-spacing:-0.5px;margin-bottom:4px}
|
|
.form-sub{font-size:13px;color:var(--text2);margin-bottom:32px}
|
|
|
|
/* Role tabs */
|
|
.role-tabs{
|
|
display:grid;grid-template-columns:1fr 1fr 1fr;
|
|
gap:6px;margin-bottom:28px;
|
|
background:rgba(255,255,255,0.03);
|
|
border:1px solid var(--border);
|
|
border-radius:14px;padding:5px;
|
|
}
|
|
.role-tab{
|
|
padding:8px 4px;
|
|
border-radius:10px;
|
|
border:none;background:transparent;
|
|
color:var(--text2);
|
|
font-family:'Sora',sans-serif;
|
|
font-size:11px;font-weight:600;
|
|
cursor:pointer;
|
|
transition:all 0.2s;
|
|
display:flex;flex-direction:column;align-items:center;gap:3px;
|
|
}
|
|
.role-tab .tab-icon{font-size:16px}
|
|
.role-tab.active{
|
|
background:var(--accent);
|
|
color:#fff;
|
|
box-shadow:0 4px 16px var(--glow);
|
|
}
|
|
.role-tab:not(.active):hover{background:rgba(255,255,255,0.05);color:var(--text)}
|
|
|
|
/* Form fields */
|
|
.field{margin-bottom:16px}
|
|
.field label{display:block;font-size:12px;font-weight:600;color:var(--text2);margin-bottom:6px;letter-spacing:0.3px}
|
|
.field-wrap{position:relative}
|
|
.field-icon{
|
|
position:absolute;left:14px;top:50%;transform:translateY(-50%);
|
|
font-size:16px;pointer-events:none;z-index:2;
|
|
}
|
|
.field input{
|
|
width:100%;
|
|
background:rgba(255,255,255,0.04);
|
|
border:1px solid var(--border);
|
|
color:var(--text);
|
|
padding:12px 14px 12px 42px;
|
|
border-radius:12px;
|
|
font-family:'Sora',sans-serif;
|
|
font-size:14px;
|
|
transition:all 0.2s;
|
|
outline:none;
|
|
}
|
|
.field input:focus{
|
|
border-color:var(--accent);
|
|
background:rgba(59,130,246,0.06);
|
|
box-shadow:0 0 0 3px var(--glow);
|
|
}
|
|
.field input::placeholder{color:rgba(124,147,181,0.4)}
|
|
|
|
.toggle-pw{
|
|
position:absolute;right:14px;top:50%;transform:translateY(-50%);
|
|
background:none;border:none;color:var(--text2);cursor:pointer;
|
|
font-size:16px;padding:2px;
|
|
}
|
|
|
|
.error-msg{
|
|
background:rgba(239,68,68,0.1);
|
|
border:1px solid rgba(239,68,68,0.3);
|
|
color:#fca5a5;
|
|
padding:10px 14px;border-radius:10px;
|
|
font-size:12px;margin-bottom:16px;
|
|
display:none;
|
|
}
|
|
.error-msg.show{display:block}
|
|
|
|
.btn-login{
|
|
width:100%;padding:14px;
|
|
background:linear-gradient(135deg,var(--accent),var(--accent2));
|
|
border:none;border-radius:12px;
|
|
color:#fff;
|
|
font-family:'Sora',sans-serif;
|
|
font-size:14px;font-weight:700;
|
|
cursor:pointer;
|
|
transition:all 0.2s;
|
|
box-shadow:0 8px 24px var(--glow);
|
|
position:relative;overflow:hidden;
|
|
}
|
|
.btn-login:hover{transform:translateY(-1px);box-shadow:0 12px 32px var(--glow)}
|
|
.btn-login:active{transform:translateY(0)}
|
|
.btn-login:disabled{opacity:0.6;cursor:not-allowed;transform:none}
|
|
.btn-login .spinner{
|
|
display:inline-block;width:16px;height:16px;
|
|
border:2px solid rgba(255,255,255,0.3);
|
|
border-top-color:#fff;
|
|
border-radius:50%;
|
|
animation:spin 0.7s linear infinite;
|
|
vertical-align:middle;margin-right:6px;
|
|
}
|
|
@keyframes spin{to{transform:rotate(360deg)}}
|
|
|
|
.form-links{
|
|
margin-top:20px;text-align:center;
|
|
font-size:12px;color:var(--text2);
|
|
}
|
|
.form-links a{color:var(--accent);text-decoration:none;font-weight:600}
|
|
.form-links a:hover{text-decoration:underline}
|
|
|
|
.register-hint{
|
|
margin-top:12px;
|
|
padding:12px;
|
|
background:rgba(16,185,129,0.06);
|
|
border:1px solid rgba(16,185,129,0.2);
|
|
border-radius:10px;
|
|
font-size:11px;color:rgba(16,185,129,0.8);
|
|
text-align:center;
|
|
}
|
|
|
|
@media(max-width:700px){
|
|
.login-wrap{grid-template-columns:1fr}
|
|
.login-hero{display:none}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="bg-grid"></div>
|
|
<div class="bg-orb orb1"></div>
|
|
<div class="bg-orb orb2"></div>
|
|
<div class="bg-orb orb3"></div>
|
|
<div class="particles" id="particles"></div>
|
|
|
|
<div class="login-wrap">
|
|
<!-- Left hero -->
|
|
<div class="login-hero">
|
|
<div class="hero-map"></div>
|
|
<div class="hero-dots"></div>
|
|
<div class="brand">
|
|
<div class="brand-icon">🗺️</div>
|
|
<div class="brand-name">WebGIS Pontianak</div>
|
|
<div class="brand-sub">SISTEM PENDUDUK MISKIN TERINTEGRASI</div>
|
|
</div>
|
|
<div class="hero-stats">
|
|
<div class="hero-stat">
|
|
<div class="hs-icon">🏘️</div>
|
|
<div>
|
|
<div class="hs-num" id="h-kk">—</div>
|
|
<div class="hs-label">Kepala Keluarga Terdaftar</div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hs-icon">🕌</div>
|
|
<div>
|
|
<div class="hs-num" id="h-ibadah">—</div>
|
|
<div class="hs-label">Rumah Ibadah Aktif</div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-stat">
|
|
<div class="hs-icon">🤝</div>
|
|
<div>
|
|
<div class="hs-num" id="h-bantuan">—</div>
|
|
<div class="hs-label">Bantuan Tersalurkan</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="hero-footer">© 2025 Pemerintah Kota Pontianak · WebGIS v2.0</div>
|
|
</div>
|
|
|
|
<!-- Right form -->
|
|
<div class="login-form-wrap">
|
|
<div class="form-title">Selamat datang 👋</div>
|
|
<div class="form-sub">Masuk sesuai peran Anda dalam sistem</div>
|
|
|
|
<div class="role-tabs">
|
|
<button class="role-tab active" onclick="setRole('masyarakat',this)" id="tab-mas">
|
|
<span class="tab-icon">👤</span>Masyarakat
|
|
</button>
|
|
<button class="role-tab" onclick="setRole('pengurus_ibadah',this)" id="tab-pen">
|
|
<span class="tab-icon">🕌</span>Pengurus
|
|
</button>
|
|
<button class="role-tab" onclick="setRole('pemerintah',this)" id="tab-pem">
|
|
<span class="tab-icon">🏛️</span>Pemerintah
|
|
</button>
|
|
</div>
|
|
|
|
<div id="error-box" class="error-msg"></div>
|
|
|
|
<form id="login-form" onsubmit="doLogin(event)">
|
|
<input type="hidden" id="role-input" value="masyarakat">
|
|
|
|
<div class="field">
|
|
<label>USERNAME / NO. HP</label>
|
|
<div class="field-wrap">
|
|
<span class="field-icon">👤</span>
|
|
<input type="text" id="username" placeholder="Masukkan username Anda" autocomplete="username" required>
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<label>KATA SANDI</label>
|
|
<div class="field-wrap">
|
|
<span class="field-icon">🔒</span>
|
|
<input type="password" id="password" placeholder="••••••••" autocomplete="current-password" required>
|
|
<button type="button" class="toggle-pw" onclick="togglePw()">👁️</button>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn-login" id="btn-login">Masuk ke Sistem</button>
|
|
</form>
|
|
|
|
<div class="form-links">
|
|
Belum punya akun? <a href="daftar.php">Daftar sebagai Masyarakat / Pengurus Rumah Ibadah</a>
|
|
</div>
|
|
<div class="register-hint" id="role-hint">
|
|
Masyarakat dapat mendaftar mandiri dan melaporkan kejadian di sekitar mereka.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Particles
|
|
const pWrap = document.getElementById('particles');
|
|
for(let i=0;i<25;i++){
|
|
const p=document.createElement('div');
|
|
p.className='particle';
|
|
p.style.cssText=`left:${Math.random()*100}%;animation-delay:${Math.random()*8}s;animation-duration:${6+Math.random()*6}s;opacity:${Math.random()*0.5}`;
|
|
pWrap.appendChild(p);
|
|
}
|
|
|
|
// Load stats
|
|
fetch('api/auth.php?action=stats')
|
|
.then(r=>r.json()).then(d=>{
|
|
document.getElementById('h-kk').textContent=d.kk??'—';
|
|
document.getElementById('h-ibadah').textContent=d.ibadah??'—';
|
|
document.getElementById('h-bantuan').textContent=d.bantuan??'—';
|
|
}).catch(()=>{});
|
|
|
|
const hints={
|
|
masyarakat:'Masyarakat dapat mendaftar mandiri dan melaporkan kejadian di sekitar mereka.',
|
|
pengurus_ibadah:'Pengurus rumah ibadah mengelola data bantuan dan laporan warga binaan.',
|
|
pemerintah:'Pemerintah mendapat akses read-only untuk memantau semua data dan statistik.'
|
|
};
|
|
|
|
function setRole(role,el){
|
|
document.querySelectorAll('.role-tab').forEach(t=>t.classList.remove('active'));
|
|
el.classList.add('active');
|
|
document.getElementById('role-input').value=role;
|
|
document.getElementById('role-hint').textContent=hints[role]||'';
|
|
}
|
|
|
|
function togglePw(){
|
|
const i=document.getElementById('password');
|
|
i.type=i.type==='password'?'text':'password';
|
|
}
|
|
|
|
async function doLogin(e){
|
|
e.preventDefault();
|
|
const btn=document.getElementById('btn-login');
|
|
const errBox=document.getElementById('error-box');
|
|
btn.disabled=true;
|
|
btn.innerHTML='<span class="spinner"></span>Memverifikasi...';
|
|
errBox.classList.remove('show');
|
|
|
|
const body={
|
|
username:document.getElementById('username').value,
|
|
password:document.getElementById('password').value,
|
|
role:document.getElementById('role-input').value
|
|
};
|
|
|
|
try{
|
|
const res=await fetch('api/auth.php',{
|
|
method:'POST',
|
|
headers:{'Content-Type':'application/json'},
|
|
body:JSON.stringify(body)
|
|
});
|
|
const data=await res.json();
|
|
if(data.success){
|
|
btn.innerHTML='✅ Berhasil! Mengalihkan...';
|
|
window.location.href=data.redirect||'index.php';
|
|
} else {
|
|
errBox.textContent=data.error||'Username atau kata sandi salah.';
|
|
errBox.classList.add('show');
|
|
btn.disabled=false;
|
|
btn.innerHTML='Masuk ke Sistem';
|
|
}
|
|
} catch(err){
|
|
errBox.textContent='Terjadi kesalahan. Periksa koneksi Anda.';
|
|
errBox.classList.add('show');
|
|
btn.disabled=false;
|
|
btn.innerHTML='Masuk ke Sistem';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|