Skip to content

Commit d3c7aed

Browse files
authored
Merge pull request #124 from SRATRC/dev
attendance scanner
2 parents 3f8ec01 + 6ce445b commit d3c7aed

3 files changed

Lines changed: 259 additions & 1 deletion

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<script src="/style/js/roleCheck.js"></script>
2+
<script>
3+
checkRoleAccess([
4+
'officeAdmin',
5+
'adhyayanAdmin',
6+
'superAdmin',
7+
'adhyayanAdminKol',
8+
'adhyayanAdminRaj',
9+
'adhyayanAdminDhu',
10+
'adhyayanAdminReadOnly'
11+
]);
12+
</script>
13+
14+
<!DOCTYPE html>
15+
<html lang="en">
16+
17+
<head>
18+
<meta charset="UTF-8">
19+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
20+
21+
<title id="pageTitle">Adhyayan Attendance Scanner</title>
22+
23+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
24+
25+
<script src="../../style/js/plugin.js"></script>
26+
<script src="../../style/js/custom.js"></script>
27+
<script src="../../style/js/config.js"></script>
28+
<script src="../../sessionstorage.js"></script>
29+
30+
<link rel="stylesheet" href="../../style/css/styles.css">
31+
32+
<style>
33+
34+
.big-alert{
35+
font-size:28px;
36+
font-weight:bold;
37+
text-align:center;
38+
padding:20px;
39+
margin-top:20px;
40+
}
41+
42+
.alert-success{ color:green }
43+
.alert-danger{ color:red }
44+
.alert-warning{ color:#856404 }
45+
46+
</style>
47+
48+
</head>
49+
50+
<body>
51+
52+
<div class="header">
53+
<div class="container">
54+
<div class="logout">
55+
<a href="javascript:void(0);" onclick="history.back()">Back</a>
56+
&nbsp; | &nbsp;
57+
<a href="javascript:void(0);" onclick="goToHome()">Home</a>
58+
&nbsp; | &nbsp;
59+
<a href="javascript:void(0);" onclick="logout()">Logout</a>
60+
</div>
61+
</div>
62+
</div>
63+
64+
<div class="middlecontent">
65+
<div class="container">
66+
<div class="whitesec">
67+
<div class="inner-padding">
68+
69+
<div class="frm-head">
70+
<h1 id="scanner-heading">Tap card for Adhyayan Attendance</h1>
71+
</div>
72+
73+
<div id="alert" class="big-alert" style="display:none"></div>
74+
75+
<div id="formWrapper">
76+
<div class="form">
77+
78+
<form id="attendanceForm">
79+
80+
<div class="form-group">
81+
<label>Tap card:</label>
82+
<input
83+
type="text"
84+
class="form-control"
85+
id="cardno"
86+
autocomplete="off"
87+
/></div>
88+
89+
</form>
90+
91+
</div>
92+
</div>
93+
94+
</div>
95+
</div>
96+
</div>
97+
</div>
98+
99+
<script src="./adhyayanAttendanceScanner.js"></script>
100+
101+
</body>
102+
</html>
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
const params = new URLSearchParams(window.location.search);
2+
const shibirId = params.get("shibir_id");
3+
const sessionNo = params.get("session") || 1;
4+
5+
let isProcessing = false;
6+
7+
document.addEventListener("DOMContentLoaded", () => {
8+
9+
const heading = document.getElementById("scanner-heading");
10+
const cardInput = document.getElementById("cardno");
11+
12+
heading.innerText = `Tap card for Adhyayan Attendance (Session ${sessionNo})`;
13+
14+
// Force focus after page load
15+
setTimeout(() => {
16+
cardInput.focus();
17+
}, 300);
18+
19+
// Prevent losing focus
20+
setInterval(() => {
21+
if (document.activeElement !== cardInput) {
22+
cardInput.focus();
23+
}
24+
}, 500);
25+
26+
// Scanner usually sends ENTER
27+
cardInput.addEventListener("keydown", function (e) {
28+
29+
if (e.key === "Enter") {
30+
e.preventDefault();
31+
32+
const cardno = cardInput.value.trim();
33+
34+
if (cardno && !isProcessing) {
35+
markAttendance(cardno);
36+
}
37+
}
38+
39+
});
40+
41+
// Backup: if scanner doesn't send ENTER
42+
cardInput.addEventListener("input", function () {
43+
44+
const value = cardInput.value.trim();
45+
46+
if (value.length >= 4 && !isProcessing) {
47+
setTimeout(() => {
48+
if (!isProcessing && cardInput.value.trim().length >= 4) {
49+
markAttendance(cardInput.value.trim());
50+
}
51+
}, 50);
52+
}
53+
54+
});
55+
56+
});
57+
58+
59+
function showAlert(element, message, type) {
60+
element.className = `big-alert alert-${type}`;
61+
element.textContent = message;
62+
element.style.display = "block";
63+
}
64+
65+
66+
function resetAlert() {
67+
68+
const alertBox = document.getElementById("alert");
69+
const formWrapper = document.getElementById("formWrapper");
70+
71+
alertBox.style.display = "none";
72+
alertBox.textContent = "";
73+
alertBox.className = "big-alert";
74+
formWrapper.style.display = "block";
75+
76+
}
77+
78+
79+
async function markAttendance(cardno) {
80+
81+
if (isProcessing) return;
82+
isProcessing = true;
83+
84+
resetAlert();
85+
86+
try {
87+
88+
const response = await fetch(
89+
`${CONFIG.basePath}/adhyayan/attendance/${shibirId}/${sessionNo}/${cardno}`,
90+
{
91+
method: "POST",
92+
headers: {
93+
Authorization: `Bearer ${sessionStorage.getItem("token")}`
94+
}
95+
}
96+
);
97+
98+
const data = await response.json();
99+
100+
const alertBox = document.getElementById("alert");
101+
const formWrapper = document.getElementById("formWrapper");
102+
const cardInput = document.getElementById("cardno");
103+
104+
formWrapper.style.display = "none";
105+
106+
if (response.ok) {
107+
108+
showAlert(
109+
alertBox,
110+
`Attendance marked for ${data.participantName}`,
111+
"success"
112+
);
113+
114+
} else {
115+
116+
let alertType = "danger";
117+
const msg = data.message?.toLowerCase() || "";
118+
119+
if (msg.includes("already")) {
120+
alertType = "warning";
121+
}
122+
123+
showAlert(alertBox, data.message || "Error marking attendance", alertType);
124+
125+
}
126+
127+
setTimeout(() => {
128+
129+
cardInput.value = "";
130+
resetAlert();
131+
cardInput.focus();
132+
isProcessing = false;
133+
134+
}, 1000);
135+
136+
} catch (error) {
137+
138+
const alertBox = document.getElementById("alert");
139+
const formWrapper = document.getElementById("formWrapper");
140+
const cardInput = document.getElementById("cardno");
141+
142+
formWrapper.style.display = "none";
143+
144+
showAlert(alertBox, "Unexpected error occurred", "danger");
145+
146+
setTimeout(() => {
147+
148+
resetAlert();
149+
cardInput.focus();
150+
isProcessing = false;
151+
152+
}, 1000);
153+
154+
}
155+
156+
}

admin/adhyayan/adhyayanReport.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ document.addEventListener('DOMContentLoaded', () => {
363363
if (!sessionNo) return;
364364

365365
const url =
366-
`adhyayanAttendanceScan.html?shibir_id=${shibirId}&session=${sessionNo}`;
366+
`adhyayanAttendanceScanner.html?shibir_id=${shibirId}&session=${sessionNo}`;
367367

368368
window.open(url, '_blank');
369369
e.target.value = '';

0 commit comments

Comments
 (0)