fix the exam draft
This commit is contained in:
@@ -98,6 +98,10 @@ class ClassProgressController extends BaseController
|
|||||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
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);
|
$attachmentErrors = $this->validateAttachmentFiles($subjectSections);
|
||||||
if (! empty($attachmentErrors)) {
|
if (! empty($attachmentErrors)) {
|
||||||
return redirect()->back()->withInput()->with('errors', $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());
|
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);
|
$attachmentErrors = $this->validateAttachmentFiles($subjectSections);
|
||||||
if (! empty($attachmentErrors)) {
|
if (! empty($attachmentErrors)) {
|
||||||
return redirect()->back()->withInput()->with('errors', $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;
|
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
|
protected function parseUnitChapterSummary(string $summary): array
|
||||||
{
|
{
|
||||||
$summary = trim($summary);
|
$summary = trim($summary);
|
||||||
|
|||||||
@@ -240,23 +240,23 @@ class ExamDraftController extends BaseController
|
|||||||
// Group legacy uploads (admin-uploaded finalized exams) by class_section for separate tab
|
// Group legacy uploads (admin-uploaded finalized exams) by class_section for separate tab
|
||||||
$legacyByClass = [];
|
$legacyByClass = [];
|
||||||
if ($this->hasIsLegacyColumn) {
|
if ($this->hasIsLegacyColumn) {
|
||||||
// Keep all submissions visible; additionally surface legacy items in a separate tab
|
// Keep legacy items out of the main submissions list; show them in the legacy tab only.
|
||||||
$drafts = $allDrafts;
|
$drafts = [];
|
||||||
|
|
||||||
foreach ($allDrafts as $d) {
|
foreach ($allDrafts as $d) {
|
||||||
$isLegacy = !empty($d['is_legacy']);
|
$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;
|
continue;
|
||||||
}
|
}
|
||||||
$cid = (int)($d['class_section_id'] ?? 0);
|
$drafts[] = $d;
|
||||||
if (!isset($legacyByClass[$cid])) {
|
|
||||||
$legacyByClass[$cid] = [
|
|
||||||
'class_section_id' => $cid,
|
|
||||||
'class_section_name' => $d['class_section_name'] ?? 'Class ' . $cid,
|
|
||||||
'items' => [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$legacyByClass[$cid]['items'][] = $d;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Column missing: keep behavior simple and avoid legacy tab
|
// Column missing: keep behavior simple and avoid legacy tab
|
||||||
@@ -284,13 +284,17 @@ class ExamDraftController extends BaseController
|
|||||||
return redirect()->to('/login');
|
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));
|
$schoolYear = trim((string) ($this->request->getPost('school_year') ?? $this->schoolYear));
|
||||||
$semester = trim((string) ($this->request->getPost('semester') ?? $this->semester));
|
$semester = trim((string) ($this->request->getPost('semester') ?? $this->semester));
|
||||||
$examType = trim((string) $this->request->getPost('exam_type'));
|
$examType = trim((string) $this->request->getPost('exam_type'));
|
||||||
|
|
||||||
if ($classSectionId <= 0) {
|
if (empty($classSectionIds)) {
|
||||||
return redirect()->back()->withInput()->with('error', 'Select a class section.');
|
return redirect()->back()->withInput()->with('error', 'Select at least one class section.');
|
||||||
}
|
}
|
||||||
if ($schoolYear === '') {
|
if ($schoolYear === '') {
|
||||||
return redirect()->back()->withInput()->with('error', 'School year is required.');
|
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.');
|
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
|
'teacher_id' => $adminId, // store under admin user since legacy uploads are admin-only
|
||||||
'class_section_id' => $classSectionId,
|
|
||||||
'semester' => ucfirst(strtolower($semester)),
|
'semester' => ucfirst(strtolower($semester)),
|
||||||
'school_year' => $schoolYear,
|
'school_year' => $schoolYear,
|
||||||
'exam_type' => $examType === '' ? null : $examType,
|
'exam_type' => $examType === '' ? null : $examType,
|
||||||
@@ -325,23 +337,22 @@ class ExamDraftController extends BaseController
|
|||||||
'version' => 1,
|
'version' => 1,
|
||||||
];
|
];
|
||||||
if ($this->hasIsLegacyColumn) {
|
if ($this->hasIsLegacyColumn) {
|
||||||
$payload['is_legacy'] = 1;
|
$basePayload['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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if ($pdfName !== null && $this->hasFinalPdfColumn) {
|
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.');
|
return redirect()->to('/administrator/exam-drafts')->with('success', 'Old exam uploaded successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,12 +168,33 @@
|
|||||||
$weekLabel .= ' – ' . date('M d, Y', strtotime($group['week_end']));
|
$weekLabel .= ' – ' . date('M d, Y', strtotime($group['week_end']));
|
||||||
}
|
}
|
||||||
$reports = $group['reports'] ?? [];
|
$reports = $group['reports'] ?? [];
|
||||||
$teacherName = '';
|
$teacherCounts = [];
|
||||||
|
$teacherLatest = [];
|
||||||
foreach ($reports as $report) {
|
foreach ($reports as $report) {
|
||||||
if (! empty($report['teacher_name'])) {
|
$name = trim((string) ($report['teacher_name'] ?? ''));
|
||||||
$teacherName = $report['teacher_name'];
|
if ($name === '') {
|
||||||
break;
|
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;
|
$exampleId = $reports ? reset($reports)['id'] : null;
|
||||||
?>
|
?>
|
||||||
@@ -198,7 +219,7 @@
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td><?= esc($teacherName ?: '-') ?></td>
|
<td><?= esc($teacherLabel) ?></td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<?php if ($exampleId): ?>
|
<?php if ($exampleId): ?>
|
||||||
<a class="btn btn-sm btn-outline-primary" href="<?= base_url('admin/progress/view/' . $exampleId) ?>">View</a>
|
<a class="btn btn-sm btn-outline-primary" href="<?= base_url('admin/progress/view/' . $exampleId) ?>">View</a>
|
||||||
|
|||||||
@@ -182,13 +182,13 @@
|
|||||||
<form method="post" action="<?= base_url('/administrator/exam-drafts/upload-legacy') ?>" enctype="multipart/form-data" class="row g-3">
|
<form method="post" action="<?= base_url('/administrator/exam-drafts/upload-legacy') ?>" enctype="multipart/form-data" class="row g-3">
|
||||||
<?= csrf_field() ?>
|
<?= csrf_field() ?>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label class="form-label small">Class Section</label>
|
<label class="form-label small">Class Sections</label>
|
||||||
<select name="class_section_id" class="form-select" required>
|
<select name="class_section_ids[]" class="form-select" multiple required>
|
||||||
<option value="">Select class</option>
|
|
||||||
<?php foreach ($classSections as $cs): ?>
|
<?php foreach ($classSections as $cs): ?>
|
||||||
<option value="<?= esc($cs['class_section_id']) ?>"><?= esc($cs['class_section_name']) ?></option>
|
<option value="<?= esc($cs['class_section_id']) ?>"><?= esc($cs['class_section_name']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
|
<div class="form-text">Hold Ctrl (Windows) or Command (Mac) to select multiple sections.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<label class="form-label small">School Year</label>
|
<label class="form-label small">School Year</label>
|
||||||
|
|||||||
@@ -306,6 +306,14 @@
|
|||||||
const forms = document.querySelectorAll('.needs-validation');
|
const forms = document.querySelectorAll('.needs-validation');
|
||||||
Array.from(forms).forEach(form => {
|
Array.from(forms).forEach(form => {
|
||||||
form.addEventListener('submit', event => {
|
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()) {
|
if (!form.checkValidity()) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -461,6 +469,10 @@
|
|||||||
confirmButton.addEventListener('click', () => {
|
confirmButton.addEventListener('click', () => {
|
||||||
confirmInput.value = '1';
|
confirmInput.value = '1';
|
||||||
const form = confirmButton.closest('form') || document.querySelector('form.needs-validation');
|
const form = confirmButton.closest('form') || document.querySelector('form.needs-validation');
|
||||||
|
if (form && typeof form.requestSubmit === 'function') {
|
||||||
|
form.requestSubmit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (form) {
|
if (form) {
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,9 @@
|
|||||||
<a href="<?= base_url('exam-drafts/files/teacher/' . $draft['teacher_file']) ?>" target="_blank">
|
<a href="<?= base_url('exam-drafts/files/teacher/' . $draft['teacher_file']) ?>" target="_blank">
|
||||||
<?= esc($draft['teacher_filename'] ?? 'Download submitted file') ?>
|
<?= esc($draft['teacher_filename'] ?? 'Download submitted file') ?>
|
||||||
</a>
|
</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>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="text-muted small">No file uploaded</div>
|
<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">
|
<a href="<?= base_url('exam-drafts/files/final/' . $draft['final_file']) ?>" target="_blank" class="link-success small">
|
||||||
<?= esc($draft['final_filename'] ?? 'Download final draft') ?>
|
<?= esc($draft['final_filename'] ?? 'Download final draft') ?>
|
||||||
</a>
|
</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>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</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">
|
<a href="<?= base_url('exam-drafts/files/final/' . $item['final_file']) ?>" target="_blank" class="btn btn-sm btn-outline-primary">
|
||||||
Download
|
Download
|
||||||
</a>
|
</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: ?>
|
<?php else: ?>
|
||||||
<span class="text-muted small">File missing</span>
|
<span class="text-muted small">File missing</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user