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.

611 lines
19 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}"></head>
  4. <style>
  5. #batchDetailscard label{
  6. /* font-size: medium; */
  7. font-weight: bold;
  8. }
  9. #batchDetailscard span{
  10. font-size: 12px;
  11. }
  12. .btncontainer button{
  13. width: 50%;
  14. }
  15. </style>
  16. <body>
  17. <div class="wrapper">
  18. <!-- header top menu Start -->
  19. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  20. <!-- header top menu end -->
  21. <div class="page-wrap">
  22. <!--=============== Left Menu side Start ================-->
  23. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  24. <!--=============== Left side End ================-->
  25. <div class="main-content">
  26. <div class="container-fluid">
  27. <div class="page-header mb-2">
  28. <div class="row align-items-end">
  29. <div class="col-lg-8">
  30. <div class="page-header-title">
  31. <!-- <i class="far fa-calendar-plus bg-blue"></i> -->
  32. <div class="d-inline">
  33. <h5>Micro-Observer Batch Information</h5>
  34. <span>View micro observer batch details </span>
  35. </div>
  36. </div>
  37. </div>
  38. </div>
  39. </div>
  40. <div class="container">
  41. <div class="row mt-2 mb-2" style="padding: 10px;border: 1px solid green;background-color: rgba(144, 238, 144, 0.4);">
  42. <div class="col-md-4">
  43. <!-- <p style="margin-bottom: 2px;font-size: medium;font-weight: bold;">Application <span id="c_completed_plus"></span> of <span id="c_noof_application"></span></p>
  44. --> <p style="margin-bottom: 2px;font-size: 15px;font-size: medium;font-weight: bold;"><span id="c_completed"></span>&nbsp;saved&nbsp;.&nbsp;<span id="c_pending"></span>&nbsp;remaining</p>
  45. </div>
  46. <div class="col-md-4">
  47. </div>
  48. <div class="col-md-4" style="text-align: right;font-weight: bold;font-size:x-large;">
  49. <!-- <span id="cc_completed_plus"></span>/<span id="cc_noof_application"></span> -->
  50. </div>
  51. </div>
  52. </div>
  53. <div class="row">
  54. <div class="col-md-12">
  55. <div class="card" id="batchDetailscard">
  56. <div class="card-header">
  57. <span style="font-weight: bold;">Micro-Observer Batch Information</span>
  58. </div>
  59. <div class="card-body">
  60. <div class="row mb-3" style="row-gap:15px;">
  61. <div class="col-md-3 col-sm-12">
  62. <label for="batch_id" >Batch ID&nbsp;:</label>
  63. </div>
  64. <div class="col-md-9 col-sm-12">
  65. <span id="batch_id" th:text="${batchdetails.id}"></span>
  66. </div>
  67. <div class="col-md-3 col-sm-12">
  68. <label for="receiving_date" >Receiving Date&nbsp;:</label>
  69. </div>
  70. <div class="col-md-9 col-sm-12">
  71. <span th:text="${batchdetails.received_date}"></span>
  72. </div>
  73. <div class="col-md-3 col-sm-12">
  74. <label for="batch_dept" >Department&nbsp;:</label>
  75. </div>
  76. <div class="col-md-9 col-sm-12">
  77. <span th:text="${batchdetails.dept_name}"></span>
  78. </div>
  79. <div class="col-md-3 col-sm-12">
  80. <label for="office_name" >Office Name&nbsp;:</label>
  81. </div>
  82. <div class="col-md-9 col-sm-12">
  83. <span th:text="${batchdetails.office_name}
  84. + ', ' + (${batchdetails.address1} ?: '')
  85. + (${batchdetails.address2} != null ? ', ' + ${batchdetails.address2} : '')
  86. + (${batchdetails.address3} != null ? ', ' + ${batchdetails.address3} : '')">
  87. </span>
  88. </div>
  89. <div class="col-md-3 col-sm-12">
  90. <label for="no_of_app" >No of Applications&nbsp;:</label>
  91. </div>
  92. <div class="col-md-9 col-sm-12">
  93. <span th:text="${batchdetails.noof_application}"></span>
  94. </div>
  95. </div>
  96. <div class="row mt-4 btncontainer">
  97. <div class="col-12 d-flex justify-content-center">
  98. <button class="btn btn-secondary" onclick="goback()" >Back</button>
  99. <button class="btn btn-primary mx-2"
  100. th:onclick="'gotoNewEntry('
  101. + ${batchdetails.id} + ','
  102. + ${batchdetails.dept_id} + ','
  103. + ${batchdetails.office_id} + ')'">
  104. Add New Entry
  105. </button>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. </div>
  112. <div class="row">
  113. <div class="col-12">
  114. <div class="card">
  115. <!-- <div class="card-header">
  116. <h3><b>Applicants for Checklist</b></h3>
  117. </div> -->
  118. <div class="card-body">
  119. <table id="batchDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid" >
  120. <thead class="thead-dark" >
  121. <tr role="row">
  122. <th class="text-center">S.No</th>
  123. <th class="text-center">Unique No / Batch No</th>
  124. <th class="text-center">Name / Pay Scale / Cur.Basic /Grade Pay</th>
  125. <th class="text-center">Sex</th>
  126. <th class="text-center">Designation</th>
  127. <th class="text-center">State /Central</th>
  128. <th class="text-center">Office Address</th>
  129. <th class="text-center">Mobile</th>
  130. <th class="text-center">Residential Address</th>
  131. <th class="text-center">Native Constituency</th>
  132. <th class="text-center">Residential Constituency</th>
  133. <th class="text-center">Working Constituency</th>
  134. <th class="text-center">Enrolled - Part / Sl.No / EPIC /
  135. Assembly Constituency</th>
  136. </tr>
  137. </thead>
  138. <tbody style="text-align:center;">
  139. </tbody>
  140. </table>
  141. </div>
  142. </div>
  143. </div>
  144. </div>
  145. </div>
  146. </div>
  147. <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;">
  148. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  149. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  150. <span class="sr-only">Loading...</span>
  151. </div>
  152. <!-- Add the 'Please wait' text below the spinner -->
  153. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  154. </div>
  155. </div>
  156. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  157. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  158. </div>
  159. </div>
  160. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  161. <script type="text/javascript">
  162. $(document).ready(function() {
  163. let batch_id=document.getElementById("batch_id").textContent;
  164. getstatuscounts(batch_id);
  165. var table = $('#batchDatatable').DataTable({
  166. dom: 'Bftip',
  167. // columnDefs: [
  168. // { targets: 'no-sort', orderable: false }
  169. columnDefs: [
  170. { width: "150px", targets: 1 }, // Name / Pay Scale column
  171. { width: "150px", targets: 2 }, // Office Address column
  172. { width: "250px", targets: 6 },
  173. {width: "150px", targets: 12},
  174. {width: "100px", targets: 7},
  175. {width: "200px", targets: 8}
  176. ],
  177. lengthMenu: [
  178. [50, 100, 200, 500, -1],
  179. ['50 rows', '100 rows', '200 rows', 'Show all']
  180. ],
  181. scrollY: '80vh',
  182. scrollX: true,
  183. buttons: [
  184. {
  185. extend: 'pageLength',
  186. className: 'btn btn-warning'
  187. },
  188. {
  189. title: 'Data export',
  190. extend: 'copyHtml5',
  191. text: 'Copy',
  192. className: 'btn btn-secondary',
  193. id: 'copyBtn'
  194. },
  195. {
  196. extend: 'excelHtml5',
  197. text: 'Excel',
  198. className: 'btn btn-secondary',
  199. id: 'excelBtn'
  200. },
  201. {
  202. extend: 'csvHtml5',
  203. text: 'CSV',
  204. className: 'btn btn-secondary',
  205. id: 'csvBtn'
  206. },
  207. {
  208. extend: 'pdfHtml5',
  209. text: 'PDF',
  210. className: 'btn btn-secondary',
  211. id: 'pdfBtn'
  212. }
  213. ],
  214. fixedHeader: true,
  215. autoWidth: true,
  216. responsive: false,
  217. searching: true,
  218. select: false,
  219. processing: false
  220. });
  221. const initialParams = new URLSearchParams({
  222. batchNo: batch_id,
  223. fromSLno: "",
  224. toSLno: "",
  225. mobileNo: "",
  226. category: "",
  227. officeName: "",
  228. notExist: ""
  229. });
  230. loadApplicants(initialParams.toString());
  231. });
  232. function loadApplicants(paramString) {
  233. $('#pageLoader').show();
  234. $.ajax({
  235. type: "GET",
  236. url: `/election/api/checklistadminmob/getApplicants?${paramString}`,
  237. success: function (response) {
  238. console.log("API Response:", response);
  239. $('#pageLoader').hide();
  240. if (response.message === "success" && Array.isArray(response.data)) {
  241. $('#batchDatatable').DataTable({
  242. destroy: true,
  243. searching: true,
  244. autoWidth: true,
  245. paging: true,
  246. info: true,
  247. data: response.data,
  248. columns: [
  249. { data: null, className: 'text-center', render: (d,t,r,m) => m.row + 1 },
  250. {
  251. data: null,
  252. className: "text-center",
  253. render: r => `${r.slno || '-'}<br>/ ${r.batch_no || '-'}`
  254. },
  255. {
  256. data: null,
  257. className: "text-center",
  258. render: r => `
  259. ${r.name || '-'}<br>
  260. <small>
  261. ${r.pay_scale || '-'} /
  262. ${r.basic_pay || '-'} /
  263. ${r.grade_pay || '-'}
  264. </small>`
  265. },
  266. { data: 'sex', className: 'text-center' },
  267. { data: 'new_designation', className: 'text-center' },
  268. { data: 'govt_type', className: 'text-center' },
  269. {
  270. data: null,
  271. className: "text-center",
  272. render: r => `${r.office_name || '-'}<br>/ ${r.address || '-'}`
  273. },
  274. {
  275. data: null,
  276. className: 'text-center',
  277. render: r => `${r.r_mobile_no || ''}`
  278. },
  279. {
  280. data: null,
  281. className: 'text-center',
  282. render: r => `${r.r_address1 || ''} ${r.r_address2 || ''} ${r.r_address3 || ''} - ${r.r_pincode || ''}`
  283. },
  284. { data: null,
  285. className: 'text-center',
  286. render : r => `${r.native_ac_no || ''} - ${r.native_constituency || ''}`
  287. },
  288. { data: null,
  289. className: 'text-center',
  290. render : r => `${r.reside_ac_no || ''} - ${r.residential_constituency || ''}`
  291. },
  292. { data: null,
  293. className: 'text-center',
  294. render : r => `${r.work_ac_no || ''} - ${r.working_constituency || ''}`
  295. },
  296. {
  297. data: null,
  298. className: 'text-center',
  299. render: {
  300. display: r => `
  301. Part: ${r.elector_part_no || '-'}<br>
  302. Sl: ${r.elector_sl_no || '-'}<br>
  303. ${r.elector_epic_no || '-'}<br>
  304. ${r.elector_ac_no || '-'} - ${r.elector_constituency || '-'}
  305. `,
  306. export: r =>
  307. `Part: ${r.elector_part_no || '-'}\n` +
  308. `Sl: ${r.elector_sl_no || '-'}\n` +
  309. `${r.elector_epic_no || '-'}\n` +
  310. `${r.elector_ac_no || '-'} - ${r.elector_constituency || '-'}`
  311. }
  312. }
  313. ],
  314. dom: 'Bfrtip',
  315. buttons: [
  316. {
  317. extend: 'pageLength',
  318. className: 'btn btn-warning'
  319. },
  320. {
  321. title: 'Data export',
  322. extend: 'copyHtml5',
  323. text: 'Copy',
  324. className: 'btn btn-secondary',
  325. id: 'copyBtn'
  326. },
  327. {
  328. extend: 'excelHtml5',
  329. text: 'Excel',
  330. className: 'btn btn-secondary',
  331. id: 'excelBtn',
  332. filename: function () {
  333. return 'micro_observer_details_' + getTimestamp();
  334. }
  335. },
  336. {
  337. extend: 'csvHtml5',
  338. text: 'CSV',
  339. className: 'btn btn-secondary',
  340. id: 'csvBtn',
  341. filename: function () {
  342. return 'micro_observer_details_' + getTimestamp();
  343. }
  344. },
  345. {
  346. extend: 'pdfHtml5',
  347. text: 'PDF',
  348. className: 'btn btn-secondary',
  349. id: 'pdfBtn',
  350. title:'Micro Observer Details',
  351. filename: function () {
  352. return 'micro_observer_details_' + getTimestamp();
  353. },
  354. orientation: 'landscape', // ⭐ important line
  355. pageSize: 'A4',
  356. customize: function (doc) {
  357. doc.pageOrientation = 'landscape';
  358. // Reduce page margins to use full width
  359. doc.pageMargins = [10, 10, 10, 10];
  360. // Reduce default font size so columns fit
  361. doc.defaultStyle.fontSize = 7;
  362. doc.styles.tableHeader.fontSize = 8;
  363. // ⭐ Force table to shrink inside page
  364. doc.content[1].table.widths = [
  365. 20, // S.No
  366. 40, // Unique/Batch
  367. 80, // Name / Pay Scale
  368. 30, // Sex
  369. 60, // Designation
  370. 30, // State / Central
  371. 100, // Office Address
  372. 50, // Mobile
  373. 90, // Residence Address
  374. 40, // Native
  375. 40, // Reside
  376. 40, // Work
  377. 80 // Enrolled
  378. ];
  379. // ⭐ Remove large default paddings
  380. var objLayout = {};
  381. objLayout['hLineWidth'] = function(i) { return 0.3; };
  382. objLayout['vLineWidth'] = function(i) { return 0.3; };
  383. objLayout['hLineColor'] = function(i) { return '#000'; };
  384. objLayout['vLineColor'] = function(i) { return '#000'; };
  385. objLayout['paddingLeft'] = function(i) { return 2; };
  386. objLayout['paddingRight'] = function(i) { return 2; };
  387. objLayout['paddingTop'] = function(i) { return 2; };
  388. objLayout['paddingBottom'] = function(i) { return 2; };
  389. doc.content[1].layout = objLayout;
  390. }
  391. }
  392. ],
  393. columnDefs: [
  394. { width: "150px", targets: 1 },
  395. { width: "150px", targets: 2 },
  396. { width: "250px", targets: 6 },
  397. {width: "150px", targets: 12},
  398. {width: "100px", targets: 7},
  399. {width: "200px", targets: 8}
  400. ],
  401. scrollY: '80vh',
  402. scrollX: true,
  403. responsive: false
  404. });
  405. } /* else {
  406. Swal.fire("No Data", "No records found", "warning");
  407. } */
  408. },
  409. error: function (xhr) {
  410. $('#pageLoader').hide();
  411. console.log(" Server Error:", xhr.responseText);
  412. Swal.fire({
  413. icon: 'error',
  414. title: 'Error',
  415. text: 'Server error! Check console.',
  416. confirmButtonText: 'OK',
  417. allowOutsideClick: false,
  418. allowEscapeKey: false,
  419. allowEnterKey: false
  420. }).then(() => {
  421. location.reload(); // optional action
  422. });
  423. }
  424. });
  425. }
  426. function getstatuscounts(batchId){
  427. $('#pageLoader').show();
  428. fetch('/election/api/dataentry_mob/batch/getbatchbyId?id=' + batchId)
  429. .then(response => response.json())
  430. .then(result => {
  431. if (result.status !== "success") {
  432. console.error("API error:", result.message);
  433. return;
  434. }
  435. let data = result.data;
  436. console.log("Details:", data);
  437. // Example: set values into input fields
  438. /* document.getElementById("c_noof_application").textContent = data.noof_application;
  439. document.getElementById("cc_noof_application").textContent = data.noof_application; */
  440. document.getElementById("c_completed").textContent = data.completed;
  441. document.getElementById("c_pending").textContent = data.pending;
  442. /* let completedCount = parseInt(data.completed) || 0;
  443. let completedPlusOne = completedCount + 1;
  444. document.getElementById("c_completed_plus").textContent = completedPlusOne;
  445. document.getElementById("cc_completed_plus").textContent = completedPlusOne; */
  446. })
  447. .catch(error => {
  448. console.error("Error fetching batch counts details:", error);
  449. })
  450. .finally(() => {
  451. $('#pageLoader').hide(); // ALWAYS hide loader
  452. });
  453. }
  454. function gotoNewEntry(batchId, deptId, officeId) {
  455. $('#pageLoader').show();
  456. fetch('/election/api/dataentry_mob/batch/getbatchbyId?id=' + batchId)
  457. .then(response => response.json())
  458. .then(result => {
  459. if (result.status !== "success") {
  460. console.error("API error:", result.message);
  461. return;
  462. }
  463. if (result.status === "success") {
  464. let data = result.data;
  465. console.log("Details:", data);
  466. let noa=data.noof_application;
  467. let coma=data.completed;
  468. if(coma>=noa){
  469. Swal.fire({
  470. icon: 'info',
  471. title: 'Already no of application is achieved',
  472. text: 'For this Batch,Total no of application is filled already.',
  473. confirmButtonText: 'OK',
  474. allowOutsideClick: false,
  475. allowEscapeKey: false,
  476. allowEnterKey: false
  477. }).then(() => {
  478. window.location.href="/election/dataentry_mob/batches";
  479. });
  480. return;
  481. }
  482. else{
  483. sessionStorage.setItem("batchId", batchId);
  484. sessionStorage.setItem("deptId", deptId);
  485. sessionStorage.setItem("officeId", officeId);
  486. window.location.href = "/election/dataentry_mob/newentry";
  487. }
  488. }
  489. })
  490. .catch(error => {
  491. console.error("Error fetching batch counts details:", error);
  492. })
  493. .finally(() => {
  494. $('#pageLoader').hide(); // ALWAYS hide loader
  495. });
  496. }
  497. function getTimestamp() {
  498. const now = new Date();
  499. const yyyy = now.getFullYear();
  500. const mm = String(now.getMonth() + 1).padStart(2, '0');
  501. const dd = String(now.getDate()).padStart(2, '0');
  502. const hh = String(now.getHours()).padStart(2, '0');
  503. const mi = String(now.getMinutes()).padStart(2, '0');
  504. const ss = String(now.getSeconds()).padStart(2, '0');
  505. return `${yyyy}${mm}${dd}_${hh}${mi}${ss}`;
  506. }
  507. function goback(){
  508. window.location.href="/election/dataentry_mob/batches";
  509. }
  510. </script>
  511. </body>
  512. </html>