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.

1844 lines
49 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. <link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css">
  5. <style>
  6. .mini-card {
  7. box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px;
  8. border-radius: 6px;
  9. padding: 12px;
  10. text-align: center;
  11. background: #ffffff;
  12. min-height: 90px;
  13. display: flex;
  14. flex-direction: column;
  15. justify-content: center;
  16. }
  17. .card-box {
  18. box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px;
  19. }
  20. /* Header styling */
  21. .govt-thead th {
  22. background-color: #212529 !important;
  23. color: #fff !important;
  24. text-align: center;
  25. vertical-align: middle;
  26. white-space: nowrap;
  27. /* 🔥 header single line */
  28. }
  29. /* Enable wrapping in body cells */
  30. #GovtTypeDatatable th,
  31. #GovtTypeDatatable td {
  32. white-space: normal !important;
  33. /* ALLOW WRAP */
  34. word-break: break-word;
  35. }
  36. /* Table layout */
  37. #GovtTypePersonDatatable {
  38. width: 100% !important;
  39. table-layout: fixed;
  40. }
  41. /* Modal body must not clip */
  42. #govtTypePersonModal .modal-body {
  43. max-height: 70vh;
  44. /* controls height */
  45. overflow-y: auto;
  46. /* ✅ vertical scroll outside table */
  47. overflow-x: hidden;
  48. }
  49. /* Table base */
  50. #GovtTypePersonDatatable {
  51. width: 100% !important;
  52. }
  53. /* Header */
  54. .govt-thead th {
  55. background: #212529;
  56. color: #fff;
  57. text-align: center;
  58. white-space: nowrap;
  59. }
  60. /* Body cells */
  61. #GovtTypePersonDatatable td {
  62. white-space: normal;
  63. word-break: break-word;
  64. vertical-align: top;
  65. font-size: 14px;
  66. }
  67. /* FORCE SAME WIDTH FOR HEADER & BODY TABLE */
  68. .dataTables_scrollHead table,
  69. .dataTables_scrollBody table {
  70. table-layout: fixed !important;
  71. width: 100% !important;
  72. }
  73. /* Modal body scroll (OUTSIDE table) */
  74. #govtTypeModal .modal-body {
  75. max-height: 70vh;
  76. /* adjust as needed */
  77. overflow-y: auto;
  78. overflow-x: hidden;
  79. }
  80. /* Normal table behavior */
  81. #GovtTypeDatatable {
  82. width: 100% !important;
  83. }
  84. /* Header cells */
  85. #GovtTypeDatatable thead th {
  86. white-space: nowrap;
  87. text-align: center;
  88. vertical-align: middle;
  89. }
  90. /* Body cells */
  91. #GovtTypeDatatable tbody td {
  92. white-space: normal;
  93. word-break: break-word;
  94. vertical-align: top;
  95. }
  96. /* 🔥 Force horizontal scroll to full width */
  97. .dataTables_wrapper {
  98. width: 100%;
  99. }
  100. .dataTables_scroll {
  101. overflow: auto !important;
  102. }
  103. .dataTables_scrollBody {
  104. overflow-x: auto !important;
  105. overflow-y: auto !important;
  106. max-height: 50vh;
  107. }
  108. /* Fix header width sync */
  109. .dataTables_scrollHeadInner,
  110. .dataTables_scrollHeadInner table {
  111. width: 100% !important;
  112. }
  113. /* Mobile fullscreen modal */
  114. @media (max-width: 768px) {
  115. #govtTypePersonModal .modal-dialog {
  116. max-width: 100%;
  117. margin: 0;
  118. }
  119. #govtTypePersonModal .modal-content {
  120. height: 100vh;
  121. border-radius: 0;
  122. }
  123. .dataTables_scrollBody {
  124. max-height: 65vh;
  125. }
  126. }
  127. /* Body cells wrap */
  128. #GovtTypePersonDatatable td {
  129. white-space: normal;
  130. word-break: break-word;
  131. vertical-align: top;
  132. font-size: 14px;
  133. }
  134. /* Fix DataTable header/body width mismatch */
  135. .dataTables_scrollHeadInner,
  136. .dataTables_scrollHeadInner table {
  137. width: 100% !important;
  138. }
  139. /* Fullscreen modal on mobile */
  140. @media (max-width: 768px) {
  141. #govtTypePersonModal .modal-dialog {
  142. max-width: 100%;
  143. margin: 0;
  144. }
  145. #govtTypePersonModal .modal-content {
  146. height: 100vh;
  147. border-radius: 0;
  148. }
  149. #govtTypePersonModal .modal-body {
  150. overflow-y: auto;
  151. }
  152. }
  153. /* MOBILE FIX */
  154. @media (max-width: 768px) {
  155. #GovtTypePersonDatatable {
  156. font-size: 13px;
  157. }
  158. .dataTables_wrapper {
  159. overflow-x: auto;
  160. }
  161. }
  162. @media (max-width: 768px) {
  163. /* #GovtTypePersonDatatable td {
  164. font-size: 13px;
  165. white-space: normal;
  166. word-break: break-word;
  167. } */
  168. #GovtTypePersonDatatable th {
  169. font-size: 13px;
  170. }
  171. }
  172. /* underline css*/
  173. .underline-hover {
  174. cursor: pointer;
  175. text-decoration: underline;
  176. }
  177. .underline-hover:hover {
  178. text-decoration: underline;
  179. /* optional, keeps underline on hover */
  180. }
  181. #completedPivotTable {
  182. table-layout: fixed;
  183. width: 100% !important;
  184. }
  185. #completedPivotTable th,
  186. #completedPivotTable td {
  187. text-align: center;
  188. vertical-align: middle;
  189. white-space: normal;
  190. }
  191. #completedPivotTable th {
  192. word-wrap: break-word;
  193. font-size: small;
  194. }
  195. /* 🔥 FIX HEADER ALIGNMENT */
  196. table.dataTable thead th {
  197. text-align: center;
  198. vertical-align: middle;
  199. white-space: normal;
  200. }
  201. /* Prevent header shifting */
  202. .dataTables_scrollHeadInner,
  203. .dataTables_scrollHeadInner table {
  204. width: 100% !important;
  205. }
  206. /* Match body + header */
  207. .dataTables_scrollBody table {
  208. width: 100% !important;
  209. }
  210. /* Fix column spacing */
  211. #completedPivotTable {
  212. border-collapse: collapse;
  213. }
  214. #personTable td:nth-child(4) {
  215. max-width: 150px;
  216. }
  217. .text-wrap {
  218. white-space: normal !important;
  219. word-break: break-word;
  220. }
  221. </style>
  222. <body>
  223. <div class="wrapper">
  224. <!-- header top menu Start -->
  225. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  226. <!-- header top menu end -->
  227. <div class="page-wrap">
  228. <!--=============== Left Menu side Start ================-->
  229. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  230. <!--=============== Left side End ================-->
  231. <div class="main-content">
  232. <div class="container-fluid">
  233. <div class="page-header mb-2">
  234. <div class="row align-items-end">
  235. <div class="col-lg-8">
  236. <div class="page-header-title">
  237. <!-- <i class="far fa-calendar-plus bg-blue"></i> -->
  238. <div class="d-inline">
  239. <h5>Dashboard</h5>
  240. <!-- <span>Mark attendance for training sessions </span> -->
  241. </div>
  242. </div>
  243. </div>
  244. </div>
  245. </div>
  246. <div class="row mt-4">
  247. <div class="col-12">
  248. <div class="card">
  249. <div class="card-body">
  250. <div class="row mt-2">
  251. <div class="col-md-3">
  252. <div class="card card-box p-3 text-center h-100">
  253. <h6 class="text-facebook mb-2">
  254. <b>Total Requirement</b>
  255. </h6>
  256. <!--<h4 class="text-twitter fw-700 mt-3"
  257. th:text="${RequirementCount.final_value}"></h4>-->
  258. <h4 class="text-twitter fw-700 mt-3">19594</h4>
  259. </div>
  260. </div>
  261. <div class="col-md-3">
  262. <div class="card card-box p-3 text-center h-100">
  263. <h6 class="text-facebook mb-2">
  264. <b>Total Applications</b>
  265. </h6>
  266. <h4 class="text-twitter fw-700 mt-3"
  267. th:text="${applicationsCount.total_applications}"></h4>
  268. </div>
  269. </div>
  270. <!-- QA&QC Calls -->
  271. <div class="col-md-3">
  272. <div class="card card-box p-3 text-center h-100">
  273. <h6 class="text-facebook mb-2">
  274. <b>Completed</b>
  275. </h6>
  276. <h4 class="text-twitter fw-700 mt-3 underline-hover"
  277. th:text="${applicationsCount.completed_applications}"
  278. onclick="openCompletedPivotModal()">
  279. </h4>
  280. <!--<h4 class="text-twitter fw-700 mt-3"
  281. th:text="${applicationsCount.completed_applications}"></h4>-->
  282. </div>
  283. </div>
  284. <!-- In-progress Calls -->
  285. <div class="col-md-3">
  286. <div class="card card-box p-3 text-center h-100">
  287. <h6 class="text-facebook mb-2">
  288. <b>Pending</b>
  289. </h6>
  290. <h4 class="text-twitter fw-700 mt-3"
  291. th:text="${applicationsCount.total_applications - applicationsCount.completed_applications}">
  292. </h4>
  293. </div>
  294. </div>
  295. </div>
  296. </div>
  297. <div class="card-body mt-2">
  298. <div class="row g-3 justify-content-center">
  299. <div class="col-6 col-sm-4 col-md-2">
  300. <div class="mini-card">
  301. <h6 class="text-facebook mb-2"><b> PO </b></h6>
  302. <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO}"></h4>
  303. </div>
  304. </div>
  305. <div class="col-6 col-sm-4 col-md-2">
  306. <div class="mini-card">
  307. <h6 class="text-facebook mb-2"><b> PO1 </b></h6>
  308. <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO1}"></h4>
  309. </div>
  310. </div>
  311. <div class="col-6 col-sm-4 col-md-2">
  312. <div class="mini-card">
  313. <h6 class="text-facebook mb-2"><b> PO2 </b></h6>
  314. <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO2}"></h4>
  315. </div>
  316. </div>
  317. <div class="col-6 col-sm-4 col-md-2">
  318. <div class="mini-card">
  319. <h6 class="text-facebook mb-2"><b> PO3 </b></h6>
  320. <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO3}"></h4>
  321. </div>
  322. </div>
  323. <div class="col-6 col-sm-4 col-md-2">
  324. <div class="mini-card">
  325. <h6 class="text-facebook mb-2"><b> PO4 </b></h6>
  326. <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO4}"></h4>
  327. </div>
  328. </div>
  329. </div>
  330. </div>
  331. <div class="card-body">
  332. <div class="row mt-4">
  333. <!-- Gender Card -->
  334. <div class="col-md-3">
  335. <div class="card card-box p-3 text-center h-100">
  336. <h6 class="text-facebook mb-2"><b>Gender</b></h6>
  337. <p class="mb-1">Male :
  338. <b class="text-twitter fw-700 mt-3"
  339. th:text="${validationCount.male}">0</b>
  340. </p>
  341. <p class="mb-0">Female :
  342. <b class="text-twitter fw-700 mt-3"
  343. th:text="${validationCount.female}">0</b>
  344. </p>
  345. <p class="mb-0">Transgender :
  346. <b class="text-twitter fw-700 mt-3"
  347. th:text="${validationCount.transgender}">0</b>
  348. </p>
  349. </div>
  350. </div>
  351. <!-- voter -->
  352. <!--<div class="col-md-3">
  353. <div class="card card-box p-3 text-center h-100">
  354. <h6 class="text-facebook mb-2"><b>Voter ID</b></h6>
  355. <p class="mb-1">Available :
  356. <b class="text-success fw-700 mt-3 underline-hover"
  357. th:text="${validationCount.voter_filled}"
  358. onclick="openCategorySummaryModal('VOTER_FILLED')">0</b>
  359. </p>
  360. <p class="mb-0">Not Available :
  361. <b class="text-danger fw-700 mt-3 underline-hover"
  362. th:text="${validationCount.voter_not_filled}"
  363. onclick="openCategorySummaryModal('VOTER_NOT_FILLED')">0</b>
  364. </p>
  365. </div>
  366. </div>
  367. &lt;!&ndash; PHONE &ndash;&gt;
  368. <div class="col-md-3">
  369. <div class="card card-box p-3 text-center h-100">
  370. <h6 class="text-facebook mb-2"><b>Phone</b></h6>
  371. <p class="mb-1">Available :
  372. <b class="text-success fw-700 mt-3 underline-hover"
  373. th:text="${validationCount.phone_filled}"
  374. onclick="openCategorySummaryModal('PHONE_FILLED')">0</b>
  375. </p>
  376. <p class="mb-0">Not Available :
  377. <b class="text-danger fw-700 mt-3 underline-hover"
  378. th:text="${validationCount.phone_not_filled}"
  379. onclick="openCategorySummaryModal('PHONE_NOT_FILLED')">0</b>
  380. </p>
  381. </div>
  382. </div>
  383. &lt;!&ndash; IMAGE &ndash;&gt;
  384. <div class="col-md-3">
  385. <div class="card card-box p-3 text-center h-100">
  386. <h6 class="text-facebook mb-2"><b>Image</b></h6>
  387. <p class="mb-1">Available :
  388. <b class="text-success fw-700 mt-3 underline-hover"
  389. th:text="${validationCount.image_filled}"
  390. onclick="openCategorySummaryModal('IMAGE_FILLED')">0</b>
  391. </p>
  392. <p class="mb-0">Not Available :
  393. <b class="text-danger fw-700 mt-3 underline-hover"
  394. th:text="${validationCount.image_not_filled}"
  395. onclick="openCategorySummaryModal('IMAGE_NOT_FILLED')">0</b>
  396. </p>
  397. </div>
  398. </div>-->
  399. <!-- Voter ID Card -->
  400. <div class="col-md-3">
  401. <div class="card card-box p-3 text-center h-100">
  402. <h6 class="text-facebook mb-2"><b>Voter ID</b></h6>
  403. <p class="mb-1">Available :
  404. <b class="text-twitter fw-700 mt-3"
  405. th:text="${validationCount.voter_filled}">0</b>
  406. </p>
  407. <p class="mb-0">Not Available :
  408. <b class="text-twitter fw-700 mt-3"
  409. th:text="${validationCount.voter_not_filled}">0</b>
  410. </p>
  411. </div>
  412. </div>
  413. <div class="col-md-3">
  414. <div class="card card-box p-3 text-center h-100">
  415. <h6 class="text-facebook mb-2"><b>Phone</b></h6>
  416. <p class="mb-1">Available :
  417. <b class="text-twitter fw-700 mt-3"
  418. th:text="${validationCount.phone_filled}">0</b>
  419. </p>
  420. <p class="mb-0">Not Available :
  421. <b class="text-twitter fw-700 mt-3"
  422. th:text="${validationCount.phone_not_filled}">0</b>
  423. </p>
  424. </div>
  425. </div>
  426. <div class="col-md-3">
  427. <div class="card card-box p-3 text-center h-100">
  428. <h6 class="text-facebook mb-2"><b>Image</b></h6>
  429. <p class="mb-1">Available :
  430. <b class="text-twitter fw-700 mt-3"
  431. th:text="${validationCount.image_filled}">0</b>
  432. </p>
  433. <p class="mb-0">Not Available :
  434. <b class="text-twitter fw-700 mt-3"
  435. th:text="${validationCount.image_not_filled}">0</b>
  436. </p>
  437. </div>
  438. </div>
  439. </div>
  440. </div>
  441. <!-- ================= Central and State Report Count ================= -->
  442. <div class="card-body">
  443. <div class="row mt-2">
  444. <div class="col-xl-6 col-sm-12">
  445. <div class="card card-box p-3 text-center h-100">
  446. <h6 class="text-facebook mb-2">
  447. <b>Central Govt Offices</b>
  448. </h6>
  449. <h4 class="text-twitter fw-700 mt-3 cursor-pointer underline-hover"
  450. th:text="${GovtTypeCount.central_count}"
  451. onclick="openGovtTypeModal('C')"></h4>
  452. <p class="mb-1">No of Applicant :
  453. <b class="text-twitter fw-700 mt-3"
  454. th:text="${GovtOfficeTypeCount.total_central}">0</b>
  455. </p>
  456. </div>
  457. </div>
  458. <!-- In-progress Calls -->
  459. <div class="col-xl-6 col-sm-12">
  460. <div class="card card-box p-3 text-center h-100">
  461. <h6 class="text-facebook mb-2">
  462. <b>State Govt Offices </b>
  463. </h6>
  464. <h4 class="text-twitter fw-700 mt-3 cursor-pointer underline-hover"
  465. th:text="${GovtTypeCount.state_count}"
  466. onclick="openGovtTypeModal('S')"></h4>
  467. <p class="mb-1">No of Applicant :
  468. <b class="text-twitter fw-700 mt-3"
  469. th:text="${GovtOfficeTypeCount.total_state}">0</b>
  470. </p>
  471. </div>
  472. </div>
  473. </div>
  474. </div>
  475. </div>
  476. </div>
  477. </div>
  478. </div>
  479. </div>
  480. <div id="pageLoader"
  481. 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;">
  482. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  483. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  484. <span class="sr-only">Loading...</span>
  485. </div>
  486. <!-- Add the 'Please wait' text below the spinner -->
  487. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  488. </div>
  489. </div>
  490. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  491. </div>
  492. </div>
  493. <div class="modal fade" id="govtTypeModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static"
  494. data-keyboard="false">
  495. <div class="modal-dialog modal-xl modal-dialog-centered" role="document">
  496. <div class="modal-content">
  497. <div class="modal-header bg-primary text-white">
  498. <h5 class="modal-title" id="govtTypeModalTitle"></h5>
  499. <button type="button" class="close text-white" data-dismiss="modal">
  500. <span>&times;</span>
  501. </button>
  502. </div>
  503. <div class="modal-body">
  504. <table id="GovtTypeDatatable" class="table table-bordered table-striped w-100">
  505. <thead class="govt-thead">
  506. <tr>
  507. <th>S.No</th>
  508. <th>Department</th>
  509. <th>Office</th>
  510. <th>Total Count</th>
  511. </tr>
  512. </thead>
  513. <tbody></tbody>
  514. </table>
  515. </div>
  516. </div>
  517. </div>
  518. </div>
  519. <div class="modal fade" id="govtTypePersonModal" tabindex="-1" role="dialog" aria-hidden="true"
  520. data-backdrop="static" data-keyboard="false">
  521. <div class="modal-dialog modal-xl modal-dialog-centered" role="document">
  522. <div class="modal-content">
  523. <div class="modal-header bg-dark text-white">
  524. <h5 class="modal-title" id="govtTypePersonModalTitle"></h5>
  525. <button type="button" class="close text-white" data-dismiss="modal">
  526. <span>&times;</span>
  527. </button>
  528. </div>
  529. <div class="modal-body">
  530. <div class="table-responsive">
  531. <table id="GovtTypePersonDatatable" class="table table-bordered table-striped nowrap">
  532. <thead class="govt-thead">
  533. <tr>
  534. <th>S.No</th>
  535. <th>Unique No</th>
  536. <th>Name</th>
  537. <th>Sex</th>
  538. <th>Mobile</th>
  539. <th>Designation</th>
  540. <th>Department</th>
  541. <th>Office</th>
  542. <th>Govt Type</th>
  543. <th>Office Address</th>
  544. <th>Residential Address</th>
  545. <th>Native AC</th>
  546. <th>Residential AC</th>
  547. <th>Elector AC</th>
  548. <th>Working AC</th>
  549. </tr>
  550. </thead>
  551. <tbody></tbody>
  552. </table>
  553. </div>
  554. </div>
  555. </div>
  556. </div>
  557. </div>
  558. <!--ak-->
  559. <div class="modal fade" id="categorySummaryModal" tabindex="-1">
  560. <div class="modal-dialog modal-xl modal-dialog-centered">
  561. <div class="modal-content">
  562. <div class="modal-header bg-primary text-white">
  563. <h5 class="modal-title" id="categorySummaryTitle"></h5>
  564. <button type="button" class="close text-white" data-dismiss="modal">
  565. <span>&times;</span>
  566. </button>
  567. </div>
  568. <div class="modal-body">
  569. <table id="categorySummaryTable" class="table table-bordered table-striped w-100">
  570. <thead class="bg-dark text-white text-center">
  571. <tr>
  572. <th>S.No</th>
  573. <th>Constiency</th>
  574. <th>Department</th>
  575. <th>Office</th>
  576. <th>Total Count</th>
  577. </tr>
  578. </thead>
  579. <tbody id="categorySummaryBody"></tbody>
  580. </table>
  581. </div>
  582. </div>
  583. </div>
  584. </div>
  585. <div class="modal fade" id="completedPivotModal" tabindex="-1">
  586. <div class="modal-dialog modal-xl modal-dialog-scrollable">
  587. <div class="modal-content">
  588. <div class="modal-header bg-primary text-white">
  589. <h5 class="modal-title">Completed - Training Centre Summary</h5>
  590. <button type="button" class="close text-white" data-dismiss="modal">
  591. <span>&times;</span>
  592. </button>
  593. </div>
  594. <div class="modal-body">
  595. <div class="table-responsive">
  596. <table id="completedPivotTable" class="table table-bordered text-center">
  597. <thead class="bg-dark text-white">
  598. <tr>
  599. <th rowspan="2">S.No</th>
  600. <th rowspan="2" class="no-sort text-center">Training Centre</th>
  601. <th colspan="4" class="text-center">PO</th>
  602. <th colspan="4" class="text-center">PO1</th>
  603. <th colspan="4" class="text-center">PO2</th>
  604. <th colspan="4" class="text-center">PO3</th>
  605. <th colspan="4" class="text-center">PO4</th>
  606. </tr>
  607. <tr>
  608. <th word-wrap="break-word" class="no-sort">Total</th>
  609. <th word-wrap="break-word" class="no-sort">No Image</th>
  610. <th word-wrap="break-word" class="no-sort">NO Phone </th>
  611. <th word-wrap="break-word" class="no-sort">NO Voter </th>
  612. <th word-wrap="break-word" class="no-sort">Total</th>
  613. <th word-wrap="break-word" class="no-sort">NO Image </th>
  614. <th word-wrap="break-word" class="no-sort">NO Phone </th>
  615. <th word-wrap="break-word" class="no-sort">NO Voter </th>
  616. <th word-wrap="break-word" class="no-sort">Total</th>
  617. <th word-wrap="break-word" class="no-sort">NO Image</th>
  618. <th word-wrap="break-word" class="no-sort">NO Phone </th>
  619. <th word-wrap="break-word" class="no-sort">NO Voter </th>
  620. <th word-wrap="break-word" class="no-sort">Total</th>
  621. <th word-wrap="break-word" class="no-sort">NO Image </th>
  622. <th word-wrap="break-word" class="no-sort">NO Phone </th>
  623. <th word-wrap="break-word" class="no-sort">NO Voter </th>
  624. <th word-wrap="break-word" class="no-sort">Total</th>
  625. <th word-wrap="break-word" class="no-sort">NO Image </th>
  626. <th word-wrap="break-word" class="no-sort">NO Phone </th>
  627. <th word-wrap="break-word" class="no-sort">NO Voter </th>
  628. </tr>
  629. </thead>
  630. <tbody id="completedPivotBody"></tbody>
  631. </table>
  632. </div>
  633. </div>
  634. </div>
  635. </div>
  636. </div>
  637. <div class="modal fade" id="hallPivotModal" tabindex="-1">
  638. <div class="modal-dialog modal-xl modal-dialog-scrollable">
  639. <div class="modal-content">
  640. <div class="modal-header bg-primary text-white">
  641. <h5 class="modal-title">Hall Wise Summary</h5>
  642. <button type="button" class="close text-white" data-dismiss="modal">
  643. <span>&times;</span>
  644. </button>
  645. </div>
  646. <div class="modal-body">
  647. <div class="table-responsive">
  648. <table id="hallPivotTable" class="table table-bordered text-center w-100">
  649. <thead class="bg-dark text-white">
  650. <tr>
  651. <th rowspan="2">S.No</th>
  652. <th rowspan="2" class="no-sort text-center">Hall No</th>
  653. <th colspan="4" class="text-center">PO</th>
  654. <th colspan="4" class="text-center">PO1</th>
  655. <th colspan="4" class="text-center">PO2</th>
  656. <th colspan="4" class="text-center">PO3</th>
  657. <th colspan="4" class="text-center">PO4</th>
  658. </tr>
  659. <tr>
  660. <th word-wrap="break-word" class="no-sort">Total</th>
  661. <th word-wrap="break-word" class="no-sort">No Image</th>
  662. <th word-wrap="break-word" class="no-sort">NO Phone</th>
  663. <th word-wrap="break-word" class="no-sort">NO Voter</th>
  664. <th word-wrap="break-word" class="no-sort">Total</th>
  665. <th word-wrap="break-word" class="no-sort">NO Image</th>
  666. <th word-wrap="break-word" class="no-sort">NO Phone</th>
  667. <th word-wrap="break-word" class="no-sort">NO Voter</th>
  668. <th word-wrap="break-word" class="no-sort">Total</th>
  669. <th word-wrap="break-word" class="no-sort">NO Image</th>
  670. <th word-wrap="break-word" class="no-sort">NO Phone</th>
  671. <th word-wrap="break-word" class="no-sort">NO Voter</th>
  672. <th word-wrap="break-word" class="no-sort">Total</th>
  673. <th word-wrap="break-word" class="no-sort">NO Image</th>
  674. <th word-wrap="break-word" class="no-sort">NO Phone</th>
  675. <th word-wrap="break-word" class="no-sort">NO Voter</th>
  676. <th word-wrap="break-word" class="no-sort">Total</th>
  677. <th word-wrap="break-word" class="no-sort">NO Image</th>
  678. <th word-wrap="break-word" class="no-sort">NO Phone</th>
  679. <th word-wrap="break-word" class="no-sort">NO Voter</th>
  680. </tr>
  681. </thead>
  682. <tbody id="hallPivotBody"></tbody>
  683. </table>
  684. </div>
  685. </div>
  686. </div>
  687. </div>
  688. </div>
  689. <div class="modal fade" id="personModal" tabindex="-1">
  690. <div class="modal-dialog modal-xl modal-dialog-scrollable">
  691. <div class="modal-content">
  692. <div class="modal-header bg-primary text-white">
  693. <h5 class="modal-title">Person Details</h5>
  694. <button type="button" class="close text-white" data-dismiss="modal">
  695. <span>&times;</span>
  696. </button>
  697. </div>
  698. <div class="modal-body">
  699. <div class="table-responsive">
  700. <table id="personTable" class="table table-bordered">
  701. <thead>
  702. <tr>
  703. <th>S.No</th>
  704. <th>Unique No</th>
  705. <th>Hall NO</th>
  706. <th>Name</th>
  707. <th>Designation</th>
  708. <th>Office Address</th>
  709. <th>Mobile</th>
  710. <th>Category</th>
  711. <th>Photo</th>
  712. </tr>
  713. </thead>
  714. <tbody id="personTableBody"></tbody>
  715. </table>
  716. </div>
  717. </div>
  718. </div>
  719. </div>
  720. </div>
  721. <!-- DataTables Buttons JS -->
  722. <!-- <script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
  723. <script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
  724. <script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.print.min.js"></script> -->
  725. <!-- Dependencies -->
  726. <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
  727. <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
  728. <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script> -->
  729. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  730. <script type="text/javascript"></script>
  731. <script>
  732. let govtTypeTable = null;
  733. function openGovtTypeModal(govtType) {
  734. const title = govtType === 'C'
  735. ? 'Central Government Details'
  736. : 'State Government Details';
  737. $('#govtTypeModalTitle').text(title);
  738. $.ajax({
  739. url: '/election/api/dataentryadmin/dashboard/govt-type-details',
  740. type: 'GET',
  741. data: { govtType: govtType },
  742. success: function (data) {
  743. if ($.fn.DataTable.isDataTable('#GovtTypeDatatable')) {
  744. govtTypeTable.destroy();
  745. $('#GovtTypeDatatable tbody').empty();
  746. }
  747. let rows = '';
  748. data.forEach((row, index) => {
  749. rows += `
  750. <tr>
  751. <td class="text-center">${index + 1}</td>
  752. <td>${row.dept_name ?? '-'}</td>
  753. <td>${row.office_address ?? '-'}</td>
  754. <td class="text-center">
  755. <a href="javascript:void(0)"
  756. class="text-primary fw-bold"
  757. onclick="openGovtTypePersonModal(
  758. '${govtType}',
  759. '${row.dept_name}',
  760. '${row.office_name}'
  761. )">
  762. ${row.total_count}
  763. </a>
  764. </td>
  765. </tr>
  766. `;
  767. });
  768. $('#GovtTypeDatatable tbody').html(rows);
  769. // DataTable with Buttons
  770. govtTypeTable = $('#GovtTypeDatatable').DataTable({
  771. dom: 'Bftip',
  772. autoWidth: false,
  773. responsive: false,
  774. ordering: true,
  775. searching: true,
  776. paging: true,
  777. pageLength: 10,
  778. buttons: [
  779. {
  780. extend: 'copy',
  781. text: 'Copy',
  782. title: title
  783. },
  784. {
  785. extend: 'excelHtml5',
  786. text: 'Excel',
  787. title: title
  788. },
  789. {
  790. extend: 'csvHtml5',
  791. text: 'CSV',
  792. title: title
  793. },
  794. /* {
  795. extend: 'pdfHtml5',
  796. text: 'PDF',
  797. title: '',
  798. orientation: 'landscape',
  799. pageSize: 'A4',
  800. customize: function (doc) {
  801. // Page margins
  802. doc.pageMargins = [20, 60, 20, 30];
  803. // Add heading manually
  804. doc.content.unshift({
  805. text: title,
  806. alignment: 'center',
  807. fontSize: 14,
  808. bold: true,
  809. margin: [0, 0, 0, 12]
  810. });
  811. doc.defaultStyle.fontSize = 11;
  812. doc.styles.tableHeader.alignment = 'center';
  813. }
  814. } */
  815. ],
  816. columnDefs: [
  817. { targets: 0, width: "60px", className: "text-center" },
  818. { targets: 3, width: "120px", className: "text-center" }
  819. ]
  820. });
  821. govtTypeTable.columns.adjust().draw();
  822. $('#govtTypeModal').modal('show');
  823. },
  824. error: function () {
  825. alert('Error loading data');
  826. }
  827. });
  828. }
  829. $('#govtTypeModal').on('shown.bs.modal', function () {
  830. if (govtTypeTable) {
  831. govtTypeTable.columns.adjust();
  832. }
  833. });
  834. </script>
  835. <script>
  836. let govtTypePersonTable = null;
  837. function openGovtTypePersonModal(govtType, deptName, officeName) {
  838. const govtLabel = govtType === 'C'
  839. ? 'Central Government'
  840. : 'State Government';
  841. const pdfHeading = govtLabel + ' - ' + deptName + ' - ' + officeName;
  842. $('#govtTypePersonModalTitle').text(
  843. govtLabel + ' - ' + deptName + ' - ' + officeName
  844. );
  845. $.ajax({
  846. url: '/election/api/dataentryadmin/dashboard/govt-type-person-details',
  847. type: 'GET',
  848. data: {
  849. govtType: govtType,
  850. deptName: deptName,
  851. officeName: officeName
  852. },
  853. success: function (data) {
  854. if ($.fn.DataTable.isDataTable('#GovtTypePersonDatatable')) {
  855. govtTypePersonTable.destroy();
  856. $('#GovtTypePersonDatatable tbody').empty();
  857. }
  858. let rows = '';
  859. data.forEach((row, index) => {
  860. rows += `
  861. <tr>
  862. <td class="text-center">${index + 1}</td> <!-- ✅ S.No -->
  863. <td class="text-center">${row.unique_no}</td>
  864. <td>${row.name}</td>
  865. <td class="text-center">${row.sex ?? ''}</td>
  866. <td>${row.r_mobile_no ?? ''}</td>
  867. <td>${row.new_designation ?? ''}</td>
  868. <td>${row.dept_name ?? ''}</td>
  869. <td>${row.office_name ?? ''}</td>
  870. <td class="text-center">${row.govt_type}</td>
  871. <td>${row.office_address ?? ''}</td>
  872. <td>${row.residential_address ?? ''}</td>
  873. <td>${row.native_constituency ?? ''}</td>
  874. <td>${row.residential_constituency ?? ''}</td>
  875. <td>${row.elector_constituency ?? ''}</td>
  876. <td>${row.working_constituency ?? ''}</td>
  877. </tr>
  878. `;
  879. });
  880. $('#GovtTypePersonDatatable tbody').html(rows);
  881. const isMobile = window.innerWidth <= 768;
  882. govtTypePersonTable = $('#GovtTypePersonDatatable').DataTable({
  883. dom: 'Bfrtip', // 🔥 Buttons + filter + table + pagination
  884. autoWidth: false,
  885. responsive: false,
  886. ordering: true,
  887. searching: true,
  888. paging: true,
  889. pageLength: 10,
  890. fixedHeader: false,
  891. buttons: [
  892. {
  893. extend: 'copy',
  894. text: 'Copy'
  895. },
  896. {
  897. extend: 'excelHtml5',
  898. text: 'Excel',
  899. title: pdfHeading
  900. },
  901. {
  902. extend: 'csvHtml5',
  903. text: 'CSV',
  904. title: pdfHeading
  905. },
  906. /* {
  907. extend: 'pdfHtml5',
  908. text: 'PDF',
  909. title: '',
  910. orientation: 'landscape',
  911. pageSize: 'A3',
  912. exportOptions: { columns: ':visible' },
  913. customize: function (doc) {
  914. // Page setup
  915. doc.pageMargins = [10, 50, 10, 20];
  916. doc.defaultStyle.fontSize = 11;
  917. // Title
  918. doc.content.unshift({
  919. text: pdfHeading,
  920. alignment: 'center',
  921. fontSize: 14,
  922. bold: true,
  923. margin: [0, 0, 0, 10]
  924. });
  925. // Header style
  926. doc.styles.tableHeader.fontSize = 12;
  927. doc.styles.tableHeader.alignment = 'center';
  928. // 🔥 IMPORTANT: Adjust column widths
  929. doc.content[1].table.widths = [
  930. 30, // S.No
  931. 50, // Unique No
  932. 85, // Name
  933. 30, // Sex
  934. 65, // Mobile
  935. 80, // Designation
  936. 85, // Department
  937. 90, // Office
  938. 40, // Govt Type
  939. 120, // Office Address
  940. 120, // Residential Address
  941. 60, // Native AC
  942. 60, // Residential AC
  943. 60, // Elector AC
  944. 70 // ✅ Working AC (FIXED WIDTH)
  945. ];
  946. // Enable wrapping for all cells
  947. doc.content[1].table.body.forEach(function (row, i) {
  948. row.forEach(function (cell) {
  949. if (typeof cell === 'object') {
  950. cell.noWrap = false;
  951. }
  952. });
  953. });
  954. }
  955. } */
  956. ],
  957. columnDefs: [
  958. { width: "60px", targets: 0 },
  959. { width: "90px", targets: 1 },
  960. { width: "180px", targets: 2 },
  961. { width: "60px", targets: 3 },
  962. { width: "120px", targets: 4 },
  963. { width: "200px", targets: 5 },
  964. { width: "220px", targets: 6 },
  965. { width: "250px", targets: 7 },
  966. { width: "80px", targets: 8 },
  967. { width: "260px", targets: 9 },
  968. { width: "260px", targets: 10 },
  969. { width: "140px", targets: 11 },
  970. { width: "140px", targets: 12 },
  971. { width: "140px", targets: 13 },
  972. { width: "140px", targets: 14 }
  973. ]
  974. });
  975. $('#govtTypePersonModal').modal('show');
  976. },
  977. error: function () {
  978. alert('Error loading person details');
  979. }
  980. });
  981. }
  982. //ak
  983. let categorySummaryTable = null;
  984. function openCategorySummaryModal(category) {
  985. $('#categorySummaryTitle').text(category.replaceAll('_', ' '));
  986. $.ajax({
  987. url: '/election/api/dataentryadmin/dashboard/category-summary',
  988. type: 'GET',
  989. data: { category: category },
  990. success: function (data) {
  991. // destroy old table
  992. if ($.fn.DataTable.isDataTable('#categorySummaryTable')) {
  993. categorySummaryTable.destroy();
  994. $('#categorySummaryBody').empty();
  995. }
  996. let rows = '';
  997. data.forEach((row, index) => {
  998. rows += `
  999. <tr>
  1000. <td>${index + 1}</td>
  1001. <td>${row.ac_display ?? ''}</td>
  1002. <td>${row.dept_name ?? ''}</td>
  1003. <td>${row.office_address ?? ''}</td>
  1004. <td class="text-center">
  1005. <a href="#" onclick="openCategoryPersonModal(
  1006. '${category}',
  1007. '${row.work_ac_no}',
  1008. '${row.dept_name}',
  1009. '${row.office_name}'
  1010. )">
  1011. ${row.total_count}
  1012. </a>
  1013. </td>
  1014. </tr>
  1015. `;
  1016. });
  1017. $('#categorySummaryBody').html(rows);
  1018. categorySummaryTable = $('#categorySummaryTable').DataTable({
  1019. dom: 'Bfrtip',
  1020. pageLength: 10,
  1021. ordering: true,
  1022. searching: true,
  1023. buttons: [
  1024. {
  1025. extend: 'excelHtml5',
  1026. text: 'Excel',
  1027. title: category
  1028. },
  1029. {
  1030. extend: 'pdfHtml5',
  1031. text: 'PDF',
  1032. title: category,
  1033. orientation: 'landscape',
  1034. pageSize: 'A4'
  1035. }
  1036. ]
  1037. });
  1038. $('#categorySummaryModal').modal('show');
  1039. }
  1040. });
  1041. }
  1042. /*function openCompletedPivotModal() {
  1043. $('#pageLoader').show();
  1044. $.get('/election/api/dataentryadmin/dashboard/training-centre-category-pivot', function(data) {
  1045. if ($.fn.DataTable.isDataTable('#completedPivotTable')) {
  1046. $('#completedPivotTable').DataTable().destroy();
  1047. }
  1048. let rows = '';
  1049. function getCell(c) {
  1050. if (!c) return '-';
  1051. return `
  1052. <div style="text-align:left; font-size:13px; line-height:1.5">
  1053. <b>Total:</b> ${c.total}<br>
  1054. <b>Image Not Filled:</b> ${c.image_not_filled}<br>
  1055. <b>Phone Not Filled:</b> ${c.phone_not_filled}<br>
  1056. <b>Voter Not Filled:</b> ${c.voter_not_filled}
  1057. </div>
  1058. `;
  1059. }
  1060. data.forEach((row, index) => {
  1061. const cats = row.categories || {};
  1062. rows += `
  1063. <tr>
  1064. <td>${index + 1}</td>
  1065. <td>
  1066. <a href="javascript:void(0)"
  1067. class="text-primary fw-bold text-decoration-underline"
  1068. onclick="openHallWiseModal('${row.training_centre_id}')">
  1069. ${row.training_centre}
  1070. </a>
  1071. </td>
  1072. <td>${getCell(cats.PO)}</td>
  1073. <td>${getCell(cats.PO1)}</td>
  1074. <td>${getCell(cats.PO2)}</td>
  1075. <td>${getCell(cats.PO3)}</td>
  1076. <td>${getCell(cats.PO4)}</td>
  1077. </tr>
  1078. `;
  1079. });
  1080. $('#completedPivotBody').html(rows);
  1081. $('#completedPivotTable').DataTable({
  1082. dom: 'Bfrtip',
  1083. buttons: [
  1084. { extend: 'excelHtml5', text: 'Excel', title: 'Training Summary' },
  1085. { extend: 'pdfHtml5', text: 'PDF', title: 'Training Summary', orientation: 'landscape' }
  1086. ]
  1087. });
  1088. $('#pageLoader').hide();
  1089. $('#completedPivotModal').modal('show');
  1090. })
  1091. .fail(function() {
  1092. $('#pageLoader').hide();
  1093. alert("Error loading data");
  1094. });
  1095. }*/
  1096. function openCompletedPivotModal() {
  1097. $('#pageLoader').show();
  1098. $.get('/election/api/dataentryadmin/dashboard/training-centre-category-pivot', function (data) {
  1099. if ($.fn.DataTable.isDataTable('#completedPivotTable')) {
  1100. $('#completedPivotTable').DataTable().destroy();
  1101. }
  1102. let rows = '';
  1103. // 🔥 return 4 columns
  1104. function getCells(c) {
  1105. if (!c) {
  1106. return `<td>0</td><td>0</td><td>0</td><td>0</td>`;
  1107. }
  1108. return `
  1109. <td>${c.total}</td>
  1110. <td>${c.image_not_filled}</td>
  1111. <td>${c.phone_not_filled}</td>
  1112. <td>${c.voter_not_filled}</td>
  1113. `;
  1114. }
  1115. data.forEach((row, index) => {
  1116. const cats = row.categories || {};
  1117. rows += `
  1118. <tr>
  1119. <td>${index + 1}</td>
  1120. <td>
  1121. <a href="javascript:void(0)"
  1122. class="text-primary fw-bold text-decoration-underline"
  1123. onclick="openHallWiseModal('${row.training_centre_id}')">
  1124. ${row.training_centre}
  1125. </a>
  1126. </td>
  1127. ${getCells(cats.PO)}
  1128. ${getCells(cats.PO1)}
  1129. ${getCells(cats.PO2)}
  1130. ${getCells(cats.PO3)}
  1131. ${getCells(cats.PO4)}
  1132. </tr>
  1133. `;
  1134. });
  1135. $('#completedPivotBody').html(rows);
  1136. // 🔥 DATATABLE (IMPORTANT SETTINGS)
  1137. $('#completedPivotTable').DataTable({
  1138. destroy: true,
  1139. fixedHeader: false,
  1140. dom: 'Bfrtip',
  1141. scrollX: true,
  1142. info: true,
  1143. autoWidth: false,
  1144. ordering: false,
  1145. responsive: false,
  1146. lengthMenu: [
  1147. [100, 200, 500, -1],
  1148. ['100 rows', '200 rows', 'Show all']
  1149. ],
  1150. columnDefs: [
  1151. { width: "150px", targets: 1 }
  1152. ],
  1153. buttons: [
  1154. { extend: 'excelHtml5', text: 'Excel', title: 'Training Summary' },
  1155. { extend: 'pdfHtml5', text: 'PDF', title: 'Training Summary', orientation: 'landscape', pageSize: 'A3' }
  1156. ]
  1157. });
  1158. $('#pageLoader').hide();
  1159. $('#completedPivotModal').modal('show');
  1160. $('#completedPivotModal').on('shown.bs.modal', function () {
  1161. setTimeout(() => {
  1162. $('#completedPivotTable').DataTable().columns.adjust();
  1163. }, 200);
  1164. });
  1165. })
  1166. .fail(function () {
  1167. $('#pageLoader').hide();
  1168. alert("Error loading data");
  1169. });
  1170. }
  1171. /*function openHallWiseModal(centreId) {
  1172. $('#pageLoader').show();
  1173. $.ajax({
  1174. url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot',
  1175. type: 'GET',
  1176. data: { trainingCentreId: centreId },
  1177. success: function(data) {
  1178. if ($.fn.DataTable.isDataTable('#hallPivotTable')) {
  1179. $('#hallPivotTable').DataTable().destroy();
  1180. }
  1181. let rows = '';
  1182. data.forEach((row, index) => {
  1183. const cats = row.categories || {};
  1184. function cell(c) {
  1185. if (!c) return '-';
  1186. return `
  1187. <b>Total:</b> ${c.total}<br>
  1188. <b>Image Not Filled:</b> ${c.image_not_filled}<br>
  1189. <b>Phone Not Filled:</b> ${c.phone_not_filled}<br>
  1190. <b>Voter Not Filled:</b> ${c.voter_not_filled}
  1191. `;
  1192. }
  1193. rows += `
  1194. <tr>
  1195. <td>${index + 1}</td>
  1196. <td>
  1197. <a href="javascript:void(0)"
  1198. class="text-primary fw-bold text-decoration-underline"
  1199. onclick="openPersonList('${centreId}', '${row.hall_no}')">
  1200. ${row.hall_no}
  1201. </a>
  1202. </td>
  1203. <td>${cell(cats.PO)}</td>
  1204. <td>${cell(cats.PO1)}</td>
  1205. <td>${cell(cats.PO2)}</td>
  1206. <td>${cell(cats.PO3)}</td>
  1207. <td>${cell(cats.PO4)}</td>
  1208. </tr>
  1209. `;
  1210. });
  1211. $('#hallPivotBody').html(rows);
  1212. $('#hallPivotTable').DataTable({
  1213. dom: 'Bfrtip',
  1214. buttons: [
  1215. { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' },
  1216. { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape' }
  1217. ]
  1218. });
  1219. $('#pageLoader').hide();
  1220. $('#hallPivotModal').modal('show');
  1221. },
  1222. error: function() {
  1223. $('#pageLoader').hide();
  1224. alert("Error loading hall data");
  1225. }
  1226. });
  1227. }*/
  1228. /*function openHallWiseModal(centreId) {
  1229. $('#pageLoader').show();
  1230. $.ajax({
  1231. url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot',
  1232. type: 'GET',
  1233. data: { trainingCentreId: centreId },
  1234. success: function(data) {
  1235. if ($.fn.DataTable.isDataTable('#hallPivotTable')) {
  1236. $('#hallPivotTable').DataTable().destroy();
  1237. }
  1238. let rows = '';
  1239. // 🔥 return 4 columns
  1240. function getCells(c) {
  1241. if (!c) {
  1242. return `<td>0</td><td>0</td><td>0</td><td>0</td>`;
  1243. }
  1244. return `
  1245. <td>${c.total}</td>
  1246. <td>${c.image_not_filled}</td>
  1247. <td>${c.phone_not_filled}</td>
  1248. <td>${c.voter_not_filled}</td>
  1249. `;
  1250. }
  1251. data.forEach((row, index) => {
  1252. const cats = row.categories || {};
  1253. rows += `
  1254. <tr>
  1255. <td>${index + 1}</td>
  1256. <td>
  1257. <a href="javascript:void(0)"
  1258. class="text-primary fw-bold text-decoration-underline"
  1259. onclick="openPersonList('${centreId}', '${row.hall_no}')">
  1260. ${row.hall_no}
  1261. </a>
  1262. </td>
  1263. ${getCells(cats.PO)}
  1264. ${getCells(cats.PO1)}
  1265. ${getCells(cats.PO2)}
  1266. ${getCells(cats.PO3)}
  1267. ${getCells(cats.PO4)}
  1268. </tr>
  1269. `;
  1270. });
  1271. $('#hallPivotBody').html(rows);
  1272. // 🔥 SIMPLE DATATABLE (avoid misalignment)
  1273. $('#hallPivotTable').DataTable({
  1274. destroy: true,
  1275. dom: 'Bfrtip',
  1276. scrollX: true,
  1277. autoWidth: false,
  1278. ordering: false,
  1279. buttons: [
  1280. { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' },
  1281. { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape', pageSize: 'A3' }
  1282. ]
  1283. });
  1284. $('#pageLoader').hide();
  1285. $('#hallPivotModal').modal('show');
  1286. // 🔥 FIX ALIGNMENT AFTER MODAL OPEN
  1287. $('#hallPivotModal').on('shown.bs.modal', function () {
  1288. setTimeout(() => {
  1289. $('#hallPivotTable').DataTable().columns.adjust();
  1290. }, 200);
  1291. });
  1292. },
  1293. error: function() {
  1294. $('#pageLoader').hide();
  1295. alert("Error loading hall data");
  1296. }
  1297. });
  1298. }*/
  1299. function openHallWiseModal(centreId) {
  1300. $('#pageLoader').show();
  1301. $.ajax({
  1302. url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot',
  1303. type: 'GET',
  1304. data: { trainingCentreId: centreId },
  1305. success: function (data) {
  1306. if ($.fn.DataTable.isDataTable('#hallPivotTable')) {
  1307. $('#hallPivotTable').DataTable().destroy();
  1308. }
  1309. let rows = '';
  1310. // 🔥 clickable cells
  1311. /*function getCells(c, hallNo, category) {
  1312. if (!c) {
  1313. return `<td>0</td><td>0</td><td>0</td><td>0</td>`;
  1314. }
  1315. return `
  1316. <td>${c.total}</td>
  1317. <td>
  1318. <a href="javascript:void(0)"
  1319. class="text-primary fw-bold text-decoration-underline"
  1320. onclick="openPersonList('${centreId}','${hallNo}','${category}','IMAGE')">
  1321. ${c.image_not_filled}
  1322. </a>
  1323. </td>
  1324. <td>
  1325. <a href="javascript:void(0)"
  1326. class="text-primary fw-bold text-decoration-underline"
  1327. onclick="openPersonList('${centreId}','${hallNo}','${category}','PHONE')">
  1328. ${c.phone_not_filled}
  1329. </a>
  1330. </td>
  1331. <td>
  1332. <a href="javascript:void(0)"
  1333. class="text-primary fw-bold text-decoration-underline"
  1334. onclick="openPersonList('${centreId}','${hallNo}','${category}','VOTER')">
  1335. ${c.voter_not_filled}
  1336. </a>
  1337. </td>
  1338. `;
  1339. }*/
  1340. function getCells(c, hallNo, category) {
  1341. if (!c) {
  1342. return `<td>0</td><td>0</td><td>0</td><td>0</td>`;
  1343. }
  1344. return `
  1345. <td>${c.total}</td>
  1346. <td>
  1347. ${c.image_not_filled > 0
  1348. ? `<a href="javascript:void(0)"
  1349. class="text-primary fw-bold text-decoration-underline"
  1350. onclick="openPersonList('${centreId}','${hallNo}','${category}','IMAGE')">
  1351. ${c.image_not_filled}
  1352. </a>`
  1353. : `<span>${c.image_not_filled}</span>`
  1354. }
  1355. </td>
  1356. <td>
  1357. ${c.phone_not_filled > 0
  1358. ? `<a href="javascript:void(0)"
  1359. class="text-primary fw-bold text-decoration-underline"
  1360. onclick="openPersonList('${centreId}','${hallNo}','${category}','PHONE')">
  1361. ${c.phone_not_filled}
  1362. </a>`
  1363. : `<span>${c.phone_not_filled}</span>`
  1364. }
  1365. </td>
  1366. <td>
  1367. ${c.voter_not_filled > 0
  1368. ? `<a href="javascript:void(0)"
  1369. class="text-primary fw-bold text-decoration-underline"
  1370. onclick="openPersonList('${centreId}','${hallNo}','${category}','VOTER')">
  1371. ${c.voter_not_filled}
  1372. </a>`
  1373. : `<span>${c.voter_not_filled}</span>`
  1374. }
  1375. </td>
  1376. `;
  1377. }
  1378. data.forEach((row, index) => {
  1379. const cats = row.categories || {};
  1380. rows += `
  1381. <tr>
  1382. <td>${index + 1}</td>
  1383. <td>${row.hall_no}</td>
  1384. ${getCells(cats.PO, row.hall_no, 'PO')}
  1385. ${getCells(cats.PO1, row.hall_no, 'PO1')}
  1386. ${getCells(cats.PO2, row.hall_no, 'PO2')}
  1387. ${getCells(cats.PO3, row.hall_no, 'PO3')}
  1388. ${getCells(cats.PO4, row.hall_no, 'PO4')}
  1389. </tr>
  1390. `;
  1391. });
  1392. $('#hallPivotBody').html(rows);
  1393. $('#hallPivotTable').DataTable({
  1394. destroy: true,
  1395. dom: 'Bfrtip',
  1396. scrollX: true,
  1397. autoWidth: false,
  1398. ordering: false,
  1399. buttons: [
  1400. { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' },
  1401. { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape', pageSize: 'A3' }
  1402. ]
  1403. });
  1404. $('#pageLoader').hide();
  1405. $('#hallPivotModal').modal('show');
  1406. setTimeout(() => {
  1407. $('#hallPivotTable').DataTable().columns.adjust();
  1408. }, 200);
  1409. }
  1410. });
  1411. }
  1412. /*function openPersonList(centreId, hallNo) {
  1413. $('#pageLoader').show();
  1414. $.ajax({
  1415. url: '/election/api/dataentryadmin/dashboard/hall-persons',
  1416. type: 'GET',
  1417. data: {
  1418. trainingCentreId: centreId,
  1419. hallNo: hallNo
  1420. },
  1421. success: function(data) {
  1422. if ($.fn.DataTable.isDataTable('#personTable')) {
  1423. $('#personTable').DataTable().destroy();
  1424. }
  1425. let rows = '';
  1426. data.forEach((row, index) => {
  1427. rows += `
  1428. <tr>
  1429. <td>${index + 1}</td>
  1430. <td>${row.name}</td>
  1431. <td>${row.designation}</td>
  1432. <td>${row.office}</td>
  1433. <td>${row.mobile}</td>
  1434. <td>${row.category}</td>
  1435. <td>
  1436. ${row.img_full_path ?
  1437. `<img src="${row.img_full_path}" width="60" height="60"/>`
  1438. : ''
  1439. }
  1440. </td>
  1441. </tr>
  1442. `;
  1443. });
  1444. $('#personTableBody').html(rows);
  1445. $('#personTable').DataTable({
  1446. dom: 'Bfrtip',
  1447. buttons: [
  1448. { extend: 'excelHtml5', text: 'Excel', title: 'Person Details' },
  1449. { extend: 'pdfHtml5', text: 'PDF', title: 'Person Details', orientation: 'landscape' }
  1450. ]
  1451. });
  1452. $('#pageLoader').hide();
  1453. $('#personModal').modal('show');
  1454. }
  1455. });
  1456. }*/
  1457. function openPersonList(centreId, hallNo, category, type) {
  1458. $('#pageLoader').show();
  1459. $.ajax({
  1460. url: '/election/api/dataentryadmin/dashboard/hall-persons',
  1461. type: 'GET',
  1462. data: {
  1463. trainingCentreId: centreId,
  1464. hallNo: hallNo,
  1465. category: category,
  1466. type: type
  1467. },
  1468. success: function (data) {
  1469. console.log(data);
  1470. if ($.fn.DataTable.isDataTable('#personTable')) {
  1471. $('#personTable').DataTable().destroy();
  1472. }
  1473. let rows = '';
  1474. data.forEach((row, index) => {
  1475. rows += `
  1476. <tr>
  1477. <td>${index + 1}</td>
  1478. <td class="text-center">${row.unique_no}</td>
  1479. <td class="text-center">${row.hall_no}</td>
  1480. <td class="text-wrap">${row.name}</td>
  1481. <td>${row.designation}</td>
  1482. <td>${row.office}</td>
  1483. <td>${row.mobile || '-'}</td>
  1484. <td>${row.category}</td>
  1485. <td>
  1486. ${row.img_full_path
  1487. ? `<img src="${row.img_full_path}" width="60" height="60"/>`
  1488. : '-'
  1489. }
  1490. </td>
  1491. </tr>
  1492. `;
  1493. });
  1494. $('#personTableBody').html(rows);
  1495. $('#personTable').DataTable({
  1496. destroy: true,
  1497. dom: 'Bfrtip',
  1498. scrollX: true,
  1499. autoWidth: false,
  1500. lengthMenu: [
  1501. [25, 100, 200, 500, -1],
  1502. ['25 rows', '100 rows', '200 rows', 'Show all']
  1503. ],
  1504. buttons: [
  1505. { extend: 'excelHtml5', text: 'Excel', title: 'Person Details' },
  1506. { extend: 'pdfHtml5', text: 'PDF', title: 'Person Details', orientation: 'landscape' }
  1507. ]
  1508. });
  1509. $('#pageLoader').hide();
  1510. $('#personModal').modal('show');
  1511. }
  1512. });
  1513. }
  1514. </script>
  1515. </body>
  1516. </html>