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.

485 lines
14 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. </style>
  6. </head>
  7. <body>
  8. <div class="wrapper">
  9. <!-- header top menu Start -->
  10. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  11. <!-- header top menu end -->
  12. <div class="page-wrap">
  13. <!--=============== Left Menu side Start ================-->
  14. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  15. <!--=============== Left side End ================-->
  16. <div class="main-content">
  17. <div class="container-fluid">
  18. <div class="page-header mb-2">
  19. <div class="row align-items-end">
  20. <div class="col-lg-8">
  21. <div class="page-header-title">
  22. <!-- <i class="far fa-calendar-plus bg-blue"></i> -->
  23. <div class="d-inline">
  24. <h5 >Create New Batch</h5>
  25. <span>Create a new batch for application bundle intake</span>
  26. </div>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. <div class="row">
  32. <div class="col-md-12">
  33. <div class="card" style="margin-top: 15px;">
  34. <div class="col-lg-8" style="margin-top: 25px;">
  35. <h3>Batch Information</h3>
  36. <span>Fill in the details for the new application batch</span>
  37. </div>
  38. <div class="card-body">
  39. <input type="hidden" id="loginUserId" th:value="${loginUserId}">
  40. <div class="form-group">
  41. <div class="row">
  42. <div class="col-sm-12 col-md-6">
  43. <label class="form-label" for="receivedate">Receiving Date<span
  44. class="text-danger">*</span></label>
  45. <input type="date" class="form-control" id="receivedate" onclick="this.showPicker()" required>
  46. </div>
  47. <!-- Department -->
  48. <div class="col-sm-12 col-md-6">
  49. <label class="form-label" for="department">Department
  50. <span class="text-danger">*</span>
  51. </label>
  52. <select class="form-control" id="department" required>
  53. <option value=""> Select Department </option>
  54. </select>
  55. </div>
  56. <!-- Office Name -->
  57. <div class="col-sm-12 col-md-6" style="margin-top: 15px;">
  58. <label class="form-label" for="officename">Office Name
  59. <span class="text-danger">*</span>
  60. </label>
  61. <select class="form-control" id="officename" required>
  62. <option value="">Select Office Name </option>
  63. </select>
  64. </div>
  65. <div class="col-sm-12 col-md-6" style="margin-top: 15px;">
  66. <label class="form-label" for="noofapplication">Number of Applications<span class="text-danger">*</span></label>
  67. <input type="text" class="form-control" id="noofapplication" oninput="this.value=this.value.replace(/[^0-9]/g,'')"/>
  68. </div>
  69. </div>
  70. </div>
  71. <div class="form-group text-center">
  72. <button type="submit" class="btn btn-primary " id="createdBtn">Create Batch</button>
  73. <button type="reset" class="btn btn-secondary ml-2" id="resetBtn">Reset</button></div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. <!-- Batch List Table -->
  79. <div class="row">
  80. <div class="col-12">
  81. <div class="card">
  82. <div class="card-header">
  83. <h3><b>All Batches</b></h3>
  84. </div>
  85. <div class="card-body">
  86. <table id="batchDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid" >
  87. <thead class="thead-dark">
  88. <tr role="row">
  89. <th class="text-center">S.No</th>
  90. <th class="text-center">Batch ID</th>
  91. <th class="text-center">Receiving Date</th>
  92. <th class="text-center">Department</th>
  93. <th class="text-center">Office Name</th>
  94. <th class="text-center">No Of Application</th>
  95. <th class="text-center">Completed</th>
  96. <th class="text-center">Pending</th>
  97. <th class="text-center">Action</th>
  98. </tr>
  99. </thead>
  100. <tbody style="text-align:center;">
  101. </tbody>
  102. </table>
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. <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;">
  110. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  111. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  112. <span class="sr-only">Loading...</span>
  113. </div>
  114. <!-- Add the 'Please wait' text below the spinner -->
  115. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  116. </div>
  117. </div>
  118. <div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
  119. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  120. </div>
  121. </div>
  122. <!-- modal box -->
  123. <div class="modal fade" id="editBatchModal" tabindex="-1">
  124. <div class="modal-dialog modal-lg">
  125. <div class="modal-content">
  126. <div class="modal-header">
  127. <h5 class="modal-title">Update Batch Details</h5>
  128. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  129. <span aria-hidden="true">&times;</span>
  130. </button>
  131. </div>
  132. <div class="modal-body">
  133. <div class="row">
  134. <input type="hidden" id="edit_batch_id">
  135. <div class="col-md-6 mb-4">
  136. <label class="form-label">Receive Date</label>
  137. <input type="date" class="form-control" id="edit_receivedate" readonly>
  138. </div>
  139. <div class="col-md-6 mb-4">
  140. <label class="form-label">Department</label>
  141. <input type="text" class="form-control" id="edit_department" readonly>
  142. </div>
  143. <div class="col-md-12 mb-4">
  144. <label class="form-label">Office Name</label>
  145. <input type="text" class="form-control" id="edit_officename" readonly>
  146. </div>
  147. <div class="col-md-6">
  148. <label class="form-label" for="edit_noofapplication">Number of Applications <span class="text-danger">*</span></label>
  149. <input type="text" class="form-control" id="edit_noofapplication" oninput="this.value=this.value.replace(/[^0-9]/g,'')"/>
  150. </div>
  151. </div>
  152. </div>
  153. <div class="row mb-2 mt-2">
  154. <div class="col-md-12 d-flex justify-content-center">
  155. <button type="button" class="btn btn-primary mx-2" onclick="updateBatch()">Update</button>
  156. </div>
  157. </div>
  158. </div>
  159. </div>
  160. </div>
  161. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  162. <script type="text/javascript">
  163. // Reset Button
  164. document.getElementById('resetBtn').addEventListener('click', function (e) {
  165. e.preventDefault();
  166. location.reload();
  167. });
  168. // Disable Future Dates
  169. document.addEventListener("DOMContentLoaded", function () {
  170. var today = new Date().toISOString().split('T')[0];
  171. document.getElementById("receivedate").setAttribute("max", today);
  172. });
  173. $(document).ready(function () {
  174. var batchTable = $('#batchDatatable').DataTable({
  175. dom: 'Bftip',
  176. autoWidth: false,
  177. responsive: false,
  178. scrollX: true,
  179. scrollY: '80vh',
  180. scrollCollapse: true,
  181. fixedHeader: true,
  182. lengthMenu: [
  183. [50, 100, 200, 500, -1],
  184. ['50 rows', '100 rows', '200 rows', 'Show all']
  185. ],
  186. buttons: [
  187. { extend: 'pageLength', className: 'btn btn-warning' },
  188. { extend: 'copyHtml5', className: 'btn btn-secondary' },
  189. { extend: 'excelHtml5', className: 'btn btn-secondary' },
  190. { extend: 'csvHtml5', className: 'btn btn-secondary' },
  191. { extend: 'pdfHtml5', className: 'btn btn-secondary' }
  192. ],
  193. ajax: {
  194. url: "/election/api/dataentryadmin/getallbatches",
  195. type: "GET",
  196. dataSrc: ""
  197. },
  198. columns: [
  199. {
  200. data: null,
  201. className: "text-center",
  202. render: (d, t, r, m) => m.row + 1
  203. },
  204. { data: "id", className: "text-center" },
  205. { data: "rec_date", className: "text-center" },
  206. { data: "dept_name", className: "text-center" },
  207. {
  208. data: null,
  209. className: "text-center",
  210. render: function (data, type, row) {
  211. let address = '';
  212. if (row.address1) address += row.address1;
  213. if (row.address2) address += (address ? ', ' : '') + row.address2;
  214. return `
  215. <div>
  216. <span>${row.office_name}</span><br>
  217. <span class="text-muted">${address || '-'}</span>
  218. </div>
  219. `;
  220. }
  221. },
  222. /*{ data: "office_name", className: "text-center" }*/
  223. { data: "noof_application", className: "text-center" },
  224. { data: "completed", className: 'text-center' },
  225. { data: "pending", className: 'text-center' },
  226. {
  227. data: "id",
  228. className: "text-center",
  229. render: d => `<button class="btn btn-primary btn-sm" onclick="editBatch(${d})">Edit</button>`
  230. }
  231. ],
  232. columnDefs: [
  233. { targets: "_all", className: "text-center" }
  234. ]
  235. });
  236. // Load Departments with searchable dropdown
  237. $.ajax({
  238. url: "/election/api/dataentryadmin/getalldepartments",
  239. method: "GET",
  240. success: function (data) {
  241. let department = $("#department");
  242. department.empty().append('<option value="">-- Select Department --</option>');
  243. data.forEach(dept => {
  244. department.append(
  245. `<option value="${dept.dept_id}">${dept.dept_name}</option>`
  246. );
  247. });
  248. // Enable search inside dropdown
  249. department.select2({
  250. placeholder: "Select Department",
  251. allowClear: true,
  252. width: '100%'
  253. });
  254. }
  255. });
  256. });
  257. $("#department").on("change", function () {
  258. let deptId = $(this).val();
  259. let office = $("#officename");
  260. // Reset office dropdown
  261. office.empty().append('<option value="">-- Select Office Name --</option>');
  262. if (deptId !== "") {
  263. $.ajax({
  264. url: "/election/api/dataentryadmin/getallofficenames",
  265. method: "GET",
  266. data: { deptId: deptId },
  267. success: function (data) {
  268. data.forEach(o => {
  269. office.append(
  270. `<option value="${o.id}">${o.office_full_address}</option>`
  271. );
  272. });
  273. // Enable searchable dropdown
  274. office.select2({
  275. placeholder: "Select Office Name",
  276. allowClear: true,
  277. width: '100%'
  278. });
  279. }
  280. });
  281. }
  282. });
  283. // Create Batch
  284. $("#createdBtn").click(function () {
  285. const $btn = $(this); // cache button
  286. let receivedate = $("#receivedate").val();
  287. let department = $("#department").val();
  288. let officename = $("#officename").val();
  289. let noofapplication = $("#noofapplication").val();
  290. let loginUserId = $("#loginUserId").val();
  291. if (!receivedate || !department || !officename || !noofapplication || noofapplication <= 0) {
  292. Swal.fire("Validation Error", "All fields are mandatory and must be valid.", "warning");
  293. return;
  294. }
  295. // Disable button immediately
  296. $btn.prop("disabled", true).text("Saving...");
  297. $.ajax({
  298. url: "/election/api/dataentryadmin/savebatchdeatils",
  299. type: "POST",
  300. data: {
  301. receivedate,
  302. department,
  303. officename,
  304. noofapplication,
  305. userid: loginUserId
  306. },
  307. success: function (response) {
  308. Swal.fire({
  309. icon: "success",
  310. title: "Batch Created Successfully!",
  311. text: "Reference ID is: " + response
  312. }).then(() => location.reload());
  313. },
  314. error: function (xhr) {
  315. Swal.fire("Error", "Failed to save data: " + xhr.responseText, "error");
  316. // Re-enable button only if error occurs
  317. $btn.prop("disabled", false).text("Create");
  318. }
  319. });
  320. });
  321. // Load Edit Modal
  322. function editBatch(batchId) {
  323. $.ajax({
  324. url: "/election/api/dataentryadmin/getbatchbyId",
  325. type: "GET",
  326. data: { id: batchId },
  327. success: function (data) {
  328. $("#edit_batch_id").val(data.id);
  329. $("#edit_receivedate").val(data.rec_date);
  330. $("#edit_department").val(data.dept_name);
  331. $("#edit_officename").val(data.office_name);
  332. // Set value + store counts for validation
  333. $("#edit_noofapplication")
  334. .val(data.noof_application)
  335. .data("oldCount", data.noof_application)
  336. .data("completed", data.completed);
  337. $("#editBatchModal").modal('show');
  338. },
  339. error: function () {
  340. Swal.fire("Error!", "Unable to load batch details", "error");
  341. }
  342. });
  343. }
  344. // Update Batch
  345. function updateBatch() {
  346. let id = $("#edit_batch_id").val();
  347. let userId = $("#loginUserId").val();
  348. let newCount = Number($("#edit_noofapplication").val());
  349. let completed = Number($("#edit_noofapplication").data("completed"));
  350. // Basic validation
  351. if (!newCount || newCount <= 0) {
  352. Swal.fire("Validation Error", "Enter a valid number of applications", "warning");
  353. return;
  354. }
  355. // Prevent reducing below completed count
  356. if (newCount < completed) {
  357. Swal.fire({
  358. icon: "warning",
  359. title: "Invalid Update",
  360. text: `Number of applications cannot be less than completed count (${completed})`,
  361. confirmButtonText: "OK"
  362. });
  363. return;
  364. }
  365. $.ajax({
  366. url: "/election/api/dataentryadmin/updatebatch",
  367. type: "POST",
  368. data: {
  369. id,
  370. noofapplication: newCount,
  371. userId
  372. },
  373. success: function () {
  374. Swal.fire("Success", "Batch Updated Successfully", "success").then(() => {
  375. $("#editBatchModal").modal("hide");
  376. $('#batchDatatable').DataTable().ajax.reload(null, false);
  377. });
  378. },
  379. error: function () {
  380. Swal.fire("Error", "Failed to update batch", "error");
  381. }
  382. });
  383. }
  384. </script>
  385. </body>
  386. </html>