File manager - Edit - /home/webapp69.cm.in.th/u69319090039/Shop39/app/Views/auth/login.php
Back
<div class="container py-5"> <div class="row justify-content-center"> <div class="col-md-5"> <div class="card border-0 shadow-sm rounded-4 overflow-hidden"> <div class="card-body p-4 p-md-5"> <div class="text-center mb-4"> <div class="d-inline-flex align-items-center justify-content-center bg-primary-subtle text-primary rounded-circle mb-2" style="width: 60px; height: 60px;"> <i class="bi bi-shield-lock-fill fs-3"></i> </div> <h3 class="fw-bold text-dark m-0">เข้าสู่ระบบ</h3> <p class="text-muted small mt-1">ยินดีต้อนรับกลับสู่ SHOP 39 Marketplace</p> </div> <?php $isLocked = !empty($lockout_seconds) && $lockout_seconds > 0; ?> <?php if ($isLocked): ?> <!-- Lockout Warning & Live Countdown Banner --> <div class="alert alert-danger rounded-3 p-3 mb-4 shadow-sm" id="lockoutBanner"> <div class="d-flex align-items-center gap-2 mb-2"> <i class="bi bi-exclamation-octagon-fill fs-4 text-danger"></i> <span class="fw-bold fs-6">ระบบถูกระงับการเข้าสู่ระบบชั่วคราว</span> </div> <p class="small mb-2">คุณตอบคำถามตรวจบอทผิดครบ 5 ครั้ง เพื่อความปลอดภัยกรุณารอ:</p> <div class="text-center py-2 bg-white rounded border border-danger"> <span class="fs-4 fw-bold text-danger font-monospace" id="countdownDisplay">--:--</span> <div class="small text-muted" style="font-size: 0.75rem;">นาที : วินาที</div> </div> </div> <?php endif; ?> <form action="<?= APP_URL ?>/login" method="POST" id="loginForm"> <input type="hidden" name="csrf_token" value="<?= $csrf_token ?>"> <?php if (!empty($_GET['redirect'])): ?> <input type="hidden" name="redirect" value="<?= Security::e($_GET['redirect']) ?>"> <?php endif; ?> <div class="mb-3"> <label class="form-label font-semibold text-dark">ชื่อผู้ใช้ หรือ อีเมล</label> <div class="input-group"> <span class="input-group-text bg-light border-end-0"><i class="bi bi-person text-secondary"></i></span> <input type="text" id="usernameInput" name="username" class="form-control border-start-0 ps-0" placeholder="username หรือ email" required autofocus <?= $isLocked ? 'disabled' : '' ?>> </div> </div> <div class="mb-3"> <label class="form-label font-semibold text-dark">รหัสผ่าน</label> <div class="input-group"> <span class="input-group-text bg-light border-end-0"><i class="bi bi-lock text-secondary"></i></span> <input type="password" id="passwordInput" name="password" class="form-control border-start-0 ps-0 border-end-0" placeholder="••••••••" required <?= $isLocked ? 'disabled' : '' ?>> <button class="btn btn-outline-secondary border-start-0 bg-light" type="button" id="togglePassword" title="แสดง/ซ่อนรหัสผ่าน"> <i class="bi bi-eye text-secondary" id="toggleIcon"></i> </button> </div> </div> <!-- Anti-Bot Math Verification Section --> <div class="mb-4 p-3 bg-light rounded-3 border"> <div class="d-flex justify-content-between align-items-center mb-2"> <label class="form-label font-semibold text-dark m-0 small"> <i class="bi bi-robot text-primary me-1"></i>ตรวจสอบบอท (Anti-Bot Verification) </label> <span class="badge bg-secondary-subtle text-secondary border small" id="attemptBadge"> โอกาสเหลือ: <?= isset($attempts_left) ? (int)$attempts_left : 5 ?>/5 </span> </div> <div class="row g-2 align-items-center"> <div class="col-6"> <div class="input-group"> <span class="input-group-text bg-white fw-bold text-primary fs-6 px-3 border-primary" id="captchaQuestionBadge" style="letter-spacing: 1px; user-select: none;"> <?= Security::e($captcha_question ?? '5 + 6') ?> = ? </span> <button class="btn btn-outline-primary" type="button" id="btnRefreshCaptcha" title="เปลี่ยนคำถามใหม่" <?= $isLocked ? 'disabled' : '' ?>> <i class="bi bi-arrow-clockwise"></i> </button> </div> </div> <div class="col-6"> <input type="number" id="captchaAnswerInput" name="captcha_answer" class="form-control fw-bold text-center" placeholder="พิมพ์คำตอบ" required autocomplete="off" <?= $isLocked ? 'disabled' : '' ?>> </div> </div> <div class="form-text text-muted mt-2" style="font-size: 0.76rem;"> <i class="bi bi-info-circle me-1"></i>กรอกผลบวกตัวเลขเพื่อเข้าสู่ระบบ (ตอบผิดได้สูงสุด 5 ครั้ง หากผิดครบระบบจะล็อค 3 นาที) </div> </div> <button type="submit" class="btn btn-primary w-100 py-2 fw-bold shadow-sm rounded-pill" id="submitLoginBtn" <?= $isLocked ? 'disabled' : '' ?>> <i class="bi bi-box-arrow-in-right me-1"></i>เข้าสู่ระบบ </button> </form> <div class="text-center text-secondary small mt-4 pt-2 border-top"> ยังไม่มีบัญชีสมาชิก? <a href="<?= APP_URL ?>/register" class="text-primary text-decoration-none fw-bold">สมัครสมาชิกที่นี่</a> </div> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // 1. Toggle Password Visibility document.getElementById('togglePassword')?.addEventListener('click', function () { const passwordInput = document.getElementById('passwordInput'); const toggleIcon = document.getElementById('toggleIcon'); if (!passwordInput || !toggleIcon) return; if (passwordInput.type === 'password') { passwordInput.type = 'text'; toggleIcon.classList.remove('bi-eye'); toggleIcon.classList.add('bi-eye-slash'); } else { passwordInput.type = 'password'; toggleIcon.classList.remove('bi-eye-slash'); toggleIcon.classList.add('bi-eye'); } }); // 2. Refresh Math CAPTCHA Question via AJAX const refreshBtn = document.getElementById('btnRefreshCaptcha'); const qBadge = document.getElementById('captchaQuestionBadge'); if (refreshBtn) { refreshBtn.addEventListener('click', function() { const icon = this.querySelector('i'); if (icon) icon.classList.add('spin-anim'); this.disabled = true; const baseUrl = (window.SHOP39 && window.SHOP39.baseUrl) ? window.SHOP39.baseUrl : '<?= rtrim(APP_URL, "/") ?>'; fetch(baseUrl + '/captcha/refresh', { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(res => res.json()) .then(data => { if (data.success && data.question) { if (qBadge) qBadge.textContent = data.question + ' = ?'; const ansInput = document.getElementById('captchaAnswerInput'); if (ansInput) { ansInput.value = ''; ansInput.focus(); } } else if (data.locked) { window.location.reload(); } }) .catch(err => { console.error('[Captcha Refresh Error]', err); }) .finally(() => { setTimeout(() => { if (icon) icon.classList.remove('spin-anim'); refreshBtn.disabled = false; }, 400); }); }); } // 3. Live Countdown Timer for Lockout (if locked) let remainingSecs = <?= (int)($lockout_seconds ?? 0) ?>; const countdownEl = document.getElementById('countdownDisplay'); if (remainingSecs > 0 && countdownEl) { function updateTimer() { if (remainingSecs <= 0) { countdownEl.textContent = '00:00'; // Lockout finished — reload to unlock form setTimeout(() => { window.location.href = window.location.pathname; }, 800); return; } const m = Math.floor(remainingSecs / 60); const s = remainingSecs % 60; countdownEl.textContent = String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0'); remainingSecs--; } updateTimer(); const timerInterval = setInterval(() => { updateTimer(); if (remainingSecs < 0) { clearInterval(timerInterval); } }, 1000); } }); </script> <style> @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .spin-anim { display: inline-block; animation: spin 0.5s ease-in-out; } </style>
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.24 |
proxy
|
phpinfo
|
Settings