attendancy-system / index.html
Jacksonnavigator7's picture
Add 3 files
f7d66b5 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile Attendance System</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>
.hidden {
display: none;
}
.active-tab {
border-bottom: 3px solid #3b82f6;
color: #3b82f6;
font-weight: 600;
}
.attendance-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.progress-bar {
height: 8px;
border-radius: 4px;
background-color: #e5e7eb;
}
.progress-fill {
height: 100%;
border-radius: 4px;
background-color: #3b82f6;
transition: width 0.5s ease-in-out;
}
#deviceIdDisplay {
font-family: monospace;
background-color: #f3f4f6;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.875rem;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- Login Screen -->
<div id="loginScreen" class="flex flex-col items-center justify-center min-h-screen p-4">
<div class="w-full max-w-md bg-white rounded-lg shadow-md p-8">
<div class="text-center mb-8">
<i class="fas fa-user-graduate text-5xl text-blue-500 mb-4"></i>
<h1 class="text-3xl font-bold text-gray-800">Attendance System</h1>
<p class="text-gray-600 mt-2">Sign in to access your account</p>
</div>
<form id="loginForm" class="space-y-6">
<div>
<label for="email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input type="email" id="email" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label for="password" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<input type="password" id="password" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input type="checkbox" id="remember" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<label for="remember" class="ml-2 block text-sm text-gray-700">Remember me</label>
</div>
<a href="#" class="text-sm text-blue-600 hover:text-blue-500">Forgot password?</a>
</div>
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150">
Sign In
</button>
</form>
<div class="mt-6 text-center">
<p class="text-sm text-gray-600">Don't have an account? <a href="#" class="text-blue-600 hover:text-blue-500 font-medium">Contact admin</a></p>
</div>
</div>
</div>
<!-- Teacher Dashboard -->
<div id="teacherDashboard" class="hidden min-h-screen">
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 py-4 sm:px-6 lg:px-8 flex justify-between items-center">
<h1 class="text-xl font-semibold text-gray-900">Teacher Dashboard</h1>
<div class="flex items-center space-x-4">
<span id="teacherName" class="text-gray-700">John Doe</span>
<button id="teacherLogout" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-sign-out-alt"></i>
</button>
</div>
</div>
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8 px-4">
<button id="teacherSessionsTab" class="py-4 px-1 border-b-2 font-medium text-sm active-tab">
Attendance Sessions
</button>
<button id="teacherStudentsTab" class="py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">
Manage Students
</button>
<button id="teacherReportsTab" class="py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">
Reports
</button>
</nav>
</div>
</header>
<main class="max-w-7xl mx-auto px-4 py-6 sm:px-6 lg:px-8">
<!-- Sessions Tab Content -->
<div id="teacherSessionsContent" class="space-y-6">
<div class="flex justify-between items-center">
<h2 class="text-lg font-medium text-gray-900">Current Sessions</h2>
<button id="createSessionBtn" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
<i class="fas fa-plus mr-2"></i> New Session
</button>
</div>
<div id="activeSessions" class="bg-white shadow overflow-hidden sm:rounded-md">
<ul class="divide-y divide-gray-200">
<!-- Active sessions will be added here dynamically -->
</ul>
</div>
<h2 class="text-lg font-medium text-gray-900">Session History</h2>
<div id="pastSessions" class="bg-white shadow overflow-hidden sm:rounded-md">
<ul class="divide-y divide-gray-200">
<!-- Past sessions will be added here dynamically -->
</ul>
</div>
</div>
<!-- Students Tab Content -->
<div id="teacherStudentsContent" class="hidden space-y-6">
<div class="flex justify-between items-center">
<h2 class="text-lg font-medium text-gray-900">Class Students</h2>
<button id="addStudentBtn" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
<i class="fas fa-user-plus mr-2"></i> Add Student
</button>
</div>
<div class="bg-white shadow overflow-hidden sm:rounded-md">
<ul id="studentsList" class="divide-y divide-gray-200">
<!-- Students will be added here dynamically -->
</ul>
</div>
</div>
<!-- Reports Tab Content -->
<div id="teacherReportsContent" class="hidden">
<h2 class="text-lg font-medium text-gray-900 mb-4">Attendance Reports</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-md font-medium text-gray-900 mb-4">Class Attendance Summary</h3>
<div id="classAttendanceChart" class="h-64">
<!-- Chart will be rendered here -->
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-md font-medium text-gray-900 mb-4">Recent Attendance</h3>
<div id="recentAttendanceTable" class="overflow-x-auto">
<!-- Table will be rendered here -->
</div>
</div>
</div>
</div>
</main>
<!-- Create Session Modal -->
<div id="createSessionModal" class="hidden fixed inset-0 overflow-y-auto z-10">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-calendar-plus text-blue-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">Create New Attendance Session</h3>
<div class="mt-2">
<form id="createSessionForm" class="space-y-4">
<div>
<label for="sessionName" class="block text-sm font-medium text-gray-700">Session Name</label>
<input type="text" id="sessionName" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
</div>
<div>
<label for="sessionDuration" class="block text-sm font-medium text-gray-700">Duration (minutes)</label>
<input type="number" id="sessionDuration" min="1" max="120" value="15" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
</div>
<div>
<label for="sessionClass" class="block text-sm font-medium text-gray-700">Class</label>
<select id="sessionClass" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
<option>CS101</option>
<option>MATH202</option>
<option>ENG150</option>
</select>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="confirmCreateSession" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
Create Session
</button>
<button type="button" id="cancelCreateSession" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
<!-- Add Student Modal -->
<div id="addStudentModal" class="hidden fixed inset-0 overflow-y-auto z-10">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-user-plus text-blue-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">Add New Student</h3>
<div class="mt-2">
<form id="addStudentForm" class="space-y-4">
<div>
<label for="studentName" class="block text-sm font-medium text-gray-700">Full Name</label>
<input type="text" id="studentName" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
</div>
<div>
<label for="studentEmail" class="block text-sm font-medium text-gray-700">Email</label>
<input type="email" id="studentEmail" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
</div>
<div>
<label for="studentId" class="block text-sm font-medium text-gray-700">Student ID</label>
<input type="text" id="studentId" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
</div>
<div>
<label for="studentClass" class="block text-sm font-medium text-gray-700">Class</label>
<select id="studentClass" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm">
<option>CS101</option>
<option>MATH202</option>
<option>ENG150</option>
</select>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="confirmAddStudent" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
Add Student
</button>
<button type="button" id="cancelAddStudent" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Student Dashboard -->
<div id="studentDashboard" class="hidden min-h-screen">
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 py-4 sm:px-6 lg:px-8 flex justify-between items-center">
<h1 class="text-xl font-semibold text-gray-900">Student Dashboard</h1>
<div class="flex items-center space-x-4">
<span id="studentName" class="text-gray-700">Jane Smith</span>
<button id="studentLogout" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-sign-out-alt"></i>
</button>
</div>
</div>
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8 px-4">
<button id="studentAttendanceTab" class="py-4 px-1 border-b-2 font-medium text-sm active-tab">
Mark Attendance
</button>
<button id="studentHistoryTab" class="py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">
My History
</button>
<button id="studentStatsTab" class="py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300">
My Stats
</button>
</nav>
</div>
</header>
<main class="max-w-7xl mx-auto px-4 py-6 sm:px-6 lg:px-8">
<!-- Attendance Tab Content -->
<div id="studentAttendanceContent" class="space-y-6">
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<h3 class="text-lg leading-6 font-medium text-gray-900">Current Attendance Sessions</h3>
<p class="mt-1 text-sm text-gray-500">Available sessions where you can mark your attendance.</p>
</div>
<div id="availableSessions" class="divide-y divide-gray-200">
<!-- Available sessions will be added here dynamically -->
</div>
</div>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<h3 class="text-lg leading-6 font-medium text-gray-900">Device Information</h3>
<p class="mt-1 text-sm text-gray-500">Your attendance is tied to this device for security.</p>
</div>
<div class="px-4 py-5 sm:p-6">
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
<div>
<label class="block text-sm font-medium text-gray-700">Device ID</label>
<div id="deviceIdDisplay" class="mt-1">Loading...</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Status</label>
<div class="mt-1">
<span id="deviceStatus" class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
<i class="fas fa-check-circle mr-1"></i> Verified
</span>
</div>
</div>
</div>
<div class="mt-4">
<p class="text-sm text-gray-600">If you need to change your device, please contact your instructor.</p>
</div>
</div>
</div>
</div>
<!-- History Tab Content -->
<div id="studentHistoryContent" class="hidden">
<h2 class="text-lg font-medium text-gray-900 mb-4">My Attendance History</h2>
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<h3 class="text-lg leading-6 font-medium text-gray-900">Recent Attendance Records</h3>
<p class="mt-1 text-sm text-gray-500">Your last 10 attendance marks.</p>
</div>
<div id="attendanceHistory" class="divide-y divide-gray-200">
<!-- Attendance history will be added here dynamically -->
</div>
</div>
</div>
<!-- Stats Tab Content -->
<div id="studentStatsContent" class="hidden">
<h2 class="text-lg font-medium text-gray-900 mb-4">My Attendance Statistics</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-md font-medium text-gray-900 mb-4">Overall Attendance</h3>
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium text-gray-700">Attendance Rate</span>
<span id="attendanceRate" class="text-sm font-medium text-blue-600">85%</span>
</div>
<div class="progress-bar">
<div id="attendanceProgress" class="progress-fill" style="width: 85%"></div>
</div>
<div class="mt-4 grid grid-cols-2 gap-4">
<div class="bg-blue-50 p-3 rounded-lg">
<p class="text-sm font-medium text-gray-500">Present</p>
<p id="presentCount" class="text-2xl font-semibold text-blue-600">17</p>
</div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-sm font-medium text-gray-500">Absent</p>
<p id="absentCount" class="text-2xl font-semibold text-gray-600">3</p>
</div>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow">
<h3 class="text-md font-medium text-gray-900 mb-4">Attendance by Class</h3>
<div id="classAttendanceStats" class="space-y-4">
<!-- Class attendance stats will be added here dynamically -->
</div>
</div>
</div>
</div>
</main>
<!-- Attendance Confirmation Modal -->
<div id="attendanceConfirmationModal" class="hidden fixed inset-0 overflow-y-auto z-10">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-check-circle text-blue-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">Confirm Attendance</h3>
<div class="mt-2">
<p class="text-sm text-gray-500">You are about to mark your attendance for <span id="confirmSessionName" class="font-medium">CS101 Lecture</span>.</p>
<p class="text-sm text-gray-500 mt-2">This action cannot be undone.</p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="confirmAttendance" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
Confirm
</button>
<button type="button" id="cancelAttendance" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
<!-- Attendance Success Modal -->
<div id="attendanceSuccessModal" class="hidden fixed inset-0 overflow-y-auto z-10">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
<i class="fas fa-check text-green-600"></i>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium text-gray-900">Attendance Recorded</h3>
<div class="mt-2">
<p class="text-sm text-gray-500">Your attendance for <span id="successSessionName" class="font-medium">CS101 Lecture</span> has been successfully recorded.</p>
<p class="text-sm text-gray-500 mt-2">Time: <span id="attendanceTime" class="font-medium">10:15 AM</span></p>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" id="closeSuccessModal" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
OK
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Database simulation
const db = {
users: [
{ id: 1, email: 'teacher@school.edu', password: 'teacher123', name: 'John Doe', role: 'teacher' },
{ id: 2, email: 'student@school.edu', password: 'student123', name: 'Jane Smith', role: 'student', studentId: 'S1001', class: 'CS101', deviceId: 'device123' },
{ id: 3, email: 'student2@school.edu', password: 'student123', name: 'Mike Johnson', role: 'student', studentId: 'S1002', class: 'CS101', deviceId: 'device456' }
],
sessions: [
{ id: 1, name: 'CS101 Lecture', class: 'CS101', teacherId: 1, status: 'active', startTime: new Date(), endTime: new Date(Date.now() + 15 * 60000), attendees: [2] },
{ id: 2, name: 'CS101 Lab', class: 'CS101', teacherId: 1, status: 'closed', startTime: new Date(Date.now() - 86400000), endTime: new Date(Date.now() - 86400000 + 60 * 60000), attendees: [2, 3] },
{ id: 3, name: 'MATH202 Lecture', class: 'MATH202', teacherId: 1, status: 'closed', startTime: new Date(Date.now() - 2 * 86400000), endTime: new Date(Date.now() - 2 * 86400000 + 30 * 60000), attendees: [2] }
],
attendance: [
{ id: 1, sessionId: 2, studentId: 2, timestamp: new Date(Date.now() - 86400000 + 5 * 60000) },
{ id: 2, sessionId: 2, studentId: 3, timestamp: new Date(Date.now() - 86400000 + 10 * 60000) },
{ id: 3, sessionId: 3, studentId: 2, timestamp: new Date(Date.now() - 2 * 86400000 + 5 * 60000) }
]
};
// Current user and device ID
let currentUser = null;
const deviceId = 'device' + Math.floor(Math.random() * 1000000);
// DOM elements
const loginScreen = document.getElementById('loginScreen');
const teacherDashboard = document.getElementById('teacherDashboard');
const studentDashboard = document.getElementById('studentDashboard');
const loginForm = document.getElementById('loginForm');
const teacherLogout = document.getElementById('teacherLogout');
const studentLogout = document.getElementById('studentLogout');
// Teacher elements
const teacherSessionsTab = document.getElementById('teacherSessionsTab');
const teacherStudentsTab = document.getElementById('teacherStudentsTab');
const teacherReportsTab = document.getElementById('teacherReportsTab');
const teacherSessionsContent = document.getElementById('teacherSessionsContent');
const teacherStudentsContent = document.getElementById('teacherStudentsContent');
const teacherReportsContent = document.getElementById('teacherReportsContent');
const createSessionBtn = document.getElementById('createSessionBtn');
const createSessionModal = document.getElementById('createSessionModal');
const cancelCreateSession = document.getElementById('cancelCreateSession');
const confirmCreateSession = document.getElementById('confirmCreateSession');
const activeSessions = document.getElementById('activeSessions');
const pastSessions = document.getElementById('pastSessions');
const addStudentBtn = document.getElementById('addStudentBtn');
const addStudentModal = document.getElementById('addStudentModal');
const cancelAddStudent = document.getElementById('cancelAddStudent');
const confirmAddStudent = document.getElementById('confirmAddStudent');
const studentsList = document.getElementById('studentsList');
// Student elements
const studentAttendanceTab = document.getElementById('studentAttendanceTab');
const studentHistoryTab = document.getElementById('studentHistoryTab');
const studentStatsTab = document.getElementById('studentStatsTab');
const studentAttendanceContent = document.getElementById('studentAttendanceContent');
const studentHistoryContent = document.getElementById('studentHistoryContent');
const studentStatsContent = document.getElementById('studentStatsContent');
const availableSessions = document.getElementById('availableSessions');
const attendanceHistory = document.getElementById('attendanceHistory');
const attendanceConfirmationModal = document.getElementById('attendanceConfirmationModal');
const confirmAttendance = document.getElementById('confirmAttendance');
const cancelAttendance = document.getElementById('cancelAttendance');
const attendanceSuccessModal = document.getElementById('attendanceSuccessModal');
const closeSuccessModal = document.getElementById('closeSuccessModal');
const deviceIdDisplay = document.getElementById('deviceIdDisplay');
const deviceStatus = document.getElementById('deviceStatus');
const attendanceRate = document.getElementById('attendanceRate');
const attendanceProgress = document.getElementById('attendanceProgress');
const presentCount = document.getElementById('presentCount');
const absentCount = document.getElementById('absentCount');
const classAttendanceStats = document.getElementById('classAttendanceStats');
// Login functionality
loginForm.addEventListener('submit', function(e) {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const user = db.users.find(u => u.email === email && u.password === password);
if (user) {
currentUser = user;
if (user.role === 'teacher') {
showTeacherDashboard();
} else if (user.role === 'student') {
// Check device binding for students
if (!user.deviceId) {
// First login - bind device
user.deviceId = deviceId;
showStudentDashboard();
} else if (user.deviceId === deviceId) {
// Device matches
showStudentDashboard();
} else {
// Device doesn't match
alert('You can only access your account from your registered device. Please contact your instructor if you need to change devices.');
return;
}
}
loginScreen.classList.add('hidden');
} else {
alert('Invalid email or password');
}
});
// Logout functionality
teacherLogout.addEventListener('click', function() {
currentUser = null;
teacherDashboard.classList.add('hidden');
loginScreen.classList.remove('hidden');
resetTeacherDashboard();
});
studentLogout.addEventListener('click', function() {
currentUser = null;
studentDashboard.classList.add('hidden');
loginScreen.classList.remove('hidden');
resetStudentDashboard();
});
// Teacher dashboard tabs
teacherSessionsTab.addEventListener('click', function() {
setActiveTab('teacher', 'sessions');
});
teacherStudentsTab.addEventListener('click', function() {
setActiveTab('teacher', 'students');
});
teacherReportsTab.addEventListener('click', function() {
setActiveTab('teacher', 'reports');
});
// Student dashboard tabs
studentAttendanceTab.addEventListener('click', function() {
setActiveTab('student', 'attendance');
});
studentHistoryTab.addEventListener('click', function() {
setActiveTab('student', 'history');
});
studentStatsTab.addEventListener('click', function() {
setActiveTab('student', 'stats');
});
// Session management
createSessionBtn.addEventListener('click', function() {
createSessionModal.classList.remove('hidden');
});
cancelCreateSession.addEventListener('click', function() {
createSessionModal.classList.add('hidden');
});
confirmCreateSession.addEventListener('click', function() {
const sessionName = document.getElementById('sessionName').value;
const sessionDuration = parseInt(document.getElementById('sessionDuration').value);
const sessionClass = document.getElementById('sessionClass').value;
const newSession = {
id: db.sessions.length + 1,
name: sessionName,
class: sessionClass,
teacherId: currentUser.id,
status: 'active',
startTime: new Date(),
endTime: new Date(Date.now() + sessionDuration * 60000),
attendees: []
};
db.sessions.push(newSession);
createSessionModal.classList.add('hidden');
document.getElementById('createSessionForm').reset();
renderTeacherSessions();
});
// Student management
addStudentBtn.addEventListener('click', function() {
addStudentModal.classList.remove('hidden');
});
cancelAddStudent.addEventListener('click', function() {
addStudentModal.classList.add('hidden');
});
confirmAddStudent.addEventListener('click', function() {
const studentName = document.getElementById('studentName').value;
const studentEmail = document.getElementById('studentEmail').value;
const studentId = document.getElementById('studentId').value;
const studentClass = document.getElementById('studentClass').value;
const newStudent = {
id: db.users.length + 1,
email: studentEmail,
password: 'student123', // Default password
name: studentName,
role: 'student',
studentId: studentId,
class: studentClass,
deviceId: null // Will be set on first login
};
db.users.push(newStudent);
addStudentModal.classList.add('hidden');
document.getElementById('addStudentForm').reset();
renderStudentsList();
});
// Attendance marking
function setupAttendanceButtons() {
document.querySelectorAll('.mark-attendance-btn').forEach(button => {
button.addEventListener('click', function() {
const sessionId = parseInt(this.getAttribute('data-session-id'));
const session = db.sessions.find(s => s.id === sessionId);
document.getElementById('confirmSessionName').textContent = session.name;
document.getElementById('confirmAttendance').setAttribute('data-session-id', sessionId);
attendanceConfirmationModal.classList.remove('hidden');
});
});
}
confirmAttendance.addEventListener('click', function() {
const sessionId = parseInt(this.getAttribute('data-session-id'));
const session = db.sessions.find(s => s.id === sessionId);
// Record attendance
const newAttendance = {
id: db.attendance.length + 1,
sessionId: sessionId,
studentId: currentUser.id,
timestamp: new Date()
};
db.attendance.push(newAttendance);
session.attendees.push(currentUser.id);
// Show success
document.getElementById('successSessionName').textContent = session.name;
document.getElementById('attendanceTime').textContent = newAttendance.timestamp.toLocaleTimeString();
attendanceConfirmationModal.classList.add('hidden');
attendanceSuccessModal.classList.remove('hidden');
// Update UI
renderAvailableSessions();
});
cancelAttendance.addEventListener('click', function() {
attendanceConfirmationModal.classList.add('hidden');
});
closeSuccessModal.addEventListener('click', function() {
attendanceSuccessModal.classList.add('hidden');
});
// Helper functions
function showTeacherDashboard() {
teacherDashboard.classList.remove('hidden');
document.getElementById('teacherName').textContent = currentUser.name;
renderTeacherSessions();
renderStudentsList();
setActiveTab('teacher', 'sessions');
}
function showStudentDashboard() {
studentDashboard.classList.remove('hidden');
document.getElementById('studentName').textContent = currentUser.name;
deviceIdDisplay.textContent = currentUser.deviceId;
// Check if device matches
if (currentUser.deviceId === deviceId) {
deviceStatus.innerHTML = '<i class="fas fa-check-circle mr-1"></i> Verified';
deviceStatus.className = 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800';
} else {
deviceStatus.innerHTML = '<i class="fas fa-exclamation-triangle mr-1"></i> Mismatch';
deviceStatus.className = 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800';
}
renderAvailableSessions();
renderAttendanceHistory();
renderStudentStats();
setActiveTab('student', 'attendance');
}
function resetTeacherDashboard() {
teacherSessionsContent.classList.remove('hidden');
teacherStudentsContent.classList.add('hidden');
teacherReportsContent.classList.add('hidden');
teacherSessionsTab.classList.add('active-tab');
teacherStudentsTab.classList.remove('active-tab');
teacherReportsTab.classList.remove('active-tab');
}
function resetStudentDashboard() {
studentAttendanceContent.classList.remove('hidden');
studentHistoryContent.classList.add('hidden');
studentStatsContent.classList.add('hidden');
studentAttendanceTab.classList.add('active-tab');
studentHistoryTab.classList.remove('active-tab');
studentStatsTab.classList.remove('active-tab');
}
function setActiveTab(role, tab) {
if (role === 'teacher') {
teacherSessionsContent.classList.add('hidden');
teacherStudentsContent.classList.add('hidden');
teacherReportsContent.classList.add('hidden');
teacherSessionsTab.classList.remove('active-tab');
teacherStudentsTab.classList.remove('active-tab');
teacherReportsTab.classList.remove('active-tab');
if (tab === 'sessions') {
teacherSessionsContent.classList.remove('hidden');
teacherSessionsTab.classList.add('active-tab');
renderTeacherSessions();
} else if (tab === 'students') {
teacherStudentsContent.classList.remove('hidden');
teacherStudentsTab.classList.add('active-tab');
renderStudentsList();
} else if (tab === 'reports') {
teacherReportsContent.classList.remove('hidden');
teacherReportsTab.classList.add('active-tab');
renderTeacherReports();
}
} else if (role === 'student') {
studentAttendanceContent.classList.add('hidden');
studentHistoryContent.classList.add('hidden');
studentStatsContent.classList.add('hidden');
studentAttendanceTab.classList.remove('active-tab');
studentHistoryTab.classList.remove('active-tab');
studentStatsTab.classList.remove('active-tab');
if (tab === 'attendance') {
studentAttendanceContent.classList.remove('hidden');
studentAttendanceTab.classList.add('active-tab');
renderAvailableSessions();
} else if (tab === 'history') {
studentHistoryContent.classList.remove('hidden');
studentHistoryTab.classList.add('active-tab');
renderAttendanceHistory();
} else if (tab === 'stats') {
studentStatsContent.classList.remove('hidden');
studentStatsTab.classList.add('active-tab');
renderStudentStats();
}
}
}
function renderTeacherSessions() {
// Active sessions
const activeSessionsList = db.sessions.filter(s => s.status === 'active' && s.teacherId === currentUser.id);
const activeSessionsUl = document.querySelector('#activeSessions ul');
activeSessionsUl.innerHTML = '';
if (activeSessionsList.length === 0) {
activeSessionsUl.innerHTML = '<li class="px-4 py-4 text-center text-gray-500">No active sessions</li>';
} else {
activeSessionsList.forEach(session => {
const attendeesCount = session.attendees.length;
const studentsCount = db.users.filter(u => u.role === 'student' && u.class === session.class).length;
const li = document.createElement('li');
li.className = 'px-4 py-4';
li.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="min-w-0 flex-1">
<div class="flex items-center">
<p class="text-sm font-medium text-blue-600 truncate">${session.name}</p>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
${session.class}
</span>
</div>
<div class="mt-2 flex">
<div class="flex items-center text-sm text-gray-500">
<i class="fas fa-users mr-1.5"></i>
<span>${attendeesCount}/${studentsCount} students</span>
</div>
<div class="ml-3 flex items-center text-sm text-gray-500">
<i class="fas fa-clock mr-1.5"></i>
<span>Ends at ${session.endTime.toLocaleTimeString()}</span>
</div>
</div>
</div>
</div>
<div>
<button class="close-session-btn inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded shadow-sm text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" data-session-id="${session.id}">
<i class="fas fa-times mr-1"></i> Close
</button>
</div>
</div>
`;
activeSessionsUl.appendChild(li);
});
}
// Past sessions
const pastSessionsList = db.sessions.filter(s => s.status === 'closed' && s.teacherId === currentUser.id)
.sort((a, b) => b.startTime - a.startTime);
const pastSessionsUl = document.querySelector('#pastSessions ul');
pastSessionsUl.innerHTML = '';
if (pastSessionsList.length === 0) {
pastSessionsUl.innerHTML = '<li class="px-4 py-4 text-center text-gray-500">No past sessions</li>';
} else {
pastSessionsList.forEach(session => {
const attendeesCount = session.attendees.length;
const studentsCount = db.users.filter(u => u.role === 'student' && u.class === session.class).length;
const li = document.createElement('li');
li.className = 'px-4 py-4';
li.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="min-w-0 flex-1">
<div class="flex items-center">
<p class="text-sm font-medium text-gray-900 truncate">${session.name}</p>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
${session.class}
</span>
</div>
<div class="mt-2 flex">
<div class="flex items-center text-sm text-gray-500">
<i class="fas fa-users mr-1.5"></i>
<span>${attendeesCount}/${studentsCount} students</span>
</div>
<div class="ml-3 flex items-center text-sm text-gray-500">
<i class="fas fa-calendar-day mr-1.5"></i>
<span>${session.startTime.toLocaleDateString()}</span>
</div>
</div>
</div>
</div>
<div>
<button class="view-session-btn inline-flex items-center px-3 py-1.5 border border-gray-300 text-xs font-medium rounded shadow-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" data-session-id="${session.id}">
<i class="fas fa-eye mr-1"></i> View
</button>
</div>
</div>
`;
pastSessionsUl.appendChild(li);
});
}
// Add event listeners to buttons
document.querySelectorAll('.close-session-btn').forEach(button => {
button.addEventListener('click', function() {
const sessionId = parseInt(this.getAttribute('data-session-id'));
const session = db.sessions.find(s => s.id === sessionId);
session.status = 'closed';
renderTeacherSessions();
});
});
document.querySelectorAll('.view-session-btn').forEach(button => {
button.addEventListener('click', function() {
const sessionId = parseInt(this.getAttribute('data-session-id'));
// In a real app, this would show detailed session info
alert('Viewing session details would show here');
});
});
}
function renderStudentsList() {
const students = db.users.filter(u => u.role === 'student' && u.class === 'CS101'); // Simplified for demo
studentsList.innerHTML = '';
if (students.length === 0) {
studentsList.innerHTML = '<li class="px-4 py-4 text-center text-gray-500">No students in this class</li>';
} else {
students.forEach(student => {
const li = document.createElement('li');
li.className = 'px-4 py-4';
li.innerHTML = `
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="h-10 w-10 rounded-full bg-gray-200 flex items-center justify-center">
<i class="fas fa-user text-gray-500"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">${student.name}</div>
<div class="text-sm text-gray-500">${student.email}</div>
</div>
</div>
<div class="flex items-center">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
${student.studentId}
</span>
<span class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${student.deviceId ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'}">
${student.deviceId ? 'Device set' : 'No device'}
</span>
</div>
</div>
`;
studentsList.appendChild(li);
});
}
}
function renderTeacherReports() {
// Simplified for demo - in a real app, this would show charts and detailed reports
document.getElementById('classAttendanceChart').innerHTML = `
<div class="flex items-center justify-center h-full">
<div class="text-center">
<i class="fas fa-chart-bar text-4xl text-gray-300 mb-2"></i>
<p class="text-gray-500">Attendance charts would display here</p>
</div>
</div>
`;
document.getElementById('recentAttendanceTable').innerHTML = `
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Class</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Attendance</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${new Date().toLocaleDateString()}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">CS101</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">15/20</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${new Date(Date.now() - 86400000).toLocaleDateString()}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">CS101</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">18/20</td>
</tr>
</tbody>
</table>
`;
}
function renderAvailableSessions() {
const availableSessionsList = db.sessions.filter(s =>
s.status === 'active' &&
s.class === currentUser.class &&
!s.attendees.includes(currentUser.id)
);
availableSessions.innerHTML = '';
if (availableSessionsList.length === 0) {
availableSessions.innerHTML = `
<div class="px-4 py-5 sm:p-6 text-center">
<i class="fas fa-calendar-check text-4xl text-gray-300 mb-3"></i>
<h3 class="text-lg font-medium text-gray-900">No available sessions</h3>
<p class="mt-1 text-sm text-gray-500">There are currently no active attendance sessions for your class.</p>
</div>
`;
} else {
availableSessionsList.forEach(session => {
const endTime = new Date(session.endTime);
const timeLeft = Math.max(0, Math.floor((endTime - new Date()) / 60000));
const div = document.createElement('div');
div.className = 'px-4 py-5 sm:p-6 attendance-card transition duration-150 ease-in-out';
div.innerHTML = `
<div class="flex items-center justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">${session.name}</h3>
<p class="mt-1 text-sm text-gray-500">${session.class} • Ends in ${timeLeft} minutes</p>
</div>
<div>
<button class="mark-attendance-btn inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" data-session-id="${session.id}">
<i class="fas fa-check-circle mr-2"></i> Mark Attendance
</button>
</div>
</div>
`;
availableSessions.appendChild(div);
});
setupAttendanceButtons();
}
}
function renderAttendanceHistory() {
const studentAttendance = db.attendance
.filter(a => a.studentId === currentUser.id)
.sort((a, b) => b.timestamp - a.timestamp)
.slice(0, 10);
attendanceHistory.innerHTML = '';
if (studentAttendance.length === 0) {
attendanceHistory.innerHTML = `
<div class="px-4 py-5 sm:p-6 text-center">
<i class="fas fa-history text-4xl text-gray-300 mb-3"></i>
<h3 class="text-lg font-medium text-gray-900">No attendance history</h3>
<p class="mt-1 text-sm text-gray-500">You haven't marked any attendance sessions yet.</p>
</div>
`;
} else {
studentAttendance.forEach(record => {
const session = db.sessions.find(s => s.id === record.sessionId);
const div = document.createElement('div');
div.className = 'px-4 py-5 sm:p-6';
div.innerHTML = `
<div class="flex items-center justify-between">
<div>
<h3 class="text-lg leading-6 font-medium text-gray-900">${session.name}</h3>
<p class="mt-1 text-sm text-gray-500">${session.class}${record.timestamp.toLocaleDateString()} at ${record.timestamp.toLocaleTimeString()}</p>
</div>
<div>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
<i class="fas fa-check mr-1"></i> Present
</span>
</div>
</div>
`;
attendanceHistory.appendChild(div);
});
}
}
function renderStudentStats() {
// Calculate stats
const totalSessions = db.sessions.filter(s => s.class === currentUser.class && s.status === 'closed').length;
const attendedSessions = db.attendance
.filter(a => a.studentId === currentUser.id)
.map(a => a.sessionId)
.filter((v, i, a) => a.indexOf(v) === i).length;
const attendancePercentage = totalSessions > 0 ? Math.round((attendedSessions / totalSessions) * 100) : 0;
// Update UI
attendanceRate.textContent = `${attendancePercentage}%`;
attendanceProgress.style.width = `${attendancePercentage}%`;
presentCount.textContent = attendedSessions;
absentCount.textContent = totalSessions - attendedSessions;
// Class stats
const classes = [...new Set(db.sessions.map(s => s.class))];
classAttendanceStats.innerHTML = '';
classes.forEach(classId => {
const classSessions = db.sessions.filter(s => s.class === classId && s.status === 'closed').length;
const classAttended = db.attendance
.filter(a => a.studentId === currentUser.id && db.sessions.find(s => s.id === a.sessionId && s.class === classId))
.map(a => a.sessionId)
.filter((v, i, a) => a.indexOf(v) === i).length;
const classPercentage = classSessions > 0 ? Math.round((classAttended / classSessions) * 100) : 0;
const div = document.createElement('div');
div.className = 'flex items-center justify-between';
div.innerHTML = `
<div>
<h4 class="text-sm font-medium text-gray-900">${classId}</h4>
<p class="text-xs text-gray-500">${classAttended}/${classSessions} sessions</p>
</div>
<div class="w-1/2">
<div class="progress-bar">
<div class="progress-fill" style="width: ${classPercentage}%"></div>
</div>
<p class="text-xs text-right mt-1 text-gray-500">${classPercentage}%</p>
</div>
`;
classAttendanceStats.appendChild(div);
});
}
// Initialize
document.addEventListener('DOMContentLoaded', function() {
// For demo purposes, pre-fill login form
document.getElementById('email').value = 'teacher@school.edu';
document.getElementById('password').value = 'teacher123';
});
</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=Jacksonnavigator7/attendancy-system" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>