AttendAIPro / student-login.html
ashrithagowthami's picture
Upload student-login.html
cb7afdd verified
Raw
History Blame Contribute Delete
12.4 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Login — AttendAI Pro</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/auth.css">
<!-- Google Identity Services -->
<script src="https://accounts.google.com/gsi/client" async defer></script>
</head>
<body class="auth-body">
<div class="auth-page">
<!-- Left Panel -->
<div class="auth-left">
<div class="auth-left-content">
<a href="index.html" class="auth-back">
← Back to Home
</a>
<div class="auth-brand">
<div class="auth-logo-icon student-gradient">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2">
<path d="M22 10v6M2 10l10-5 10 5-10 5z"/>
<path d="M6 12v5c3 3 9 3 12 0v-5"/>
</svg>
</div>
<div>
<div class="auth-app-name">AttendAI Pro</div>
<div class="auth-portal-name">Student Portal</div>
</div>
</div>
<h2 class="auth-headline">Mark your attendance<br>the smart way</h2>
<p class="auth-desc">Secure, fast, and tamper-proof attendance using face recognition and GPS verification.</p>
<div class="auth-features">
<div class="auth-feature"><span>🔒</span> Google OAuth — No passwords needed</div>
<div class="auth-feature"><span>🤖</span> Face recognition verification</div>
<div class="auth-feature"><span>📍</span> GPS geofencing ensures you're in class</div>
<div class="auth-feature"><span></span> Mark attendance in under 3 seconds</div>
</div>
</div>
<div class="auth-left-footer">
<div class="auth-security-badges">
<span>🔐 Encrypted</span>
<span>✓ ISO Compliant</span>
<span>🛡️ Zero Proxy</span>
</div>
</div>
</div>
<!-- Right Panel -->
<div class="auth-right">
<div class="auth-form-wrapper">
<!-- Login Card -->
<div class="auth-card" id="loginCard">
<div class="auth-card-header">
<h1>Student Login</h1>
<p>Sign in with your institutional Google account</p>
</div>
<!-- Alert Area -->
<div id="alertArea" style="margin-bottom:16px;display:none"></div>
<!-- Role Reminder -->
<div class="role-reminder student-reminder">
<div class="reminder-icon">🎓</div>
<div>
<strong>Students Only</strong>
<p>Use your institutional email. Your account must be pre-registered by your administrator.</p>
</div>
</div>
<!-- Google Sign In Button -->
<div style="margin: 24px 0;">
<button class="btn btn-google btn-full" id="googleSignInBtn" onclick="initiateGoogleLogin()">
<img src="https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg" alt="Google">
Continue with Google
</button>
</div>
<!-- Loading State -->
<div id="loadingState" class="auth-loading hidden">
<div class="spinner spinner-dark"></div>
<span id="loadingText">Authenticating with Google...</span>
</div>
<div class="auth-divider">
<span>Verification process</span>
</div>
<div class="auth-steps-preview">
<div class="auth-step-item active">
<div class="step-dot">1</div>
<span>Google Authentication</span>
</div>
<div class="step-connector"></div>
<div class="auth-step-item">
<div class="step-dot">2</div>
<span>Database Verification</span>
</div>
<div class="step-connector"></div>
<div class="auth-step-item">
<div class="step-dot">3</div>
<span>Access Granted</span>
</div>
</div>
<div class="auth-notice-box">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg>
<span>Only pre-registered students can log in. If you're new, contact your institution's admin.</span>
</div>
</div>
<!-- Unauthorized Message -->
<div class="auth-card hidden" id="unauthorizedCard">
<div class="auth-error-state">
<div class="error-icon">🚫</div>
<h2>Unauthorized Email</h2>
<p id="unauthorizedMsg">Your Google account is not registered in our system. Please contact your institution's administrator to register your account.</p>
<div class="error-details" id="errorEmail"></div>
<button class="btn btn-primary btn-full" onclick="resetLogin()">
Try Different Account
</button>
<a href="index.html" class="btn btn-secondary btn-full" style="margin-top:10px">
Go Back to Home
</a>
</div>
</div>
<!-- Welcome Back (brief) -->
<div class="auth-card hidden" id="welcomeCard">
<div class="auth-success-state">
<img id="welcomeAvatar" src="" alt="Profile" class="avatar avatar-xl" style="margin:0 auto 16px;display:block">
<h2>Welcome back!</h2>
<p id="welcomeName"></p>
<div class="auth-loading" style="margin-top:20px">
<div class="spinner spinner-dark"></div>
<span>Redirecting to your dashboard...</span>
</div>
</div>
</div>
<div class="auth-footer-text">
Are you a teacher? <a href="teacher-login.html">Teacher Login →</a>
</div>
</div>
</div>
</div>
<script src="js/config.js"></script>
<script>
// Check if already authenticated
const existingUser = AuthState.get();
if (existingUser && existingUser.role === 'student') {
window.location.href = 'student-dashboard.html';
} else if (existingUser && existingUser.role === 'teacher') {
window.location.href = 'teacher-dashboard.html';
} else if (existingUser && existingUser.role === 'admin') {
window.location.href = 'admin-panel.html';
}
function showAlert(message, type = 'danger') {
const area = document.getElementById('alertArea');
area.style.display = 'block';
area.innerHTML = `<div class="alert alert-${type}"><span class="alert-icon">${type === 'danger' ? '❌' : type === 'success' ? '✅' : 'ℹ️'}</span><div>${message}</div></div>`;
}
function showLoading(text = 'Verifying your account...') {
document.getElementById('loadingState').classList.remove('hidden');
document.getElementById('loadingText').textContent = text;
document.getElementById('googleSignInBtn').disabled = true;
}
function hideLoading() {
document.getElementById('loadingState').classList.add('hidden');
document.getElementById('googleSignInBtn').disabled = false;
}
function showUnauthorized(email, message) {
document.getElementById('loginCard').classList.add('hidden');
document.getElementById('unauthorizedCard').classList.remove('hidden');
document.getElementById('errorEmail').textContent = `Attempted email: ${email}`;
if (message) document.getElementById('unauthorizedMsg').textContent = message;
}
function showWelcome(user) {
document.getElementById('loginCard').classList.add('hidden');
document.getElementById('welcomeCard').classList.remove('hidden');
document.getElementById('welcomeAvatar').src = user.picture;
document.getElementById('welcomeName').textContent = `${user.email} — Redirecting...`;
}
function resetLogin() {
document.getElementById('loginCard').classList.remove('hidden');
document.getElementById('unauthorizedCard').classList.add('hidden');
document.getElementById('alertArea').style.display = 'none';
hideLoading();
if (typeof google !== 'undefined' && google.accounts) {
google.accounts.id.disableAutoSelect();
}
}
async function verifyStudentInDB(googleUser) {
try {
showLoading('Checking student database...');
// Search for user by email
const result = await API.get('users', {
search: googleUser.email,
limit: 100
});
const users = result.data || [];
const user = users.find(u =>
u.email && u.email.toLowerCase() === googleUser.email.toLowerCase()
);
if (!user) {
showUnauthorized(googleUser.email, 'Your email is not registered in the student database. Please contact your institution administrator to register your account.');
await Logger.log('LOGIN_FAILED', 'auth', { email: googleUser.email, reason: 'not_registered', role: 'student' }, 'failure');
return;
}
if (user.role !== 'student') {
showUnauthorized(googleUser.email, `Your account is registered as "${user.role}", not as a student. Please use the correct login portal.`);
await Logger.log('LOGIN_FAILED', 'auth', { email: googleUser.email, reason: 'wrong_role', role: user.role }, 'failure');
return;
}
if (user.is_active === false) {
showUnauthorized(googleUser.email, 'Your student account has been deactivated. Please contact your institution administrator.');
return;
}
// Merge Google profile data with DB record
const sessionUser = {
id: user.id,
google_id: googleUser.sub,
email: user.email,
name: googleUser.name || user.name,
picture: googleUser.picture || '',
role: user.role,
roll_number: user.roll_number,
department: user.department,
institution: user.institution,
face_data: user.face_data
};
// Update last login
await API.patch('users', user.id, {
last_login: Date.now(),
name: sessionUser.name,
picture: sessionUser.picture
});
AuthState.save(sessionUser);
await Logger.log('LOGIN_SUCCESS', 'auth', { email: googleUser.email, role: 'student' }, 'success');
showWelcome(sessionUser);
setTimeout(() => { window.location.href = 'student-dashboard.html'; }, 1800);
} catch (err) {
console.error('Verification error:', err);
hideLoading();
showAlert('System error during verification. Please try again.');
}
}
// Google OAuth callback
function handleGoogleCredential(response) {
try {
// Decode JWT payload (verification happens server-side in production)
const parts = response.credential.split('.');
if (parts.length !== 3) throw new Error('Invalid token');
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
if (!payload.email_verified) {
showAlert('Your Google email is not verified. Please verify your Google account first.');
return;
}
verifyStudentInDB({
sub: payload.sub,
email: payload.email,
name: payload.name,
picture: payload.picture
});
} catch (err) {
console.error('Token decode error:', err);
showAlert('Authentication failed. Please try again.');
}
}
function initiateGoogleLogin() {
if (APP_CONFIG.googleClientId === 'YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com') {
showAlert(`
<strong>Google OAuth Not Configured</strong><br>
To enable Google login, a system administrator must configure the Google OAuth Client ID.<br>
Please contact your institution's technical team.
`, 'warning');
return;
}
if (typeof google !== 'undefined' && google.accounts) {
google.accounts.id.prompt();
} else {
showAlert('Google authentication service unavailable. Check your internet connection.', 'warning');
}
}
// Initialize Google Identity Services
window.addEventListener('load', () => {
if (APP_CONFIG.googleClientId !== 'YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com') {
if (typeof google !== 'undefined') {
google.accounts.id.initialize({
client_id: APP_CONFIG.googleClientId,
callback: handleGoogleCredential,
auto_select: false,
cancel_on_tap_outside: true
});
}
}
});
</script>
</body>
</html>