v22: modal confirm, validate operador/turno, print from confirm, fix parseNum/fmtNum
Build Fechamento de Caixa / build (macos-14, app) (push) Has been cancelled
Build Fechamento de Caixa / build (ubuntu-22.04, deb) (push) Has been cancelled
Build Fechamento de Caixa / build (windows-2022, msi) (push) Has been cancelled

This commit is contained in:
root
2026-06-22 18:15:05 +00:00
parent adee99d8ad
commit feeaa02396
+52 -44
View File
@@ -576,11 +576,30 @@ let estado = {
// ─── Helpers ──────────────────────────────────────────────────────────────
const fmt = v => 'R$ ' + (parseFloat(v) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 });
const parseNum = v => parseFloat((String(v) || '0').replace(/\./g,'').replace(',','.')) || 0;
const parseNum = v => {
const s = String(v || '0');
// Handle empty or whitespace
if (!s.trim()) return 0;
// Brazilian format: 1.234,56 → 1234.56
// Strategy: remove thousand dots, replace decimal comma with dot
// "10,55" → "1055,00" (wrong) → fix: split on comma first
// "1.055,00" → parts=["1.055","00"] → intPart="1055", decPart="00" → 1055.00
const lastComma = s.lastIndexOf(',');
if (lastComma === -1) {
// No comma: just remove thousand separators (dots)
return parseFloat(s.replace(/,/g, '').replace(/\./g, '')) || 0;
}
const intPart = s.slice(0, lastComma).replace(/\./g, '').replace(/,/g, '');
const decPart = s.slice(lastComma + 1);
return parseFloat(intPart + '.' + decPart) || 0;
};
const setText = (id, t) => { const e = document.getElementById(id); if (e) e.textContent = t; };
const setVal = (id, v) => { const e = document.getElementById(id); if (e) e.value = v; };
const val = id => { const e = document.getElementById(id); return e ? e.value : ''; };
const fmtNum = v => { const n = parseNum(v); return isNaN(n) ? '' : n.toLocaleString('pt-BR', { minimumFractionDigits: 2 }); };
const fmtNum = v => {
const n = typeof v === 'number' ? v : parseNum(v);
return isNaN(n) ? '' : n.toLocaleString('pt-BR', { minimumFractionDigits: 2 });
};
// Format time: 4 digits → HH:MM
function fmtTime(v) {
@@ -839,45 +858,43 @@ function updateTotals() {
// Strategy: detect "comma-only" input and convert to ",00" immediately.
// For normal digit input: add ,00 on blur (not on every digit).
let _justEnteredDatalist = false;
// ─── Numeric input: auto ,00 on digit+blur pattern ───────────────────────
// These fields are plain text inputs (no datalist). Format on blur only.
// For sys-troco which is user-editable: also format on Enter keydown.
['troco','credito','debito','alimentacao','vales','receber','pix'].forEach(k => {
const el = document.getElementById(`sys-${k}`);
if (!el) return;
// On input: handle comma-only typed as immediate ,00
// On input: just track for autosave
el.addEventListener('input', () => {
const v = el.value;
// If user just typed a comma as last char (and no ,00 yet), convert to ,00
if (v.endsWith(',') && !v.endsWith(',00')) {
el.value = v + '00';
// Move cursor before the trailing 00
const pos = v.length; // position after the comma
setTimeout(() => { el.selectionStart = el.selectionEnd = pos; }, 0);
}
updateTotals(); scheduleSave();
updateTotals();
scheduleSave();
});
// On Enter: trigger datalist, then blur+focus cycle
// On keydown Enter: format value directly (Enter does not trigger blur for tabindex=-1)
el.addEventListener('keydown', e => {
if (e.key === 'Enter') {
_justEnteredDatalist = true;
el.blur();
el.focus();
setTimeout(() => { _justEnteredDatalist = false; }, 400);
e.preventDefault();
const raw = el.value.trim();
if (!raw) { el.value = ''; return; }
const num = parseNum(raw);
if (isNaN(num) || num === 0) { el.value = ''; }
else { el.value = fmtNum(num); }
updateTotals();
scheduleSave();
}
});
// On blur: format to proper number if it looks like a partial entry
// On blur: format the value
el.addEventListener('blur', () => {
if (_justEnteredDatalist) return;
const v = parseNum(el.value);
if (isNaN(v) || v === 0) {
el.value = '';
} else {
el.value = fmtNum(v);
}
const raw = el.value.trim();
if (!raw) { el.value = ''; return; }
const num = parseNum(raw);
if (isNaN(num) || num === 0) { el.value = ''; }
else { el.value = fmtNum(num); }
updateTotals();
scheduleSave();
});
});
@@ -887,32 +904,23 @@ let _justEnteredDatalist = false;
el.addEventListener('input', () => {
const v = el.value;
if (v.endsWith(',') && !v.endsWith(',00')) {
if (v.endsWith(',') && !v.includes(',') && v !== ',') {
el.value = v + '00';
const pos = v.length;
setTimeout(() => { el.selectionStart = el.selectionEnd = pos; }, 0);
}
updateTotals(); scheduleSave();
});
el.addEventListener('keydown', e => {
if (e.key === 'Enter') {
_justEnteredDatalist = true;
el.blur();
el.focus();
setTimeout(() => { _justEnteredDatalist = false; }, 400);
}
updateTotals();
scheduleSave();
});
el.addEventListener('blur', () => {
if (_justEnteredDatalist) return;
const v = parseNum(el.value);
if (isNaN(v) || v === 0) {
el.value = '';
} else {
el.value = fmtNum(v);
}
const raw = el.value.trim();
if (!raw) { el.value = ''; return; }
const num = parseNum(raw);
if (isNaN(num) || num === 0) { el.value = ''; }
else { el.value = fmtNum(num); }
updateTotals();
scheduleSave();
});
});