You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

374 lines
12 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}">
  4. <style>
  5. #AttendanceDatatable td {
  6. vertical-align: middle !important;
  7. }
  8. #AttendanceDatatable td:last-child {
  9. text-align: center;
  10. }
  11. .mark-present,
  12. .mark-absent {
  13. width: 90px;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <div class="wrapper">
  19. <!-- header top menu Start -->
  20. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  21. <!-- header top menu end -->
  22. <div class="page-wrap">
  23. <!--=============== Left Menu side Start ================-->
  24. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  25. <!--=============== Left side End ================-->
  26. <div class="main-content">
  27. <div class="container-fluid">
  28. <div class="row mt-1">
  29. <div class="col-md-12">
  30. <div class="card mt-2">
  31. <div class="card-header" style="font-weight: bold;">
  32. Attendance Training Data
  33. </div>
  34. <div class="card-body d-flex align-items-end">
  35. <!-- SL No -->
  36. <div class="col-sm-3">
  37. <label for="slNoInput">Search by Unique No</label>
  38. <input type="text" id="slNoInput" class="form-control"
  39. placeholder="Enter Unique No">
  40. </div>
  41. <div class="col-md-1 col-sm-12 text-center pt-4">
  42. <span style="font-weight: bold;">OR</span>
  43. </div>
  44. <!-- Mobile Number -->
  45. <div class="col-sm-3">
  46. <label for="mobileInput">Search by Mobile No</label>
  47. <input type="text" id="mobileInput" class="form-control"
  48. placeholder="Enter Mobile Number" maxlength="10">
  49. </div>
  50. <!-- Button (hidden initially) -->
  51. <div class="col-sm-4 d-flex align-items-end">
  52. <button id="searchBtn" class="btn btn-success mr-2">
  53. Search
  54. </button>
  55. <button id="clearSearchBtn" class="btn btn-danger">
  56. Clear
  57. </button>
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. <div class="row mt-1">
  64. <div class="col-12">
  65. <div class="card">
  66. <div class="card-body">
  67. <table id="AttendanceDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid" >
  68. <thead class="thead-dark" >
  69. <tr role="row">
  70. <th class="text-center">S.No</th>
  71. <th class="text-center">Unique No</th>
  72. <th class="text-center">Constituency</th>
  73. <th class="text-center">Training Center Name</th>
  74. <th class="text-center">Hall No</th>
  75. <th class="text-center">Category</th>
  76. <th class="text-center">Name</th>
  77. <th class="text-center">Attendance Status</th>
  78. <th class="text-center">Action</th>
  79. </tr>
  80. </thead>
  81. <tbody style="text-align:center;">
  82. </tbody>
  83. </table>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. <div id="pageLoader" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;">
  91. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  92. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  93. <span class="sr-only">Loading...</span>
  94. </div>
  95. <!-- Add the 'Please wait' text below the spinner -->
  96. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  97. </div>
  98. </div>
  99. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  100. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  101. </div>
  102. </div>
  103. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  104. <script src="dist/js/xlsx.full.min.js"></script>
  105. <script type="text/javascript">
  106. var table;
  107. $(document).ready(function() {
  108. table = $('#AttendanceDatatable').DataTable({
  109. dom: 'Bftip',
  110. columnDefs: [
  111. { targets: 'no-sort', orderable: false }
  112. ],
  113. lengthMenu: [
  114. [50, 100, 200, 500, -1],
  115. ['50 rows', '100 rows', '200 rows', 'Show all']
  116. ],
  117. scrollY: '50vh',
  118. scrollX: true,
  119. buttons: [
  120. {
  121. extend: 'pageLength',
  122. className: 'btn btn-warning'
  123. },
  124. {
  125. title: 'Data export',
  126. extend: 'copyHtml5',
  127. text: 'Copy',
  128. className: 'btn btn-secondary'
  129. },
  130. {
  131. extend: 'excelHtml5',
  132. text: 'Excel',
  133. className: 'btn btn-secondary'
  134. },
  135. {
  136. extend: 'csvHtml5',
  137. text: 'CSV',
  138. className: 'btn btn-secondary'
  139. },
  140. {
  141. extend: 'pdfHtml5',
  142. text: 'PDF',
  143. className: 'btn btn-secondary'
  144. }
  145. ],
  146. fixedHeader: true,
  147. autoWidth: false,
  148. responsive: false,
  149. searching: true,
  150. select: false,
  151. processing: false
  152. });
  153. $("#searchBtn").click(function () {
  154. searchAttendance();
  155. });
  156. });
  157. function searchAttendance() {
  158. let slNo = $("#slNoInput").val().trim();
  159. let mobile = $("#mobileInput").val().trim();
  160. if (!slNo && !mobile) {
  161. Swal.fire({
  162. icon: "warning",
  163. title: "Please enter SL No or Mobile Number",
  164. confirmButtonText: "OK",
  165. allowOutsideClick: false
  166. });
  167. return;
  168. }
  169. $("#pageLoader").show();
  170. $.ajax({
  171. url: "/election/api/dataentryadmin/attendance/searchAttendance",
  172. type: "GET",
  173. data: {
  174. slNo: slNo,
  175. mobileNo: mobile
  176. },
  177. success: function (res) {
  178. $("#pageLoader").hide();
  179. table.clear();
  180. if (res && res.length > 0) {
  181. res.forEach(function (data) {
  182. statusBadge = data.attendance_status === 'P'
  183. ? '<span style="color:#28a745;font-weight:600;">Present</span>'
  184. : '<span style="color:#dc3545;font-weight:600;">Absent</span>' ;
  185. /* let statusBadge = data.attendance_status === 'P'
  186. ? '<span class="status-present-soft">Present</span>'
  187. : '<span class="badge badge-danger">Absent</span>';*/
  188. let actionButtons = `
  189. <div class="d-flex flex-column align-items-center justify-content-center">
  190. <button class="btn btn-success btn-sm mb-1 mark-present" data-slno="${data.slno}">
  191. Present
  192. </button>
  193. <button class="btn btn-danger btn-sm mark-absent" data-slno="${data.slno}">
  194. Absent
  195. </button>
  196. </div>
  197. `;
  198. let index = table.rows().count() + 1;
  199. table.row.add([
  200. index,
  201. data.slno || '',
  202. data.constituency_details || '',
  203. data.c_name || '',
  204. data.hallno || '',
  205. data.category || '',
  206. data.name || '',
  207. statusBadge,
  208. actionButtons
  209. ]);
  210. });
  211. } else {
  212. Swal.fire({
  213. icon: "info",
  214. title: "No data found",
  215. confirmButtonText: "OK",
  216. allowOutsideClick: false
  217. });
  218. }
  219. table.draw();
  220. },
  221. error: function () {
  222. $("#pageLoader").hide();
  223. Swal.fire({
  224. icon: "error",
  225. title: "Error while fetching data",
  226. confirmButtonText: "OK",
  227. allowOutsideClick: false,
  228. allowEscapeKey: false
  229. });
  230. }
  231. });
  232. }
  233. // present
  234. $(document).on("click", ".mark-present", function () {
  235. let slno = $(this).data("slno");
  236. updateAttendance(slno, 'P');
  237. });
  238. // Absent
  239. $(document).on("click", ".mark-absent", function () {
  240. let slno = $(this).data("slno");
  241. updateAttendance(slno, 'A');
  242. });
  243. function updateAttendance(slno, status) {
  244. Swal.fire({
  245. title: "Are you sure?",
  246. text: "Update attendance status?",
  247. icon: "warning",
  248. showCancelButton: true,
  249. confirmButtonText: "Yes",
  250. allowOutsideClick: false,
  251. allowEscapeKey: false
  252. }).then((result) => {
  253. if (result.isConfirmed) {
  254. $.ajax({
  255. url: "/election/api/dataentryadmin/attendance/updateAttendance",
  256. type: "POST",
  257. contentType: "application/json",
  258. data: JSON.stringify({
  259. slno: slno,
  260. status: status
  261. }),
  262. success: function () {
  263. Swal.fire({
  264. icon: "success",
  265. title: "Updated successfully!",
  266. confirmButtonText: "OK",
  267. allowOutsideClick: false,
  268. allowEscapeKey: false
  269. }).then(() => {
  270. location.reload();
  271. });
  272. },
  273. error: function () {
  274. Swal.fire({
  275. icon: "error",
  276. title: "Error updating attendance",
  277. confirmButtonText: "OK",
  278. allowOutsideClick: false,
  279. allowEscapeKey: false
  280. });
  281. }
  282. });
  283. }
  284. });
  285. }
  286. $('#clearSearchBtn').click(function () {
  287. // Clear input fields
  288. $('#slNoInput').val('');
  289. $('#mobileInput').val('');
  290. // Optional: hide loader if visible
  291. $('#pageLoader').hide();
  292. });
  293. </script>
  294. </body>
  295. </html>