fix: replace type=time with text inputs to force 24h HH:MM format (no AM/PM)
Some checks failed
Build & Push Docker / build (push) Has been cancelled
Some checks failed
Build & Push Docker / build (push) Has been cancelled
This commit is contained in:
@@ -1004,3 +1004,15 @@ body {
|
|||||||
.hidden {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Time text inputs (replacing type=time to avoid AM/PM) */
|
||||||
|
.time-input {
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-input.input-error {
|
||||||
|
border-color: var(--danger) !important;
|
||||||
|
background: #fff5f5;
|
||||||
|
}
|
||||||
|
|||||||
@@ -191,11 +191,11 @@
|
|||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Začátek</label>
|
<label>Začátek</label>
|
||||||
<input type="time" id="modalBlockStart" step="900">
|
<input type="text" id="modalBlockStart" placeholder="HH:MM" maxlength="5" class="time-input" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Konec</label>
|
<label>Konec</label>
|
||||||
<input type="time" id="modalBlockEnd" step="900">
|
<input type="text" id="modalBlockEnd" placeholder="HH:MM" maxlength="5" class="time-input" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|||||||
@@ -293,8 +293,10 @@ const App = {
|
|||||||
const responsible = document.getElementById('modalBlockResponsible').value.trim() || null;
|
const responsible = document.getElementById('modalBlockResponsible').value.trim() || null;
|
||||||
const notes = document.getElementById('modalBlockNotes').value.trim() || null;
|
const notes = document.getElementById('modalBlockNotes').value.trim() || null;
|
||||||
|
|
||||||
|
const timeRe = /^\d{2}:\d{2}$/;
|
||||||
if (!title) { this.toast('Zadejte název bloku', 'error'); return; }
|
if (!title) { this.toast('Zadejte název bloku', 'error'); return; }
|
||||||
if (!start || !end) { this.toast('Zadejte čas začátku a konce', 'error'); return; }
|
if (!start || !end) { this.toast('Zadejte čas začátku a konce', 'error'); return; }
|
||||||
|
if (!timeRe.test(start) || !timeRe.test(end)) { this.toast('Neplatný formát času (HH:MM)', 'error'); return; }
|
||||||
|
|
||||||
if (blockId) {
|
if (blockId) {
|
||||||
// Edit existing block (no series expansion on edit — user edits only this one)
|
// Edit existing block (no series expansion on edit — user edits only this one)
|
||||||
@@ -370,7 +372,48 @@ const App = {
|
|||||||
|
|
||||||
// ─── Events ───────────────────────────────────────────────────────
|
// ─── Events ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
// ─── Time input helpers ───────────────────────────────────────────
|
||||||
|
|
||||||
|
_initTimeInput(el) {
|
||||||
|
// Auto-format: allow only digits + colon, insert ':' after 2 digits
|
||||||
|
el.addEventListener('input', (e) => {
|
||||||
|
let v = e.target.value.replace(/[^0-9:]/g, '');
|
||||||
|
// Strip colons and rebuild
|
||||||
|
const digits = v.replace(/:/g, '');
|
||||||
|
if (digits.length >= 3) {
|
||||||
|
v = digits.slice(0, 2) + ':' + digits.slice(2, 4);
|
||||||
|
} else {
|
||||||
|
v = digits;
|
||||||
|
}
|
||||||
|
e.target.value = v;
|
||||||
|
});
|
||||||
|
el.addEventListener('blur', (e) => {
|
||||||
|
const v = e.target.value;
|
||||||
|
if (!v) return;
|
||||||
|
// Validate HH:MM format
|
||||||
|
if (!/^\d{2}:\d{2}$/.test(v)) {
|
||||||
|
e.target.classList.add('input-error');
|
||||||
|
this.toast('Neplatný čas (formát HH:MM)', 'error');
|
||||||
|
} else {
|
||||||
|
const [h, m] = v.split(':').map(Number);
|
||||||
|
if (h > 23 || m > 59) {
|
||||||
|
e.target.classList.add('input-error');
|
||||||
|
this.toast('Neplatný čas (00:00–23:59)', 'error');
|
||||||
|
} else {
|
||||||
|
e.target.classList.remove('input-error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.addEventListener('focus', (e) => {
|
||||||
|
e.target.classList.remove('input-error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
bindEvents() {
|
bindEvents() {
|
||||||
|
// Init time inputs
|
||||||
|
this._initTimeInput(document.getElementById('modalBlockStart'));
|
||||||
|
this._initTimeInput(document.getElementById('modalBlockEnd'));
|
||||||
|
|
||||||
// Import JSON
|
// Import JSON
|
||||||
document.getElementById('importJsonInput').addEventListener('change', (e) => {
|
document.getElementById('importJsonInput').addEventListener('change', (e) => {
|
||||||
if (e.target.files[0]) importJson(e.target.files[0]);
|
if (e.target.files[0]) importJson(e.target.files[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user