SmartPark Pro

Basis Data Administrasi

Akses: WARGA

Form Pendaftaran Warga

Semua kolom wajib diisi untuk verifikasi fasilitas parkir lingkungan.

Informasi Pembayaran Iuran:
  • Warga RW 06: Rp 25.000 | Non-RW 06: Rp 30.000 | Parkir Insidental/dirumah: Rp 10.000
  • Transfer Bank BCA: 7770841415 a.n Ari Friansyah
  • E-Wallet DANA / QRIS: 085315325335 a.n Ari Friansyah
// Penampung State Data Lokal Aplikasi /* PLACEHOLDER: JS UPDATE DATA */ // Penampung State Data Lokal Aplikasi let currentRole = "warga"; // default user login role let dataPendaftarGlobal = []; // KOSONGKAN (HAPUS BUDI & AHMAD DI SINI) // Inisialisasi awal saat halaman termuat window.addEventListener('DOMContentLoaded', () => { simulasiRoleAkses(); loadDataAdmin(); // Panggil fungsi penarikan data dari Google Sheets }); // Fungsi simulasi pembagian hak akses tampilan UI function simulasiRoleAkses() { const areaAdmin = document.getElementById('area-admin-panel'); const areaWarga = document.getElementById('area-pendaftaran-warga'); const labelRole = document.getElementById('label-role'); if (currentRole === "admin") { areaAdmin.classList.remove('hidden'); areaWarga.classList.add('hidden'); labelRole.textContent = "Akses: ADMIN"; renderDataAdmin(dataPendaftarGlobal); } else { areaAdmin.classList.add('hidden'); areaWarga.classList.remove('hidden'); labelRole.textContent = "Akses: WARGA"; } } // Fungsi Render List Data khusus untuk Admin via Template Literals function renderDataAdmin(dataArray) { const kontainer = document.getElementById('list-data-pendaftar'); if (dataArray.length === 0) { kontainer.innerHTML = `
Tidak ada data pendaftaran ditemukan.
`; return; } kontainer.innerHTML = dataArray.map(item => `
${item.id} ${item.status}

${item.nama}

NIK: ${item.nik} | RT: ${item.rt}

${item.paket}

`).join(''); } // Fungsi Pencarian Data function handleSearch(query) { const filtered = dataPendaftarGlobal.filter(item => item.nama.toLowerCase().includes(query.toLowerCase()) || item.nik.includes(query) || item.id.toLowerCase().includes(query.toLowerCase()) ); renderDataAdmin(filtered); } // Helper konversi file unggahan gambar menjadi string base64 murni function fileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result.split(',')[1]); reader.onerror = error => reject(error); }); } // Fungsi Utama Penanganan Form Submit Kirim Pendaftaran Warga async function handlePendaftaran(event) { event.preventDefault(); const fileKtpInput = document.getElementById('reg-file-ktp').files[0]; const fileMotorInput = document.getElementById('reg-file-motor').files[0]; if (!fileKtpInput || !fileMotorInput) { alert("❌ Harap lengkapi unggahan foto KTP dan foto Motor terlebih dahulu!"); return; } const nama = document.getElementById('reg-nama').value; const wa = document.getElementById('reg-wa').value; const nik = document.getElementById('reg-nik').value; const rt = document.getElementById('reg-rt').value; const rw = document.getElementById('reg-rw').value; const alamat = document.getElementById('reg-alamat').value; const paket = document.getElementById('reg-paket').value; try { const base64Ktp = await fileToBase64(fileKtpInput); const base64Motor = await fileToBase64(fileMotorInput); const payload = { action: "daftarWarga", nama: document.getElementById('reg-nama').value, namaPanggilan: document.getElementById('reg-panggilan').value, // <--- BARU statusPekerjaan: document.getElementById('reg-status').value, // <--- BARU wa: document.getElementById('reg-wa').value, nik: document.getElementById('reg-nik').value, rt: document.getElementById('reg-rt').value, rw: document.getElementById('reg-rw').value, alamat: document.getElementById('reg-alamat').value, paket: document.getElementById('reg-paket').value, fotoKtp: base64Ktp, namaKtpFile: fileKtpInput.name, fotoMotor: base64Motor, namaMotorFile: fileMotorInput.name }; // Kondisi jika aplikasi berjalan di dalam PREVIEW_MODE internal if (PREVIEW_MODE) { alert(`🎉 [Preview Mode Sukses]\nData ${nama} berhasil diproses secara lokal!\nBerkas gambar berhasil dienkripsi ke Base64.`); // Optimistic UI update data lokal dummy dataPendaftarGlobal.push({ id: "REG-" + new Date().getTime().toString().slice(-4), nama: nama, nik: nik, rt: rt, paket: paket, status: "Menunggu Verifikasi" }); document.getElementById('form-daftar-warga').reset(); return; } // Eksekusi pengiriman data asinkron asli ke database Cloud Google Spreadsheet const response = await fetch(APP_URL, { method: "POST", body: JSON.stringify(payload) }); const result = await response.json(); if (result.status === "success") { alert("✅ Pendaftaran berhasil dikirim! Silakan tunggu verifikasi oleh pihak kepengurusan RW."); document.getElementById('form-daftar-warga').reset(); } else { alert("❌ Gagal mengirim berkas: " + result.message); } } catch (error) { console.error(error); alert("❌ Terjadi kegagalan komunikasi sistem atau ukuran berkas foto terlalu besar."); } } // Fungsi Refresh / Sinkronisasi Data function refreshData() { alert("🔄 Data ter-sinkronisasi dengan versi terbaru!"); if (currentRole === "admin") renderDataAdmin(dataPendaftarGlobal); } // Fungsi Keluar / Logout akun function handleLogout() { if (confirm("Apakah kamu yakin ingin keluar dari aplikasi?")) { // 1. Hapus session/token login pengguna jika disimpan di localStorage atau sessionStorage localStorage.removeItem("user_session"); sessionStorage.clear(); // 2. Jika kamu memiliki modal/layar login di index.html, tampilkan layar login tersebut: const areaLogin = document.getElementById('area-login'); if (areaLogin) { areaLogin.classList.remove('hidden'); } else { // 3. Jika menggunakan halaman terpisah atau refresh untuk reset state aplikasi: window.location.reload(); } } } /* PLACEHOLDER: JS BARU */ /* PLACEHOLDER: JS BARU */ // Update Variabel Role & Session Handling Login let currentRole = localStorage.getItem("user_role") || null; // Inisialisasi awal saat halaman di-load window.addEventListener('DOMContentLoaded', () => { if (currentRole) { document.getElementById('modal-login').classList.add('hidden'); simulasiRoleAkses(); } else { document.getElementById('modal-login').classList.remove('hidden'); } }); // Fungsi Masuk Sesuai Role function masukSebagai(role) { currentRole = role; localStorage.setItem("user_role", role); document.getElementById('modal-login').classList.add('hidden'); simulasiRoleAkses(); } // Perbaikan Fungsi Keluar (Logout) function handleLogout() { if (confirm("Apakah kamu yakin ingin keluar dari aplikasi?")) { localStorage.removeItem("user_role"); currentRole = null; document.getElementById('modal-login').classList.remove('hidden'); } } // Update Handler Pendaftaran Warga (Termasuk Validasi Foto Depan & Samping Motor) async function handlePendaftaran(event) { event.preventDefault(); const fileKtpInput = document.getElementById('reg-file-ktp').files[0]; const fileMotorDepanInput = document.getElementById('reg-file-motor-depan').files[0]; const fileMotorSampingInput = document.getElementById('reg-file-motor-samping').files[0]; // Validasi Wajib Isi Semua Berkas if (!fileKtpInput || !fileMotorDepanInput || !fileMotorSampingInput) { alert("❌ Harap lengkapi SEMUA berkas unggahan: Foto KTP, Foto Motor Tampak Depan, dan Foto Motor Tampak Samping!"); return; } try { const base64Ktp = await fileToBase64(fileKtpInput); const base64MotorDepan = await fileToBase64(fileMotorDepanInput); const base64MotorSamping = await fileToBase64(fileMotorSampingInput); const payload = { action: "daftarWarga", nama: document.getElementById('reg-nama').value, namaPanggilan: document.getElementById('reg-panggilan').value, statusPekerjaan: document.getElementById('reg-status').value, wa: document.getElementById('reg-wa').value, nik: document.getElementById('reg-nik').value, rt: document.getElementById('reg-rt').value, rw: document.getElementById('reg-rw').value, alamat: document.getElementById('reg-alamat').value, paket: document.getElementById('reg-paket').value, fotoKtp: base64Ktp, namaKtpFile: fileKtpInput.name, fotoMotorDepan: base64MotorDepan, namaMotorDepanFile: fileMotorDepanInput.name, fotoMotorSamping: base64MotorSamping, namaMotorSampingFile: fileMotorSampingInput.name }; if (PREVIEW_MODE) { alert("🎉 [Preview Mode Sukses]\nPendaftaran berhasil diproses! Ketiga foto berkas (KTP, Motor Depan, & Motor Samping) terverifikasi."); document.getElementById('form-daftar-warga').reset(); return; } const response = await fetch(APP_URL, { method: "POST", body: JSON.stringify(payload) }); const result = await response.json(); if (result.status === "success") { alert("✅ Pendaftaran berhasil dikirim! Berkas foto KTP dan Motor lengkap."); document.getElementById('form-daftar-warga').reset(); } else { alert("❌ Gagal mengirim berkas: " + result.message); } } catch (error) { console.error(error); alert("❌ Terjadi kesalahan saat memproses gambar."); } } /* PLACEHOLDER: JS BARU */ // Variabel Penampung State Akses Login let currentRole = localStorage.getItem("user_role") || null; // Cek status sesi saat halaman selesai di-load window.addEventListener('DOMContentLoaded', () => { const loginScreen = document.getElementById('login-screen'); const mainApp = document.getElementById('main-app'); if (currentRole) { if (loginScreen) loginScreen.classList.add('hidden'); if (mainApp) mainApp.classList.remove('hidden'); simulasiRoleAkses(); } else { if (loginScreen) loginScreen.classList.remove('hidden'); if (mainApp) mainApp.classList.add('hidden'); } }); // Fungsi Masuk Sebagai WARGA function loginWarga() { const wa = document.getElementById('input-wa').value; if (!wa) return alert("❌ Harap masukkan nomor WhatsApp terlebih dahulu!"); currentRole = "warga"; localStorage.setItem("user_role", "warga"); localStorage.setItem("user_wa", wa); // Buka tampilan utama document.getElementById('login-screen').classList.add('hidden'); document.getElementById('main-app').classList.remove('hidden'); simulasiRoleAkses(); } // Fungsi Masuk Sebagai ADMIN function showAdminLogin() { const pass = prompt("Masukkan Password Admin:"); if (pass === "123" || pass === "admin") { // Password default admin currentRole = "admin"; localStorage.setItem("user_role", "admin"); document.getElementById('login-screen').classList.add('hidden'); document.getElementById('main-app').classList.remove('hidden'); simulasiRoleAkses(); } else if (pass !== null) { alert("❌ Password Admin Salah!"); } } // Fungsi Pengatur Tampilan Sesuai Peran (Admin vs Warga) function simulasiRoleAkses() { const areaAdmin = document.getElementById('area-admin-panel'); const areaWarga = document.getElementById('area-pendaftaran-warga'); const labelRole = document.getElementById('label-role'); if (currentRole === "admin") { if (areaAdmin) areaAdmin.classList.remove('hidden'); if (areaWarga) areaWarga.classList.add('hidden'); if (labelRole) labelRole.textContent = "Akses: ADMIN"; if (typeof renderDataAdmin === 'function') renderDataAdmin(dataPendaftarGlobal); } else { if (areaAdmin) areaAdmin.classList.add('hidden'); if (areaWarga) areaWarga.classList.remove('hidden'); if (labelRole) labelRole.textContent = "Akses: WARGA"; } } // Perbaikan Fungsi Keluar (Logout) function handleLogout() { if (confirm("Apakah kamu yakin ingin keluar dari aplikasi?")) { localStorage.clear(); currentRole = null; // Sembunyikan main app, tampilkan layar login document.getElementById('main-app').classList.add('hidden'); document.getElementById('login-screen').classList.remove('hidden'); // Reset form nomor WA const inputWa = document.getElementById('input-wa'); if (inputWa) inputWa.value = ""; } }

Selamat Datang

Silakan pilih akses untuk melanjutkan

Atau
/* PLACEHOLDER: JS BARU */ // 1. Inisialisasi variabel global data if (typeof dataPendaftarGlobal === 'undefined') { var dataPendaftarGlobal = []; } // 2. Fungsi Ambil Data Real-time dari Google Sheets ke Admin Panel /* PLACEHOLDER: JS BARU */ /* PLACEHOLDER: JS BARU */ /* PLACEHOLDER: JS BARU */ // 1. Variabel State Mode Login let activeLoginMode = "warga"; // 2. Fungsi Otomatis Merubah UI Mode Admin / Warga function switchLoginMode(mode) { activeLoginMode = mode; const label = document.getElementById('loginLabel'); const input = document.getElementById('loginInput'); const passGroup = document.getElementById('passAdminGroup'); const btnSubmit = document.getElementById('btnSubmitLogin'); const btnToggle = document.getElementById('btnToggleAdmin'); if (!input) return; if (mode === "admin") { if (label) label.innerText = "Username Admin"; input.placeholder = "Ketik 'admin'"; input.value = "admin"; if (passGroup) passGroup.classList.remove('hidden'); if (btnSubmit) { btnSubmit.innerText = "Masuk Portal Admin"; btnSubmit.onclick = () => eksekusiLogin('admin'); } if (btnToggle) { btnToggle.innerText = "Kembali ke Login Warga"; btnToggle.onclick = () => switchLoginMode('warga'); } } else { if (label) label.innerText = "Nomor WhatsApp / NIK Warga"; input.placeholder = "Contoh: 085315325335"; input.value = ""; if (passGroup) passGroup.classList.add('hidden'); if (btnSubmit) { btnSubmit.innerText = "Masuk sebagai Warga"; btnSubmit.onclick = () => eksekusiLogin('warga'); } if (btnToggle) { btnToggle.innerText = "Masuk sebagai Admin"; btnToggle.onclick = () => switchLoginMode('admin'); } } } // 3. Fungsi Eksekusi Login (Cek Ke Google Sheets / Local Preview) async function eksekusiLogin(role) { const inputEl = document.getElementById('loginInput'); const passEl = document.getElementById('loginPassword'); const inputValue = inputEl ? inputEl.value.trim() : ""; const passwordValue = passEl ? passEl.value.trim() : ""; if (!inputValue) { alert("Silakan isi kolom input terlebih dahulu!"); return; } // A. Jika Masih Mode PREVIEW if (typeof PREVIEW_MODE !== 'undefined' && PREVIEW_MODE) { if (role === "admin" && (inputValue !== "admin" || passwordValue !== "123")) { alert("Login Admin Gagal! Username: admin | Password: 123"); return; } alert(`Login ${role.toUpperCase()} Berhasil! (Mode Preview)`); if (typeof simulasiRoleAkses === 'function') simulasiRoleAkses(role); return; } // B. Jika Mode Live (Koneksi Ke Google Sheets) try { const payload = { action: "login", role: role, input: inputValue, password: passwordValue }; const response = await fetch(APP_URL, { method: "POST", body: JSON.stringify(payload) }); const result = await response.json(); if (result.status === "success") { alert(result.message || "Login Berhasil!"); if (typeof simulasiRoleAkses === 'function') { simulasiRoleAkses(role, result.userData); } } else { alert("Gagal Login: " + result.message); } } catch (err) { alert("Terjadi kesalahan koneksi: " + err.message); } } // 4. Inject Element Field Password Admin Secara Otomatis document.addEventListener('DOMContentLoaded', () => { const loginInput = document.getElementById('loginInput'); if (loginInput && !document.getElementById('passAdminGroup')) { const parentContainer = loginInput.parentElement ? loginInput.parentElement.parentElement : null; if (parentContainer) { const passDiv = document.createElement('div'); passDiv.id = 'passAdminGroup'; passDiv.className = 'hidden mt-3 text-left'; passDiv.innerHTML = ` `; loginInput.parentElement.after(passDiv); } } }); /* PLACEHOLDER: JS BARU */ async function loadDataAdmin() { // Cari kontainer list admin di DOM const container = document.getElementById('adminDataList') || document.querySelector('.space-y-4'); if (!container) return; // 1. Tampilkan Indikator Loading container.innerHTML = `

Menghubungkan ke Google Sheets...

`; // 2. Jika PREVIEW_MODE false & APP_URL terisi, langsung ambil data asli if (!PREVIEW_MODE && APP_URL && APP_URL !== "") { try { const response = await fetch(APP_URL); const result = await response.json(); if (result.status === "success" && Array.isArray(result.data)) { // Jika database di Google Sheets kosong if (result.data.length === 0) { container.innerHTML = `

Belum Ada Data Pendaftaran

Data warga yang mendaftar akan otomatis muncul di sini.

`; return; } // Render Data Asli (Ari Friansyah & pendaftar lainnya) container.innerHTML = result.data.map(item => `
${item.id || 'REG-NEW'} ${item.status || 'Menunggu Verifikasi'}

${item.nama} ${item.panggilan ? '(' + item.panggilan + ')' : ''}

NIK: ${item.nik || '-'} | RT: ${item.rt || '-'} | WA: ${item.wa || '-'}

🚗 ${item.paket || '-'}
${item.urlKtp ? `Lihat Berkas` : ''}
`).join(''); } else { throw new Error(result.message || "Gagal mengambil data"); } } catch (err) { console.error(err); container.innerHTML = `

Gagal Mengambil Data Database

${err.message}

`; } } else { container.innerHTML = `
⚠️ PREVIEW_MODE masih TRUE atau APP_URL belum diisi dengan URL Apps Script.
`; } } // Handler Tombol Sinkron Data async function syncDataAdmin(event) { const btn = event?.currentTarget || document.getElementById('btnSync'); if (btn) btn.classList.add('opacity-50', 'pointer-events-none'); await loadDataAdmin(); if (btn) btn.classList.remove('opacity-50', 'pointer-events-none'); } // 3. Override/Perbarui Fungsi Cek Akses Sesi function cekSesiAkses() { const loginScreen = document.getElementById('login-screen'); const mainApp = document.getElementById('main-app'); const areaAdmin = document.getElementById('area-admin-panel'); const areaWarga = document.getElementById('area-pendaftaran-warga'); const labelRole = document.getElementById('label-role'); if (currentRole) { if (loginScreen) loginScreen.style.display = 'none'; if (mainApp) mainApp.classList.remove('hidden'); if (currentRole === "admin") { if (areaAdmin) areaAdmin.classList.remove('hidden'); if (areaWarga) areaWarga.classList.add('hidden'); if (labelRole) labelRole.textContent = "Akses: ADMIN"; // Jalankan pengambilan data Google Sheets jika bukan mode preview if (typeof PREVIEW_MODE !== 'undefined' && !PREVIEW_MODE) { loadDataAdmin(); } else if (typeof renderDataAdmin === 'function') { renderDataAdmin(dataPendaftarGlobal); } } else { if (areaAdmin) areaAdmin.classList.add('hidden'); if (areaWarga) areaWarga.classList.remove('hidden'); if (labelRole) labelRole.textContent = "Akses: WARGA"; } } else { if (loginScreen) loginScreen.style.display = 'flex'; if (mainApp) mainApp.classList.add('hidden'); } } // 4. Pastikan fungsi dipanggil otomatis saat halaman selesai dimuat document.addEventListener('DOMContentLoaded', () => { try { currentRole = localStorage.getItem("user_role") || null; } catch(e) {} cekSesiAkses(); });