sitche_form

This commit is contained in:
Mateusz Gruszczyński
2025-09-26 23:25:13 +02:00
parent 052439b340
commit ee05bf74b5
2 changed files with 44 additions and 43 deletions

View File

@@ -1,71 +1,74 @@
// static/js/postepy_guard.js // static/js/przelaczniki_zabezpieczenie.js
(function () { (function () {
'use strict'; 'use strict';
function ready(fn) { function onReady(cb) {
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', fn); document.addEventListener('DOMContentLoaded', cb);
} else { } else {
fn(); cb();
} }
} }
ready(function () { onReady(function () {
var boxes = Array.prototype.slice.call( var boxes = Array.prototype.slice.call(
document.querySelectorAll('input.form-check-input[type="checkbox"][data-group="postepy"]') document.querySelectorAll('input.form-check-input[type="checkbox"][data-group="postepy"]')
); );
if (!boxes.length) return;
var warning = document.getElementById('postepyWarning'); var warning = document.getElementById('postepyWarning');
function atLeastOneChecked() { if (!boxes.length || !warning) {
return boxes.some(function (b) { return b.checked; }); // Nic do zrobienia, brak elementów
return;
} }
function updateWarning() { function atLeastOneChecked() {
var show = !atLeastOneChecked(); return boxes.some(function (b) { return !!b.checked; });
if (warning) { }
warning.classList.toggle('d-none', !show);
if (show) { function showWarning(show) {
// delikatny highlight warning.classList.toggle('d-none', !show);
warning.classList.add('animate__animated', 'animate__headShake'); if (show) {
setTimeout(function () { // dyskretny highlight
warning.classList.remove('animate__animated', 'animate__headShake'); warning.classList.add('border', 'border-warning');
}, 700); warning.style.transition = 'box-shadow 0.2s ease';
} warning.style.boxShadow = '0 0 0.25rem rgba(255,193,7,.6)';
setTimeout(function () {
warning.style.boxShadow = '';
}, 300);
} }
} }
// Blokuj odznaczenie ostatniego i pokaż ostrzeżenie function enforceAtLeastOne(e) {
// Jeżeli po zmianie byłaby 0/3, przywróć zaznaczenie klikniętego i pokaż ostrzeżenie
if (!atLeastOneChecked()) {
e.target.checked = true;
showWarning(true);
e.target.classList.add('is-invalid');
setTimeout(function () { e.target.classList.remove('is-invalid'); }, 400);
return;
}
// Jeśli >=1, ostrzeżenie ukryj
showWarning(false);
}
// Podpinka zdarzeń
boxes.forEach(function (box) { boxes.forEach(function (box) {
box.addEventListener('change', function () { box.addEventListener('change', enforceAtLeastOne);
if (!atLeastOneChecked()) {
// przywróć zaznaczenie i pokaż ostrzeżenie
box.checked = true;
updateWarning();
// krótka wizualna informacja na samym przycisku
box.classList.add('is-invalid');
setTimeout(function(){ box.classList.remove('is-invalid'); }, 500);
return;
}
updateWarning();
});
}); });
// Walidacja przy submit — pokaż blok zamiast alertu // Walidacja przy submit (na wszelki wypadek)
var form = boxes[0].closest('form'); var form = boxes[0].closest('form');
if (form) { if (form) {
form.addEventListener('submit', function (e) { form.addEventListener('submit', function (e) {
if (!atLeastOneChecked()) { if (!atLeastOneChecked()) {
e.preventDefault(); e.preventDefault();
updateWarning(); showWarning(true);
// focus na pierwszy przełącznik
boxes[0].focus(); boxes[0].focus();
} }
}); });
} }
// Inicjalny stan // Inicjalny stan (np. po rerenderze z błędem)
updateWarning(); showWarning(!atLeastOneChecked());
}); });
})(); })();

View File

@@ -297,10 +297,6 @@
</div> </div>
<div class="row g-3 mt-2"> <div class="row g-3 mt-2">
<div id="postepyWarning" class="alert alert-warning d-none mt-2" role="alert">
Nie można wyłączyć wszystkich wskaźników postępu. Pozostaw przynajmniej jeden włączony.
</div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input <input
@@ -343,7 +339,9 @@
</div> </div>
</div> </div>
</div> </div>
<div id="postepyWarning" class="alert alert-warning d-none mt-2" role="alert">
Nie można wyłączyć wszystkich wskaźników postępu. Pozostaw przynajmniej jeden włączony.
</div>
</div> </div>