Files
alrahma_sunday_school/public/assets/js/age_validation.js
T
root 1ef2800f12
Tests / PHPUnit (push) Successful in 1m26s
fix enrollment for the new school-year
2026-08-07 23:43:31 -04:00

97 lines
3.7 KiB
JavaScript

export function validateAgeLive(inputEl, minAge = 5, maxAge = 18) {
const dob = inputEl.value.trim();
if (!dob) return false;
const birthDate = parseDateOnly(dob);
if (isNaN(birthDate.getTime())) {
showFeedback(inputEl, false, "Invalid date format (Use YYYY-MM-DD)");
return false;
}
const registrationAgeDeadline = window.appConfig?.registrationAgeDeadline;
const schoolYearAgeDeadline = window.appConfig?.schoolYearAgeDeadline || registrationAgeDeadline;
const minimumAgeDeadline = parseDateOnlyOrToday(registrationAgeDeadline);
const ageDeadline = parseDateOnlyOrToday(schoolYearAgeDeadline);
const minBirthDate = new Date(Date.UTC(ageDeadline.getUTCFullYear() - maxAge - 1, ageDeadline.getUTCMonth(), ageDeadline.getUTCDate() + 1)); // oldest
const maxBirthDate = new Date(Date.UTC(minimumAgeDeadline.getUTCFullYear() - minAge, minimumAgeDeadline.getUTCMonth(), minimumAgeDeadline.getUTCDate())); // youngest
const isValidAge = birthDate >= minBirthDate && birthDate <= maxBirthDate;
// Format date as MM-DD-YYYY for error message (use original deadline, not adjusted)
const formatDateMMDDYYYY = (dateStr) => {
if (!dateStr) return dateStr;
// Parse as UTC to avoid timezone issues that could shift the date
const date = new Date(dateStr + 'T00:00:00.000Z');
if (isNaN(date.getTime())) return dateStr;
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
const day = String(date.getUTCDate()).padStart(2, '0');
const year = date.getUTCFullYear();
return `${month}-${day}-${year}`;
};
const errorMessage = isValidAge
? ""
: `Must be at least ${minAge} years old by ${formatDateMMDDYYYY(registrationAgeDeadline)} and no older than ${maxAge} by ${formatDateMMDDYYYY(schoolYearAgeDeadline)}.`;
showFeedback(inputEl, isValidAge, errorMessage);
return isValidAge;
}
function normalize(date) {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
}
function parseDateOnly(value) {
const match = String(value || '').match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (!match) return new Date(NaN);
const year = Number(match[1]);
const monthIndex = Number(match[2]) - 1;
const day = Number(match[3]);
const date = new Date(Date.UTC(year, monthIndex, day));
if (
date.getUTCFullYear() !== year ||
date.getUTCMonth() !== monthIndex ||
date.getUTCDate() !== day
) {
return new Date(NaN);
}
return date;
}
function parseDateOnlyOrToday(value) {
const date = parseDateOnly(value);
return isNaN(date.getTime()) ? normalize(new Date()) : date;
}
// Helper function (unchanged)
function showFeedback(inputEl, isValid, message) {
inputEl.classList.toggle("is-invalid", !isValid);
const feedbackEl = inputEl.nextElementSibling || document.createElement("div");
feedbackEl.textContent = message;
feedbackEl.className = `invalid-feedback ${isValid ? "d-none" : ""}`;
inputEl.parentNode.appendChild(feedbackEl);
}
// Set max birthdate (2025 - minAge)
window.addEventListener("DOMContentLoaded", () => {
const minAge = 5; // Must match validateAgeLive's default
const deadline = parseDateOnlyOrToday(window.appConfig?.schoolYearAgeDeadline);
const registrationAgeDeadline = parseDateOnly(window.appConfig?.registrationAgeDeadline);
const maxDeadline = isNaN(registrationAgeDeadline.getTime()) ? deadline : registrationAgeDeadline;
const maxBirthYear = maxDeadline.getUTCFullYear() - minAge;
const maxDateStr = `${maxBirthYear}-12-31`; // Latest allowed birthdate for age-5 registration grace
document.querySelectorAll(".dob-input").forEach((input) => {
input.setAttribute("max", maxDateStr);
input.setAttribute(
"aria-label",
`Born before ${maxBirthYear + 1} (${minAge}+ years by ${maxDeadline.getUTCFullYear()})`
);
});
});