@ -289,7 +289,9 @@
// const supervisor = Number(r.SupervisorCount) || 0;
// const supervisor = Number(r.SupervisorCount) || 0;
html += `< tr > < td > ${zone || '-'}< / td > `;
html += `< tr > < td > ${zone || '-'}< / td > `;
html += `< td class = "text-center" > ${total}< / td > `;
html += `< td class = "text-center" > ` + (total > 0
? `< a href = "#" class = "zone-count" data-zone = "${zone}" data-emptype = "${empType}" data-category = "total" > ${total}< / a > `
: `< span class = "disabled-count" > ${total}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ${facialRegistered}< / td > `;
html += `< td class = "text-center" > ${facialRegistered}< / td > `;
html += `< td class = "text-center" > ` + (facialNotRegistered > 0
html += `< td class = "text-center" > ` + (facialNotRegistered > 0
? `< a href = "#" class = "zone-count" data-zone = "${zone}" data-emptype = "${empType}" data-category = "notregistered" > ${facialNotRegistered}< / a > `
? `< a href = "#" class = "zone-count" data-zone = "${zone}" data-emptype = "${empType}" data-category = "notregistered" > ${facialNotRegistered}< / a > `
@ -437,10 +439,38 @@
if (!Array.isArray(data)) { modalBody.innerText = JSON.stringify(data); return; }
if (!Array.isArray(data)) { modalBody.innerText = JSON.stringify(data); return; }
if (data.length === 0) { modalBody.innerHTML = '< div class = "alert alert-info" > No park-wise records< / div > '; return; }
if (data.length === 0) { modalBody.innerHTML = '< div class = "alert alert-info" > No park-wise records< / div > '; return; }
// Filter parks: when a category is selected, only show parks with count > 0 for that category
const catLower = (category || '').toLowerCase();
const displayData = !catLower ? data : data.filter(r => {
const total = Number(r.TotalCount) || 0;
const present = Number(r.AttendanceMarked) || 0;
const od = Number(r.ODCount) || 0;
const leave = Number(r.LeaveCount) || 0;
const facialNotRegistered = Number(r.facialNotRegistered) || 0;
const notMarked = Math.max(0, total - present - od - leave - facialNotRegistered);
if (catLower === 'total') return total > 0;
if (catLower === 'present') return present > 0;
if (catLower === 'od') return od > 0;
if (catLower === 'leave') return leave > 0;
if (catLower === 'notmarked') return notMarked > 0;
if (catLower === 'notregistered') return facialNotRegistered > 0;
return true;
});
if (displayData.length === 0) { modalBody.innerHTML = '< div class = "alert alert-info" > No parks with ' + (category || '').toUpperCase() + ' count< / div > '; return; }
const showAll = !catLower;
let html = '< div class = "table-responsive" > < table class = "table table-sm table-striped" > < thead > < tr > ';
let html = '< div class = "table-responsive" > < table class = "table table-sm table-striped" > < thead > < tr > ';
html += '< th style = "display:none;" > Park ID< / th > < th > Park Name< / th > < th > Supervisor Name< / th > < th > Supervisor Mobile< / th > < th class = "text-center" > Total< / th > < th class = "text-center" > Facial Registered< / th > < th class = "text-center" > Facial Not Registered< / th > < th class = "text-center" > Present< / th > < th class = "text-center" > OD< / th > < th class = "text-center" > Leave< / th > < th class = "text-center" > Not Marked< / th > ';
html += '< th style = "display:none;" > Park ID< / th > < th > Park Name< / th > < th > Supervisor Name< / th > < th > Supervisor Mobile< / th > ';
if (showAll) {
html += '< th class = "text-center" > Total< / th > < th class = "text-center" > Facial Registered< / th > < th class = "text-center" > Facial Not Registered< / th > < th class = "text-center" > Present< / th > < th class = "text-center" > OD< / th > < th class = "text-center" > Leave< / th > < th class = "text-center" > Not Marked< / th > ';
} else {
const categoryLabel = { present: 'Present', od: 'OD', leave: 'Leave', notmarked: 'Not Marked', notregistered: 'Facial Not Registered' };
html += `< th class = "text-center" > ${categoryLabel[catLower] || category}< / th > `;
}
html += '< / tr > < / thead > < tbody > ';
html += '< / tr > < / thead > < tbody > ';
data.forEach(r => {
displayD ata.forEach(r => {
const parkId = r.park_id || '';
const parkId = r.park_id || '';
const park = r.park_name || '';
const park = r.park_name || '';
const parkDisplay = park === '' ? (parkId || 'Unknown') : park;
const parkDisplay = park === '' ? (parkId || 'Unknown') : park;
@ -458,19 +488,29 @@
html += `< td > ${parkDisplay}< / td > `;
html += `< td > ${parkDisplay}< / td > `;
html += `< td > ${supervisorName}< / td > `;
html += `< td > ${supervisorName}< / td > `;
html += `< td > ${supervisorMobile}< / td > `;
html += `< td > ${supervisorMobile}< / td > `;
if (showAll) {
html += `< td class = "text-center" > ${total}< / td > `;
html += `< td class = "text-center" > ${total}< / td > `;
html += `< td class = "text-center" > ${facialRegistered}< / td > `;
html += `< td class = "text-center" > ${facialRegistered}< / td > `;
// html += `< td class = "text-center" > ${facialNotRegistered}< / td > `;
html += `< td class = "text-center" > ` + (facialNotRegistered > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "notregistered" > ${facialNotRegistered}< / a > ` : `< span class = "disabled-count" > ${facialNotRegistered}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (facialNotRegistered > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "notregistered" > ${facialNotRegistered}< / a > ` : `< span class = "disabled-count" > ${facialNotRegistered}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (present > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "present" > ${present}< / a > ` : `< span class = "disabled-count" > ${present}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (present > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "present" > ${present}< / a > ` : `< span class = "disabled-count" > ${present}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (od > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "od" > ${od}< / a > ` : `< span class = "disabled-count" > ${od}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (od > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "od" > ${od}< / a > ` : `< span class = "disabled-count" > ${od}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (leave > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "leave" > ${leave}< / a > ` : `< span class = "disabled-count" > ${leave}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (leave > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "leave" > ${leave}< / a > ` : `< span class = "disabled-count" > ${leave}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (notMarked > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "notmarked" > ${notMarked}< / a > ` : `< span class = "disabled-count" > ${notMarked}< / span > `) + `< / td > `;
html += `< td class = "text-center" > ` + (notMarked > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "notmarked" > ${notMarked}< / a > ` : `< span class = "disabled-count" > ${notMarked}< / span > `) + `< / td > `;
} else {
// Show only the selected category column
let catValue = 0;
if (catLower === 'present') catValue = present;
else if (catLower === 'od') catValue = od;
else if (catLower === 'leave') catValue = leave;
else if (catLower === 'notmarked') catValue = notMarked;
else if (catLower === 'notregistered') catValue = facialNotRegistered;
html += `< td class = "text-center" > ` + (catValue > 0 ? `< a href = "#" class = "park-employee-count" data-zone = "${zone}" data-parkid = "${parkId}" data-parkname = "${parkDisplay}" data-category = "${catLower}" > ${catValue}< / a > ` : `< span class = "disabled-count" > ${catValue}< / span > `) + `< / td > `;
}
html += '< / tr > ';
html += '< / tr > ';
});
});
// Compute grand totals for park-wise summary
let grandTotal = 0, grandSupervisor = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
// Compute grand totals from ALL data to match zone summary (no count mismatch)
let grandTotal = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
data.forEach(r => {
data.forEach(r => {
const total = Number(r.TotalCount) || 0;
const total = Number(r.TotalCount) || 0;
const facialRegistered = Number(r.facialRegistered) || 0;
const facialRegistered = Number(r.facialRegistered) || 0;
@ -490,6 +530,7 @@
html += '< td > Total< / td > ';
html += '< td > Total< / td > ';
html += '< td > < / td > ';
html += '< td > < / td > ';
html += '< td > < / td > ';
html += '< td > < / td > ';
if (showAll) {
html += `< td class = "text-center" > ${grandTotal}< / td > `;
html += `< td class = "text-center" > ${grandTotal}< / td > `;
html += `< td class = "text-center" > ${grandFacialReg}< / td > `;
html += `< td class = "text-center" > ${grandFacialReg}< / td > `;
html += `< td class = "text-center" > ${grandFacialNotReg}< / td > `;
html += `< td class = "text-center" > ${grandFacialNotReg}< / td > `;
@ -497,6 +538,15 @@
html += `< td class = "text-center" > ${grandOd}< / td > `;
html += `< td class = "text-center" > ${grandOd}< / td > `;
html += `< td class = "text-center" > ${grandLeave}< / td > `;
html += `< td class = "text-center" > ${grandLeave}< / td > `;
html += `< td class = "text-center" > ${grandNotMarked}< / td > `;
html += `< td class = "text-center" > ${grandNotMarked}< / td > `;
} else {
let grandCatValue = 0;
if (catLower === 'present') grandCatValue = grandPresent;
else if (catLower === 'od') grandCatValue = grandOd;
else if (catLower === 'leave') grandCatValue = grandLeave;
else if (catLower === 'notmarked') grandCatValue = grandNotMarked;
else if (catLower === 'notregistered') grandCatValue = grandFacialNotReg;
html += `< td class = "text-center" > ${grandCatValue}< / td > `;
}
html += '< / tr > < / tfoot > < / table > < / div > ';
html += '< / tr > < / tfoot > < / table > < / div > ';
modalBody.innerHTML = html;
modalBody.innerHTML = html;
} catch (e) {
} catch (e) {
@ -583,7 +633,9 @@
let displayColumns = [];
let displayColumns = [];
const catLower = (category || 'present').toLowerCase();
const catLower = (category || 'present').toLowerCase();
if (catLower === 'present') {
if (catLower === 'total') {
displayColumns = ['park_name', 'supervisor_name', 'supervisor_mobile', 'enrollment_id', 'name', 'emp_mobile'];
} else if (catLower === 'present') {
displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno', 'App Version', 'App Type', 'Location'];
displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno', 'App Version', 'App Type', 'Location'];
if (empType === 'Park') displayColumns.push('park_name');
if (empType === 'Park') displayColumns.push('park_name');
displayColumns.push('intime', 'inphoto', 'outtime', 'outphoto');
displayColumns.push('intime', 'inphoto', 'outtime', 'outphoto');
@ -642,6 +694,9 @@
location: 'Location',
location: 'Location',
image: 'Image',
image: 'Image',
supervisor_id: 'Supervisor ID',
supervisor_id: 'Supervisor ID',
supervisor_name: 'Supervisor Name',
supervisor_mobile: 'Supervisor Mobile',
emp_mobile: 'Employee Mobile',
};
};
if (map[key]) return map[key];
if (map[key]) return map[key];
return key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
return key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
@ -715,8 +770,8 @@
const zone = zoneAnchor.getAttribute('data-zone');
const zone = zoneAnchor.getAttribute('data-zone');
const empType = zoneAnchor.getAttribute('data-emptype');
const empType = zoneAnchor.getAttribute('data-emptype');
const category = zoneAnchor.getAttribute('data-category');
const category = zoneAnchor.getAttribute('data-category');
// Supervisor: show employee details directly (no park-wise drill-down)
if (category === 'supervisor') {
// Supervisor & Total : show employee details directly (no park-wise drill-down)
if (category === 'supervisor' || category === 'total' ) {
loadDetailed(empType, category, zone);
loadDetailed(empType, category, zone);
} else if (empType === 'Park') {
} else if (empType === 'Park') {
loadParkWiseSummary(zone, category);
loadParkWiseSummary(zone, category);