@ -97,13 +97,11 @@
overflow-x: auto !important;
}
/* IMPORTANT */
/* Force Absolute DataTables Dimensions, overriding JS calculations */
.dataTables_scrollHeadInner,
.report-container table.dataTable {
/* width: max-content !important; */
width: 100% !important;
/* ✅ instead of max-content */
/* force table to expand */
min-width: 100% !important;
width: max-content !important;
}
/* Sticky columns background fix */
@ -118,7 +116,7 @@
.report-container table.dataTable tbody tr.grand-total-row td.dtfc-fixed-left {
background-color: #003366 !important;
color: #fff !important;
color: #826969 !important;
}
.dataTables_scrollBody::-webkit-scrollbar {
@ -141,6 +139,7 @@
}
/* Modal tweaks */
#detailModal .modal-content {
border-radius: 8px;
}
@ -215,29 +214,28 @@
< / div >
< div class = "report-container" >
< div style = "overflow-x:auto;" >
< table id = "ComplianceAbstractTable" class = "table table-striped table-bordered display nowrap" >
< thead >
< tr id = "header-row-1" >
< th rowspan = "3" style = "vertical-align: middle;" > Zone< / th >
< th rowspan = "3"
style="vertical-align: middle; white-space: normal; min-width: 250px; max-width: 350px;">
Kitchen Name / Address< / th >
< th rowspan = "3" style = "vertical-align: middle;" > Shift< / th >
<!-- Category Headers will be appended here via JS -->
< / tr >
< tr id = "header-row-2" >
<!-- Questions sub - headers will be appended here via JS -->
< / tr >
< tr id = "header-row-3" class = "sub-header" >
<!-- Issue/No Issue sub - headers will be appended here via JS -->
< / tr >
< / thead >
< tbody >
<!-- Populated via JS -->
< / tbody >
< / table >
< / div >
< table id = "ComplianceAbstractTable" class = "table table-striped table-bordered display nowrap"
style="width:100%;">
< thead >
< tr id = "header-row-1" >
< th rowspan = "3" style = "vertical-align: middle;" > Zone< / th >
< th rowspan = "3"
style="vertical-align: middle; white-space: normal; min-width: 250px; max-width: 350px;">
Kitchen Name / Address< / th >
< th rowspan = "3" style = "vertical-align: middle;" > Shift< / th >
<!-- Category Headers will be appended here via JS -->
< / tr >
< tr id = "header-row-2" >
<!-- Questions sub - headers will be appended here via JS -->
< / tr >
< tr id = "header-row-3" class = "sub-header" >
<!-- Issue/No Issue sub - headers will be appended here via JS -->
< / tr >
< / thead >
< tbody >
<!-- Populated via JS -->
< / tbody >
< / table >
< / div >
<!-- Details Modal -->
@ -273,6 +271,7 @@
< th class = "text-center" > CE Status< / th >
< th class = "text-center" > CE Remarks< / th >
< th class = "text-center" > CE Updated By< / th >
< th class = "text-center" > Penalty Amount< / th >
< / tr >
< / thead >
< tbody id = "modalTableBody" >
@ -308,6 +307,8 @@
< script src = "https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js" > < / script >
< script src = "https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/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 src = "https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js" > < / script >
< script src = "https://cdn.datatables.net/fixedcolumns/4.2.2/js/dataTables.fixedColumns.min.js" > < / script >
@ -364,7 +365,8 @@
{ width: "150px", targets: 16 }, // fsImgBtn
{ width: "120px", targets: 17 }, // CE Status
{ width: "220px", targets: 18 }, // CE Remarks
{ width: "150px", targets: 19 } // Chief Engineer
{ width: "150px", targets: 19 }, // Chief Engineer
{ width: "150px", targets: 20 } // Penalty Amount
],
responsive: false,
scrollX: true,
@ -373,7 +375,48 @@
searching: true,
paging: true,
info: true,
ordering: false
ordering: false,
dom: '< "d-flex justify-content-between align-items-center mb-2"lfB>rtip',
buttons: [
{
extend: 'excelHtml5',
text: 'Excel',
className: 'btn btn-success btn-sm',
exportOptions: {
format: {
body: function (data, row, column, node) {
if (typeof data === 'string' & & data.indexOf('showMedia') !== -1) {
var match = data.match(/showMedia\('([^']+)'/);
if (match) return match[1];
}
var div = document.createElement("div");
div.innerHTML = data;
return div.textContent || div.innerText || "";
}
}
}
},
{
extend: 'pdfHtml5',
text: 'PDF',
className: 'btn btn-danger btn-sm',
orientation: 'landscape',
pageSize: 'A3',
exportOptions: {
format: {
body: function (data, row, column, node) {
if (typeof data === 'string' & & data.indexOf('showMedia') !== -1) {
var match = data.match(/showMedia\('([^']+)'/);
if (match) return match[1];
}
var div = document.createElement("div");
div.innerHTML = data;
return div.textContent || div.innerText || "";
}
}
}
}
]
});
// 1) Fetch categories first
@ -477,6 +520,8 @@
// Add Total column header
hr1.append('< th rowspan = "3" style = "vertical-align: middle; background-color: #003366 !important; color: white !important; min-width: 120px;" > Total Issue Found< / th > ');
hr1.append('< th rowspan = "3" style = "vertical-align: middle; background-color: #003366 !important; color: white !important; min-width: 120px;" > Penalty Initiated< / th > ');
hr1.append('< th rowspan = "3" style = "vertical-align: middle; background-color: #003366 !important; color: white !important; min-width: 120px;" > Penalty Amount< / th > ');
}
function loadAbstractReport() {
@ -564,6 +609,8 @@
var hubGroups = {};
var questionTotals = {};
var grandTotal = 0;
var grandTotalInit = 0;
var grandTotalAmt = 0;
data.forEach(function (row) {
var kId = row.hub_id;
@ -590,11 +637,16 @@
var qId = row.qid;
if (qId) {
if (!hubGroups[kId].shifts[shiftId].counts[qId]) {
hubGroups[kId].shifts[shiftId].counts[qId] = { 'Issue Found': 0, 'No Issue': 0, 'fs_review': 0 };
hubGroups[kId].shifts[shiftId].counts[qId] = { 'Issue Found': 0, 'No Issue': 0, 'fs_review': 0, 'penalty_initiated': 0, 'penalty_amount': 0, 'pending_count': 0 };
}
var s = row.answer_status;
if (s === 'Issue Found' || s === 'No Issue') {
hubGroups[kId].shifts[shiftId].counts[qId][s] += row.issue_count;
if (s === 'Issue Found') {
hubGroups[kId].shifts[shiftId].counts[qId]['penalty_initiated'] += (row.penalty_initiated || 0);
hubGroups[kId].shifts[shiftId].counts[qId]['penalty_amount'] += (row.penalty_amount || 0);
hubGroups[kId].shifts[shiftId].counts[qId]['pending_count'] += (row.pending_count || 0);
}
if (row.fs_review_count & & row.fs_review_count > 0) {
hubGroups[kId].shifts[shiftId].counts[qId]['fs_review'] += row.fs_review_count;
}
@ -626,14 +678,20 @@
// Loop in the same order as headers
var totalIssues = 0;
var shiftTotalInit = 0;
var shiftTotalAmt = 0;
var shiftPendingCount = 0;
Object.values(groupedCategories).forEach(function (cat) {
cat.questions.forEach(function (q) {
var counts = shift.counts[q.qid] || { 'Issue Found': 0 };
var counts = shift.counts[q.qid] || { 'Issue Found': 0, 'penalty_initiated': 0, 'penalty_amount': 0, 'pending_count': 0 };
var issueCount = counts['Issue Found'] || 0;
var fsRevCount = counts['fs_review'] || 0;
totalIssues += issueCount;
shiftTotalInit += (counts['penalty_initiated'] || 0);
shiftTotalAmt += (counts['penalty_amount'] || 0);
shiftPendingCount += (counts['pending_count'] || 0);
questionTotals[q.qid] = (questionTotals[q.qid] || 0) + issueCount;
var textVal = issueCount > 0 ? '< span class = "clickable-cell" ' + ( fsRevCount > 0 ? 'style="color: red;"' : '') + ' data-hubid="' + hub.hub_id + '" data-shiftid="' + shift.shift_id + '" data-qid="' + q.qid + '" data-status="Issue Found">' + issueCount + '< / span > ' : '';
@ -644,9 +702,16 @@
});
tr.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.1em; color: #dc3545;" > ' + (totalIssues > 0 ? totalIssues : '') + '< / td > ');
tr.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.1em; color: #dc3545;" > ' + (shiftTotalInit > 0 ? shiftTotalInit : '') + '< / td > ');
var amtText = shiftTotalAmt > 0 ? shiftTotalAmt : '';
tr.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.1em; color: #dc3545;" > ' + amtText + '< / td > ');
tbody.append(tr);
grandTotal += totalIssues;
grandTotalInit += shiftTotalInit;
grandTotalAmt += shiftTotalAmt;
});
});
@ -664,6 +729,8 @@
});
totalRow.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.25em; color: #dc3545; background-color: #f8d7da;" > ' + (grandTotal > 0 ? grandTotal : '') + '< / td > ');
totalRow.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.25em; color: #dc3545; background-color: #f8d7da;" > ' + (grandTotalInit > 0 ? grandTotalInit : '') + '< / td > ');
totalRow.append('< td class = "text-center align-middle" style = "font-weight: bold; font-size: 1.25em; color: #dc3545; background-color: #f8d7da;" > ' + (grandTotalAmt > 0 ? grandTotalAmt : '') + '< / td > ');
tbody.append(totalRow);
}
@ -686,6 +753,25 @@
fsImgBtn = '< button onclick = "showMedia(\'' + item.fsVideoLink + '\', ' + isFsVideo + ')" class = "btn btn-sm btn-info text-white" > < i class = "fa fa-' + (isFsVideo ? 'video' : 'image') + '" > < / i > View< / button > ';
}
var fsStsStr = (item.fsStatus || '').toLowerCase();
var ceStsStr = (item.chief_engineer_status || '').toLowerCase();
var pAmt = parseInt(item.penalty_amt) || 0;
var finalPenalty = pAmt;
if (item.english_name === 'Issue Found') {
if (fsStsStr === 'challenge' & & ceStsStr === 'reject') {
finalPenalty = pAmt;
} else if (fsStsStr === 'accept') {
finalPenalty = pAmt;
} else if (fsStsStr === 'challenge' & & ceStsStr === 'accept') {
finalPenalty = '-';
} else if (fsStsStr === 'challenge' & & (ceStsStr === '' || ceStsStr === '-')) {
finalPenalty = 'Pending';
}
} else {
finalPenalty = '-';
}
modalTable.row.add([
index + 1,
item.auditDate || '-',
@ -706,7 +792,8 @@
fsImgBtn,
item.chief_engineer_status || '-',
item.chief_engineer_remarks || '-',
item.chief_engineer || '-'
item.chief_engineer || '-',
finalPenalty
]);
});
modalTable.draw();
@ -855,6 +942,7 @@
}
});
// Recalculate precisely after Bootstrap entirely finishes destroying modal padding
< / script >
< / body >