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
+189 -71
View File
@@ -1,8 +1,21 @@
<?= $this->extend('layout/management_layout') ?>
<?= $this->section('content') ?>
<style>
#adminProgressTable thead th {
.admin-progress-table thead th {
position: static !important;
top: auto !important;
z-index: auto !important;
background: #f8f9fa;
white-space: nowrap;
line-height: 1.2;
padding-top: .75rem;
padding-bottom: .75rem;
}
.admin-progress-table td {
vertical-align: top;
}
.bg-orange {
background-color: #fd7e14 !important;
}
</style>
<div class="container py-4">
@@ -12,6 +25,23 @@
<h3 class="mb-0">Class Progress Reports</h3>
<div class="text-muted">Filter by week, class, and status</div>
</div>
<div>
<?php
$lowProgressSectionIds = $lowProgressSectionIds ?? [];
$lowProgressQuery = implode(',', $lowProgressSectionIds);
$lowProgressUrl = base_url('administrator/teacher-submissions');
if ($lowProgressQuery !== '') {
$lowProgressUrl .= '?low_progress_sections=' . rawurlencode($lowProgressQuery);
}
?>
<a
class="btn btn-sm btn-outline-warning <?= empty($lowProgressSectionIds) ? 'disabled' : '' ?>"
href="<?= esc($lowProgressUrl) ?>"
<?= empty($lowProgressSectionIds) ? 'tabindex="-1" aria-disabled="true"' : '' ?>
>
Teachers &lt; 50%
</a>
</div>
</div>
</div>
@@ -56,79 +86,167 @@
</form>
<div class="card shadow-sm mt-5">
<div class="card-body pt-4 px-0">
<div class="table-responsive px-4" style="margin-top: 1.5rem;">
<table id="adminProgressTable" class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>Week</th>
<th>Subjects</th>
<th>Teacher</th>
<th class="text-end">Action</th>
</tr>
</thead>
<tbody>
<div class="card-body pt-4">
<?php
$reportGroupsBySection = $reportGroupsBySection ?? [];
$subjectSections = $subjectSections ?? [];
$classSections = $classSections ?? [];
$sectionStats = $sectionStats ?? [];
$sectionSubjectCounts = $sectionSubjectCounts ?? [];
$expectedDays = (int) ($expectedDays ?? 0);
?>
<?php if (empty($classSections)): ?>
<div class="text-center text-muted py-4">No class sections found.</div>
<?php else: ?>
<div class="accordion" id="adminProgressAccordion">
<?php foreach ($classSections as $index => $cs): ?>
<?php
$reportGroups = $reportGroups ?? [];
$subjectSections = $subjectSections ?? [];
$sectionId = (int) ($cs['class_section_id'] ?? 0);
$sectionName = $cs['class_section_name'] ?? 'Unknown Section';
$sectionGroups = $reportGroupsBySection[$sectionId] ?? [];
$hasReports = ! empty($sectionGroups);
$collapseId = 'progress-section-' . $sectionId;
$headingId = 'progress-heading-' . $sectionId;
$stat = $sectionStats[$sectionId] ?? null;
$subjectCount = (int) ($sectionSubjectCounts[$sectionId] ?? 0);
if (! $stat) {
if ($expectedDays === 0) {
$stat = [
'submitted' => 0,
'expected' => 0,
'percent' => 0,
'badgeClass' => 'bg-secondary',
'labelClass' => 'text-muted',
];
} else {
$stat = [
'submitted' => 0,
'expected' => $expectedDays,
'percent' => 0,
'badgeClass' => 'bg-danger',
'labelClass' => 'text-danger',
];
}
}
$percentLabel = $expectedDays > 0 ? number_format((float) $stat['percent'], 1) . '%' : 'N/A';
$submissionLabel = $expectedDays > 0
? ('Submitted: ' . (int) $stat['submitted'] . ' / ' . (int) $expectedDays . ' (' . $percentLabel . ')')
: 'Submitted: N/A';
$subjectLabel = 'Units: ' . $subjectCount;
?>
<?php if (empty($reportGroups)): ?>
<tr><td colspan="4" class="text-center text-muted py-4">No reports found.</td></tr>
<?php else: ?>
<?php foreach ($reportGroups as $group): ?>
<?php
$weekLabel = $group['week_start'] ? date('M d, Y', strtotime($group['week_start'])) : '-';
if (!empty($group['week_end'])) {
$weekLabel .= ' ' . date('M d, Y', strtotime($group['week_end']));
}
$reports = $group['reports'] ?? [];
$teacherName = '';
foreach ($reports as $report) {
if (!empty($report['teacher_name'])) {
$teacherName = $report['teacher_name'];
break;
}
}
$exampleId = $reports ? reset($reports)['id'] : null;
?>
<tr>
<td>
<div class="fw-semibold"><?= esc($weekLabel) ?></div>
<?php if (!empty($group['class_section_name'])): ?>
<div class="text-muted small">Class: <?= esc($group['class_section_name']) ?></div>
<?php endif; ?>
</td>
<td>
<div class="d-flex flex-column gap-2">
<?php foreach ($subjectSections as $slug => $section): ?>
<?php
$subjectName = $section['db_subject'] ?? $section['label'] ?? $slug;
$report = $reports[$subjectName] ?? null;
$statusTag = $report ? ($report['status_label'] ?? 'Unknown') : 'No entry';
$badgeClass = $report ? 'bg-secondary' : 'bg-light text-muted';
?>
<div class="border rounded-3 p-2">
<div class="d-flex justify-content-between align-items-center">
<strong class="small mb-0"><?= esc($section['label'] ?? $subjectName) ?></strong>
<span class="badge <?= $badgeClass ?>"><?= esc($statusTag) ?></span>
</div>
<div class="small text-muted"><?= $report ? esc($report['unit_title'] ?: '-') : 'No submission' ?></div>
</div>
<?php endforeach; ?>
<div class="accordion-item mb-2">
<h2 class="accordion-header" id="<?= esc($headingId) ?>">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#<?= esc($collapseId) ?>" aria-expanded="false" aria-controls="<?= esc($collapseId) ?>">
<?= esc($sectionName) ?>
<span class="badge <?= esc($stat['badgeClass']) ?> ms-2"><?= esc($submissionLabel) ?></span>
<span class="badge bg-info text-dark ms-2"><?= esc($subjectLabel) ?></span>
<?php if ($hasReports): ?>
<span class="badge bg-secondary ms-2"><?= count($sectionGroups) ?> weeks</span>
<?php endif; ?>
</button>
</h2>
<div id="<?= esc($collapseId) ?>" class="accordion-collapse collapse" aria-labelledby="<?= esc($headingId) ?>" data-bs-parent="#adminProgressAccordion">
<div class="accordion-body">
<?php if (! $hasReports): ?>
<div class="text-muted">No reports found for this section.</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0 admin-progress-table no-mgmt-sticky" data-no-mgmt-sticky>
<thead class="table-light">
<tr>
<th>Week</th>
<th>Subjects</th>
<th>Teacher</th>
<th class="text-end">Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($sectionGroups as $group): ?>
<?php
$weekLabel = $group['week_start'] ? date('M d, Y', strtotime($group['week_start'])) : '-';
if (! empty($group['week_end'])) {
$weekLabel .= ' ' . date('M d, Y', strtotime($group['week_end']));
}
$reports = $group['reports'] ?? [];
$teacherCounts = [];
$teacherLatest = [];
foreach ($reports as $report) {
$name = trim((string) ($report['teacher_name'] ?? ''));
if ($name === '') {
continue;
}
$teacherCounts[$name] = ($teacherCounts[$name] ?? 0) + 1;
$stamp = (string) ($report['updated_at'] ?? $report['created_at'] ?? '');
if ($stamp !== '' && (!isset($teacherLatest[$name]) || $stamp > $teacherLatest[$name])) {
$teacherLatest[$name] = $stamp;
}
}
$teacherLabel = '-';
if (!empty($teacherCounts)) {
$bestName = '';
$bestCount = -1;
$bestStamp = '';
foreach ($teacherCounts as $name => $count) {
$stamp = $teacherLatest[$name] ?? '';
if ($count > $bestCount || ($count === $bestCount && $stamp > $bestStamp)) {
$bestName = $name;
$bestCount = $count;
$bestStamp = $stamp;
}
}
$teacherLabel = $bestName ?: '-';
}
$exampleId = $reports ? reset($reports)['id'] : null;
?>
<tr>
<td><div class="fw-semibold"><?= esc($weekLabel) ?></div></td>
<td>
<div class="d-flex flex-column gap-2">
<?php foreach ($subjectSections as $slug => $section): ?>
<?php
$subjectName = $section['db_subject'] ?? $section['label'] ?? $slug;
$report = $reports[$subjectName] ?? null;
$statusTag = $report ? ($report['status_label'] ?? 'Unknown') : 'No entry';
$badgeClass = $report ? 'bg-secondary' : 'bg-light text-muted';
?>
<div class="border rounded-3 p-2">
<div class="d-flex justify-content-between align-items-center">
<strong class="small mb-0"><?= esc($section['label'] ?? $subjectName) ?></strong>
<span class="badge <?= $badgeClass ?>"><?= esc($statusTag) ?></span>
</div>
<div class="small">
<?php if ($report): ?>
<?= view('admin/partials/class_progress_unit_display', [
'unitTitle' => (string) ($report['unit_title'] ?? ''),
'isQuran' => ($subjectName === 'Quran/Arabic'),
'compact' => true,
]) ?>
<?php else: ?>
<span class="text-muted">No submission</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</td>
<td><?= esc($teacherLabel) ?></td>
<td class="text-end">
<?php if ($exampleId): ?>
<a class="btn btn-sm btn-outline-primary" href="<?= base_url('admin/progress/view/' . $exampleId) ?>">View</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</td>
<td><?= esc($teacherName ?: '-') ?></td>
<td class="text-end">
<?php if ($exampleId): ?>
<a class="btn btn-sm btn-outline-primary" href="<?= base_url('admin/progress/view/' . $exampleId) ?>">View</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
+7 -2
View File
@@ -39,7 +39,6 @@
<?php
$subjectName = $section['db_subject'] ?? $section['label'] ?? $slug;
$isQuran = $subjectName === 'Quran/Arabic';
$unitLabel = $isQuran ? 'Surah / Custom Arabic' : 'Unit / Chapter';
$homeworkLabel = $isQuran ? 'Arabic Practice / Homework' : 'Assigned Homework';
$report = $reportsBySubject[$subjectName] ?? null;
?>
@@ -51,7 +50,13 @@
<?php if (! $report): ?>
<div class="text-muted">No entry submitted for this subject this week.</div>
<?php else: ?>
<div class="mb-2"><strong><?= $unitLabel ?>:</strong> <?= esc($report['unit_title'] ?: '-') ?></div>
<div class="mb-2">
<?= view('admin/partials/class_progress_unit_display', [
'unitTitle' => (string) ($report['unit_title'] ?? ''),
'isQuran' => $isQuran,
'compact' => false,
]) ?>
</div>
<?php if (!empty($report['materials'])): ?>
<div class="mb-2"><strong>Materials:</strong> <?= esc($report['materials']) ?></div>
<?php endif; ?>
View File
View File
View File
View File
View File
+48
View File
@@ -0,0 +1,48 @@
<?php
/**
* Renders class progress unit_title with explicit curriculum vs custom subject lines.
*
* @var string $unitTitle
* @var bool $isQuran
* @var bool $compact If true, tighter layout for the list accordion.
*/
use App\Controllers\ClassProgressController;
$unitTitle = trim((string) ($unitTitle ?? ''));
$compact = ! empty($compact);
$isQuran = ! empty($isQuran);
$split = ClassProgressController::splitUnitTitleForDisplay($unitTitle);
$curriculumLines = $split['curriculum'];
$customTopics = $split['custom'];
$labelCurriculum = $isQuran ? 'Surah / curriculum' : 'Unit / chapter';
$labelCustom = $isQuran ? 'Custom Surah / Arabic' : 'Custom subject(s)';
?>
<?php if ($unitTitle === ''): ?>
<span class="text-muted">-</span>
<?php elseif ($compact): ?>
<?php if (! empty($customTopics)): ?>
<div class="small">
<span class="badge text-bg-info me-1"><?= $isQuran ? 'Custom' : 'Custom subject' ?></span><?= esc(implode(', ', $customTopics)) ?>
</div>
<?php endif; ?>
<?php if (! empty($curriculumLines)): ?>
<div class="small <?= ! empty($customTopics) ? 'text-muted mt-1' : 'text-muted' ?>"><?= esc(implode(' · ', $curriculumLines)) ?></div>
<?php endif; ?>
<?php if (empty($customTopics) && empty($curriculumLines)): ?>
<div class="small text-muted"><?= esc($unitTitle) ?></div>
<?php endif; ?>
<?php else: ?>
<?php if (! empty($curriculumLines)): ?>
<div class="mb-2"><strong><?= esc($labelCurriculum) ?>:</strong> <?= esc(implode(' ; ', $curriculumLines)) ?></div>
<?php endif; ?>
<?php if (! empty($customTopics)): ?>
<div class="mb-2"><strong><?= esc($labelCustom) ?>:</strong> <?= esc(implode(' ; ', $customTopics)) ?></div>
<?php endif; ?>
<?php if (empty($curriculumLines) && empty($customTopics)): ?>
<div class="mb-2"><strong><?= esc($labelCurriculum) ?>:</strong> <?= esc($unitTitle) ?></div>
<?php endif; ?>
<?php endif; ?>
View File