Files
WebGIS_Project/05/daftar.php
T
luthfihadinugroho79 e950468760 add files
2026-06-10 19:42:59 +07:00

614 lines
32 KiB
PHP

<?php
require_once 'includes/config.php';
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daftar Akun — WebGIS Pontianak</title>
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<style>
:root{
--bg:#080c14;--surface:#0f1522;--card:#141b2d;--border:rgba(99,179,237,0.12);
--accent:#3b82f6;--accent2:#06b6d4;--green:#10b981;--red:#ef4444;--amber:#f59e0b;
--text:#e2e8f0;--text2:#7c93b5;--glow:rgba(59,130,246,0.25);
--purple:#8b5cf6;--purple-glow:rgba(139,92,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;padding:24px}
.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;pointer-events:none}
.orb{position:fixed;border-radius:50%;filter:blur(80px);pointer-events:none}
.o1{width:500px;height:500px;background:rgba(59,130,246,0.06);top:-200px;right:-100px}
.o2{width:400px;height:400px;background:rgba(6,182,212,0.05);bottom:-100px;left:-100px}
.wrap{position:relative;z-index:10;width:100%;max-width:560px;background:var(--card);border:1px solid var(--border);border-radius:24px;overflow:hidden;box-shadow:0 40px 80px rgba(0,0,0,0.5);animation:wrapIn 0.6s cubic-bezier(0.23,1,0.32,1)}
@keyframes wrapIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
.wrap-head{background:linear-gradient(135deg,#0d1929,#060e1a);padding:22px 28px;text-align:center;border-bottom:1px solid var(--border)}
.head-title{font-size:18px;font-weight:800;margin-bottom:3px}
.head-sub{font-size:11px;color:var(--text2)}
/* ROLE TABS */
.role-tabs{display:flex;gap:0;padding:12px 16px 0;border-bottom:1px solid var(--border);background:rgba(0,0,0,0.2)}
.rtab{flex:1;padding:9px 6px;border:none;background:none;font-family:'Sora',sans-serif;font-size:11px;font-weight:700;color:var(--text2);cursor:pointer;border-bottom:2px solid transparent;transition:all 0.2s;display:flex;align-items:center;justify-content:center;gap:5px}
.rtab.active{color:var(--accent);border-bottom-color:var(--accent)}
.rtab.active.pengurus-tab{color:var(--purple);border-bottom-color:var(--purple)}
.form-body{padding:20px 28px}
/* STEP BAR */
.step-bar{display:flex;gap:0;margin-bottom:18px;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:12px;padding:4px}
.step{flex:1;padding:6px;border-radius:9px;text-align:center;font-size:9px;font-weight:700;color:var(--text2);transition:all 0.2s}
.step.active{background:var(--accent);color:#fff;box-shadow:0 4px 12px var(--glow)}
.step.active.p-step{background:var(--purple);box-shadow:0 4px 12px var(--purple-glow)}
.step.done{background:rgba(16,185,129,0.15);color:var(--green)}
/* FIELDS */
.fl{margin-bottom:11px}
.fl label{display:block;font-size:10px;font-weight:800;color:var(--text2);margin-bottom:4px;letter-spacing:0.4px;text-transform:uppercase}
.fl input,.fl select{width:100%;background:rgba(255,255,255,0.04);border:1px solid var(--border);color:var(--text);padding:9px 11px;border-radius:10px;font-family:'Sora',sans-serif;font-size:12px;transition:all 0.2s;outline:none}
.fl input:focus,.fl select:focus{border-color:var(--accent);background:rgba(59,130,246,0.05);box-shadow:0 0 0 3px var(--glow)}
.fl input::placeholder{color:rgba(124,147,181,0.4)}
.fl .hint{font-size:9px;color:var(--text2);margin-top:3px;min-height:13px}
.fl select option{background:#0d1424}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.pw-wrap{position:relative}
.pw-wrap input{padding-right:38px}
.pw-toggle{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;color:var(--text2);cursor:pointer;font-size:14px;padding:2px}
.strength-bar{height:3px;border-radius:2px;background:rgba(255,255,255,0.08);margin-top:4px;overflow:hidden}
.strength-fill{height:100%;border-radius:2px;transition:all 0.3s;width:0}
/* MAP */
.map-section{margin-bottom:11px}
.map-section label{display:block;font-size:10px;font-weight:800;color:var(--text2);margin-bottom:4px;letter-spacing:0.4px;text-transform:uppercase}
#loc-map{height:220px;border-radius:10px;border:1px solid var(--border);overflow:hidden;cursor:crosshair}
.map-info{background:rgba(59,130,246,0.06);border:1px solid rgba(59,130,246,0.18);border-radius:8px;padding:8px 10px;font-size:10px;color:rgba(147,197,253,0.85);margin-top:6px;line-height:1.6;display:flex;align-items:flex-start;gap:6px}
.map-info.has-loc{background:rgba(16,185,129,0.06);border-color:rgba(16,185,129,0.2);color:rgba(110,231,183,0.9)}
.map-coords{display:flex;gap:6px;margin-top:6px}
.map-coords .fl{flex:1;margin-bottom:0}
/* RADIUS SLIDER */
.radius-section{margin-bottom:11px}
.radius-section label{display:block;font-size:10px;font-weight:800;color:var(--text2);margin-bottom:4px;letter-spacing:0.4px;text-transform:uppercase}
.radius-ctrl{display:flex;align-items:center;gap:10px;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:10px;padding:10px 12px}
.radius-ctrl input[type=range]{flex:1;-webkit-appearance:none;height:4px;border-radius:2px;background:linear-gradient(to right,var(--purple) 0%,var(--purple) var(--pct,30%),rgba(255,255,255,0.1) var(--pct,30%),rgba(255,255,255,0.1) 100%);outline:none;cursor:pointer}
.radius-ctrl input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--purple);box-shadow:0 2px 8px var(--purple-glow);cursor:pointer}
.radius-val{font-size:13px;font-weight:800;color:var(--purple);min-width:52px;text-align:right}
/* ALERTS */
.alert-box{padding:9px 12px;border-radius:10px;font-size:11px;margin-bottom:10px;display:none;align-items:center;gap:7px}
.alert-box.show{display:flex}
.alert-err{background:rgba(239,68,68,0.1);border:1px solid rgba(239,68,68,0.3);color:#fca5a5}
.alert-ok{background:rgba(16,185,129,0.1);border:1px solid rgba(16,185,129,0.3);color:#6ee7b7}
/* BUTTONS */
.btn{width:100%;padding:11px;border-radius:11px;border:none;font-family:'Sora',sans-serif;font-size:12px;font-weight:700;cursor:pointer;transition:all 0.2s;display:flex;align-items:center;justify-content:center;gap:7px;text-decoration:none}
.btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;box-shadow:0 8px 24px var(--glow)}
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 12px 32px var(--glow)}
.btn-primary:disabled{opacity:0.6;cursor:not-allowed;transform:none}
.btn-purple{background:linear-gradient(135deg,var(--purple),#a78bfa);color:#fff;box-shadow:0 8px 24px var(--purple-glow)}
.btn-purple:hover{transform:translateY(-1px);box-shadow:0 12px 32px var(--purple-glow)}
.btn-purple:disabled{opacity:0.6;cursor:not-allowed;transform:none}
.btn-ghost{background:rgba(255,255,255,0.04);border:1px solid var(--border);color:var(--text2)}
.btn-ghost:hover{background:rgba(255,255,255,0.08);color:var(--text)}
.btn-row{display:flex;gap:8px}
.btn-row .btn{flex:1}
.spinner{width:14px;height:14px;border:2px solid rgba(255,255,255,0.3);border-top-color:#fff;border-radius:50%;animation:spin 0.7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.info-box{background:rgba(59,130,246,0.06);border:1px solid rgba(59,130,246,0.18);border-radius:9px;padding:9px 11px;font-size:10px;color:rgba(147,197,253,0.85);margin-bottom:11px;line-height:1.6}
.info-box.purple{background:rgba(139,92,246,0.06);border-color:rgba(139,92,246,0.18);color:rgba(196,181,253,0.9)}
.form-foot{padding:12px 28px;border-top:1px solid var(--border);text-align:center;font-size:11px;color:var(--text2)}
.form-foot a{color:var(--accent);text-decoration:none;font-weight:600}
/* SUCCESS */
.success-wrap{text-align:center;padding:8px 0}
.success-icon{font-size:48px;margin-bottom:12px;animation:pop 0.5s cubic-bezier(0.23,1,0.32,1)}
@keyframes pop{from{transform:scale(0)}to{transform:scale(1)}}
.success-title{font-size:17px;font-weight:800;margin-bottom:7px}
.success-sub{font-size:12px;color:var(--text2);margin-bottom:16px;line-height:1.6}
.success-list{background:rgba(16,185,129,0.07);border:1px solid rgba(16,185,129,0.2);border-radius:11px;padding:12px;text-align:left;font-size:10px;color:var(--text2);line-height:2.1;margin-bottom:18px}
.success-list b{color:var(--green)}
.success-warn{background:rgba(245,158,11,0.07);border:1px solid rgba(245,158,11,0.2);border-radius:11px;padding:12px;text-align:left;font-size:10px;color:rgba(253,230,138,0.85);line-height:2;margin-bottom:18px}
.loc-btn{width:100%;padding:8px;border-radius:8px;border:1px dashed rgba(139,92,246,0.3);background:rgba(139,92,246,0.05);color:rgba(196,181,253,0.8);font-family:'Sora',sans-serif;font-size:10px;font-weight:700;cursor:pointer;transition:all 0.2s;margin-bottom:7px}
.loc-btn:hover{background:rgba(139,92,246,0.12);border-color:rgba(139,92,246,0.5)}
</style>
</head>
<body>
<div class="bg-grid"></div>
<div class="orb o1"></div>
<div class="orb o2"></div>
<div class="wrap">
<div class="wrap-head">
<div class="head-title">📋 Daftar Akun</div>
<div class="head-sub">WebGIS Pontianak — Pilih jenis akun yang ingin Anda buat</div>
</div>
<!-- ROLE TABS -->
<div class="role-tabs">
<button class="rtab active" id="tab-masy" onclick="switchRole('masyarakat')">
👤 Masyarakat
</button>
<button class="rtab pengurus-tab" id="tab-peng" onclick="switchRole('pengurus')">
🕌 Pengurus Ibadah
</button>
</div>
<!-- ══════════════ FORM MASYARAKAT ══════════════ -->
<div id="form-masyarakat">
<div class="form-body">
<div class="step-bar" id="masy-steps">
<div class="step active" id="ms1">① Akun</div>
<div class="step" id="ms2">② Data Diri</div>
<div class="step" id="ms3">③ Selesai</div>
</div>
<div id="m-alert" class="alert-box"></div>
<!-- M-Step 1 -->
<div id="m-s1">
<div class="fl">
<label>Username *</label>
<input type="text" id="m-username" placeholder="Minimal 4 karakter, tanpa spasi" oninput="checkUname('m')">
<div class="hint" id="m-uname-hint"></div>
</div>
<div class="fl">
<label>Kata Sandi *</label>
<div class="pw-wrap">
<input type="password" id="m-password" placeholder="Minimal 6 karakter" oninput="checkPw('m')">
<button type="button" class="pw-toggle" onclick="togPw('m-password')">👁️</button>
</div>
<div class="strength-bar"><div class="strength-fill" id="m-pw-str"></div></div>
<div class="hint" id="m-pw-hint"></div>
</div>
<div class="fl">
<label>Konfirmasi Kata Sandi *</label>
<div class="pw-wrap">
<input type="password" id="m-confirm" placeholder="Ulangi kata sandi" oninput="checkConfirm('m')">
<button type="button" class="pw-toggle" onclick="togPw('m-confirm')">👁️</button>
</div>
<div class="hint" id="m-confirm-hint"></div>
</div>
<button class="btn btn-primary" onclick="mNext()">Lanjut →</button>
</div>
<!-- M-Step 2 -->
<div id="m-s2" style="display:none">
<div class="info-box">💡 Data ini untuk menghubungkan akun dengan data keluarga dalam sistem.</div>
<div class="fl"><label>Nama Lengkap *</label><input type="text" id="m-nama" placeholder="Nama lengkap sesuai KTP"></div>
<div class="fl"><label>Nomor HP / WhatsApp *</label><input type="tel" id="m-hp" placeholder="08xx-xxxx-xxxx"></div>
<div class="fl"><label>Email (opsional)</label><input type="email" id="m-email" placeholder="email@contoh.com"></div>
<div class="fl">
<label>Nomor KK (opsional)</label>
<input type="text" id="m-nokk" placeholder="16 digit nomor Kartu Keluarga" maxlength="16" inputmode="numeric">
<div class="hint">Jika diisi, akun Anda terhubung otomatis ke data keluarga.</div>
</div>
<div class="btn-row">
<button class="btn btn-ghost" onclick="mBack()">← Kembali</button>
<button class="btn btn-primary" id="m-btn-reg" onclick="doRegisterMasy()">✅ Buat Akun</button>
</div>
</div>
<!-- M-Step 3 Sukses -->
<div id="m-s3" style="display:none">
<div class="success-wrap">
<div class="success-icon">🎉</div>
<div class="success-title">Akun Berhasil Dibuat!</div>
<div class="success-sub">Selamat datang di WebGIS Pontianak.<br>Anda siap berkontribusi untuk komunitas.</div>
<div class="success-list">
<b>Yang bisa Anda lakukan:</b><br>
📢 Laporkan kelahiran, kematian, kepindahan<br>
🗺️ Lihat peta sebaran penduduk sekitar<br>
🤝 Pantau riwayat bantuan keluarga<br>
📍 Bagikan lokasi Anda di peta
</div>
<a href="login.php" class="btn btn-primary">🚀 Masuk Sekarang</a>
</div>
</div>
</div>
<div class="form-foot" id="m-foot">Sudah punya akun? <a href="login.php">Masuk di sini</a></div>
</div>
<!-- ══════════════ FORM PENGURUS ══════════════ -->
<div id="form-pengurus" style="display:none">
<div class="form-body">
<div class="step-bar" id="peng-steps">
<div class="step active p-step" id="ps1">① Akun</div>
<div class="step" id="ps2">② Rumah Ibadah</div>
<div class="step" id="ps3">③ Lokasi</div>
<div class="step" id="ps4">④ Selesai</div>
</div>
<div id="p-alert" class="alert-box"></div>
<!-- P-Step 1: Data Akun -->
<div id="p-s1">
<div class="info-box purple">🕌 Daftar sebagai pengurus rumah ibadah baru. Akun dan data rumah ibadah akan dibuat langsung setelah pendaftaran.</div>
<div class="fl"><label>Nama Lengkap *</label><input type="text" id="p-nama" placeholder="Nama lengkap pengurus"></div>
<div class="fl">
<label>Username *</label>
<input type="text" id="p-username" placeholder="Minimal 4 karakter" oninput="checkUname('p')">
<div class="hint" id="p-uname-hint"></div>
</div>
<div class="form-grid">
<div class="fl"><label>Nomor HP *</label><input type="tel" id="p-hp" placeholder="08xx-xxxx-xxxx"></div>
<div class="fl"><label>Email</label><input type="email" id="p-email" placeholder="email@..."></div>
</div>
<div class="fl">
<label>Kata Sandi *</label>
<div class="pw-wrap">
<input type="password" id="p-password" placeholder="Minimal 6 karakter" oninput="checkPw('p')">
<button type="button" class="pw-toggle" onclick="togPw('p-password')">👁️</button>
</div>
<div class="strength-bar"><div class="strength-fill" id="p-pw-str"></div></div>
<div class="hint" id="p-pw-hint"></div>
</div>
<div class="fl">
<label>Konfirmasi Kata Sandi *</label>
<div class="pw-wrap">
<input type="password" id="p-confirm" placeholder="Ulangi kata sandi" oninput="checkConfirm('p')">
<button type="button" class="pw-toggle" onclick="togPw('p-confirm')">👁️</button>
</div>
<div class="hint" id="p-confirm-hint"></div>
</div>
<button class="btn btn-purple" onclick="pNext1()">Lanjut →</button>
</div>
<!-- P-Step 2: Info Rumah Ibadah -->
<div id="p-s2" style="display:none">
<div class="fl"><label>Nama Rumah Ibadah *</label><input type="text" id="p-nama-ibadah" placeholder="Masjid Al-Ikhlas / GBI Pontianak..."></div>
<div class="form-grid">
<div class="fl">
<label>Jenis *</label>
<select id="p-jenis">
<option>Masjid</option><option>Gereja</option><option>Vihara</option>
<option>Pura</option><option>Klenteng</option><option>Lainnya</option>
</select>
</div>
<div class="fl"><label>Kelurahan</label><input type="text" id="p-kel" placeholder="Auto dari peta"></div>
</div>
<div class="fl"><label>Kecamatan</label><input type="text" id="p-kec" placeholder="Auto dari peta"></div>
<!-- Radius Slider -->
<div class="radius-section">
<label>Radius Binaan (meter)</label>
<div class="radius-ctrl">
<input type="range" id="p-radius-range" min="50" max="2000" value="300"
oninput="updateRadiusDisplay('p',this.value)">
<span class="radius-val" id="p-radius-val">300 m</span>
</div>
<div class="hint" style="margin-top:5px">Jangkauan wilayah binaan rumah ibadah di peta</div>
</div>
<div class="btn-row">
<button class="btn btn-ghost" onclick="pBack1()">← Kembali</button>
<button class="btn btn-purple" onclick="pNext2()">Lanjut →</button>
</div>
</div>
<!-- P-Step 3: Lokasi via Peta -->
<div id="p-s3" style="display:none">
<div class="map-section">
<label>📍 Klik peta untuk tentukan lokasi rumah ibadah *</label>
<button class="loc-btn" id="btn-gps" onclick="getGPS()">📡 Gunakan lokasi GPS saya sebagai titik awal</button>
<div id="loc-map"></div>
<div class="map-info" id="map-info">
🖱️ Klik di peta untuk menandai lokasi rumah ibadah. Alamat akan terisi otomatis.
</div>
</div>
<div class="map-coords">
<div class="fl"><label>Latitude</label><input class="finput" type="text" id="p-lat" readonly placeholder="—"></div>
<div class="fl"><label>Longitude</label><input class="finput" type="text" id="p-lng" readonly placeholder="—"></div>
</div>
<div class="fl"><label>Alamat Lengkap</label><input type="text" id="p-alamat" placeholder="Diisi otomatis dari peta"></div>
<div class="btn-row" style="margin-top:6px">
<button class="btn btn-ghost" onclick="pBack2()">← Kembali</button>
<button class="btn btn-purple" id="p-btn-reg" onclick="doRegisterPengurus()">📨 Kirim Pendaftaran</button>
</div>
</div>
<!-- P-Step 4: Sukses -->
<div id="p-s4" style="display:none">
<div class="success-wrap">
<div class="success-icon">✅</div>
<div class="success-title">Akun Berhasil Dibuat!</div>
<div class="success-sub">Akun pengurus dan rumah ibadah telah berhasil dibuat.<br>Silakan login untuk mulai menggunakan layanan.</div>
<div class="success-warn">
🏠 <b style="color:var(--accent)">Akun Anda sudah aktif</b><br>
Username dan kata sandi yang Anda daftarkan sudah bisa digunakan untuk login.<br>
Jika ingin mengelola radius atau data rumah ibadah, masuk ke dashboard pengurus.
</div>
<a href="login.php" class="btn btn-purple">🚀 Masuk Sekarang</a>
</div>
</div>
</div>
<div class="form-foot" id="p-foot">Sudah punya akun? <a href="login.php">Masuk di sini</a></div>
</div>
</div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
// ── State ────────────────────────────────────────────────────
const ST = {
m: { unameOk:false, pwOk:false, confirmOk:false },
p: { unameOk:false, pwOk:false, confirmOk:false }
};
let locMap = null, locMarker = null, locCircle = null;
let selectedLat = null, selectedLng = null;
// ── Role switch ──────────────────────────────────────────────
function switchRole(role) {
document.getElementById('form-masyarakat').style.display = role==='masyarakat'?'':'none';
document.getElementById('form-pengurus').style.display = role==='pengurus'?'':'none';
document.getElementById('tab-masy').className = 'rtab' + (role==='masyarakat'?' active':'');
document.getElementById('tab-peng').className = 'rtab pengurus-tab' + (role==='pengurus'?' active':'');
if (role==='pengurus' && !locMap) setTimeout(initMap, 100);
}
// ── Shared helpers ───────────────────────────────────────────
function togPw(id){const i=document.getElementById(id);i.type=i.type==='password'?'text':'password';}
function showAlert(prefix, msg, type='err'){
const el=document.getElementById(prefix+'-alert');
el.className='alert-box show alert-'+type;
el.innerHTML=(type==='err'?'❌ ':'✅ ')+msg;
setTimeout(()=>el.classList.remove('show'),5000);
}
function checkUname(prefix){
const val=document.getElementById(prefix+'-username').value.trim();
const hint=document.getElementById(prefix+'-uname-hint');
if(!val){hint.textContent='';ST[prefix].unameOk=false;return;}
if(val.length<4){hint.style.color='#fca5a5';hint.textContent='❌ Minimal 4 karakter';ST[prefix].unameOk=false;return;}
if(/\s/.test(val)){hint.style.color='#fca5a5';hint.textContent='❌ Tidak boleh ada spasi';ST[prefix].unameOk=false;return;}
if(!/^[a-zA-Z0-9_]+$/.test(val)){hint.style.color='#fca5a5';hint.textContent='❌ Hanya huruf, angka, dan _';ST[prefix].unameOk=false;return;}
ST[prefix].unameOk=true;hint.style.color='#6ee7b7';hint.textContent='✅ Username valid';
}
function checkPw(prefix){
const val=document.getElementById(prefix+'-password').value;
const fill=document.getElementById(prefix+'-pw-str');
const hint=document.getElementById(prefix+'-pw-hint');
if(!val){fill.style.width='0';hint.textContent='';ST[prefix].pwOk=false;return;}
let s=0;
if(val.length>=6)s++;if(val.length>=10)s++;if(/[A-Z]/.test(val))s++;
if(/[0-9]/.test(val))s++;if(/[^A-Za-z0-9]/.test(val))s++;
const C=['','#ef4444','#f97316','#f59e0b','#10b981','#3b82f6'];
const L=['','Sangat Lemah','Lemah','Cukup','Kuat','Sangat Kuat'];
fill.style.width=(s*20)+'%';fill.style.background=C[s]||'#ef4444';
hint.style.color=C[s]||'#ef4444';hint.textContent='Kekuatan: '+(L[s]||'Sangat Lemah');
ST[prefix].pwOk=s>=2&&val.length>=6;
const cv=document.getElementById(prefix+'-confirm').value;if(cv)checkConfirm(prefix);
}
function checkConfirm(prefix){
const val=document.getElementById(prefix+'-confirm').value;
const hint=document.getElementById(prefix+'-confirm-hint');
const pw=document.getElementById(prefix+'-password').value;
if(!val){hint.textContent='';ST[prefix].confirmOk=false;return;}
if(val===pw){hint.style.color='#6ee7b7';hint.textContent='✅ Kata sandi cocok';ST[prefix].confirmOk=true;}
else{hint.style.color='#fca5a5';hint.textContent='❌ Kata sandi tidak cocok';ST[prefix].confirmOk=false;}
}
// ── RADIUS SLIDER DISPLAY ────────────────────────────────────
function updateRadiusDisplay(prefix, val){
document.getElementById(prefix+'-radius-val').textContent = val + ' m';
// Update slider gradient
const min=50, max=2000;
const pct = ((val-min)/(max-min)*100).toFixed(1);
document.getElementById(prefix+'-radius-range').style.setProperty('--pct', pct+'%');
// Update lingkaran di peta jika sudah ada
if(prefix==='p' && locCircle){
locCircle.setRadius(parseInt(val));
}
}
// ── MASYARAKAT STEPS ─────────────────────────────────────────
function mNext(){
if(!ST.m.unameOk){showAlert('m','Username tidak valid — periksa kembali');return;}
if(!ST.m.pwOk){showAlert('m','Kata sandi terlalu lemah (minimal 6 karakter)');return;}
if(!ST.m.confirmOk){showAlert('m','Konfirmasi kata sandi tidak cocok');return;}
show('m-s1','m-s2');
setStep('ms','ms1','done');setStep('ms','ms2','active');
}
function mBack(){show('m-s2','m-s1');setStep('ms','ms1','active');setStep('ms','ms2','');}
// ── PENGURUS STEPS ───────────────────────────────────────────
function pNext1(){
const nama=document.getElementById('p-nama').value.trim();
const hp=document.getElementById('p-hp').value.trim();
if(!nama){showAlert('p','Nama lengkap wajib diisi');return;}
if(!hp){showAlert('p','Nomor HP wajib diisi');return;}
if(!ST.p.unameOk){showAlert('p','Username tidak valid');return;}
if(!ST.p.pwOk){showAlert('p','Kata sandi terlalu lemah');return;}
if(!ST.p.confirmOk){showAlert('p','Konfirmasi kata sandi tidak cocok');return;}
show('p-s1','p-s2');
setStep('ps','ps1','done');setStep('ps','ps2','active p-step');
}
function pBack1(){show('p-s2','p-s1');setStep('ps','ps1','active p-step');setStep('ps','ps2','');}
function pNext2(){
const ni=document.getElementById('p-nama-ibadah').value.trim();
if(!ni){showAlert('p','Nama rumah ibadah wajib diisi');return;}
show('p-s2','p-s3');
setStep('ps','ps2','done');setStep('ps','ps3','active p-step');
if(!locMap)initMap();else locMap.invalidateSize();
}
function pBack2(){show('p-s3','p-s2');setStep('ps','ps2','active p-step');setStep('ps','ps3','');}
function show(hide,show){document.getElementById(hide).style.display='none';document.getElementById(show).style.display='block';}
function setStep(bar,id,cls){
document.getElementById(id).className='step '+(cls||'');
}
// ── PETA REVERSE GEOCODING ───────────────────────────────────
function initMap(){
if(locMap)return;
locMap = L.map('loc-map',{zoomControl:true}).setView([-0.0236,109.3282],13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
attribution:'© OpenStreetMap',maxZoom:19
}).addTo(locMap);
locMap.on('click', e => placeMarker(e.latlng.lat, e.latlng.lng));
}
function placeMarker(lat,lng){
selectedLat=lat; selectedLng=lng;
const rad=parseInt(document.getElementById('p-radius-range').value)||300;
if(locMarker) locMarker.setLatLng([lat,lng]);
else locMarker=L.marker([lat,lng],{draggable:true}).addTo(locMap)
.on('dragend',e=>{const p=e.target.getLatLng();placeMarker(p.lat,p.lng);});
if(locCircle) locCircle.setLatLng([lat,lng]).setRadius(rad);
else locCircle=L.circle([lat,lng],{radius:rad,color:'#8b5cf6',fillColor:'#8b5cf6',fillOpacity:0.08,weight:1.5,dashArray:'5,5'}).addTo(locMap);
document.getElementById('p-lat').value=lat.toFixed(7);
document.getElementById('p-lng').value=lng.toFixed(7);
const info=document.getElementById('map-info');
info.className='map-info';
info.textContent='⏳ Mengambil informasi alamat...';
reverseGeocode(lat,lng);
}
async function reverseGeocode(lat,lng){
try{
const url=`https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&addressdetails=1&accept-language=id`;
const r=await fetch(url,{headers:{'Accept-Language':'id'}});
const d=await r.json();
const a=d.address||{};
// Susun alamat
const road = a.road||a.pedestrian||a.footway||'';
const hn = a.house_number||'';
const alamat = [road+(hn?' '+hn:''), a.suburb||a.neighbourhood||''].filter(Boolean).join(', ');
const kel = a.village||a.suburb||a.neighbourhood||a.quarter||'';
const kec = a.city_district||a.municipality||a.town||'';
document.getElementById('p-alamat').value=alamat||d.display_name?.split(',').slice(0,3).join(',').trim()||'';
document.getElementById('p-kel').value=kel;
document.getElementById('p-kec').value=kec;
const info=document.getElementById('map-info');
info.className='map-info has-loc';
info.innerHTML=`✅ <span><b>${d.display_name?.split(',').slice(0,3).join(', ')}</b><br><small>Klik/geser marker untuk ubah lokasi</small></span>`;
}catch(e){
document.getElementById('map-info').textContent='⚠️ Gagal mengambil alamat. Isi manual di bawah.';
}
}
function getGPS(){
if(!navigator.geolocation){showAlert('p','Browser tidak mendukung GPS');return;}
const btn=document.getElementById('btn-gps');
btn.textContent='📡 Mengambil lokasi...';btn.disabled=true;
navigator.geolocation.getCurrentPosition(pos=>{
const {latitude:lat,longitude:lng}=pos.coords;
if(locMap)locMap.setView([lat,lng],17);
placeMarker(lat,lng);
btn.textContent='📡 Gunakan lokasi GPS saya sebagai titik awal';btn.disabled=false;
},err=>{
showAlert('p','GPS tidak tersedia: '+err.message);
btn.textContent='📡 Gunakan lokasi GPS saya sebagai titik awal';btn.disabled=false;
},{enableHighAccuracy:true,timeout:10000});
}
// ── REGISTER MASYARAKAT ──────────────────────────────────────
async function doRegisterMasy(){
const nama=document.getElementById('m-nama').value.trim();
const hp =document.getElementById('m-hp').value.trim();
if(!nama){showAlert('m','Nama lengkap wajib diisi');return;}
if(!hp) {showAlert('m','Nomor HP wajib diisi');return;}
const btn=document.getElementById('m-btn-reg');
btn.disabled=true;btn.innerHTML='<div class="spinner"></div> Memproses...';
const payload={
username: document.getElementById('m-username').value.trim(),
password: document.getElementById('m-password').value,
nama_lengkap: nama,
no_hp: hp,
email: document.getElementById('m-email').value.trim(),
no_kk: document.getElementById('m-nokk').value.trim()
};
try{
const res=await fetch('api/auth.php?action=register',{
method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)
});
const ct=res.headers.get('content-type')||'';
if(!ct.includes('application/json')){throw new Error('Server mengembalikan respon tidak valid.');}
const data=await res.json();
if(data.success){
document.getElementById('m-s2').style.display='none';
document.getElementById('m-s3').style.display='block';
document.getElementById('m-foot').style.display='none';
setStep('ms','ms2','done');setStep('ms','ms3','active');
}else{
showAlert('m',data.error||'Gagal membuat akun. Coba lagi.');
btn.disabled=false;btn.innerHTML='✅ Buat Akun';
}
}catch(err){
showAlert('m','Terjadi kesalahan: '+err.message);
btn.disabled=false;btn.innerHTML='✅ Buat Akun';
}
}
// ── REGISTER PENGURUS ────────────────────────────────────────
async function doRegisterPengurus(){
if(!selectedLat||!selectedLng){showAlert('p','Klik peta untuk menentukan lokasi rumah ibadah');return;}
const btn=document.getElementById('p-btn-reg');
btn.disabled=true;btn.innerHTML='<div class="spinner"></div> Mengirim...';
const payload={
nama_lengkap: document.getElementById('p-nama').value.trim(),
username: document.getElementById('p-username').value.trim(),
no_hp: document.getElementById('p-hp').value.trim(),
email: document.getElementById('p-email').value.trim(),
password: document.getElementById('p-password').value,
nama_ibadah: document.getElementById('p-nama-ibadah').value.trim(),
jenis_ibadah: document.getElementById('p-jenis').value,
latitude: selectedLat,
longitude: selectedLng,
alamat: document.getElementById('p-alamat').value.trim(),
kelurahan: document.getElementById('p-kel').value.trim(),
kecamatan: document.getElementById('p-kec').value.trim(),
radius: parseInt(document.getElementById('p-radius-range').value)||300
};
try{
const res=await fetch('api/auth.php?action=register_pengurus',{
method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)
});
const ct=res.headers.get('content-type')||'';
if(!ct.includes('application/json')){throw new Error('Server mengembalikan respon tidak valid.');}
const data=await res.json();
if(data.success){
document.getElementById('p-s3').style.display='none';
document.getElementById('p-s4').style.display='block';
document.getElementById('p-foot').style.display='none';
setStep('ps','ps3','done');setStep('ps','ps4','active p-step');
}else{
showAlert('p',data.error||'Gagal mendaftar. Coba lagi.');
btn.disabled=false;btn.innerHTML='📨 Kirim Pendaftaran';
}
}catch(err){
showAlert('p','Terjadi kesalahan: '+err.message);
btn.disabled=false;btn.innerHTML='📨 Kirim Pendaftaran';
}
}
// Inisialisasi radius display
updateRadiusDisplay('p', document.getElementById('p-radius-range').value);
</script>
</body>
</html>