|
|
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/modules/base/head :: head}"></head><link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.dataTables.min.css">
<style> .mini-card { box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px; border-radius: 6px; padding: 12px; text-align: center; background: #ffffff; min-height: 90px; display: flex; flex-direction: column; justify-content: center; }
.card-box { box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px; }
/* Header styling */ .govt-thead th { background-color: #212529 !important; color: #fff !important; text-align: center; vertical-align: middle; white-space: nowrap; /* 🔥 header single line */ }
/* Enable wrapping in body cells */ #GovtTypeDatatable th, #GovtTypeDatatable td { white-space: normal !important; /* ALLOW WRAP */ word-break: break-word; }
/* Table layout */ #GovtTypePersonDatatable { width: 100% !important; table-layout: fixed; }
/* Modal body must not clip */ #govtTypePersonModal .modal-body { max-height: 70vh; /* controls height */ overflow-y: auto; /* ✅ vertical scroll outside table */ overflow-x: hidden; }
/* Table base */ #GovtTypePersonDatatable { width: 100% !important; }
/* Header */ .govt-thead th { background: #212529; color: #fff; text-align: center; white-space: nowrap; }
/* Body cells */ #GovtTypePersonDatatable td { white-space: normal; word-break: break-word; vertical-align: top; font-size: 14px; }
/* FORCE SAME WIDTH FOR HEADER & BODY TABLE */ .dataTables_scrollHead table, .dataTables_scrollBody table { table-layout: fixed !important; width: 100% !important; }
/* Modal body scroll (OUTSIDE table) */ #govtTypeModal .modal-body { max-height: 70vh; /* adjust as needed */ overflow-y: auto; overflow-x: hidden; }
/* Normal table behavior */ #GovtTypeDatatable { width: 100% !important; }
/* Header cells */ #GovtTypeDatatable thead th { white-space: nowrap; text-align: center; vertical-align: middle; }
/* Body cells */ #GovtTypeDatatable tbody td { white-space: normal; word-break: break-word; vertical-align: top; }
/* 🔥 Force horizontal scroll to full width */ .dataTables_wrapper { width: 100%; }
.dataTables_scroll { overflow: auto !important; }
.dataTables_scrollBody { overflow-x: auto !important; overflow-y: auto !important; max-height: 50vh; }
/* Fix header width sync */ .dataTables_scrollHeadInner, .dataTables_scrollHeadInner table { width: 100% !important; }
/* Mobile fullscreen modal */ @media (max-width: 768px) { #govtTypePersonModal .modal-dialog { max-width: 100%; margin: 0; }
#govtTypePersonModal .modal-content { height: 100vh; border-radius: 0; }
.dataTables_scrollBody { max-height: 65vh; } }
/* Body cells wrap */ #GovtTypePersonDatatable td { white-space: normal; word-break: break-word; vertical-align: top; font-size: 14px; }
/* Fix DataTable header/body width mismatch */ .dataTables_scrollHeadInner, .dataTables_scrollHeadInner table { width: 100% !important; }
/* Fullscreen modal on mobile */ @media (max-width: 768px) { #govtTypePersonModal .modal-dialog { max-width: 100%; margin: 0; }
#govtTypePersonModal .modal-content { height: 100vh; border-radius: 0; }
#govtTypePersonModal .modal-body { overflow-y: auto; } }
/* MOBILE FIX */ @media (max-width: 768px) { #GovtTypePersonDatatable { font-size: 13px; }
.dataTables_wrapper { overflow-x: auto; } }
@media (max-width: 768px) { /* #GovtTypePersonDatatable td { font-size: 13px; white-space: normal; word-break: break-word; } */
#GovtTypePersonDatatable th { font-size: 13px; } }
/* underline css*/
.underline-hover { cursor: pointer; text-decoration: underline; }
.underline-hover:hover { text-decoration: underline; /* optional, keeps underline on hover */ }
#completedPivotTable { table-layout: fixed; width: 100% !important; }
#completedPivotTable th, #completedPivotTable td { text-align: center; vertical-align: middle; white-space: normal; }
#completedPivotTable th { word-wrap: break-word; font-size: small; }
/* 🔥 FIX HEADER ALIGNMENT */ table.dataTable thead th { text-align: center; vertical-align: middle; white-space: normal; }
/* Prevent header shifting */ .dataTables_scrollHeadInner, .dataTables_scrollHeadInner table { width: 100% !important; }
/* Match body + header */ .dataTables_scrollBody table { width: 100% !important; }
/* Fix column spacing */ #completedPivotTable { border-collapse: collapse; }
#personTable td:nth-child(4) { max-width: 150px; }
.text-wrap { white-space: normal !important; word-break: break-word; }</style>
<body>
<div class="wrapper"> <!-- header top menu Start --> <header th:replace="~{fragments/modules/base/header :: header}"></header> <!-- header top menu end --> <div class="page-wrap"> <!--=============== Left Menu side Start ================--> <div th:replace="~{fragments/modules/base/menu :: menu}"></div> <!--=============== Left side End ================--> <div class="main-content"> <div class="container-fluid">
<div class="page-header mb-2"> <div class="row align-items-end"> <div class="col-lg-8"> <div class="page-header-title"> <!-- <i class="far fa-calendar-plus bg-blue"></i> --> <div class="d-inline"> <h5>Dashboard</h5> <!-- <span>Mark attendance for training sessions </span> --> </div> </div> </div> </div> </div>
<div class="row mt-4"> <div class="col-12"> <div class="card"> <div class="card-body"> <div class="row mt-2"> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>Total Requirement</b> </h6> <!--<h4 class="text-twitter fw-700 mt-3"
th:text="${RequirementCount.final_value}"></h4>--> <h4 class="text-twitter fw-700 mt-3">19594</h4> </div> </div>
<div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>Total Applications</b> </h6> <h4 class="text-twitter fw-700 mt-3" th:text="${applicationsCount.total_applications}"></h4> </div> </div> <!-- QA&QC Calls --> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>Completed</b> </h6> <h4 class="text-twitter fw-700 mt-3 underline-hover" th:text="${applicationsCount.completed_applications}" onclick="openCompletedPivotModal()"> </h4> <!--<h4 class="text-twitter fw-700 mt-3"
th:text="${applicationsCount.completed_applications}"></h4>--> </div> </div> <!-- In-progress Calls --> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>Pending</b> </h6> <h4 class="text-twitter fw-700 mt-3" th:text="${applicationsCount.total_applications - applicationsCount.completed_applications}"> </h4> </div> </div>
</div> </div>
<div class="card-body mt-2"> <div class="row g-3 justify-content-center">
<div class="col-6 col-sm-4 col-md-2"> <div class="mini-card"> <h6 class="text-facebook mb-2"><b> PO </b></h6> <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO}"></h4> </div> </div>
<div class="col-6 col-sm-4 col-md-2"> <div class="mini-card"> <h6 class="text-facebook mb-2"><b> PO1 </b></h6> <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO1}"></h4> </div> </div>
<div class="col-6 col-sm-4 col-md-2"> <div class="mini-card"> <h6 class="text-facebook mb-2"><b> PO2 </b></h6> <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO2}"></h4> </div> </div>
<div class="col-6 col-sm-4 col-md-2"> <div class="mini-card"> <h6 class="text-facebook mb-2"><b> PO3 </b></h6> <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO3}"></h4> </div> </div>
<div class="col-6 col-sm-4 col-md-2"> <div class="mini-card"> <h6 class="text-facebook mb-2"><b> PO4 </b></h6> <h4 class="text-twitter fw-700 mt-3" th:text="${gradeCounts.PO4}"></h4> </div> </div>
</div> </div> <div class="card-body"> <div class="row mt-4">
<!-- Gender Card --> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Gender</b></h6> <p class="mb-1">Male : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.male}">0</b> </p> <p class="mb-0">Female : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.female}">0</b> </p> <p class="mb-0">Transgender : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.transgender}">0</b> </p> </div> </div>
<!-- voter --> <!--<div class="col-md-3">
<div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Voter ID</b></h6>
<p class="mb-1">Available : <b class="text-success fw-700 mt-3 underline-hover" th:text="${validationCount.voter_filled}" onclick="openCategorySummaryModal('VOTER_FILLED')">0</b> </p>
<p class="mb-0">Not Available : <b class="text-danger fw-700 mt-3 underline-hover" th:text="${validationCount.voter_not_filled}" onclick="openCategorySummaryModal('VOTER_NOT_FILLED')">0</b> </p> </div> </div>
<!– PHONE –> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Phone</b></h6>
<p class="mb-1">Available : <b class="text-success fw-700 mt-3 underline-hover" th:text="${validationCount.phone_filled}" onclick="openCategorySummaryModal('PHONE_FILLED')">0</b> </p>
<p class="mb-0">Not Available : <b class="text-danger fw-700 mt-3 underline-hover" th:text="${validationCount.phone_not_filled}" onclick="openCategorySummaryModal('PHONE_NOT_FILLED')">0</b> </p> </div> </div>
<!– IMAGE –> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Image</b></h6>
<p class="mb-1">Available : <b class="text-success fw-700 mt-3 underline-hover" th:text="${validationCount.image_filled}" onclick="openCategorySummaryModal('IMAGE_FILLED')">0</b> </p>
<p class="mb-0">Not Available : <b class="text-danger fw-700 mt-3 underline-hover" th:text="${validationCount.image_not_filled}" onclick="openCategorySummaryModal('IMAGE_NOT_FILLED')">0</b> </p> </div> </div>-->
<!-- Voter ID Card --> <div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Voter ID</b></h6> <p class="mb-1">Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.voter_filled}">0</b> </p> <p class="mb-0">Not Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.voter_not_filled}">0</b> </p> </div> </div>
<div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Phone</b></h6> <p class="mb-1">Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.phone_filled}">0</b> </p> <p class="mb-0">Not Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.phone_not_filled}">0</b> </p> </div> </div>
<div class="col-md-3"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"><b>Image</b></h6> <p class="mb-1">Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.image_filled}">0</b> </p> <p class="mb-0">Not Available : <b class="text-twitter fw-700 mt-3" th:text="${validationCount.image_not_filled}">0</b> </p> </div> </div>
</div>
</div>
<!-- ================= Central and State Report Count ================= --> <div class="card-body"> <div class="row mt-2"> <div class="col-xl-6 col-sm-12"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>Central Govt Offices</b> </h6> <h4 class="text-twitter fw-700 mt-3 cursor-pointer underline-hover" th:text="${GovtTypeCount.central_count}" onclick="openGovtTypeModal('C')"></h4> <p class="mb-1">No of Applicant : <b class="text-twitter fw-700 mt-3" th:text="${GovtOfficeTypeCount.total_central}">0</b> </p>
</div> </div>
<!-- In-progress Calls --> <div class="col-xl-6 col-sm-12"> <div class="card card-box p-3 text-center h-100"> <h6 class="text-facebook mb-2"> <b>State Govt Offices </b> </h6> <h4 class="text-twitter fw-700 mt-3 cursor-pointer underline-hover" th:text="${GovtTypeCount.state_count}" onclick="openGovtTypeModal('S')"></h4>
<p class="mb-1">No of Applicant : <b class="text-twitter fw-700 mt-3" th:text="${GovtOfficeTypeCount.total_state}">0</b> </p>
</div> </div>
</div> </div>
</div> </div> </div>
</div> </div> <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;"> <div style="position: relative; top: 50%; transform: translateY(-50%);"> <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"> <span class="sr-only">Loading...</span> </div> <!-- Add the 'Please wait' text below the spinner --> <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p> </div> </div>
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> </div> </div>
<div class="modal fade" id="govtTypeModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-xl modal-dialog-centered" role="document"> <div class="modal-content">
<div class="modal-header bg-primary text-white"> <h5 class="modal-title" id="govtTypeModalTitle"></h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body"> <table id="GovtTypeDatatable" class="table table-bordered table-striped w-100"> <thead class="govt-thead"> <tr> <th>S.No</th> <th>Department</th> <th>Office</th> <th>Total Count</th> </tr> </thead> <tbody></tbody> </table>
</div>
</div> </div> </div>
<div class="modal fade" id="govtTypePersonModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-xl modal-dialog-centered" role="document"> <div class="modal-content">
<div class="modal-header bg-dark text-white"> <h5 class="modal-title" id="govtTypePersonModalTitle"></h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body"> <div class="table-responsive"> <table id="GovtTypePersonDatatable" class="table table-bordered table-striped nowrap">
<thead class="govt-thead"> <tr> <th>S.No</th> <th>Unique No</th> <th>Name</th> <th>Sex</th> <th>Mobile</th> <th>Designation</th> <th>Department</th> <th>Office</th> <th>Govt Type</th> <th>Office Address</th> <th>Residential Address</th> <th>Native AC</th> <th>Residential AC</th> <th>Elector AC</th> <th>Working AC</th> </tr> </thead> <tbody></tbody> </table>
</div> </div>
</div> </div> </div>
<!--ak--> <div class="modal fade" id="categorySummaryModal" tabindex="-1"> <div class="modal-dialog modal-xl modal-dialog-centered"> <div class="modal-content">
<div class="modal-header bg-primary text-white"> <h5 class="modal-title" id="categorySummaryTitle"></h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body">
<table id="categorySummaryTable" class="table table-bordered table-striped w-100"> <thead class="bg-dark text-white text-center"> <tr> <th>S.No</th> <th>Constiency</th>
<th>Department</th> <th>Office</th> <th>Total Count</th> </tr> </thead>
<tbody id="categorySummaryBody"></tbody> </table>
</div> </div> </div> </div> <div class="modal fade" id="completedPivotModal" tabindex="-1"> <div class="modal-dialog modal-xl modal-dialog-scrollable"> <div class="modal-content">
<div class="modal-header bg-primary text-white"> <h5 class="modal-title">Completed - Training Centre Summary</h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body"> <div class="table-responsive">
<table id="completedPivotTable" class="table table-bordered text-center"> <thead class="bg-dark text-white"> <tr> <th rowspan="2">S.No</th> <th rowspan="2" class="no-sort text-center">Training Centre</th> <th colspan="4" class="text-center">PO</th> <th colspan="4" class="text-center">PO1</th> <th colspan="4" class="text-center">PO2</th> <th colspan="4" class="text-center">PO3</th> <th colspan="4" class="text-center">PO4</th>
</tr> <tr>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">No Image</th> <th word-wrap="break-word" class="no-sort">NO Phone </th> <th word-wrap="break-word" class="no-sort">NO Voter </th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image </th> <th word-wrap="break-word" class="no-sort">NO Phone </th> <th word-wrap="break-word" class="no-sort">NO Voter </th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image</th> <th word-wrap="break-word" class="no-sort">NO Phone </th> <th word-wrap="break-word" class="no-sort">NO Voter </th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image </th> <th word-wrap="break-word" class="no-sort">NO Phone </th> <th word-wrap="break-word" class="no-sort">NO Voter </th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image </th> <th word-wrap="break-word" class="no-sort">NO Phone </th> <th word-wrap="break-word" class="no-sort">NO Voter </th> </tr> </thead> <tbody id="completedPivotBody"></tbody> </table> </div>
</div> </div> </div> </div> <div class="modal fade" id="hallPivotModal" tabindex="-1"> <div class="modal-dialog modal-xl modal-dialog-scrollable"> <div class="modal-content">
<div class="modal-header bg-primary text-white"> <h5 class="modal-title">Hall Wise Summary</h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body"> <div class="table-responsive">
<table id="hallPivotTable" class="table table-bordered text-center w-100"> <thead class="bg-dark text-white"> <tr> <th rowspan="2">S.No</th> <th rowspan="2" class="no-sort text-center">Hall No</th> <th colspan="4" class="text-center">PO</th> <th colspan="4" class="text-center">PO1</th> <th colspan="4" class="text-center">PO2</th> <th colspan="4" class="text-center">PO3</th> <th colspan="4" class="text-center">PO4</th> </tr> <tr> <th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">No Image</th> <th word-wrap="break-word" class="no-sort">NO Phone</th> <th word-wrap="break-word" class="no-sort">NO Voter</th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image</th> <th word-wrap="break-word" class="no-sort">NO Phone</th> <th word-wrap="break-word" class="no-sort">NO Voter</th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image</th> <th word-wrap="break-word" class="no-sort">NO Phone</th> <th word-wrap="break-word" class="no-sort">NO Voter</th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image</th> <th word-wrap="break-word" class="no-sort">NO Phone</th> <th word-wrap="break-word" class="no-sort">NO Voter</th>
<th word-wrap="break-word" class="no-sort">Total</th> <th word-wrap="break-word" class="no-sort">NO Image</th> <th word-wrap="break-word" class="no-sort">NO Phone</th> <th word-wrap="break-word" class="no-sort">NO Voter</th> </tr> </thead> <tbody id="hallPivotBody"></tbody> </table> </div>
</div> </div> </div> </div> <div class="modal fade" id="personModal" tabindex="-1"> <div class="modal-dialog modal-xl modal-dialog-scrollable"> <div class="modal-content">
<div class="modal-header bg-primary text-white"> <h5 class="modal-title">Person Details</h5> <button type="button" class="close text-white" data-dismiss="modal"> <span>×</span> </button> </div>
<div class="modal-body"> <div class="table-responsive">
<table id="personTable" class="table table-bordered"> <thead> <tr> <th>S.No</th> <th>Unique No</th> <th>Hall NO</th> <th>Name</th> <th>Designation</th> <th>Office Address</th> <th>Mobile</th> <th>Category</th> <th>Photo</th> </tr> </thead> <tbody id="personTableBody"></tbody> </table> </div>
</div> </div> </div> </div>
<!-- DataTables Buttons JS --> <!-- <script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script><script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.print.min.js"></script> -->
<!-- Dependencies --> <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script> -->
<script th:replace="~{fragments/modules/base/script :: script}"></script> <script type="text/javascript"></script>
<script> let govtTypeTable = null;
function openGovtTypeModal(govtType) {
const title = govtType === 'C' ? 'Central Government Details' : 'State Government Details';
$('#govtTypeModalTitle').text(title);
$.ajax({ url: '/election/api/dataentryadmin/dashboard/govt-type-details', type: 'GET', data: { govtType: govtType }, success: function (data) {
if ($.fn.DataTable.isDataTable('#GovtTypeDatatable')) { govtTypeTable.destroy(); $('#GovtTypeDatatable tbody').empty(); }
let rows = ''; data.forEach((row, index) => { rows += ` <tr> <td class="text-center">${index + 1}</td> <td>${row.dept_name ?? '-'}</td> <td>${row.office_address ?? '-'}</td> <td class="text-center"> <a href="javascript:void(0)" class="text-primary fw-bold" onclick="openGovtTypePersonModal( '${govtType}', '${row.dept_name}', '${row.office_name}' )"> ${row.total_count} </a> </td> </tr> `; });
$('#GovtTypeDatatable tbody').html(rows);
// DataTable with Buttons govtTypeTable = $('#GovtTypeDatatable').DataTable({ dom: 'Bftip', autoWidth: false, responsive: false, ordering: true, searching: true, paging: true, pageLength: 10,
buttons: [ { extend: 'copy', text: 'Copy', title: title }, { extend: 'excelHtml5', text: 'Excel', title: title }, { extend: 'csvHtml5', text: 'CSV', title: title }, /* { extend: 'pdfHtml5', text: 'PDF', title: '', orientation: 'landscape', pageSize: 'A4', customize: function (doc) { // Page margins doc.pageMargins = [20, 60, 20, 30]; // Add heading manually doc.content.unshift({ text: title, alignment: 'center', fontSize: 14, bold: true, margin: [0, 0, 0, 12] }); doc.defaultStyle.fontSize = 11; doc.styles.tableHeader.alignment = 'center'; } } */ ],
columnDefs: [ { targets: 0, width: "60px", className: "text-center" }, { targets: 3, width: "120px", className: "text-center" } ] });
govtTypeTable.columns.adjust().draw(); $('#govtTypeModal').modal('show'); }, error: function () { alert('Error loading data'); } }); }
$('#govtTypeModal').on('shown.bs.modal', function () { if (govtTypeTable) { govtTypeTable.columns.adjust(); } }); </script>
<script> let govtTypePersonTable = null;
function openGovtTypePersonModal(govtType, deptName, officeName) {
const govtLabel = govtType === 'C' ? 'Central Government' : 'State Government'; const pdfHeading = govtLabel + ' - ' + deptName + ' - ' + officeName;
$('#govtTypePersonModalTitle').text( govtLabel + ' - ' + deptName + ' - ' + officeName );
$.ajax({ url: '/election/api/dataentryadmin/dashboard/govt-type-person-details', type: 'GET', data: { govtType: govtType, deptName: deptName, officeName: officeName }, success: function (data) {
if ($.fn.DataTable.isDataTable('#GovtTypePersonDatatable')) { govtTypePersonTable.destroy(); $('#GovtTypePersonDatatable tbody').empty(); }
let rows = ''; data.forEach((row, index) => { rows += ` <tr> <td class="text-center">${index + 1}</td> <!-- ✅ S.No --> <td class="text-center">${row.unique_no}</td> <td>${row.name}</td> <td class="text-center">${row.sex ?? ''}</td> <td>${row.r_mobile_no ?? ''}</td> <td>${row.new_designation ?? ''}</td> <td>${row.dept_name ?? ''}</td> <td>${row.office_name ?? ''}</td> <td class="text-center">${row.govt_type}</td> <td>${row.office_address ?? ''}</td> <td>${row.residential_address ?? ''}</td> <td>${row.native_constituency ?? ''}</td> <td>${row.residential_constituency ?? ''}</td> <td>${row.elector_constituency ?? ''}</td> <td>${row.working_constituency ?? ''}</td> </tr> `; });
$('#GovtTypePersonDatatable tbody').html(rows);
const isMobile = window.innerWidth <= 768;
govtTypePersonTable = $('#GovtTypePersonDatatable').DataTable({ dom: 'Bfrtip', // 🔥 Buttons + filter + table + pagination autoWidth: false, responsive: false, ordering: true, searching: true, paging: true, pageLength: 10, fixedHeader: false,
buttons: [ { extend: 'copy', text: 'Copy' }, { extend: 'excelHtml5', text: 'Excel', title: pdfHeading }, { extend: 'csvHtml5', text: 'CSV', title: pdfHeading }, /* { extend: 'pdfHtml5', text: 'PDF', title: '', orientation: 'landscape', pageSize: 'A3', exportOptions: { columns: ':visible' }, customize: function (doc) { // Page setup doc.pageMargins = [10, 50, 10, 20]; doc.defaultStyle.fontSize = 11; // Title doc.content.unshift({ text: pdfHeading, alignment: 'center', fontSize: 14, bold: true, margin: [0, 0, 0, 10] }); // Header style doc.styles.tableHeader.fontSize = 12; doc.styles.tableHeader.alignment = 'center'; // 🔥 IMPORTANT: Adjust column widths doc.content[1].table.widths = [ 30, // S.No 50, // Unique No 85, // Name 30, // Sex 65, // Mobile 80, // Designation 85, // Department 90, // Office 40, // Govt Type 120, // Office Address 120, // Residential Address 60, // Native AC 60, // Residential AC 60, // Elector AC 70 // ✅ Working AC (FIXED WIDTH) ]; // Enable wrapping for all cells doc.content[1].table.body.forEach(function (row, i) { row.forEach(function (cell) { if (typeof cell === 'object') { cell.noWrap = false; } }); }); } } */ ],
columnDefs: [ { width: "60px", targets: 0 }, { width: "90px", targets: 1 }, { width: "180px", targets: 2 }, { width: "60px", targets: 3 }, { width: "120px", targets: 4 }, { width: "200px", targets: 5 }, { width: "220px", targets: 6 }, { width: "250px", targets: 7 }, { width: "80px", targets: 8 }, { width: "260px", targets: 9 }, { width: "260px", targets: 10 }, { width: "140px", targets: 11 }, { width: "140px", targets: 12 }, { width: "140px", targets: 13 }, { width: "140px", targets: 14 } ] });
$('#govtTypePersonModal').modal('show'); }, error: function () { alert('Error loading person details'); } }); }
//ak let categorySummaryTable = null; function openCategorySummaryModal(category) {
$('#categorySummaryTitle').text(category.replaceAll('_', ' '));
$.ajax({ url: '/election/api/dataentryadmin/dashboard/category-summary', type: 'GET', data: { category: category },
success: function (data) { // destroy old table if ($.fn.DataTable.isDataTable('#categorySummaryTable')) { categorySummaryTable.destroy(); $('#categorySummaryBody').empty(); }
let rows = '';
data.forEach((row, index) => {
rows += ` <tr> <td>${index + 1}</td> <td>${row.ac_display ?? ''}</td> <td>${row.dept_name ?? ''}</td> <td>${row.office_address ?? ''}</td> <td class="text-center"> <a href="#" onclick="openCategoryPersonModal( '${category}', '${row.work_ac_no}', '${row.dept_name}', '${row.office_name}' )"> ${row.total_count} </a> </td> </tr> `; });
$('#categorySummaryBody').html(rows); categorySummaryTable = $('#categorySummaryTable').DataTable({ dom: 'Bfrtip', pageLength: 10, ordering: true, searching: true,
buttons: [
{ extend: 'excelHtml5', text: 'Excel', title: category },
{ extend: 'pdfHtml5', text: 'PDF', title: category, orientation: 'landscape', pageSize: 'A4' } ] }); $('#categorySummaryModal').modal('show'); } }); } /*function openCompletedPivotModal() { $('#pageLoader').show(); $.get('/election/api/dataentryadmin/dashboard/training-centre-category-pivot', function(data) { if ($.fn.DataTable.isDataTable('#completedPivotTable')) { $('#completedPivotTable').DataTable().destroy(); } let rows = ''; function getCell(c) { if (!c) return '-'; return ` <div style="text-align:left; font-size:13px; line-height:1.5"> <b>Total:</b> ${c.total}<br> <b>Image Not Filled:</b> ${c.image_not_filled}<br> <b>Phone Not Filled:</b> ${c.phone_not_filled}<br> <b>Voter Not Filled:</b> ${c.voter_not_filled} </div> `; } data.forEach((row, index) => { const cats = row.categories || {}; rows += ` <tr> <td>${index + 1}</td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openHallWiseModal('${row.training_centre_id}')"> ${row.training_centre} </a> </td> <td>${getCell(cats.PO)}</td> <td>${getCell(cats.PO1)}</td> <td>${getCell(cats.PO2)}</td> <td>${getCell(cats.PO3)}</td> <td>${getCell(cats.PO4)}</td> </tr> `; }); $('#completedPivotBody').html(rows); $('#completedPivotTable').DataTable({ dom: 'Bfrtip', buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Training Summary' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Training Summary', orientation: 'landscape' } ] }); $('#pageLoader').hide(); $('#completedPivotModal').modal('show'); }) .fail(function() { $('#pageLoader').hide(); alert("Error loading data"); }); }*/ function openCompletedPivotModal() {
$('#pageLoader').show();
$.get('/election/api/dataentryadmin/dashboard/training-centre-category-pivot', function (data) {
if ($.fn.DataTable.isDataTable('#completedPivotTable')) { $('#completedPivotTable').DataTable().destroy(); }
let rows = '';
// 🔥 return 4 columns function getCells(c) { if (!c) { return `<td>0</td><td>0</td><td>0</td><td>0</td>`; }
return ` <td>${c.total}</td> <td>${c.image_not_filled}</td> <td>${c.phone_not_filled}</td> <td>${c.voter_not_filled}</td> `; }
data.forEach((row, index) => {
const cats = row.categories || {};
rows += ` <tr> <td>${index + 1}</td>
<td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openHallWiseModal('${row.training_centre_id}')"> ${row.training_centre} </a> </td>
${getCells(cats.PO)} ${getCells(cats.PO1)} ${getCells(cats.PO2)} ${getCells(cats.PO3)} ${getCells(cats.PO4)}
</tr> `; });
$('#completedPivotBody').html(rows);
// 🔥 DATATABLE (IMPORTANT SETTINGS) $('#completedPivotTable').DataTable({ destroy: true, fixedHeader: false, dom: 'Bfrtip', scrollX: true, info: true, autoWidth: false, ordering: false, responsive: false, lengthMenu: [ [100, 200, 500, -1], ['100 rows', '200 rows', 'Show all'] ],
columnDefs: [ { width: "150px", targets: 1 }
],
buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Training Summary' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Training Summary', orientation: 'landscape', pageSize: 'A3' } ] });
$('#pageLoader').hide(); $('#completedPivotModal').modal('show');
$('#completedPivotModal').on('shown.bs.modal', function () { setTimeout(() => { $('#completedPivotTable').DataTable().columns.adjust(); }, 200); }); }) .fail(function () { $('#pageLoader').hide(); alert("Error loading data"); }); } /*function openHallWiseModal(centreId) { $('#pageLoader').show(); $.ajax({ url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot', type: 'GET', data: { trainingCentreId: centreId }, success: function(data) { if ($.fn.DataTable.isDataTable('#hallPivotTable')) { $('#hallPivotTable').DataTable().destroy(); } let rows = ''; data.forEach((row, index) => { const cats = row.categories || {}; function cell(c) { if (!c) return '-'; return ` <b>Total:</b> ${c.total}<br> <b>Image Not Filled:</b> ${c.image_not_filled}<br> <b>Phone Not Filled:</b> ${c.phone_not_filled}<br> <b>Voter Not Filled:</b> ${c.voter_not_filled} `; } rows += ` <tr> <td>${index + 1}</td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}', '${row.hall_no}')"> ${row.hall_no} </a> </td> <td>${cell(cats.PO)}</td> <td>${cell(cats.PO1)}</td> <td>${cell(cats.PO2)}</td> <td>${cell(cats.PO3)}</td> <td>${cell(cats.PO4)}</td> </tr> `; }); $('#hallPivotBody').html(rows); $('#hallPivotTable').DataTable({ dom: 'Bfrtip', buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape' } ] }); $('#pageLoader').hide(); $('#hallPivotModal').modal('show'); }, error: function() { $('#pageLoader').hide(); alert("Error loading hall data"); } }); }*/ /*function openHallWiseModal(centreId) { $('#pageLoader').show(); $.ajax({ url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot', type: 'GET', data: { trainingCentreId: centreId }, success: function(data) { if ($.fn.DataTable.isDataTable('#hallPivotTable')) { $('#hallPivotTable').DataTable().destroy(); } let rows = ''; // 🔥 return 4 columns function getCells(c) { if (!c) { return `<td>0</td><td>0</td><td>0</td><td>0</td>`; } return ` <td>${c.total}</td> <td>${c.image_not_filled}</td> <td>${c.phone_not_filled}</td> <td>${c.voter_not_filled}</td> `; } data.forEach((row, index) => { const cats = row.categories || {}; rows += ` <tr> <td>${index + 1}</td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}', '${row.hall_no}')"> ${row.hall_no} </a> </td> ${getCells(cats.PO)} ${getCells(cats.PO1)} ${getCells(cats.PO2)} ${getCells(cats.PO3)} ${getCells(cats.PO4)} </tr> `; }); $('#hallPivotBody').html(rows); // 🔥 SIMPLE DATATABLE (avoid misalignment) $('#hallPivotTable').DataTable({ destroy: true, dom: 'Bfrtip', scrollX: true, autoWidth: false, ordering: false, buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape', pageSize: 'A3' } ] }); $('#pageLoader').hide(); $('#hallPivotModal').modal('show'); // 🔥 FIX ALIGNMENT AFTER MODAL OPEN $('#hallPivotModal').on('shown.bs.modal', function () { setTimeout(() => { $('#hallPivotTable').DataTable().columns.adjust(); }, 200); }); }, error: function() { $('#pageLoader').hide(); alert("Error loading hall data"); } }); }*/ function openHallWiseModal(centreId) {
$('#pageLoader').show();
$.ajax({ url: '/election/api/dataentryadmin/dashboard/hall-wise-pivot', type: 'GET', data: { trainingCentreId: centreId },
success: function (data) {
if ($.fn.DataTable.isDataTable('#hallPivotTable')) { $('#hallPivotTable').DataTable().destroy(); }
let rows = '';
// 🔥 clickable cells /*function getCells(c, hallNo, category) { if (!c) { return `<td>0</td><td>0</td><td>0</td><td>0</td>`; } return ` <td>${c.total}</td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','IMAGE')"> ${c.image_not_filled} </a> </td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','PHONE')"> ${c.phone_not_filled} </a> </td> <td> <a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','VOTER')"> ${c.voter_not_filled} </a> </td> `; }*/ function getCells(c, hallNo, category) {
if (!c) { return `<td>0</td><td>0</td><td>0</td><td>0</td>`; }
return ` <td>${c.total}</td>
<td> ${c.image_not_filled > 0 ? `<a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','IMAGE')"> ${c.image_not_filled} </a>` : `<span>${c.image_not_filled}</span>` } </td>
<td> ${c.phone_not_filled > 0 ? `<a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','PHONE')"> ${c.phone_not_filled} </a>` : `<span>${c.phone_not_filled}</span>` } </td>
<td> ${c.voter_not_filled > 0 ? `<a href="javascript:void(0)" class="text-primary fw-bold text-decoration-underline" onclick="openPersonList('${centreId}','${hallNo}','${category}','VOTER')"> ${c.voter_not_filled} </a>` : `<span>${c.voter_not_filled}</span>` } </td> `; }
data.forEach((row, index) => {
const cats = row.categories || {};
rows += ` <tr> <td>${index + 1}</td> <td>${row.hall_no}</td>
${getCells(cats.PO, row.hall_no, 'PO')} ${getCells(cats.PO1, row.hall_no, 'PO1')} ${getCells(cats.PO2, row.hall_no, 'PO2')} ${getCells(cats.PO3, row.hall_no, 'PO3')} ${getCells(cats.PO4, row.hall_no, 'PO4')}
</tr> `; });
$('#hallPivotBody').html(rows);
$('#hallPivotTable').DataTable({ destroy: true, dom: 'Bfrtip', scrollX: true, autoWidth: false, ordering: false, buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Hall Summary' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Hall Summary', orientation: 'landscape', pageSize: 'A3' } ] });
$('#pageLoader').hide(); $('#hallPivotModal').modal('show');
setTimeout(() => { $('#hallPivotTable').DataTable().columns.adjust(); }, 200); } }); } /*function openPersonList(centreId, hallNo) { $('#pageLoader').show(); $.ajax({ url: '/election/api/dataentryadmin/dashboard/hall-persons', type: 'GET', data: { trainingCentreId: centreId, hallNo: hallNo }, success: function(data) { if ($.fn.DataTable.isDataTable('#personTable')) { $('#personTable').DataTable().destroy(); } let rows = ''; data.forEach((row, index) => { rows += ` <tr> <td>${index + 1}</td> <td>${row.name}</td> <td>${row.designation}</td> <td>${row.office}</td> <td>${row.mobile}</td> <td>${row.category}</td> <td> ${row.img_full_path ? `<img src="${row.img_full_path}" width="60" height="60"/>` : '' } </td> </tr> `; }); $('#personTableBody').html(rows); $('#personTable').DataTable({ dom: 'Bfrtip', buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Person Details' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Person Details', orientation: 'landscape' } ] }); $('#pageLoader').hide(); $('#personModal').modal('show'); } }); }*/
function openPersonList(centreId, hallNo, category, type) {
$('#pageLoader').show();
$.ajax({ url: '/election/api/dataentryadmin/dashboard/hall-persons', type: 'GET', data: { trainingCentreId: centreId, hallNo: hallNo, category: category, type: type },
success: function (data) { console.log(data);
if ($.fn.DataTable.isDataTable('#personTable')) { $('#personTable').DataTable().destroy(); }
let rows = '';
data.forEach((row, index) => {
rows += ` <tr> <td>${index + 1}</td> <td class="text-center">${row.unique_no}</td> <td class="text-center">${row.hall_no}</td> <td class="text-wrap">${row.name}</td> <td>${row.designation}</td> <td>${row.office}</td> <td>${row.mobile || '-'}</td> <td>${row.category}</td>
<td> ${row.img_full_path ? `<img src="${row.img_full_path}" width="60" height="60"/>` : '-' } </td> </tr> `; });
$('#personTableBody').html(rows);
$('#personTable').DataTable({ destroy: true, dom: 'Bfrtip',
scrollX: true, autoWidth: false, lengthMenu: [ [25, 100, 200, 500, -1], ['25 rows', '100 rows', '200 rows', 'Show all'] ], buttons: [ { extend: 'excelHtml5', text: 'Excel', title: 'Person Details' }, { extend: 'pdfHtml5', text: 'PDF', title: 'Person Details', orientation: 'landscape' } ] });
$('#pageLoader').hide(); $('#personModal').modal('show'); } }); }
</script>
</body>
</html>
|