Add timetable end-time validation
This commit is contained in:
@@ -47,6 +47,101 @@
|
||||
return Number.isNaN(date.getTime()) ? null : date;
|
||||
}
|
||||
|
||||
function parseDateTimeLocalValue(value) {
|
||||
var raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var date = new Date(raw);
|
||||
return Number.isNaN(date.getTime()) ? null : date;
|
||||
}
|
||||
|
||||
function clearFieldValidity(input) {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
input.setCustomValidity('');
|
||||
input.classList.remove('is-invalid');
|
||||
if (input.removeAttribute) {
|
||||
input.removeAttribute('aria-invalid');
|
||||
}
|
||||
}
|
||||
|
||||
function setFieldValidity(input, message) {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
input.setCustomValidity(message);
|
||||
input.classList.add('is-invalid');
|
||||
if (input.setAttribute) {
|
||||
input.setAttribute('aria-invalid', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
function validateEntryRow(row) {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startInput = row.querySelector('[name="entry_start_datetime[]"]');
|
||||
var endInput = row.querySelector('[name="entry_end_datetime[]"]');
|
||||
var startValue;
|
||||
var endValue;
|
||||
var startDate;
|
||||
var endDate;
|
||||
|
||||
clearFieldValidity(endInput);
|
||||
|
||||
if (!startInput || !endInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
startValue = String(startInput.value || '').trim();
|
||||
endValue = String(endInput.value || '').trim();
|
||||
|
||||
if (!startValue || !endValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
startDate = parseDateTimeLocalValue(startValue);
|
||||
endDate = parseDateTimeLocalValue(endValue);
|
||||
|
||||
if (!startDate || !endDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (endDate.getTime() < startDate.getTime() + 60000) {
|
||||
setFieldValidity(endInput, 'End time must be at least 1 minute after the start time.');
|
||||
}
|
||||
}
|
||||
|
||||
function bindRowValidation(row) {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startInput = row.querySelector('[name="entry_start_datetime[]"]');
|
||||
var endInput = row.querySelector('[name="entry_end_datetime[]"]');
|
||||
|
||||
if (!startInput || !endInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
function handleValidation() {
|
||||
validateEntryRow(row);
|
||||
}
|
||||
|
||||
startInput.addEventListener('input', handleValidation);
|
||||
startInput.addEventListener('change', handleValidation);
|
||||
endInput.addEventListener('input', handleValidation);
|
||||
endInput.addEventListener('change', handleValidation);
|
||||
|
||||
validateEntryRow(row);
|
||||
}
|
||||
|
||||
function toUtcDateTimeLocalValue(value) {
|
||||
var localDate = new Date(String(value || '').trim());
|
||||
return Number.isNaN(localDate.getTime()) ? '' : localDate.toISOString();
|
||||
@@ -110,6 +205,7 @@
|
||||
return;
|
||||
}
|
||||
bindRemove(row);
|
||||
bindRowValidation(row);
|
||||
body.appendChild(fragment);
|
||||
markDirty();
|
||||
}
|
||||
@@ -117,6 +213,7 @@
|
||||
body.querySelectorAll('[data-timetable-entry-row]').forEach(function (row) {
|
||||
bindRemove(row);
|
||||
syncRowValuesToLocal(row);
|
||||
bindRowValidation(row);
|
||||
});
|
||||
|
||||
form.addEventListener('formdata', function (event) {
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<input type="datetime-local" name="entry_end_datetime[]" class="form-control" value="{{endValue}}" />
|
||||
<div class="invalid-feedback">End time must be at least 1 minute after the start time.</div>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" data-remove-timetable-entry>Remove</button>
|
||||
@@ -86,6 +87,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<input type="datetime-local" name="entry_end_datetime[]" class="form-control" value="" />
|
||||
<div class="invalid-feedback">End time must be at least 1 minute after the start time.</div>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm" data-remove-timetable-entry>Remove</button>
|
||||
|
||||
Reference in New Issue
Block a user