Compare commits

..

2 Commits

Author SHA1 Message Date
Administrator d158650be9 Merge branch 'develop_fix_expenses' into 'develop'
Fixed the date shift by making date-only strings stay in the user timezone...

See merge request root/alrahma_sunday_school!5
2026-04-02 04:05:31 +00:00
root 61facee902 fix the exam draft 2026-04-02 00:03:59 -04:00
6 changed files with 111 additions and 39 deletions
@@ -98,6 +98,10 @@ class ClassProgressController extends BaseController
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
}
if (! $this->hasIslamicUnitSelection()) {
return redirect()->back()->withInput()->with('error', 'Please select at least one Islamic Studies unit.');
}
$attachmentErrors = $this->validateAttachmentFiles($subjectSections);
if (! empty($attachmentErrors)) {
return redirect()->back()->withInput()->with('errors', $attachmentErrors);
@@ -431,6 +435,10 @@ class ClassProgressController extends BaseController
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
}
if (! $this->hasIslamicUnitSelection()) {
return redirect()->back()->withInput()->with('error', 'Please select at least one Islamic Studies unit.');
}
$attachmentErrors = $this->validateAttachmentFiles($subjectSections);
if (! empty($attachmentErrors)) {
return redirect()->back()->withInput()->with('errors', $attachmentErrors);
@@ -694,6 +702,17 @@ class ClassProgressController extends BaseController
return mb_strlen($summary) > 120 ? mb_substr($summary, 0, 120) : $summary;
}
protected function hasIslamicUnitSelection(): bool
{
$unitValues = array_map('trim', (array) $this->request->getPost('unit_islamic'));
foreach ($unitValues as $value) {
if ($value !== '') {
return true;
}
}
return false;
}
protected function parseUnitChapterSummary(string $summary): array
{
$summary = trim($summary);
+42 -31
View File
@@ -240,23 +240,23 @@ class ExamDraftController extends BaseController
// Group legacy uploads (admin-uploaded finalized exams) by class_section for separate tab
$legacyByClass = [];
if ($this->hasIsLegacyColumn) {
// Keep all submissions visible; additionally surface legacy items in a separate tab
$drafts = $allDrafts;
// Keep legacy items out of the main submissions list; show them in the legacy tab only.
$drafts = [];
foreach ($allDrafts as $d) {
$isLegacy = !empty($d['is_legacy']);
if (!$isLegacy) {
if ($isLegacy) {
$cid = (int)($d['class_section_id'] ?? 0);
if (!isset($legacyByClass[$cid])) {
$legacyByClass[$cid] = [
'class_section_id' => $cid,
'class_section_name' => $d['class_section_name'] ?? 'Class ' . $cid,
'items' => [],
];
}
$legacyByClass[$cid]['items'][] = $d;
continue;
}
$cid = (int)($d['class_section_id'] ?? 0);
if (!isset($legacyByClass[$cid])) {
$legacyByClass[$cid] = [
'class_section_id' => $cid,
'class_section_name' => $d['class_section_name'] ?? 'Class ' . $cid,
'items' => [],
];
}
$legacyByClass[$cid]['items'][] = $d;
$drafts[] = $d;
}
} else {
// Column missing: keep behavior simple and avoid legacy tab
@@ -284,13 +284,17 @@ class ExamDraftController extends BaseController
return redirect()->to('/login');
}
$classSectionId = (int) ($this->request->getPost('class_section_id') ?? 0);
$classSectionIds = $this->request->getPost('class_section_ids');
if (!is_array($classSectionIds)) {
$classSectionIds = [$classSectionIds];
}
$classSectionIds = array_values(array_filter(array_map('intval', $classSectionIds)));
$schoolYear = trim((string) ($this->request->getPost('school_year') ?? $this->schoolYear));
$semester = trim((string) ($this->request->getPost('semester') ?? $this->semester));
$examType = trim((string) $this->request->getPost('exam_type'));
if ($classSectionId <= 0) {
return redirect()->back()->withInput()->with('error', 'Select a class section.');
if (empty($classSectionIds)) {
return redirect()->back()->withInput()->with('error', 'Select at least one class section.');
}
if ($schoolYear === '') {
return redirect()->back()->withInput()->with('error', 'School year is required.');
@@ -309,9 +313,17 @@ class ExamDraftController extends BaseController
return redirect()->back()->withInput()->with('error', 'File type not allowed or upload failed.');
}
$payload = [
$pdfName = null;
if (strtolower($file->getClientExtension()) === 'pdf') {
$pdfName = $stored;
} else {
$pdfName = $this->convertDocToPdf(
$this->fullUploadPath(self::FINAL_UPLOAD_DIR, $stored),
self::FINAL_UPLOAD_DIR
);
}
$basePayload = [
'teacher_id' => $adminId, // store under admin user since legacy uploads are admin-only
'class_section_id' => $classSectionId,
'semester' => ucfirst(strtolower($semester)),
'school_year' => $schoolYear,
'exam_type' => $examType === '' ? null : $examType,
@@ -325,23 +337,22 @@ class ExamDraftController extends BaseController
'version' => 1,
];
if ($this->hasIsLegacyColumn) {
$payload['is_legacy'] = 1;
}
$pdfName = null;
if (strtolower($file->getClientExtension()) === 'pdf') {
$pdfName = $stored;
} else {
$pdfName = $this->convertDocToPdf(
$this->fullUploadPath(self::FINAL_UPLOAD_DIR, $stored),
self::FINAL_UPLOAD_DIR
);
$basePayload['is_legacy'] = 1;
}
if ($pdfName !== null && $this->hasFinalPdfColumn) {
$payload['final_pdf_file'] = $pdfName;
$basePayload['final_pdf_file'] = $pdfName;
}
if ($this->examDraftModel->insert($payload)) {
$saved = 0;
foreach ($classSectionIds as $classSectionId) {
$payload = $basePayload;
$payload['class_section_id'] = $classSectionId;
if ($this->examDraftModel->insert($payload)) {
$saved++;
}
}
if ($saved > 0) {
return redirect()->to('/administrator/exam-drafts')->with('success', 'Old exam uploaded successfully.');
}
+26 -5
View File
@@ -168,12 +168,33 @@
$weekLabel .= ' ' . date('M d, Y', strtotime($group['week_end']));
}
$reports = $group['reports'] ?? [];
$teacherName = '';
$teacherCounts = [];
$teacherLatest = [];
foreach ($reports as $report) {
if (! empty($report['teacher_name'])) {
$teacherName = $report['teacher_name'];
break;
$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;
?>
@@ -198,7 +219,7 @@
<?php endforeach; ?>
</div>
</td>
<td><?= esc($teacherName ?: '-') ?></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>
+3 -3
View File
@@ -182,13 +182,13 @@
<form method="post" action="<?= base_url('/administrator/exam-drafts/upload-legacy') ?>" enctype="multipart/form-data" class="row g-3">
<?= csrf_field() ?>
<div class="col-md-4">
<label class="form-label small">Class Section</label>
<select name="class_section_id" class="form-select" required>
<option value="">Select class</option>
<label class="form-label small">Class Sections</label>
<select name="class_section_ids[]" class="form-select" multiple required>
<?php foreach ($classSections as $cs): ?>
<option value="<?= esc($cs['class_section_id']) ?>"><?= esc($cs['class_section_name']) ?></option>
<?php endforeach; ?>
</select>
<div class="form-text">Hold Ctrl (Windows) or Command (Mac) to select multiple sections.</div>
</div>
<div class="col-md-2">
<label class="form-label small">School Year</label>
@@ -306,6 +306,14 @@
const forms = document.querySelectorAll('.needs-validation');
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
const islamicUnits = form.querySelectorAll('input[name="unit_islamic[]"]');
const hasIslamicUnit = Array.from(islamicUnits).some(input => input.value.trim() !== '');
if (!hasIslamicUnit) {
event.preventDefault();
event.stopPropagation();
alert('Please select at least one Islamic Studies unit.');
return;
}
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
@@ -461,6 +469,10 @@
confirmButton.addEventListener('click', () => {
confirmInput.value = '1';
const form = confirmButton.closest('form') || document.querySelector('form.needs-validation');
if (form && typeof form.requestSubmit === 'function') {
form.requestSubmit();
return;
}
if (form) {
form.submit();
}
+9
View File
@@ -137,6 +137,9 @@
<a href="<?= base_url('exam-drafts/files/teacher/' . $draft['teacher_file']) ?>" target="_blank">
<?= esc($draft['teacher_filename'] ?? 'Download submitted file') ?>
</a>
<a href="<?= base_url('exam-drafts/files/teacher/' . $draft['teacher_file']) ?>" target="_blank" class="btn btn-sm btn-outline-secondary ms-2">
View
</a>
</div>
<?php else: ?>
<div class="text-muted small">No file uploaded</div>
@@ -152,6 +155,9 @@
<a href="<?= base_url('exam-drafts/files/final/' . $draft['final_file']) ?>" target="_blank" class="link-success small">
<?= esc($draft['final_filename'] ?? 'Download final draft') ?>
</a>
<a href="<?= base_url('exam-drafts/files/final/' . $draft['final_file']) ?>" target="_blank" class="btn btn-sm btn-outline-secondary ms-2">
View
</a>
</div>
<?php endif; ?>
</td>
@@ -199,6 +205,9 @@
<a href="<?= base_url('exam-drafts/files/final/' . $item['final_file']) ?>" target="_blank" class="btn btn-sm btn-outline-primary">
Download
</a>
<a href="<?= base_url('exam-drafts/files/final/' . $item['final_file']) ?>" target="_blank" class="btn btn-sm btn-outline-secondary ms-2">
View
</a>
<?php else: ?>
<span class="text-muted small">File missing</span>
<?php endif; ?>