merge prod to main

This commit is contained in:
root
2026-05-16 13:44:12 -04:00
parent 663c0cdbda
commit b32fb853f6
901 changed files with 11241 additions and 1340 deletions
+102 -1
View File
@@ -71,9 +71,20 @@
max-height: none;
overflow: visible;
}
.attn-pie-wrap {
width: 320px;
height: 320px;
margin: 0 auto;
}
@media (max-width: 1200px) {
.attn-analysis-half { grid-column: span 12; }
}
@media (max-width: 576px) {
.attn-pie-wrap {
width: 180px;
height: 180px;
}
}
</style>
<?= $this->endSection() ?>
@@ -239,6 +250,54 @@
$analysisSectionTotals[] = (int)($s['total_students'] ?? 0);
}
// ---- Student absences/late list ----
$sectionLabelByKey = [];
foreach ($grades as $classId => $sections) {
foreach ($sections as $section) {
$sectionKey = (string)($section['class_section_id'] ?? ($section['id'] ?? ''));
if ($sectionKey === '') continue;
$secNameRaw = trim((string)($section['class_section_name'] ?? ''));
$sectionLabelByKey[$sectionKey] = $secNameRaw !== '' ? $secNameRaw : ('Section ' . $sectionKey);
}
}
$studentIssueRows = [];
foreach ($studentsBySection as $sectionKey => $students) {
foreach ($students as $stu) {
$sid = (int)($stu['id'] ?? 0);
if ($sid <= 0) continue;
$entries = $attendanceData[$sectionKey][$sid] ?? [];
if (!is_array($entries)) continue;
$abs = 0;
$late = 0;
foreach ($entries as $e) {
$d = substr((string)($e['date'] ?? ''), 0, 10);
if ($d === '') continue;
if ($filterStart !== '' && $d < $filterStart) continue;
if ($filterEnd !== '' && $d > $filterEnd) continue;
$st = strtolower(trim((string)($e['status'] ?? '')));
if ($st === 'absent') {
$abs++;
} elseif ($st === 'late') {
$late++;
}
}
if (($abs + $late) <= 0) continue;
$studentIssueRows[] = [
'name' => trim((string)($stu['firstname'] ?? '') . ' ' . (string)($stu['lastname'] ?? '')),
'section' => $sectionLabelByKey[(string)$sectionKey] ?? ('Section ' . $sectionKey),
'absent' => $abs,
'late' => $late,
];
}
}
usort($studentIssueRows, static function ($a, $b) {
$sec = strcmp($a['section'], $b['section']);
if ($sec !== 0) return $sec;
return strcmp($a['name'], $b['name']);
});
$totalDaysForPercent = 0;
if ($filterStart === '' && $filterEnd === '' && !empty($totalPassedDays)) {
$totalDaysForPercent = (int)$totalPassedDays;
@@ -291,7 +350,9 @@
<div class="attn-analysis-grid">
<div class="attn-analysis-card attn-analysis-half">
<h6>Overall Distribution</h6>
<canvas id="attnPieChart" height="50" aria-label="Overall attendance pie chart"></canvas>
<div class="attn-pie-wrap">
<canvas id="attnPieChart" aria-label="Overall attendance pie chart"></canvas>
</div>
<table class="attn-analysis-table mt-3 no-mgmt-sticky" data-no-mgmt-sticky>
<thead>
<tr>
@@ -360,6 +421,37 @@
</table>
</div>
</div>
<div class="attn-analysis-card attn-analysis-wide">
<h6>Students With Absences / Late</h6>
<div class="attn-analysis-scroll">
<table id="studentIssueTable" class="attn-analysis-table no-mgmt-sticky" data-no-mgmt-sticky>
<thead>
<tr>
<th>Student Name</th>
<th>Class Section</th>
<th class="text-end">Nbr of ABS</th>
<th class="text-end">Nbr of LATE</th>
</tr>
</thead>
<tbody>
<?php if (empty($studentIssueRows)): ?>
<tr>
<td colspan="4" class="text-center text-muted">No absences or late records in the selected range.</td>
</tr>
<?php else: ?>
<?php foreach ($studentIssueRows as $row): ?>
<tr>
<td><?= esc($row['name']) ?></td>
<td><?= esc($row['section']) ?></td>
<td class="text-end"><?= (int)$row['absent'] ?></td>
<td class="text-end"><?= (int)$row['late'] ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@@ -415,6 +507,8 @@
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
@@ -465,6 +559,13 @@
info: false,
order: [[0, 'asc']]
});
$('#studentIssueTable').DataTable({
paging: true,
searching: true,
info: true,
order: [[1, 'asc'], [0, 'asc']],
pageLength: 25
});
}
});
</script>