// ===== PARTICLES BACKGROUND ===== function createParticles() { const container = document.getElementById('particles'); if (!container) return; const count = 30; for (let i = 0; i < count; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); particle.style.left = Math.random() * 100 + '%'; particle.style.width = (Math.random() * 2 + 1) + 'px'; particle.style.height = particle.style.width; particle.style.animationDuration = (Math.random() * 15 + 10) + 's'; particle.style.animationDelay = (Math.random() * 10) + 's'; particle.style.opacity = Math.random() * 0.3 + 0.05; container.appendChild(particle); } } // ===== TOGGLE PASSWORD VISIBILITY ===== function togglePassword(inputId, toggleEl) { const input = document.getElementById(inputId); if (!input) return; if (input.type === 'password') { input.type = 'text'; toggleEl.classList.add('active'); } else { input.type = 'password'; toggleEl.classList.remove('active'); } } // ===== TOAST NOTIFICATIONS ===== function showToast(message, type = 'info') { // Remove existing toasts document.querySelectorAll('.toast').forEach(t => t.remove()); const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; document.body.appendChild(toast); // Trigger reflow for animation toast.offsetHeight; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); setTimeout(() => toast.remove(), 400); }, 3000); } // ===== BUTTON LOADING STATE ===== function setLoading(btn, loading) { const text = btn.querySelector('.btn-text'); const loader = btn.querySelector('.btn-loader'); if (loading) { text.style.display = 'none'; loader.style.display = 'inline-flex'; btn.disabled = true; btn.style.pointerEvents = 'none'; } else { text.style.display = 'inline'; loader.style.display = 'none'; btn.disabled = false; btn.style.pointerEvents = 'auto'; } } // ===== LOGIN HANDLER ===== function handleLogin(e) { e.preventDefault(); const email = document.getElementById('loginEmail').value.trim(); const password = document.getElementById('loginPassword').value; const btn = document.getElementById('loginBtn'); if (!email || !password) { showToast('Silakan isi semua field', 'error'); return; } setLoading(btn, true); // Simulate login process setTimeout(() => { setLoading(btn, false); showToast('Login berhasil! Mengalihkan...', 'success'); // Redirect to dashboard setTimeout(() => { window.location.href = 'dashboard.html'; }, 1500); }, 1800); } // ===== REGISTER HANDLER ===== function handleRegister(e) { e.preventDefault(); const username = document.getElementById('regUsername').value.trim(); const email = document.getElementById('regEmail').value.trim(); const password = document.getElementById('regPassword').value; const confirmPassword = document.getElementById('regConfirmPassword').value; const btn = document.getElementById('registerBtn'); if (!username || !email || !password || !confirmPassword) { showToast('Silakan isi semua field', 'error'); return; } if (password.length < 6) { showToast('Password minimal 6 karakter', 'error'); return; } if (password !== confirmPassword) { showToast('Password dan konfirmasi tidak cocok', 'error'); return; } setLoading(btn, true); // Simulate registration setTimeout(() => { setLoading(btn, false); showToast('Registrasi berhasil! Mengalihkan ke login...', 'success'); setTimeout(() => { window.location.href = 'login.html'; }, 1500); }, 2000); } // ===== PASSWORD MATCH CHECKER ===== function setupPasswordMatch() { const password = document.getElementById('regPassword'); const confirm = document.getElementById('regConfirmPassword'); const indicator = document.getElementById('passwordMatch'); if (!password || !confirm || !indicator) return; function checkMatch() { const pw = password.value; const cpw = confirm.value; if (cpw.length === 0) { indicator.style.display = 'none'; return; } indicator.style.display = 'flex'; if (pw === cpw) { indicator.className = 'password-match-indicator match'; indicator.querySelector('.match-icon').textContent = '✓'; indicator.querySelector('.match-text').textContent = 'Password cocok'; } else { indicator.className = 'password-match-indicator no-match'; indicator.querySelector('.match-icon').textContent = '✗'; indicator.querySelector('.match-text').textContent = 'Password tidak cocok'; } } password.addEventListener('input', checkMatch); confirm.addEventListener('input', checkMatch); } // ===== INPUT FOCUS ANIMATIONS ===== function setupInputAnimations() { document.querySelectorAll('.input-group input').forEach(input => { input.addEventListener('focus', () => { input.parentElement.style.transform = 'translateY(-1px)'; }); input.addEventListener('blur', () => { input.parentElement.style.transform = 'translateY(0)'; }); }); } // ===== INIT ===== document.addEventListener('DOMContentLoaded', () => { createParticles(); setupPasswordMatch(); setupInputAnimations(); }); setTimeout(() => { const toast = document.querySelector('.toast'); if(toast){ toast.classList.remove('show'); } },3000);