498 lines
22 KiB
PHP
498 lines
22 KiB
PHP
<?= $this->extend('layout/main_layout') ?>
|
||
<?= $this->section('content') ?>
|
||
<?php
|
||
$isEdit = (bool) ($isEdit ?? false);
|
||
$formAction = $formAction ?? base_url('teacher/progress/store');
|
||
$submitLabel = $submitLabel ?? 'Submit Progress';
|
||
$hasClass = !empty($classSectionId);
|
||
$assignedClassName = $classSectionName ?? '';
|
||
$sundayOptions = $sundayOptions ?? [];
|
||
$defaultWeekStart = $defaultWeekStart ?? ($sundayOptions[0] ?? '');
|
||
$weekStartSelected = set_value('week_start', $defaultWeekStart);
|
||
$weekEndValue = set_value('week_end', $existingWeekEnd ?? '');
|
||
$existingReports = $existingReports ?? [];
|
||
if (!$weekEndValue && $weekStartSelected) {
|
||
try {
|
||
$dt = new \DateTime($weekStartSelected);
|
||
$dt->modify('+6 days');
|
||
$weekEndValue = $dt->format('Y-m-d');
|
||
} catch (\Exception $e) {
|
||
$weekEndValue = '';
|
||
}
|
||
}
|
||
$weekEndLabel = '';
|
||
if ($weekEndValue) {
|
||
try {
|
||
$weekEndLabel = (new \DateTime($weekEndValue))->format('M d, Y');
|
||
} catch (\Exception $e) {
|
||
$weekEndLabel = 'Week end';
|
||
}
|
||
} else {
|
||
$weekEndLabel = 'Select a week';
|
||
}
|
||
?>
|
||
<div class="py-4">
|
||
<div class="d-flex flex-wrap align-items-center justify-content-between mb-3">
|
||
<div>
|
||
<h3 class="mb-0">
|
||
<?php if ($isEdit): ?>
|
||
<?= esc($classSectionName ? "Edit {$classSectionName} Progress" : 'Edit Class Progress') ?>
|
||
<?php else: ?>
|
||
<?= esc($classSectionName ? "Class {$classSectionName} Progress Submission" : 'Class Progress Submission') ?>
|
||
<?php endif; ?>
|
||
</h3>
|
||
<div class="text-muted">
|
||
<?= $isEdit ? 'Update your weekly progress submission.' : 'Submit weekly progress for a single subject' ?>
|
||
</div>
|
||
</div>
|
||
<a href="<?= base_url('teacher/progress/history') ?>" class="btn btn-outline-secondary">My Submissions</a>
|
||
</div>
|
||
|
||
<?php if (session()->getFlashdata('success')): ?>
|
||
<div class="alert alert-success"><?= esc(session()->getFlashdata('success')) ?></div>
|
||
<?php endif; ?>
|
||
<?php $overwritePrompt = session()->getFlashdata('confirm_overwrite'); ?>
|
||
<?php if (session()->getFlashdata('warning') && ! $overwritePrompt): ?>
|
||
<div class="alert alert-warning"><?= esc(session()->getFlashdata('warning')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('error')): ?>
|
||
<div class="alert alert-danger"><?= esc(session()->getFlashdata('error')) ?></div>
|
||
<?php endif; ?>
|
||
<?php if (session()->getFlashdata('errors')): ?>
|
||
<div class="alert alert-danger">
|
||
<ul class="mb-0">
|
||
<?php foreach (session()->getFlashdata('errors') as $error): ?>
|
||
<li><?= esc($error) ?></li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form action="<?= esc($formAction) ?>" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="class_section_id" value="<?= esc($classSectionId ?? '') ?>">
|
||
<input type="hidden" name="confirm_overwrite" id="confirmOverwriteInput" value="0">
|
||
<div class="row g-3">
|
||
<div class="col">
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-header bg-white d-flex flex-wrap align-items-center justify-content-between gap-3">
|
||
<strong class="mb-0">Date Selection</strong>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<select id="weekStartSelect" name="week_start" class="form-select form-select-sm" required <?= $isEdit ? 'data-original-week="' . esc($weekStartSelected) . '"' : '' ?>>
|
||
<option value="">Select week</option>
|
||
<?php foreach ($sundayOptions as $sunday): ?>
|
||
<?php
|
||
try {
|
||
$startDt = new \DateTime($sunday);
|
||
$displayStart = $startDt->format('M d, Y');
|
||
} catch (\Exception $e) {
|
||
$displayStart = $sunday;
|
||
}
|
||
?>
|
||
<option value="<?= esc($sunday) ?>" <?= $sunday === $weekStartSelected ? 'selected' : '' ?>>
|
||
<?= esc($displayStart) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<div class="invalid-feedback">Week start is required.</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<input type="hidden" name="week_end" id="weekEndInput" value="<?= esc($weekEndValue) ?>" required>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row g-3 mt-1">
|
||
<?php
|
||
$subjectSections = $subjectSections ?? [];
|
||
$subjectCurriculum = $subjectCurriculum ?? [];
|
||
?>
|
||
<?php foreach ($subjectSections as $slug => $section): ?>
|
||
<?php
|
||
$unitValues = old("unit_$slug") ?? ($existingReports[$slug]['unit_values'] ?? []);
|
||
$chapterValues = old("chapter_$slug") ?? ($existingReports[$slug]['chapter_values'] ?? []);
|
||
$coveredValue = old("covered_$slug", $existingReports[$slug]['covered'] ?? '');
|
||
$homeworkValue = old("homework_$slug", $existingReports[$slug]['homework'] ?? '');
|
||
$rowsCount = max(count($unitValues), count($chapterValues));
|
||
?>
|
||
<div class="col-lg-6">
|
||
<div class="border border-dark rounded-3 p-3 h-100 subject-section">
|
||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||
<h4 class="mb-0"><?= esc($section['label'] ?? $slug) ?></h4>
|
||
</div>
|
||
<?php $curriculumOptions = $subjectCurriculum[$slug] ?? []; ?>
|
||
<?php
|
||
$preparedEntries = array_values(array_filter(array_map(function ($option) {
|
||
$chapterName = trim($option['chapter_name'] ?? '');
|
||
if ($chapterName === '') {
|
||
return null;
|
||
}
|
||
return [
|
||
'unit_number' => $option['unit_number'] ?? '',
|
||
'unit_title' => trim($option['unit_title'] ?? ''),
|
||
'chapter_name' => $chapterName,
|
||
];
|
||
}, $curriculumOptions)));
|
||
?>
|
||
<div class="mb-2 d-flex justify-content-between align-items-center">
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div class="position-relative">
|
||
<button type="button"
|
||
class="btn btn-sm btn-outline-dark"
|
||
data-add-unit-chapter
|
||
data-subject="<?= esc($slug) ?>">
|
||
<?= $slug === 'quran' ? '+ Add Surah, Arabic Subject' : '+ Add Unit, Chapter' ?>
|
||
</button>
|
||
<div class="subject-curriculum-list position-absolute d-none border rounded shadow-sm bg-white mt-1" id="curriculumList-<?= esc($slug) ?>" style="min-width: 220px; z-index: 5;">
|
||
<?php if (empty($preparedEntries)): ?>
|
||
<div class="p-2 text-muted small">No saved entries.</div>
|
||
<?php else: ?>
|
||
<?php foreach ($preparedEntries as $entry): ?>
|
||
<?php
|
||
$unitNumber = $entry['unit_number'] ?? '';
|
||
$unitTitle = $entry['unit_title'] ?? '';
|
||
$chapterName = $entry['chapter_name'] ?? '';
|
||
$displayParts = [];
|
||
if ($slug === 'islamic') {
|
||
if ($unitNumber) $displayParts[] = 'Unit ' . $unitNumber;
|
||
if ($unitTitle !== '') $displayParts[] = $unitTitle;
|
||
$prefix = $displayParts ? implode(' – ', $displayParts) . ' / ' : '';
|
||
$display = $prefix . $chapterName;
|
||
} else {
|
||
$display = 'Surah: ' . $chapterName;
|
||
}
|
||
?>
|
||
<button type="button"
|
||
class="dropdown-item text-start"
|
||
data-curriculum-entry
|
||
data-subject="<?= esc($slug) ?>"
|
||
data-unit-number="<?= esc($unitNumber) ?>"
|
||
data-unit-title="<?= esc($unitTitle) ?>"
|
||
data-chapter="<?= esc($chapterName) ?>">
|
||
<?= esc($display) ?>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
<?php if ($slug === 'quran'): ?>
|
||
<div class="px-2 py-2 border-top">
|
||
<div class="input-group input-group-sm">
|
||
<input type="text" class="form-control" placeholder="Custom Surah" data-custom-input data-subject="<?= esc($slug) ?>">
|
||
<button type="button" class="btn btn-outline-secondary" data-custom-entry data-subject="<?= esc($slug) ?>">Add</button>
|
||
</div>
|
||
<div class="form-text small text-muted">Add a custom Surah or Arabic target.</div>
|
||
</div>
|
||
<?php elseif ($slug === 'islamic'): ?>
|
||
<div class="px-2 py-2 border-top">
|
||
<div class="input-group input-group-sm">
|
||
<input type="text" class="form-control" placeholder="Type subject or topic" data-custom-input data-subject="<?= esc($slug) ?>">
|
||
<button type="button" class="btn btn-outline-secondary" data-custom-entry data-subject="<?= esc($slug) ?>">Add</button>
|
||
</div>
|
||
<div class="form-text small text-muted">Add a subject or unit not listed above (e.g. Seerah, Fiqh, Akhlaq).</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="unit-chapter-rows mb-3" id="unitChapterRows-<?= esc($slug) ?>">
|
||
<?php for ($i = 0; $i < $rowsCount; $i++): ?>
|
||
<div class="row g-2 align-items-end mb-2 unit-chapter-entry">
|
||
<div class="col">
|
||
<input type="text" name="unit_<?= esc($slug) ?>[]" class="form-control form-control-sm" placeholder="Unit name" value="<?= esc($unitValues[$i] ?? '') ?>" readonly>
|
||
</div>
|
||
<div class="col">
|
||
<input type="text" name="chapter_<?= esc($slug) ?>[]" class="form-control form-control-sm" placeholder="Chapter" value="<?= esc($chapterValues[$i] ?? '') ?>" readonly>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button type="button" class="btn btn-outline-danger btn-sm" data-remove-unit-chapter aria-label="Remove entry">X</button>
|
||
</div>
|
||
</div>
|
||
<?php endfor; ?>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">What has been covered?</label>
|
||
<textarea name="covered_<?= esc($slug) ?>" class="form-control" rows="4" required placeholder="What was taught? Key topics, activities, memorization, etc."><?= esc($coveredValue) ?></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">Assigned homework:</label>
|
||
<textarea name="homework_<?= esc($slug) ?>" class="form-control" rows="3" placeholder="Homework, practice quizzes, review pages"><?= esc($homeworkValue) ?></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label mb-1">Attachment (optional):</label>
|
||
<input type="file" name="attachment_<?= esc($slug) ?>[]" class="form-control" accept=".pdf,.jpg,.jpeg,.png" multiple>
|
||
<div class="form-text small">Upload worksheets, quizzes, or reference files for <?= esc(strtolower($section['label'] ?? 'this subject')) ?>. You can select multiple files.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<div class="row mt-3">
|
||
<div class="col">
|
||
<div class="card shadow-sm">
|
||
<div class="card-body d-flex flex-column">
|
||
<button class="btn btn-primary w-100 mt-auto" type="submit" <?= $hasClass ? '' : 'disabled' ?>><?= esc($submitLabel) ?></button>
|
||
<?php if (! $hasClass): ?>
|
||
<div class="text-muted small mt-2">
|
||
You are not assigned to a class. Contact the administrator to submit progress.
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="text-muted small mt-2">Make sure week dates and subject information are accurate before submitting.</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<?= $this->endSection() ?>
|
||
|
||
<?= $this->section('scripts') ?>
|
||
<?php
|
||
$submitSuccess = session()->getFlashdata('success');
|
||
$submitError = session()->getFlashdata('error');
|
||
$overwriteWarning = session()->getFlashdata('warning');
|
||
$overwritePrompt = session()->getFlashdata('confirm_overwrite');
|
||
?>
|
||
<?php if ($submitSuccess || $submitError): ?>
|
||
<div class="modal fade" id="submissionStatusModal" tabindex="-1" aria-labelledby="submissionStatusLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="submissionStatusLabel">
|
||
<?= $submitSuccess ? 'Submission Successful' : 'Submission Failed' ?>
|
||
</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<?= esc($submitSuccess ?: $submitError) ?>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if ($overwritePrompt && $overwriteWarning): ?>
|
||
<div class="modal fade" id="overwriteConfirmModal" tabindex="-1" aria-labelledby="overwriteConfirmLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="overwriteConfirmLabel">Override Existing Report</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<?= esc($overwriteWarning) ?>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||
<button type="button" class="btn btn-primary" id="confirmOverwriteButton">Override</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
<script>
|
||
(() => {
|
||
'use strict';
|
||
const forms = document.querySelectorAll('.needs-validation');
|
||
Array.from(forms).forEach(form => {
|
||
form.addEventListener('submit', event => {
|
||
const originalWeek = weekStartSelect?.dataset.originalWeek || '';
|
||
if (originalWeek && weekStartSelect && weekStartSelect.value && weekStartSelect.value !== originalWeek) {
|
||
const ok = confirm('A progress report already exists for the original week. Change the week and override any existing report for the new date?');
|
||
if (!ok) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
return;
|
||
}
|
||
const confirmInput = document.getElementById('confirmOverwriteInput');
|
||
if (confirmInput) {
|
||
confirmInput.value = '1';
|
||
}
|
||
}
|
||
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();
|
||
}
|
||
form.classList.add('was-validated');
|
||
}, false);
|
||
});
|
||
|
||
const weekStartSelect = document.getElementById('weekStartSelect');
|
||
const weekEndInput = document.getElementById('weekEndInput');
|
||
const updateWeekEnd = (value) => {
|
||
if (!weekEndInput) return;
|
||
if (!value) {
|
||
weekEndInput.value = '';
|
||
return;
|
||
}
|
||
const startDate = new Date(value);
|
||
if (Number.isNaN(startDate.valueOf())) {
|
||
weekEndInput.value = '';
|
||
return;
|
||
}
|
||
const endDate = new Date(startDate);
|
||
endDate.setDate(endDate.getDate() + 6);
|
||
weekEndInput.value = endDate.toISOString().slice(0, 10);
|
||
};
|
||
|
||
if (weekStartSelect) {
|
||
weekStartSelect.addEventListener('change', () => updateWeekEnd(weekStartSelect.value));
|
||
updateWeekEnd(weekStartSelect.value);
|
||
}
|
||
|
||
const buildRow = (slug, unitValue = '', chapterValue = '') => {
|
||
const row = document.createElement('div');
|
||
row.className = 'row g-2 align-items-end mb-2 unit-chapter-entry';
|
||
row.innerHTML = `
|
||
<div class="col">
|
||
<input type="text" name="unit_${slug}[]" class="form-control form-control-sm" placeholder="Unit name" readonly />
|
||
</div>
|
||
<div class="col">
|
||
<input type="text" name="chapter_${slug}[]" class="form-control form-control-sm" placeholder="Chapter" readonly />
|
||
</div>
|
||
<div class="col-auto">
|
||
<button type="button" class="btn btn-outline-danger btn-sm" data-remove-unit-chapter aria-label="Remove entry">X</button>
|
||
</div>
|
||
`;
|
||
const inputs = row.querySelectorAll('input');
|
||
if (inputs[0]) {
|
||
inputs[0].value = unitValue;
|
||
}
|
||
if (inputs[1]) {
|
||
inputs[1].value = chapterValue;
|
||
}
|
||
return row;
|
||
};
|
||
|
||
const appendUnitChapterRow = (slug, unitValue = '', chapterValue = '') => {
|
||
const container = document.getElementById(`unitChapterRows-${slug}`);
|
||
if (!container) return;
|
||
container.appendChild(buildRow(slug, unitValue, chapterValue));
|
||
};
|
||
|
||
const buildUnitDisplay = (subject, unitNumber, unitTitle, { isQuran = false, isCustom = false } = {}) => {
|
||
const parts = [];
|
||
if (unitNumber) {
|
||
parts.push(`Unit ${unitNumber}`);
|
||
}
|
||
if (unitTitle) {
|
||
parts.push(unitTitle);
|
||
}
|
||
if (isQuran) {
|
||
return isCustom ? 'Custom' : 'Surah';
|
||
}
|
||
if (subject === 'islamic' && isCustom) {
|
||
return 'Custom';
|
||
}
|
||
return parts.join(' – ');
|
||
};
|
||
|
||
const hideMenus = () => {
|
||
document.querySelectorAll('.subject-curriculum-list').forEach(menu => menu.classList.add('d-none'));
|
||
};
|
||
|
||
document.addEventListener('click', () => hideMenus());
|
||
|
||
document.querySelectorAll('[data-add-unit-chapter]').forEach(button => {
|
||
const subject = button.dataset.subject;
|
||
if (!subject) return;
|
||
const menu = document.getElementById(`curriculumList-${subject}`);
|
||
if (menu) {
|
||
menu.addEventListener('click', event => event.stopPropagation());
|
||
}
|
||
button.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
if (!menu) return;
|
||
const shouldShow = menu.classList.contains('d-none');
|
||
hideMenus();
|
||
if (shouldShow) {
|
||
menu.classList.remove('d-none');
|
||
activeMenus.add(menu);
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('[data-curriculum-entry]').forEach(entry => {
|
||
entry.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
const subject = entry.dataset.subject;
|
||
const unitNumber = entry.dataset.unitNumber || '';
|
||
const unitTitle = entry.dataset.unitTitle || '';
|
||
const chapterValue = entry.dataset.chapter || '';
|
||
if (!subject) return;
|
||
const unitValue = buildUnitDisplay(subject, unitNumber, unitTitle, { isQuran: subject === 'quran' });
|
||
appendUnitChapterRow(subject, unitValue, chapterValue);
|
||
hideMenus();
|
||
});
|
||
});
|
||
|
||
document.addEventListener('click', event => {
|
||
const button = event.target.closest('[data-remove-unit-chapter]');
|
||
if (!button) return;
|
||
const row = button.closest('.unit-chapter-entry');
|
||
if (row) {
|
||
row.remove();
|
||
}
|
||
});
|
||
|
||
document.querySelectorAll('[data-custom-entry]').forEach(button => {
|
||
button.addEventListener('click', event => {
|
||
event.stopPropagation();
|
||
const subject = button.dataset.subject;
|
||
if (!subject) return;
|
||
const input = document.querySelector(`[data-custom-input][data-subject="${subject}"]`);
|
||
if (!input) return;
|
||
const customValue = input.value.trim();
|
||
if (customValue === '') return;
|
||
const unitValue = buildUnitDisplay(subject, '', '', {
|
||
isQuran: subject === 'quran',
|
||
isCustom: subject === 'quran' || subject === 'islamic',
|
||
});
|
||
appendUnitChapterRow(subject, unitValue, customValue);
|
||
input.value = '';
|
||
hideMenus();
|
||
});
|
||
});
|
||
|
||
const statusModalEl = document.getElementById('submissionStatusModal');
|
||
if (statusModalEl && typeof bootstrap !== 'undefined') {
|
||
const statusModal = new bootstrap.Modal(statusModalEl);
|
||
statusModal.show();
|
||
}
|
||
|
||
const overwriteModalEl = document.getElementById('overwriteConfirmModal');
|
||
if (overwriteModalEl && typeof bootstrap !== 'undefined') {
|
||
const overwriteModal = new bootstrap.Modal(overwriteModalEl);
|
||
overwriteModal.show();
|
||
const confirmButton = document.getElementById('confirmOverwriteButton');
|
||
const confirmInput = document.getElementById('confirmOverwriteInput');
|
||
if (confirmButton && confirmInput) {
|
||
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();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
})();
|
||
</script>
|
||
<?= $this->endSection() ?>
|