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.

590 lines
21 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. .width1{
  6. width: 120px;
  7. }
  8. .width2{
  9. width: 150px;
  10. }
  11. </style>
  12. <body>
  13. <div class="wrapper">
  14. <!-- header top menu Start -->
  15. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  16. <!-- header top menu end -->
  17. <div class="page-wrap">
  18. <!--=============== Left Menu side Start ================-->
  19. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  20. <!--=============== Left side End ================-->
  21. <div class="main-content">
  22. <div class="container-fluid">
  23. <div class="page-header mb-2">
  24. <div class="row align-items-end">
  25. <div class="col-lg-8">
  26. <div class="page-header-title">
  27. <!-- <i class="far fa-calendar-plus bg-blue"></i> -->
  28. <div class="d-inline">
  29. <h5>Micro-Observer Updation</h5>
  30. <span>View and manage micro observer application batches </span>
  31. </div>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. <div class="row">
  37. <div class="col-md-12">
  38. <div class="card">
  39. <div class="card-header">
  40. <span>Fill in the details </span>
  41. </div>
  42. <div class="card-body">
  43. <div class="row">
  44. <div class="col-md-3 col-sm-12">
  45. <label class="form-label" for="unique_num">Unique Number</label>
  46. <input type="text" class="form-control" id="unique_num">
  47. </div>
  48. <div class="col-md-1 col-sm-12 text-center pt-4">
  49. <span style="font-weight: bold;">OR</span>
  50. </div>
  51. <div class="col-md-3 col-sm-12">
  52. <label class="form-label" for="batch_num">Batch No</label>
  53. <input type="text" class="form-control" id="batch_num">
  54. </div>
  55. <div class="col-md-1 col-sm-12 text-center pt-4">
  56. <span style="font-weight: bold;">OR</span>
  57. </div>
  58. <div class="col-md-3 col-sm-12">
  59. <label class="form-label" for="mobile_num">Mobile Number</label>
  60. <input type="text" class="form-control" id="mobile_num">
  61. </div>
  62. </div>
  63. <div class="row mt-3">
  64. <div class="col-12 d-flex justify-content-center">
  65. <button type="submit" id="searchBtn"
  66. class="btn btn-primary mx-2">Search</button>
  67. <button class="btn btn-danger mx-2" id="resetBtn"
  68. name="reset">Reset</button>
  69. </div>
  70. </div>
  71. </div>
  72. </div>
  73. </div>
  74. </div>
  75. <div class="row" id="detailscard">
  76. <div class="col-md-12">
  77. <div class="card">
  78. <div class="card-body">
  79. <div class="table-responsive">
  80. <table id="DetailsDatatable"
  81. class="table table-striped table-bordered table-hover dataTable"
  82. role="grid">
  83. <thead class="thead-dark">
  84. <tr role="row">
  85. <th class="text-center">S.No</th>
  86. <th class="text-center">Unique No/Batch No</th>
  87. <th class="text-center width1">Name / Pay Scale / Cur.Basic / Grade Pay</th>
  88. <th class="text-center">Sex</th>
  89. <th class="text-center">Designation</th>
  90. <th class="text-center">State / Central</th>
  91. <th class="text-center width2">Office Address</th>
  92. <th class="text-center">Mobile Number</th>
  93. <th class="text-center">Residential Address</th>
  94. <th class="text-center">Native Constituency</th>
  95. <th class="text-center">Residential Constituency</th>
  96. <th class="text-center">Working Constituency</th>
  97. <th class="text-center">Enrolled - Part / Sl.No / EPIC / Assembly Constituency</th>
  98. <th class="text-center">Photo</th>
  99. <th class="text-center">Action</th>
  100. </tr>
  101. </thead>
  102. <tbody>
  103. </tbody>
  104. </table>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. </div>
  112. <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;">
  113. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  114. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  115. <span class="sr-only">Loading...</span>
  116. </div>
  117. <!-- Add the 'Please wait' text below the spinner -->
  118. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  119. </div>
  120. </div>
  121. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  122. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  123. </div>
  124. </div>
  125. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  126. <script type="text/javascript">
  127. $(document).ready(function() {
  128. // MOBILE NO: exactly 10 digits
  129. $('#mobile_num').on('input', function () {
  130. // Allow only digits
  131. this.value = this.value.replace(/\D/g, '');
  132. // Max 10 digits
  133. if (this.value.length > 10) {
  134. this.value = this.value.slice(0, 10);
  135. }
  136. });
  137. $('#unique_num').on('input', function () {
  138. // Allow only digits
  139. this.value = this.value.replace(/\D/g, '');
  140. });
  141. $('#batch_num').on('input', function () {
  142. // Allow only digits
  143. this.value = this.value.replace(/\D/g, '');
  144. });
  145. var table = $('#DetailsDatatable').DataTable({
  146. dom: 'Bftip',
  147. columnDefs: [
  148. { width: "150px", targets: 2 }, // Name / Pay Scale column
  149. { width: "150px", targets: 6 }, // Office Address column
  150. { width: "150px", targets: 8 },
  151. { width: "150px", targets: 12 }
  152. ],
  153. lengthMenu: [
  154. [50, 100, 200, 500, -1],
  155. ['50 rows', '100 rows', '200 rows', 'Show all']
  156. ],
  157. scrollY: '50vh',
  158. scrollX: true,
  159. buttons: [
  160. {
  161. extend: 'pageLength',
  162. className: 'btn btn-warning'
  163. },
  164. {
  165. title: 'Data export',
  166. extend: 'copyHtml5',
  167. text: 'Copy',
  168. className: 'btn btn-secondary',
  169. id: 'copyBtn'
  170. },
  171. {
  172. extend: 'excelHtml5',
  173. text: 'Excel',
  174. className: 'btn btn-secondary',
  175. id: 'excelBtn'
  176. },
  177. {
  178. extend: 'csvHtml5',
  179. text: 'CSV',
  180. className: 'btn btn-secondary',
  181. id: 'csvBtn'
  182. },
  183. {
  184. extend: 'pdfHtml5',
  185. text: 'PDF',
  186. className: 'btn btn-secondary',
  187. id: 'pdfBtn'
  188. }
  189. ],
  190. fixedHeader: true,
  191. autoWidth: true,
  192. responsive: false,
  193. searching: true,
  194. select: false,
  195. processing: false
  196. });
  197. });
  198. document.getElementById('resetBtn').addEventListener('click', function (e) {
  199. location.reload();
  200. });
  201. document.getElementById('searchBtn').addEventListener('click', function (e) {
  202. $('#pageLoader').show();
  203. let unique_num = document.getElementById('unique_num').value;
  204. let mobile_num = document.getElementById('mobile_num').value;
  205. let batch_num = document.getElementById('batch_num').value;
  206. console.log(unique_num,",",mobile_num,",",batch_num);
  207. if(!unique_num && !mobile_num && !batch_num){
  208. $('#pageLoader').hide();
  209. Swal.fire({
  210. icon: 'warning',
  211. title: 'For Search, Any One Is Required ',
  212. text: 'Please Enter required details',
  213. showConfirmButton: true,
  214. timer: 3000
  215. });
  216. e.preventDefault();
  217. return;
  218. }
  219. if(mobile_num){
  220. // Rule 1: Must be exactly 10 digits & must not start with 0
  221. if (!/^[1-9][0-9]{9}$/.test(mobile_num)) {
  222. $('#pageLoader').hide();
  223. Swal.fire({
  224. icon: 'warning',
  225. title: 'Invalid Mobile Number',
  226. text: 'Mobile number must be 10 digits and cannot start with 0.'
  227. });
  228. return;
  229. }
  230. // Rule 2: Reject sequential numbers like 1234567890
  231. if (mobile_num === "1234567890") {
  232. $('#pageLoader').hide();
  233. Swal.fire({
  234. icon: 'warning',
  235. title: 'Invalid Mobile Number',
  236. text: 'Sequential numbers like 1234567890 are not allowed.'
  237. });
  238. return;
  239. }
  240. // Rule 3: Reject all digits same (1111111111, 2222222222, etc.)
  241. if (/^(\d)\1{9}$/.test(mobile_num)) {
  242. $('#pageLoader').hide();
  243. Swal.fire({
  244. icon: 'warning',
  245. title: 'Invalid Mobile Number',
  246. text: 'All digits cannot be the same.'
  247. });
  248. return;
  249. }
  250. }
  251. $.ajax({
  252. type: "GET",
  253. url: `/election/api/dataentry_mob/update/getbymobanduniq`,
  254. data:{
  255. mobilenum:mobile_num,
  256. uniquenum:unique_num,
  257. batch_num:batch_num
  258. },
  259. contentType: "application/json",
  260. success: function (response) {
  261. console.log("API Response:", response);
  262. $('#pageLoader').hide();
  263. if (response.status === "success") {
  264. console.log("Details Array:", response.data);
  265. // Convert object → array
  266. let records = response.data || [];
  267. console.log("Table Records:", records);
  268. let table = $('#DetailsDatatable').DataTable({
  269. destroy: true,
  270. searching: true,
  271. autoWidth: true,
  272. paging: true,
  273. info: true,
  274. data: records,
  275. columns: [
  276. {
  277. data: null,
  278. render: (data, type, row, meta) => meta.row + 1,
  279. className: 'text-center'
  280. },
  281. { data: null,
  282. className: 'text-center' ,
  283. render: r => `${r.slno || '-'}<br>/ ${r.batch_no || '-'}`
  284. },
  285. { data: null,
  286. className: 'text-center width1' ,
  287. render: r => `
  288. ${r.name || '-'}<br>
  289. <small>
  290. ${r.pay_scale || '-'} /
  291. ${r.basic_pay || '-'} /
  292. ${r.grade_pay || '-'}
  293. </small>`
  294. },
  295. { data: 'sex',className: 'text-center' },
  296. { data: 'new_designation',className: 'text-center' },
  297. { data: 'govt_type',className: 'text-center' },
  298. { data: null,
  299. className: 'text-center width2' ,
  300. render: r => `${r.office_name || '-'}<br>/ <small>${r.office_address || '-'}</small>`
  301. },
  302. { data: 'r_mobile_no' ,className: 'text-center' },
  303. { data: 'res_address', className: 'text-center' },
  304. { data: null,
  305. className: 'text-center' ,
  306. render: r => `${r.native_ac_no || '-'} - ${r.native_assembly || '-'}`
  307. },
  308. { data: null,
  309. className: 'text-center' ,
  310. render: r => `${r.reside_ac_no || '-'} - ${r.res_assembly || '-'}`
  311. },
  312. { data: null,
  313. className: 'text-center' ,
  314. render: r => `${r.work_ac_no || '-'} - ${r.work_assembly || '-'}`
  315. },
  316. {
  317. data: null,
  318. className: 'text-center',
  319. render: {
  320. display: r => `
  321. Part: ${r.elector_part_no || '-'}<br>
  322. Sl: ${r.elector_sl_no || '-'}<br>
  323. ${r.elector_epic_no || '-'}<br>
  324. ${r.elector_ac_no || '-'} - ${r.enrolled_assembly || '-'}
  325. `,
  326. export: r =>
  327. `Part: ${r.elector_part_no || '-'}\n` +
  328. `Sl: ${r.elector_sl_no || '-'}\n` +
  329. `${r.elector_epic_no || '-'}\n` +
  330. `${r.elector_ac_no || '-'} - ${r.enrolled_assembly || '-'}`
  331. }
  332. },
  333. {
  334. data: 'img_full_path',
  335. className: 'text-center',
  336. render: function (url, type, row) {
  337. if (!url) {
  338. return `<span style="color:red;">No Image</span>`;
  339. }
  340. return `
  341. <img src="${url}"
  342. style="height: 100px; width: 100px; object-fit: cover; border:1px solid #ccc;"
  343. alt="Photo">
  344. `;
  345. }
  346. },
  347. {
  348. data: null,
  349. className: 'text-center',
  350. render: function (data) {
  351. let id = data.id;
  352. let dept = data.dept;
  353. let desigId = data.designation_id;
  354. let officeId = data.office_id;
  355. let batchId = data.batch_id;
  356. return `
  357. <button class="btn btn-primary btn-sm"
  358. onclick="goToUpdateForm('${id}','${dept}','${desigId}','${officeId}','${batchId}')">
  359. Update
  360. </button>
  361. `;
  362. }
  363. }
  364. ],
  365. dom: 'Bfrtip',
  366. buttons: [
  367. {
  368. extend: 'pageLength',
  369. className: 'btn btn-warning'
  370. },
  371. {
  372. title: 'Data export',
  373. extend: 'copyHtml5',
  374. text: 'Copy',
  375. className: 'btn btn-secondary',
  376. id: 'copyBtn'
  377. },
  378. {
  379. extend: 'excelHtml5',
  380. text: 'Excel',
  381. className: 'btn btn-secondary',
  382. id: 'excelBtn',
  383. filename: function () {
  384. return 'micro_observer_details_' + getTimestamp();
  385. }
  386. },
  387. {
  388. extend: 'csvHtml5',
  389. text: 'CSV',
  390. className: 'btn btn-secondary',
  391. id: 'csvBtn',
  392. filename: function () {
  393. return 'micro_observer_details_' + getTimestamp();
  394. }
  395. },
  396. {
  397. extend: 'pdfHtml5',
  398. text: 'PDF',
  399. className: 'btn btn-secondary',
  400. id: 'pdfBtn',
  401. title:'Polling Personnel Details',
  402. filename: function () {
  403. return 'micro_observer_details_' + getTimestamp();
  404. },
  405. orientation: 'landscape', // ⭐ important line
  406. pageSize: 'A4',
  407. customize: function (doc) {
  408. doc.pageOrientation = 'landscape';
  409. // Reduce page margins to use full width
  410. doc.pageMargins = [10, 10, 10, 10];
  411. // Reduce default font size so columns fit
  412. doc.defaultStyle.fontSize = 7;
  413. doc.styles.tableHeader.fontSize = 8;
  414. // ⭐ Force table to shrink inside page
  415. doc.content[1].table.widths = [
  416. 20, // S.No
  417. 30, // Unique/Batch
  418. 60, // Name / Pay Scale
  419. 20, // Sex
  420. 60, // Designation
  421. 30, // State / Central
  422. 100, // Office Address
  423. 40, // Mobile
  424. 90, // Residence Address
  425. 60, // Native
  426. 60, // Reside
  427. 60, // Work
  428. 70, // Enrolled
  429. 50, // Photo
  430. 30
  431. ];
  432. // ⭐ Remove large default paddings
  433. var objLayout = {};
  434. objLayout['hLineWidth'] = function(i) { return 0.3; };
  435. objLayout['vLineWidth'] = function(i) { return 0.3; };
  436. objLayout['hLineColor'] = function(i) { return '#000'; };
  437. objLayout['vLineColor'] = function(i) { return '#000'; };
  438. objLayout['paddingLeft'] = function(i) { return 2; };
  439. objLayout['paddingRight'] = function(i) { return 2; };
  440. objLayout['paddingTop'] = function(i) { return 2; };
  441. objLayout['paddingBottom'] = function(i) { return 2; };
  442. doc.content[1].layout = objLayout;
  443. }
  444. }
  445. ],
  446. columnDefs: [
  447. { width: "150px", targets: 2},
  448. { width: "150px", targets: 6},
  449. { width: "120px", targets: 8},
  450. { width: "150px", targets: 12} ,
  451. { width: "150px", targets: 12}
  452. ],
  453. lengthMenu: [
  454. [50, 100, 200, 500, -1],
  455. ['50 rows', '100 rows', '200 rows', 'Show all']
  456. ],
  457. scrollY: '80vh',
  458. scrollX: true,
  459. responsive: false,
  460. searching: true
  461. });
  462. }
  463. else if (response.status === "no_data") {
  464. $('#pageLoader').hide();
  465. Swal.fire({
  466. icon: 'info',
  467. title: 'No Data',
  468. text: response.data || 'Something went wrong!'
  469. });
  470. }
  471. else if (response.status === "error") {
  472. $('#pageLoader').hide();
  473. Swal.fire({
  474. icon: 'error',
  475. title: 'Error',
  476. text: response.message || 'Something went wrong!'
  477. });
  478. }
  479. else {
  480. $('#pageLoader').hide();
  481. Swal.fire({
  482. icon: 'error',
  483. title: 'Error',
  484. text: response.message || 'Something went wrong!'
  485. });
  486. }
  487. },
  488. error: function (error) {
  489. $('#pageLoader').hide();
  490. Swal.fire({
  491. icon: 'error',
  492. title: 'Error',
  493. text: response.message || 'Something went wrong!'
  494. });
  495. }
  496. });
  497. });
  498. function getTimestamp() {
  499. const now = new Date();
  500. const yyyy = now.getFullYear();
  501. const mm = String(now.getMonth() + 1).padStart(2, '0');
  502. const dd = String(now.getDate()).padStart(2, '0');
  503. const hh = String(now.getHours()).padStart(2, '0');
  504. const mi = String(now.getMinutes()).padStart(2, '0');
  505. const ss = String(now.getSeconds()).padStart(2, '0');
  506. return `${yyyy}${mm}${dd}_${hh}${mi}${ss}`;
  507. }
  508. function goToUpdateForm(id, dept, designationId, officeId, batchId) {
  509. // Save values in sessionStorage
  510. sessionStorage.setItem("upd_id", id);
  511. sessionStorage.setItem("upd_dept", dept);
  512. sessionStorage.setItem("upd_office_id", officeId);
  513. sessionStorage.setItem("upd_batch_id", batchId);
  514. // Redirect to form page
  515. window.location.href = "/election/dataentryadmin_mob/updateform";
  516. }
  517. </script>
  518. </body>
  519. </html>