|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>WiFi Attendance Tracker - Login</title> |
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> |
|
|
<style> |
|
|
* { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
box-sizing: border-box; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
min-height: 100vh; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
} |
|
|
|
|
|
.login-container { |
|
|
background: white; |
|
|
padding: 2rem; |
|
|
border-radius: 15px; |
|
|
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1); |
|
|
width: 100%; |
|
|
max-width: 400px; |
|
|
text-align: center; |
|
|
} |
|
|
|
|
|
.login-header { |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.login-header i { |
|
|
font-size: 3rem; |
|
|
color: #667eea; |
|
|
margin-bottom: 1rem; |
|
|
} |
|
|
|
|
|
.login-header h1 { |
|
|
color: #333; |
|
|
font-size: 1.8rem; |
|
|
margin-bottom: 0.5rem; |
|
|
} |
|
|
|
|
|
.login-header p { |
|
|
color: #666; |
|
|
font-size: 0.9rem; |
|
|
} |
|
|
|
|
|
.form-group { |
|
|
margin-bottom: 1.5rem; |
|
|
text-align: left; |
|
|
} |
|
|
|
|
|
.form-group label { |
|
|
display: block; |
|
|
margin-bottom: 0.5rem; |
|
|
color: #333; |
|
|
font-weight: 500; |
|
|
} |
|
|
|
|
|
.password-input-container { |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.form-group input { |
|
|
width: 100%; |
|
|
padding: 0.75rem; |
|
|
border: 2px solid #e1e5e9; |
|
|
border-radius: 8px; |
|
|
font-size: 1rem; |
|
|
transition: border-color 0.3s ease; |
|
|
} |
|
|
|
|
|
.form-group input:focus { |
|
|
outline: none; |
|
|
border-color: #667eea; |
|
|
} |
|
|
|
|
|
.toggle-password { |
|
|
position: absolute; |
|
|
right: 10px; |
|
|
top: 50%; |
|
|
transform: translateY(-50%); |
|
|
background: none; |
|
|
border: none; |
|
|
color: #666; |
|
|
cursor: pointer; |
|
|
font-size: 1rem; |
|
|
} |
|
|
|
|
|
.login-btn { |
|
|
width: 100%; |
|
|
padding: 0.75rem; |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
color: white; |
|
|
border: none; |
|
|
border-radius: 8px; |
|
|
font-size: 1rem; |
|
|
font-weight: 600; |
|
|
cursor: pointer; |
|
|
transition: transform 0.2s ease; |
|
|
} |
|
|
|
|
|
.login-btn:hover { |
|
|
transform: translateY(-2px); |
|
|
} |
|
|
|
|
|
.login-btn:disabled { |
|
|
opacity: 0.6; |
|
|
cursor: not-allowed; |
|
|
transform: none; |
|
|
} |
|
|
|
|
|
.error-message { |
|
|
background: #fee; |
|
|
color: #c33; |
|
|
padding: 0.75rem; |
|
|
border-radius: 8px; |
|
|
margin-bottom: 1rem; |
|
|
border-left: 4px solid #c33; |
|
|
display: none; |
|
|
} |
|
|
|
|
|
.loading { |
|
|
display: none; |
|
|
margin-top: 1rem; |
|
|
} |
|
|
|
|
|
.loading i { |
|
|
animation: spin 1s linear infinite; |
|
|
} |
|
|
|
|
|
@keyframes spin { |
|
|
0% { transform: rotate(0deg); } |
|
|
100% { transform: rotate(360deg); } |
|
|
} |
|
|
|
|
|
.footer { |
|
|
margin-top: 2rem; |
|
|
padding-top: 1rem; |
|
|
border-top: 1px solid #eee; |
|
|
color: #666; |
|
|
font-size: 0.8rem; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="login-container"> |
|
|
<div class="login-header"> |
|
|
<i class="fas fa-wifi"></i> |
|
|
<h1>WiFi Attendance Tracker</h1> |
|
|
<p>Please enter your password to access the dashboard</p> |
|
|
</div> |
|
|
|
|
|
<div id="errorMessage" class="error-message"></div> |
|
|
|
|
|
<form id="loginForm"> |
|
|
<div class="form-group"> |
|
|
<label for="password">Dashboard Password</label> |
|
|
<div class="password-input-container"> |
|
|
<input type="password" id="password" name="password" required placeholder="Enter dashboard password" autocomplete="current-password"> |
|
|
<button type="button" class="toggle-password" onclick="togglePassword()"> |
|
|
<i class="fas fa-eye" id="toggleIcon"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<button type="submit" class="login-btn" id="loginBtn"> |
|
|
<i class="fas fa-sign-in-alt"></i> Access Dashboard |
|
|
</button> |
|
|
</form> |
|
|
|
|
|
<div class="loading" id="loading"> |
|
|
<i class="fas fa-spinner"></i> Authenticating... |
|
|
</div> |
|
|
|
|
|
<div class="footer"> |
|
|
<p>Default password: <strong>admin123</strong></p> |
|
|
<p>Advanced Employee Management System</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
function togglePassword() { |
|
|
const passwordInput = document.getElementById('password'); |
|
|
const toggleIcon = document.getElementById('toggleIcon'); |
|
|
|
|
|
if (passwordInput.type === 'password') { |
|
|
passwordInput.type = 'text'; |
|
|
toggleIcon.className = 'fas fa-eye-slash'; |
|
|
} else { |
|
|
passwordInput.type = 'password'; |
|
|
toggleIcon.className = 'fas fa-eye'; |
|
|
} |
|
|
} |
|
|
|
|
|
function showError(message) { |
|
|
const errorDiv = document.getElementById('errorMessage'); |
|
|
errorDiv.textContent = message; |
|
|
errorDiv.style.display = 'block'; |
|
|
} |
|
|
|
|
|
function hideError() { |
|
|
const errorDiv = document.getElementById('errorMessage'); |
|
|
errorDiv.style.display = 'none'; |
|
|
} |
|
|
|
|
|
function setLoading(loading) { |
|
|
const loginBtn = document.getElementById('loginBtn'); |
|
|
const loadingDiv = document.getElementById('loading'); |
|
|
const form = document.getElementById('loginForm'); |
|
|
|
|
|
if (loading) { |
|
|
loginBtn.disabled = true; |
|
|
loadingDiv.style.display = 'block'; |
|
|
form.style.opacity = '0.6'; |
|
|
} else { |
|
|
loginBtn.disabled = false; |
|
|
loadingDiv.style.display = 'none'; |
|
|
form.style.opacity = '1'; |
|
|
} |
|
|
} |
|
|
|
|
|
document.getElementById('loginForm').addEventListener('submit', async function(e) { |
|
|
e.preventDefault(); |
|
|
|
|
|
const password = document.getElementById('password').value; |
|
|
|
|
|
if (!password) { |
|
|
showError('Please enter a password'); |
|
|
return; |
|
|
} |
|
|
|
|
|
hideError(); |
|
|
setLoading(true); |
|
|
|
|
|
try { |
|
|
const response = await fetch('/api/login', { |
|
|
method: 'POST', |
|
|
headers: { |
|
|
'Content-Type': 'application/json', |
|
|
}, |
|
|
body: JSON.stringify({ password: password }) |
|
|
}); |
|
|
|
|
|
const result = await response.json(); |
|
|
|
|
|
if (result.success) { |
|
|
|
|
|
window.location.href = '/dashboard'; |
|
|
} else { |
|
|
showError(result.message || 'Invalid password'); |
|
|
} |
|
|
} catch (error) { |
|
|
console.error('Login error:', error); |
|
|
showError('Connection error. Please try again.'); |
|
|
} finally { |
|
|
setLoading(false); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
document.getElementById('password').focus(); |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('password').addEventListener('keypress', function(e) { |
|
|
if (e.key === 'Enter') { |
|
|
document.getElementById('loginForm').dispatchEvent(new Event('submit')); |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|
|
|
|