This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user