|
|
<!DOCTYPE html> |
|
|
<html lang="en" class="h-full"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Zetech University Attendance</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
|
|
|
.progress-ring__circle { |
|
|
transition: stroke-dashoffset 0.5s; |
|
|
transform: rotate(-90deg); |
|
|
transform-origin: 50% 50%; |
|
|
} |
|
|
.drawer { |
|
|
transition: transform 0.3s ease-in-out; |
|
|
} |
|
|
.drawer-closed { |
|
|
transform: translateX(-100%); |
|
|
} |
|
|
.drawer-open { |
|
|
transform: translateX(0); |
|
|
} |
|
|
.face-scan-animation { |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
@keyframes pulse { |
|
|
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); } |
|
|
70% { box-shadow: 0 0 0 15px rgba(59, 130, 246, 0); } |
|
|
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-100 h-full font-sans antialiased text-gray-800"> |
|
|
|
|
|
<div class="max-w-md mx-auto bg-white h-screen flex flex-col overflow-hidden shadow-xl relative"> |
|
|
|
|
|
<header class="bg-blue-600 text-white p-4 flex items-center justify-between"> |
|
|
<button id="menu-btn" class="text-white focus:outline-none"> |
|
|
<i class="fas fa-bars text-xl"></i> |
|
|
</button> |
|
|
<div class="flex items-center"> |
|
|
<img src="https://via.placeholder.com/40" alt="Zetech Logo" class="h-8 w-8 mr-2 rounded-full"> |
|
|
<h1 class="font-bold text-lg">Zetech Attendance</h1> |
|
|
</div> |
|
|
<div class="w-8"></div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div id="drawer" class="drawer drawer-closed absolute top-0 left-0 h-full w-64 bg-white shadow-lg z-50"> |
|
|
<div class="p-4 bg-blue-600 text-white flex items-center"> |
|
|
<img src="https://via.placeholder.com/40" alt="User" class="h-10 w-10 rounded-full mr-3"> |
|
|
<div> |
|
|
<p class="font-bold">John Doe</p> |
|
|
<p class="text-xs opacity-80">Student ID: STU12345</p> |
|
|
</div> |
|
|
</div> |
|
|
<nav class="py-4"> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-home mr-3 text-blue-500"></i> |
|
|
<span>Dashboard</span> |
|
|
</a> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-calendar-check mr-3 text-blue-500"></i> |
|
|
<span>Attendance</span> |
|
|
</a> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-file-alt mr-3 text-blue-500"></i> |
|
|
<span>Reports</span> |
|
|
</a> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-envelope mr-3 text-blue-500"></i> |
|
|
<span>Absence Requests</span> |
|
|
</a> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-cog mr-3 text-blue-50"></i> |
|
|
<span>Settings</span> |
|
|
</a> |
|
|
<a href="#" class="flex items-center px-4 py-3 text-gray-700 hover:bg-blue-50"> |
|
|
<i class="fas fa-sign-out-alt mr-3 text-red-500"></i> |
|
|
<span>Logout</span> |
|
|
</a> |
|
|
</nav> |
|
|
</div> |
|
|
|
|
|
|
|
|
<main class="flex-1 overflow-y-auto pb-20"> |
|
|
|
|
|
<section class="p-4"> |
|
|
<h2 class="text-xl font-bold mb-4">Attendance Overview</h2> |
|
|
<div class="bg-white rounded-xl shadow p-6 mb-4"> |
|
|
<div class="flex justify-between items-center mb-4"> |
|
|
<div> |
|
|
<h3 class="font-semibold text-gray-700">Current Attendance</h3> |
|
|
<p class="text-sm text-gray-500">This Semester</p> |
|
|
</div> |
|
|
<div class="relative w-20 h-20"> |
|
|
<svg class="w-full h-full" viewBox="0 0 36 36"> |
|
|
<path |
|
|
d="M18 2.0845 |
|
|
a 15.9155 15.9155 0 0 1 0 31.831 |
|
|
a 15.9155 15.9155 0 0 1 0 -31.831" |
|
|
fill="none" |
|
|
stroke="#e6e6e6" |
|
|
stroke-width="3" |
|
|
/> |
|
|
<path |
|
|
id="progress-ring" |
|
|
class="progress-ring__circle" |
|
|
d="M18 2.0845 |
|
|
a 15.9155 15.9155 0 0 1 0 31.831 |
|
|
a 15.9155 15.9155 0 0 1 0 -31.831" |
|
|
fill="none" |
|
|
stroke="#3b82f6" |
|
|
stroke-width="3" |
|
|
stroke-dasharray="85, 100" |
|
|
/> |
|
|
<text x="18" y="20.5" text-anchor="middle" font-size="10" fill="#3b82f6" font-weight="bold">85%</text> |
|
|
</svg> |
|
|
</div> |
|
|
</div> |
|
|
<div class="grid grid-cols-2 gap-4"> |
|
|
<div class="bg-blue-50 p-3 rounded-lg"> |
|
|
<p class="text-sm text-gray-600">Attended</p> |
|
|
<p class="font-bold text-blue-600">34</p> |
|
|
</div> |
|
|
<div class="bg-red-50 p-3 rounded-lg"> |
|
|
<p class="text-sm text-gray-600">Missed</p> |
|
|
<p class="font-bold text-red-600">6</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="p-4"> |
|
|
<h2 class="text-xl font-bold mb-4">Next Class</h2> |
|
|
<div class="bg-white rounded-xl shadow p-4 mb-4"> |
|
|
<div class="flex items-start"> |
|
|
<div class="bg-blue-100 p-3 rounded-lg mr-4"> |
|
|
<i class="fas fa-book text-blue-600 text-xl"></i> |
|
|
</div> |
|
|
<div class="flex-1"> |
|
|
<h3 class="font-bold">Advanced Programming</h3> |
|
|
<p class="text-sm text-gray-600">Dr. Wambua</p> |
|
|
<div class="flex items-center mt-2 text-sm"> |
|
|
<i class="fas fa-clock text-gray-500 mr-2"></i> |
|
|
<span>10:00 AM - 12:00 PM</span> |
|
|
</div> |
|
|
<div class="flex items-center mt-1 text-sm"> |
|
|
<i class="fas fa-map-marker-alt text-gray-500 mr-2"></i> |
|
|
<span>Block A, Room 203</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="mt-4 flex justify-between"> |
|
|
<button class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center"> |
|
|
<i class="fas fa-bell mr-2"></i> Remind Me |
|
|
</button> |
|
|
<button class="border border-blue-600 text-blue-600 px-4 py-2 rounded-lg text-sm font-medium"> |
|
|
View Details |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="p-4" id="attendance-section"> |
|
|
<h2 class="text-xl font-bold mb-4">Check-in</h2> |
|
|
<div class="bg-white rounded-xl shadow p-6 text-center"> |
|
|
<div class="mb-4"> |
|
|
<i class="fas fa-bluetooth-b text-blue-500 text-4xl mb-2"></i> |
|
|
<h3 class="font-bold text-lg">Bluetooth Attendance</h3> |
|
|
<p class="text-gray-600 text-sm">Automatically check-in when near class beacon</p> |
|
|
</div> |
|
|
|
|
|
<div id="ble-status" class="mb-6"> |
|
|
<div class="inline-block bg-gray-100 px-4 py-2 rounded-full text-sm font-medium"> |
|
|
<i class="fas fa-circle-notch fa-spin mr-2"></i> |
|
|
Scanning for beacons... |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div id="face-verification" class="hidden mb-6"> |
|
|
<div class="face-scan-animation mx-auto w-32 h-32 rounded-full border-4 border-blue-400 flex items-center justify-center mb-4"> |
|
|
<i class="fas fa-user text-4xl text-blue-500"></i> |
|
|
</div> |
|
|
<p class="text-gray-700 mb-4">Please look at your device for face verification</p> |
|
|
<button id="cancel-verification" class="text-red-500 text-sm font-medium">Cancel</button> |
|
|
</div> |
|
|
|
|
|
<div id="manual-options" class="hidden"> |
|
|
<p class="text-gray-600 text-sm mb-4">BLE not detected? Try these options:</p> |
|
|
<button class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium w-full mb-2"> |
|
|
<i class="fas fa-qrcode mr-2"></i> Scan QR Code |
|
|
</button> |
|
|
<button class="border border-blue-600 text-blue-600 px-4 py-2 rounded-lg text-sm font-medium w-full"> |
|
|
<i class="fas fa-user-tie mr-2"></i> Request Lecturer Check-in |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</section> |
|
|
|
|
|
|
|
|
<section class="p-4"> |
|
|
<h2 class="text-xl font-bold mb-4">Quick Actions</h2> |
|
|
<div class="grid grid-cols-2 gap-4"> |
|
|
<button class="bg-white rounded-xl shadow p-4 text-center"> |
|
|
<div class="bg-green-100 p-3 rounded-full inline-block mb-2"> |
|
|
<i class="fas fa-file-alt text-green-600 text-xl"></i> |
|
|
</div> |
|
|
<p class="font-medium">Submit Absence</p> |
|
|
</button> |
|
|
<button class="bg-white rounded-xl shadow p-4 text-center"> |
|
|
<div class="bg-purple-100 p-3 rounded-full inline-block mb-2"> |
|
|
<i class="fas fa-chart-bar text-purple-600 text-xl"></i> |
|
|
</div> |
|
|
<p class="font-medium">View Reports</p> |
|
|
</button> |
|
|
<button class="bg-white rounded-xl shadow p-4 text-center"> |
|
|
<div class="bg-yellow-100 p-3 rounded-full inline-block mb-2"> |
|
|
<i class="fas fa-calendar-day text-yellow-600 text-xl"></i> |
|
|
</div> |
|
|
<p class="font-medium">Timetable</p> |
|
|
</button> |
|
|
<button class="bg-white rounded-xl shadow p-4 text-center"> |
|
|
<div class="bg-red-100 p-3 rounded-full inline-block mb-2"> |
|
|
<i class="fas fa-question-circle text-red-600 text-xl"></i> |
|
|
</div> |
|
|
<p class="font-medium">Help</p> |
|
|
</button> |
|
|
</div> |
|
|
</section> |
|
|
</main> |
|
|
|
|
|
|
|
|
<nav class="bg-white border-t border-gray-200 flex justify-around py-3 px-2 fixed bottom-0 w-full max-w-md"> |
|
|
<a href="#" class="text-blue-600 flex flex-col items-center"> |
|
|
<i class="fas fa-home text-xl"></i> |
|
|
<span class="text-xs mt-1">Home</span> |
|
|
</a> |
|
|
<a href="#" class="text-gray-500 flex flex-col items-center"> |
|
|
<i class="fas fa-calendar-alt text-xl"></i> |
|
|
<span class="text-xs mt-1">Schedule</span> |
|
|
</a> |
|
|
<a href="#" class="text-gray-500 flex flex-col items-center"> |
|
|
<i class="fas fa-file-alt text-xl"></i> |
|
|
<span class="text-xs mt-1">Reports</span> |
|
|
</a> |
|
|
<a href="#" class="text-gray-500 flex flex-col items-center"> |
|
|
<i class="fas fa-user text-xl"></i> |
|
|
<span class="text-xs mt-1">Profile</span> |
|
|
</a> |
|
|
</nav> |
|
|
|
|
|
|
|
|
<div id="toast" class="hidden fixed bottom-20 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-2 rounded-lg shadow-lg"> |
|
|
<div class="flex items-center"> |
|
|
<i class="fas fa-bell mr-2"></i> |
|
|
<span>Attendance recorded successfully!</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
document.getElementById('menu-btn').addEventListener('click', function() { |
|
|
const drawer = document.getElementById('drawer'); |
|
|
drawer.classList.toggle('drawer-closed'); |
|
|
drawer.classList.toggle('drawer-open'); |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('click', function(event) { |
|
|
const drawer = document.getElementById('drawer'); |
|
|
const menuBtn = document.getElementById('menu-btn'); |
|
|
|
|
|
if (!drawer.contains(event.target) && event.target !== menuBtn && !menuBtn.contains(event.target)) { |
|
|
drawer.classList.add('drawer-closed'); |
|
|
drawer.classList.remove('drawer-open'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
setTimeout(function() { |
|
|
document.getElementById('ble-status').innerHTML = ` |
|
|
<div class="inline-block bg-green-100 px-4 py-2 rounded-full text-sm font-medium text-green-800"> |
|
|
<i class="fas fa-check-circle mr-2"></i> |
|
|
Class beacon detected! |
|
|
</div> |
|
|
`; |
|
|
|
|
|
|
|
|
document.getElementById('face-verification').classList.remove('hidden'); |
|
|
|
|
|
|
|
|
setTimeout(function() { |
|
|
document.getElementById('face-verification').innerHTML = ` |
|
|
<div class="mx-auto w-32 h-32 rounded-full border-4 border-green-400 flex items-center justify-center mb-4 bg-green-50"> |
|
|
<i class="fas fa-check text-4xl text-green-500"></i> |
|
|
</div> |
|
|
<p class="text-gray-700 mb-4 font-medium">Verification successful!</p> |
|
|
<p class="text-sm text-gray-600">Attendance recorded for Advanced Programming</p> |
|
|
`; |
|
|
|
|
|
|
|
|
const toast = document.getElementById('toast'); |
|
|
toast.classList.remove('hidden'); |
|
|
setTimeout(() => toast.classList.add('hidden'), 3000); |
|
|
|
|
|
|
|
|
setTimeout(resetAttendanceSection, 3000); |
|
|
}, 2000); |
|
|
}, 3000); |
|
|
|
|
|
|
|
|
document.getElementById('cancel-verification').addEventListener('click', function() { |
|
|
resetAttendanceSection(); |
|
|
document.getElementById('manual-options').classList.remove('hidden'); |
|
|
}); |
|
|
|
|
|
function resetAttendanceSection() { |
|
|
document.getElementById('ble-status').innerHTML = ` |
|
|
<div class="inline-block bg-gray-100 px-4 py-2 rounded-full text-sm font-medium"> |
|
|
<i class="fas fa-circle-notch fa-spin mr-2"></i> |
|
|
Scanning for beacons... |
|
|
</div> |
|
|
`; |
|
|
document.getElementById('face-verification').classList.add('hidden'); |
|
|
document.getElementById('face-verification').innerHTML = ` |
|
|
<div class="face-scan-animation mx-auto w-32 h-32 rounded-full border-4 border-blue-400 flex items-center justify-center mb-4"> |
|
|
<i class="fas fa-user text-4xl text-blue-500"></i> |
|
|
</div> |
|
|
<p class="text-gray-700 mb-4">Please look at your device for face verification</p> |
|
|
<button id="cancel-verification" class="text-red-500 text-sm font-medium">Cancel</button> |
|
|
`; |
|
|
document.getElementById('manual-options').classList.add('hidden'); |
|
|
|
|
|
|
|
|
document.getElementById('cancel-verification').addEventListener('click', function() { |
|
|
resetAttendanceSection(); |
|
|
document.getElementById('manual-options').classList.remove('hidden'); |
|
|
}); |
|
|
|
|
|
|
|
|
setTimeout(function() { |
|
|
document.getElementById('ble-status').innerHTML = ` |
|
|
<div class="inline-block bg-green-100 px-4 py-2 rounded-full text-sm font-medium text-green-800"> |
|
|
<i class="fas fa-check-circle mr-2"></i> |
|
|
Class beacon detected! |
|
|
</div> |
|
|
`; |
|
|
document.getElementById('face-verification').classList.remove('hidden'); |
|
|
|
|
|
setTimeout(function() { |
|
|
document.getElementById('face-verification').innerHTML = ` |
|
|
<div class="mx-auto w-32 h-32 rounded-full border-4 border-green-400 flex items-center justify-center mb-4 bg-green-50"> |
|
|
<i class="fas fa-check text-4xl text-green-500"></i> |
|
|
</div> |
|
|
<p class="text-gray-700 mb-4 font-medium">Verification successful!</p> |
|
|
<p class="text-sm text-gray-600">Attendance recorded for Advanced Programming</p> |
|
|
`; |
|
|
|
|
|
const toast = document.getElementById('toast'); |
|
|
toast.classList.remove('hidden'); |
|
|
setTimeout(() => toast.classList.add('hidden'), 3000); |
|
|
|
|
|
setTimeout(resetAttendanceSection, 3000); |
|
|
}, 2000); |
|
|
}, 5000); |
|
|
} |
|
|
|
|
|
|
|
|
const darkModeToggle = document.createElement('button'); |
|
|
darkModeToggle.innerHTML = '<i class="fas fa-moon"></i>'; |
|
|
darkModeToggle.className = 'absolute top-4 right-4 text-white'; |
|
|
darkModeToggle.addEventListener('click', function() { |
|
|
document.documentElement.classList.toggle('dark'); |
|
|
this.innerHTML = document.documentElement.classList.contains('dark') |
|
|
? '<i class="fas fa-sun"></i>' |
|
|
: '<i class="fas fa-moon"></i>'; |
|
|
}); |
|
|
document.body.appendChild(darkModeToggle); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Maxie254/zetech" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |