File manager - Edit - /home/webapp69.cm.in.th/u69319090038/Shop/public/js/ui.js
Back
// ============================================================ // ui.js — Toast Notifications, Modals, Loading states // ============================================================ // ─── Toast System ──────────────────────────────────────────── let toastContainer = null; function getToastContainer() { if (!toastContainer) { toastContainer = document.createElement('div'); toastContainer.id = 'toast-container'; toastContainer.className = 'toast-container'; document.body.appendChild(toastContainer); } return toastContainer; } export function showToast(message, type = 'info', duration = 4000) { const container = getToastContainer(); const toast = document.createElement('div'); toast.className = `toast toast-${type}`; const icons = { success: '✅', error: '❌', warning: '⚠️', info: 'ℹ️' }; toast.innerHTML = ` <span class="toast-icon">${icons[type] || icons.info}</span> <span class="toast-msg">${message}</span> <button class="toast-close" onclick="this.parentElement.remove()">×</button> `; container.appendChild(toast); requestAnimationFrame(() => toast.classList.add('show')); setTimeout(() => { toast.classList.remove('show'); toast.classList.add('hide'); toast.addEventListener('transitionend', () => toast.remove(), { once: true }); }, duration); } // ─── Auth Prompt Modal (guest user tries to buy/cart) ──────── let authModal = null; export function showAuthModal(action = 'continue') { if (!authModal) { authModal = document.createElement('div'); authModal.id = 'auth-modal-overlay'; authModal.className = 'modal-overlay'; authModal.innerHTML = ` <div class="modal-card" id="auth-modal-card"> <button class="modal-close" id="auth-modal-close">×</button> <div class="modal-brand"> <div class="modal-logo">🛒</div> <h2 class="modal-title">เข้าสู่ระบบเพื่อ${action === 'cart' ? 'เพิ่มสินค้าลงตะกร้า' : 'ซื้อสินค้า'}</h2> <p class="modal-subtitle">กรุณาเข้าสู่ระบบหรือสมัครสมาชิกก่อนทำการสั่งซื้อ</p> </div> <div class="modal-actions"> <a href="./auth.php?tab=login" class="btn btn-primary btn-block" id="modal-login-btn"> เข้าสู่ระบบ </a> <a href="./auth.php?tab=register" class="btn btn-outline btn-block" id="modal-register-btn"> สมัครสมาชิก </a> </div> <p class="modal-footer-text">มีกว่า 50 ล้านคนใช้งาน Sarin Shop ทุกวัน</p> </div> `; document.body.appendChild(authModal); document.getElementById('auth-modal-close').addEventListener('click', hideAuthModal); authModal.addEventListener('click', (e) => { if (e.target === authModal) hideAuthModal(); }); } authModal.classList.add('active'); document.body.style.overflow = 'hidden'; } export function hideAuthModal() { if (authModal) { authModal.classList.remove('active'); document.body.style.overflow = ''; } } // ─── Loading Overlay ───────────────────────────────────────── let loadingEl = null; export function showLoading() { if (!loadingEl) { loadingEl = document.createElement('div'); loadingEl.id = 'loading-overlay'; loadingEl.className = 'loading-overlay'; loadingEl.innerHTML = '<div class="spinner"></div>'; document.body.appendChild(loadingEl); } loadingEl.classList.add('active'); } export function hideLoading() { if (loadingEl) loadingEl.classList.remove('active'); } // ─── Button Loading State ──────────────────────────────────── export function setButtonLoading(btn, loading, text = '') { if (loading) { btn.disabled = true; btn._originalText = btn.innerHTML; btn.innerHTML = `<span class="btn-spinner"></span>${text || 'กำลังโหลด...'}`; } else { btn.disabled = false; btn.innerHTML = btn._originalText || btn.innerHTML; } } // ─── Password Strength Checker ─────────────────────────────── export function checkPasswordStrength(password) { let score = 0; const checks = { length: password.length >= 8, upper: /[A-Z]/.test(password), lower: /[a-z]/.test(password), number: /[0-9]/.test(password), symbol: /[!@#$%^&*()\-_=+[\]{};:'",.<>?/\\|`~]/.test(password), long: password.length >= 12, }; score = Object.values(checks).filter(Boolean).length; if (score <= 2) return { level: 0, label: 'อ่อนแอมาก', color: '#ef4444', width: '20%' }; if (score === 3) return { level: 1, label: 'อ่อนแอ', color: '#f97316', width: '40%' }; if (score === 4) return { level: 2, label: 'ปานกลาง', color: '#eab308', width: '60%' }; if (score === 5) return { level: 3, label: 'แข็งแกร่ง', color: '#22c55e', width: '80%' }; return { level: 4, label: 'แข็งแกร่งมาก', color: '#10b981', width: '100%' }; } // ─── OTP Countdown Timer ───────────────────────────────────── export function startOtpCountdown(displayEl, resendBtn, seconds = 300) { let remaining = seconds; resendBtn.disabled = true; const interval = setInterval(() => { remaining--; const m = String(Math.floor(remaining / 60)).padStart(2, '0'); const s = String(remaining % 60).padStart(2, '0'); displayEl.textContent = `${m}:${s}`; if (remaining <= 0) { clearInterval(interval); displayEl.textContent = '00:00'; resendBtn.disabled = false; } }, 1000); return () => clearInterval(interval); // cleanup function } // ─── OTP Input — auto-focus next box ──────────────────────── export function initOtpInputs(containerSelector) { const inputs = document.querySelectorAll(`${containerSelector} .otp-digit`); inputs.forEach((input, i) => { input.addEventListener('input', (e) => { const val = e.target.value.replace(/[^0-9]/g, ''); e.target.value = val.slice(-1); if (val && i < inputs.length - 1) inputs[i + 1].focus(); }); input.addEventListener('keydown', (e) => { if (e.key === 'Backspace' && !input.value && i > 0) inputs[i - 1].focus(); }); input.addEventListener('paste', (e) => { e.preventDefault(); const pasted = e.clipboardData.getData('text').replace(/[^0-9]/g, ''); pasted.split('').forEach((char, j) => { if (inputs[i + j]) inputs[i + j].value = char; }); const nextEmpty = [...inputs].findIndex(inp => !inp.value); if (nextEmpty !== -1) inputs[nextEmpty].focus(); }); }); } export function getOtpValue(containerSelector) { return [...document.querySelectorAll(`${containerSelector} .otp-digit`)] .map(i => i.value).join(''); } // ─── Render user info in nav ───────────────────────────────── export function renderNavUser(user) { const navUser = document.getElementById('nav-user'); const navGuest = document.getElementById('nav-guest'); const navAvatar = document.getElementById('nav-avatar'); const navName = document.getElementById('nav-username'); const navRole = document.getElementById('nav-role-badge'); if (user) { if (navUser) navUser.style.display = 'flex'; if (navGuest) navGuest.style.display = 'none'; if (navAvatar) navAvatar.src = user.avatar_url || `https://ui-avatars.com/api/?name=${user.username}&background=ee4d2d&color=fff`; if (navName) navName.textContent = user.username; if (navRole) { navRole.textContent = user.role; navRole.className = `role-badge role-${user.role}`; } } else { if (navUser) navUser.style.display = 'none'; if (navGuest) navGuest.style.display = 'flex'; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.23 |
proxy
|
phpinfo
|
Settings