fix enrollment for the new school-year
Tests / PHPUnit (push) Successful in 1m26s

This commit is contained in:
root
2026-08-07 23:43:31 -04:00
parent b6f3b14e7b
commit 1ef2800f12
66 changed files with 8997 additions and 498 deletions
+29 -17
View File
@@ -64,6 +64,7 @@ $allergyOptions = $allergyOptions ?? [
];
$gradeOptions = $gradeOptions ?? ['KG', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', 'Youth'];
$selectedYear = trim((string)($selectedYear ?? ''));
?>
<?= $this->extend('layout/management_layout') ?>
@@ -279,8 +280,8 @@ $gradeOptions = $gradeOptions ?? ['KG', '1', '2', '3', '4', '5', '6', '7', '8',
<!-- age (readonly) -->
<div class="col-md-3">
<label class="form-label">Age</label>
<input type="number" name="age" class="form-control js-age" value="<?= (int)($student['age'] ?? 0) ?>" min="0" step="1" readonly>
<div class="form-text">Auto-calculated from DOB.</div>
<input type="number" name="age" class="form-control js-age" value="<?= esc((string)($student['age'] ?? '')) ?>" min="0" step="1" readonly>
<div class="form-text">Auto-calculated from DOB as of Sep 1 of the school year.</div>
</div>
<!-- registration_grade -->
@@ -589,32 +590,43 @@ $gradeOptions = $gradeOptions ?? ['KG', '1', '2', '3', '4', '5', '6', '7', '8',
// Bind all multi-selects present on the page (all modals rendered server-side)
document.querySelectorAll('select.js-multi').forEach(bindSelect);
const fallbackSchoolYear = <?= json_encode($selectedYear, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
function ageAsOfSchoolYearStart(dobValue, schoolYearValue) {
if (!dobValue) return '';
const yearMatch = String(schoolYearValue || fallbackSchoolYear || '').match(/^(\d{4})/);
if (!yearMatch) return '';
const birthParts = dobValue.split('-').map(Number);
if (birthParts.length !== 3 || birthParts.some(Number.isNaN)) return '';
const dob = new Date(birthParts[0], birthParts[1] - 1, birthParts[2]);
const cutoff = new Date(Number(yearMatch[1]), 8, 1);
if (Number.isNaN(dob.getTime()) || dob > cutoff) return '';
let age = cutoff.getFullYear() - dob.getFullYear();
const monthDelta = cutoff.getMonth() - dob.getMonth();
if (monthDelta < 0 || (monthDelta === 0 && cutoff.getDate() < dob.getDate())) age--;
return age >= 0 ? String(age) : '';
}
// Modal lifecycle: wire age + (re)bind selects inside shown modal
document.querySelectorAll('.modal').forEach((modal) => {
modal.addEventListener('shown.bs.modal', () => {
// Age from DOB
const dob = modal.querySelector('.js-dob');
const age = modal.querySelector('.js-age');
const schoolYear = modal.querySelector('input[name="school_year"]');
if (dob && age) {
const update = () => {
if (!dob.value) {
age.value = '';
return;
}
const d = new Date(dob.value + 'T00:00:00');
if (isNaN(d.getTime())) {
age.value = '';
return;
}
const t = new Date();
let a = t.getFullYear() - d.getFullYear();
const m = t.getMonth() - d.getMonth();
if (m < 0 || (m === 0 && t.getDate() < d.getDate())) a--;
age.value = a >= 0 ? a : '';
age.value = ageAsOfSchoolYearStart(dob.value, schoolYear ? schoolYear.value : '');
};
update();
dob.addEventListener('change', update);
dob.addEventListener('input', update);
if (schoolYear) {
schoolYear.addEventListener('change', update);
schoolYear.addEventListener('input', update);
}
}
modal.querySelectorAll('select.js-multi').forEach(bindSelect);