Major Refactor: Refactor the codebase to improve readability and maintainability
This commit is contained in:
42
static/js/admin_productos.js
Normal file
42
static/js/admin_productos.js
Normal file
@@ -0,0 +1,42 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
window.formatHelpers.bindMoneyInput('.money-input');
|
||||
|
||||
const editModal = document.getElementById('editProductModal');
|
||||
if (editModal) {
|
||||
editModal.addEventListener('show.bs.modal', function (event) {
|
||||
const button = event.relatedTarget;
|
||||
if (!button || !button.hasAttribute('data-id')) return;
|
||||
|
||||
const id = button.getAttribute('data-id');
|
||||
const name = button.getAttribute('data-name');
|
||||
const price = button.getAttribute('data-price');
|
||||
const commission = button.getAttribute('data-commission');
|
||||
const zonaId = button.getAttribute('data-zona');
|
||||
|
||||
const form = editModal.querySelector('#editProductForm');
|
||||
form.action = `/admin/productos/edit/${id}`;
|
||||
|
||||
editModal.querySelector('#edit_name').value = name;
|
||||
editModal.querySelector('#edit_price').value = price;
|
||||
editModal.querySelector('#edit_commission').value = commission;
|
||||
editModal.querySelector('#edit_zona_id').value = zonaId;
|
||||
|
||||
editModal.querySelectorAll('.money-input').forEach(input => {
|
||||
input.dispatchEvent(new Event('input'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const searchInput = document.getElementById('searchProduct');
|
||||
const productRows = document.querySelectorAll('.product-row');
|
||||
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', function () {
|
||||
const term = this.value.toLowerCase();
|
||||
productRows.forEach(row => {
|
||||
const name = row.cells[0].textContent.toLowerCase();
|
||||
row.style.display = name.includes(term) ? '' : 'none';
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
137
static/js/admin_rendiciones.js
Normal file
137
static/js/admin_rendiciones.js
Normal file
@@ -0,0 +1,137 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
window.formatHelpers.bindMoneyInput('.money-input');
|
||||
|
||||
window.updateBadge = function (selectElement, badgeId) {
|
||||
const option = selectElement.options[selectElement.selectedIndex];
|
||||
const tipo = option ? option.getAttribute('data-tipo') : null;
|
||||
const badgeDiv = document.getElementById(badgeId);
|
||||
if (!badgeDiv) return;
|
||||
|
||||
if (!tipo) {
|
||||
badgeDiv.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const color = (tipo === 'Full Time') ? 'bg-success' : 'bg-secondary';
|
||||
badgeDiv.innerHTML = `<span class="badge ${color}">${tipo}</span>`;
|
||||
};
|
||||
|
||||
window.toggleCompDiv = function (id, select) {
|
||||
const compDiv = document.getElementById(`comp_com_div_${id}`);
|
||||
if (compDiv) compDiv.style.display = select.value ? 'flex' : 'none';
|
||||
window.updateBadge(select, `badge_comp_${id}`);
|
||||
window.updateComisionToggle(select, `cc_${id}`);
|
||||
};
|
||||
|
||||
window.updateComisionToggle = function (selectElement, toggleId) {
|
||||
const option = selectElement.options[selectElement.selectedIndex];
|
||||
const tipoJornada = option ? option.getAttribute('data-tipo') : null;
|
||||
const toggleSwitch = document.getElementById(toggleId);
|
||||
|
||||
if (toggleSwitch && tipoJornada) {
|
||||
toggleSwitch.checked = (tipoJornada === 'Full Time');
|
||||
} else if (toggleSwitch && !selectElement.value) {
|
||||
toggleSwitch.checked = false;
|
||||
}
|
||||
|
||||
const baseId = toggleId.split('_')[1];
|
||||
const targetBadge = toggleId.startsWith('wc') ? `badge_worker_${baseId}` : `badge_comp_${baseId}`;
|
||||
window.updateBadge(selectElement, targetBadge);
|
||||
};
|
||||
|
||||
window.recalcProductLine = function (input) {
|
||||
const qty = parseInt(input.value) || 0;
|
||||
const price = parseInt(input.getAttribute('data-price')) || 0;
|
||||
const rid = input.getAttribute('data-rid');
|
||||
const row = input.closest('tr');
|
||||
|
||||
const lineTotal = qty * price;
|
||||
const lineCell = row.querySelector('.item-total-line');
|
||||
if (lineCell) lineCell.innerText = '$' + lineTotal.toLocaleString('es-CL');
|
||||
|
||||
const modal = document.getElementById(`editRendicion${rid}`);
|
||||
let newSysTotal = 0;
|
||||
if (modal) {
|
||||
modal.querySelectorAll('.prod-qty-input').forEach(inp => {
|
||||
newSysTotal += (parseInt(inp.value) || 0) * (parseInt(inp.getAttribute('data-price')) || 0);
|
||||
});
|
||||
}
|
||||
const sysTotalEl = document.getElementById(`sys_total_${rid}`);
|
||||
if (sysTotalEl) sysTotalEl.innerText = '$' + newSysTotal.toLocaleString('es-CL');
|
||||
};
|
||||
|
||||
window.calcTotalEdit = function (id) {
|
||||
const getVal = (inputId) => window.formatHelpers.getMoneyInputValue(inputId);
|
||||
const total = getVal(`edit_debito_${id}`) + getVal(`edit_credito_${id}`)
|
||||
+ getVal(`edit_mp_${id}`) + getVal(`edit_efectivo_${id}`);
|
||||
const el = document.getElementById(`display_nuevo_total_${id}`);
|
||||
if (el) el.innerText = '$' + total.toLocaleString('es-CL');
|
||||
};
|
||||
|
||||
const editModals = document.querySelectorAll('[id^="editRendicion"]');
|
||||
const editForms = document.querySelectorAll('form[action*="/admin/rendiciones/edit/"]');
|
||||
const errorModalEl = document.getElementById('errorPersonaModal');
|
||||
const errorModal = errorModalEl ? new bootstrap.Modal(errorModalEl) : null;
|
||||
const errorBody = document.getElementById('errorPersonaModalBody');
|
||||
|
||||
editForms.forEach(form => {
|
||||
form.addEventListener('submit', function (e) {
|
||||
const workerId = this.querySelector('select[name="worker_id"]').value;
|
||||
const companionId = this.querySelector('select[name="companion_id"]').value;
|
||||
|
||||
if (companionId && workerId === companionId) {
|
||||
e.preventDefault();
|
||||
if (errorModal && errorBody) {
|
||||
errorBody.innerHTML = "<strong>Error:</strong> El trabajador titular y el acompañante no pueden ser la misma persona. Por favor, selecciona a alguien más.";
|
||||
errorModal.show();
|
||||
} else {
|
||||
alert("Un trabajador no puede ser su propio acompañante. Por favor, corrige la selección.");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
editModals.forEach(modal => {
|
||||
modal.addEventListener('show.bs.modal', function () {
|
||||
const rid = this.id.replace('editRendicion', '');
|
||||
const workerSelect = this.querySelector('select[name="worker_id"]');
|
||||
if (workerSelect) window.updateBadge(workerSelect, `badge_worker_${rid}`);
|
||||
|
||||
const compSelect = this.querySelector('select[name="companion_id"]');
|
||||
if (compSelect && compSelect.value) window.updateBadge(compSelect, `badge_comp_${rid}`);
|
||||
});
|
||||
|
||||
modal.addEventListener('hidden.bs.modal', function () {
|
||||
const form = this.querySelector('form');
|
||||
if (!form) return;
|
||||
form.reset();
|
||||
const rid = this.id.replace('editRendicion', '');
|
||||
window.calcTotalEdit(rid);
|
||||
this.querySelectorAll('.prod-qty-input').forEach(inp => window.recalcProductLine(inp));
|
||||
});
|
||||
});
|
||||
|
||||
const zonaSelect = document.getElementById('zonaSelect');
|
||||
const moduloSelect = document.getElementById('moduloSelect');
|
||||
|
||||
if (zonaSelect && moduloSelect) {
|
||||
const moduloOptions = Array.from(moduloSelect.options);
|
||||
|
||||
function filterModulos() {
|
||||
const selectedZona = zonaSelect.value;
|
||||
moduloOptions.forEach(option => {
|
||||
if (option.value === "") {
|
||||
option.style.display = '';
|
||||
} else if (!selectedZona || option.dataset.zona === selectedZona) {
|
||||
option.style.display = '';
|
||||
} else {
|
||||
option.style.display = 'none';
|
||||
if (option.selected) moduloSelect.value = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
zonaSelect.addEventListener('change', filterModulos);
|
||||
filterModulos();
|
||||
}
|
||||
});
|
||||
80
static/js/admin_workers.js
Normal file
80
static/js/admin_workers.js
Normal file
@@ -0,0 +1,80 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const editWorkerModal = document.getElementById('editWorkerModal');
|
||||
const confirmResetModal = document.getElementById('confirmResetPass');
|
||||
|
||||
if (editWorkerModal) {
|
||||
editWorkerModal.addEventListener('show.bs.modal', function (event) {
|
||||
const button = event.relatedTarget;
|
||||
if (!button || !button.hasAttribute('data-id')) return;
|
||||
|
||||
const id = button.getAttribute('data-id');
|
||||
const name = button.getAttribute('data-name');
|
||||
|
||||
const editForm = editWorkerModal.querySelector('#editWorkerForm');
|
||||
const resetForm = confirmResetModal ? confirmResetModal.querySelector('form') : null;
|
||||
|
||||
editForm.action = "/admin/workers/edit/" + id;
|
||||
if (resetForm) resetForm.action = "/admin/workers/reset_password/" + id;
|
||||
|
||||
if (confirmResetModal) {
|
||||
confirmResetModal.querySelector('.modal-body').textContent =
|
||||
`¿Estás seguro de generar una nueva contraseña para ${name}? La anterior dejará de funcionar.`;
|
||||
}
|
||||
|
||||
editWorkerModal.querySelector('#edit_worker_rut').value = button.getAttribute('data-rut');
|
||||
editWorkerModal.querySelector('#edit_worker_name').value = name;
|
||||
editWorkerModal.querySelector('#edit_worker_phone').value = button.getAttribute('data-phone');
|
||||
editWorkerModal.querySelector('#edit_worker_modulo').value = button.getAttribute('data-modulo');
|
||||
editWorkerModal.querySelector('#edit_worker_tipo').value = button.getAttribute('data-tipo');
|
||||
});
|
||||
}
|
||||
|
||||
if (editWorkerModal && confirmResetModal) {
|
||||
const btnCancelar = confirmResetModal.querySelector('.btn-secondary');
|
||||
const btnCerrarX = confirmResetModal.querySelector('.btn-close');
|
||||
|
||||
const reabrirEdicion = () => {
|
||||
const modalEdicion = new bootstrap.Modal(editWorkerModal);
|
||||
modalEdicion.show();
|
||||
};
|
||||
|
||||
if (btnCancelar) btnCancelar.addEventListener('click', reabrirEdicion);
|
||||
if (btnCerrarX) btnCerrarX.addEventListener('click', reabrirEdicion);
|
||||
}
|
||||
|
||||
const rutInput = document.getElementById('rutInput');
|
||||
if (rutInput) {
|
||||
window.formatHelpers.bindRutInput('#rutInput');
|
||||
}
|
||||
|
||||
window.formatHelpers.bindPhoneInput('.phone-input, #phoneInput');
|
||||
|
||||
const searchInputWorker = document.getElementById('searchWorker');
|
||||
const moduleSelectFilter = document.getElementById('filterModule');
|
||||
const typeSelectFilter = document.getElementById('filterType');
|
||||
const workerRows = document.querySelectorAll('.worker-row');
|
||||
|
||||
function filterWorkers() {
|
||||
if (!searchInputWorker) return;
|
||||
const searchTerm = searchInputWorker.value.toLowerCase();
|
||||
const selectedModule = moduleSelectFilter ? moduleSelectFilter.value : 'all';
|
||||
const selectedType = typeSelectFilter ? typeSelectFilter.value : 'all';
|
||||
|
||||
workerRows.forEach(row => {
|
||||
const rut = row.cells[0].textContent.toLowerCase();
|
||||
const name = row.cells[1].textContent.toLowerCase();
|
||||
const rowModule = row.getAttribute('data-modulo');
|
||||
const rowType = row.getAttribute('data-tipo');
|
||||
|
||||
const matchesSearch = rut.includes(searchTerm) || name.includes(searchTerm);
|
||||
const matchesModule = selectedModule === 'all' || rowModule === selectedModule;
|
||||
const matchesType = selectedType === 'all' || rowType === selectedType;
|
||||
|
||||
row.style.display = (matchesSearch && matchesModule && matchesType) ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
if (searchInputWorker) searchInputWorker.addEventListener('input', filterWorkers);
|
||||
if (moduleSelectFilter) moduleSelectFilter.addEventListener('change', filterWorkers);
|
||||
if (typeSelectFilter) typeSelectFilter.addEventListener('change', filterWorkers);
|
||||
});
|
||||
71
static/js/format-helpers.js
Normal file
71
static/js/format-helpers.js
Normal file
@@ -0,0 +1,71 @@
|
||||
window.formatHelpers = (function () {
|
||||
function formatRutInput(input) {
|
||||
let value = input.value.replace(/[^0-9kK]/g, '').toUpperCase();
|
||||
if (value.length > 9) value = value.slice(0, 9);
|
||||
if (value.length > 1) {
|
||||
let body = value.slice(0, -1);
|
||||
let dv = value.slice(-1);
|
||||
body = body.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
|
||||
input.value = `${body}-${dv}`;
|
||||
} else {
|
||||
input.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
function bindRutInput(selector) {
|
||||
document.querySelectorAll(selector).forEach(function (inp) {
|
||||
inp.addEventListener('input', function () { formatRutInput(inp); });
|
||||
});
|
||||
}
|
||||
|
||||
function formatPhone(input) {
|
||||
let value = input.value.replace(/\D/g, '');
|
||||
if (value.startsWith('56')) value = value.substring(2);
|
||||
value = value.substring(0, 9);
|
||||
if (value.length > 5) input.value = value.replace(/(\d{1})(\d{4})(\d+)/, '$1 $2 $3');
|
||||
else if (value.length > 1) input.value = value.replace(/(\d{1})(\d+)/, '$1 $2');
|
||||
else input.value = value;
|
||||
}
|
||||
|
||||
function bindPhoneInput(selector) {
|
||||
document.querySelectorAll(selector).forEach(function (inp) {
|
||||
inp.addEventListener('input', function () { formatPhone(inp); });
|
||||
});
|
||||
}
|
||||
|
||||
function formatMoneyInput(input) {
|
||||
if (input.dataset.formatted === '1') return;
|
||||
let value = input.value.replace(/\D/g, '');
|
||||
input.value = value === '' ? '' : parseInt(value, 10).toLocaleString('es-CL');
|
||||
input.dataset.formatted = '1';
|
||||
}
|
||||
|
||||
function bindMoneyInput(selector) {
|
||||
document.querySelectorAll(selector).forEach(function (input) {
|
||||
formatMoneyInput(input);
|
||||
input.addEventListener('input', function () {
|
||||
let value = input.value.replace(/\D/g, '');
|
||||
input.value = value === '' ? '' : parseInt(value, 10).toLocaleString('es-CL');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function parseMoney(value) {
|
||||
return parseInt(String(value).replace(/\D/g, ''), 10) || 0;
|
||||
}
|
||||
|
||||
function getMoneyInputValue(id) {
|
||||
return parseMoney(document.getElementById(id).value);
|
||||
}
|
||||
|
||||
return {
|
||||
formatRutInput: formatRutInput,
|
||||
bindRutInput: bindRutInput,
|
||||
formatPhone: formatPhone,
|
||||
bindPhoneInput: bindPhoneInput,
|
||||
formatMoneyInput: formatMoneyInput,
|
||||
bindMoneyInput: bindMoneyInput,
|
||||
parseMoney: parseMoney,
|
||||
getMoneyInputValue: getMoneyInputValue
|
||||
};
|
||||
})();
|
||||
3
static/js/login.js
Normal file
3
static/js/login.js
Normal file
@@ -0,0 +1,3 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
window.formatHelpers.bindRutInput('#rutInput');
|
||||
});
|
||||
30
static/js/navbar.js
Normal file
30
static/js/navbar.js
Normal file
@@ -0,0 +1,30 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const brandIcon = document.getElementById("brandIcon");
|
||||
if (!brandIcon) return;
|
||||
|
||||
let clickCount = 0;
|
||||
let clickResetTimer;
|
||||
|
||||
brandIcon.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
clickCount++;
|
||||
clearTimeout(clickResetTimer);
|
||||
clickResetTimer = setTimeout(() => { clickCount = 0; }, 800);
|
||||
|
||||
if (clickCount >= 5) {
|
||||
clickCount = 0;
|
||||
clearTimeout(clickResetTimer);
|
||||
|
||||
const originalClass = this.className;
|
||||
this.className = "fs-3 me-2 baguette-spin";
|
||||
this.innerHTML = "🥖";
|
||||
|
||||
setTimeout(() => {
|
||||
this.className = originalClass;
|
||||
this.innerHTML = "";
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
});
|
||||
55
static/js/product-history-chart.js
Normal file
55
static/js/product-history-chart.js
Normal file
@@ -0,0 +1,55 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
if (typeof Chart === "undefined") return;
|
||||
|
||||
const COLORS = ['#0d6efd', '#198754', '#dc3545', '#ffc107', '#0dcaf0'];
|
||||
let priceChartInstance = null;
|
||||
|
||||
window.showHistory = async function (prodId, prodName) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('chartModal'));
|
||||
document.getElementById('chartModalTitle').innerText = 'Fluctuación de Precio: ' + prodName;
|
||||
modal.show();
|
||||
|
||||
const res = await fetch(`/admin/api/productos/${prodId}/historial`);
|
||||
const data = await res.json();
|
||||
|
||||
const zonas = [...new Set(data.map(d => d.zona))];
|
||||
const fechas = [...new Set(data.map(d => d.fecha.split(' ')[0]))].sort();
|
||||
|
||||
const datasets = zonas.map((zona, index) => {
|
||||
let lastPrice = 0;
|
||||
const dataPoints = fechas.map(f => {
|
||||
const hits = data.filter(d => d.zona === zona && d.fecha.startsWith(f));
|
||||
if (hits.length > 0) {
|
||||
lastPrice = hits[hits.length - 1].price;
|
||||
}
|
||||
return lastPrice;
|
||||
});
|
||||
return {
|
||||
label: zona,
|
||||
data: dataPoints,
|
||||
borderColor: COLORS[index % COLORS.length],
|
||||
backgroundColor: COLORS[index % COLORS.length],
|
||||
stepped: true,
|
||||
borderWidth: 2
|
||||
};
|
||||
});
|
||||
|
||||
const ctx = document.getElementById('priceChart').getContext('2d');
|
||||
if (priceChartInstance) priceChartInstance.destroy();
|
||||
|
||||
priceChartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: { labels: fechas, datasets: datasets },
|
||||
options: {
|
||||
responsive: true,
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: { callback: v => '$' + v.toLocaleString('es-CL') }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
206
static/js/worker_dashboard.js
Normal file
206
static/js/worker_dashboard.js
Normal file
@@ -0,0 +1,206 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
window.formatHelpers.bindMoneyInput('.money-input');
|
||||
|
||||
const companionSelect = document.getElementById('companion_select');
|
||||
if (companionSelect) {
|
||||
companionSelect.addEventListener('change', function () {
|
||||
const timeDiv = document.getElementById('companion_times_div');
|
||||
const compIn = document.getElementById('comp_in');
|
||||
const compOut = document.getElementById('comp_out');
|
||||
if (this.value) {
|
||||
timeDiv.style.display = 'block';
|
||||
compIn.required = true;
|
||||
compOut.required = true;
|
||||
} else {
|
||||
timeDiv.style.display = 'none';
|
||||
compIn.required = false;
|
||||
compOut.required = false;
|
||||
compIn.value = '';
|
||||
compOut.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getVal(id) {
|
||||
return window.formatHelpers.getMoneyInputValue(id);
|
||||
}
|
||||
|
||||
function checkWarnings() {
|
||||
const totalProductos = getVal('total_productos_calc');
|
||||
const totalDeclarado = getVal('total_general');
|
||||
const gastos = getVal('gastos');
|
||||
const efectivo = getVal('venta_efectivo');
|
||||
|
||||
let warnings = [];
|
||||
if ((totalProductos > 0 || totalDeclarado > 0) && totalProductos !== totalDeclarado) {
|
||||
warnings.push("El <strong>Total Venta por Productos</strong> no coincide con el <strong>Total Ventas Declaradas</strong>.");
|
||||
}
|
||||
if (gastos > efectivo) {
|
||||
warnings.push("El <strong>Monto de Gastos</strong> es mayor que el <strong>Efectivo</strong> declarado.");
|
||||
}
|
||||
|
||||
const warningContainer = document.getElementById('discrepancy_warning');
|
||||
const warningText = document.getElementById('discrepancy_text');
|
||||
if (warnings.length > 0) {
|
||||
warningText.innerHTML = warnings.join("<br>");
|
||||
warningContainer.style.display = 'block';
|
||||
} else {
|
||||
warningContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
const inputsCantidad = document.querySelectorAll('input[name^="qty_"]');
|
||||
const displayTotalProductos = document.getElementById('total_productos_calc');
|
||||
|
||||
function calcularVentaProductos() {
|
||||
if (!displayTotalProductos) return;
|
||||
let granTotal = 0;
|
||||
const filas = document.querySelectorAll('tbody tr');
|
||||
|
||||
filas.forEach(fila => {
|
||||
const inputQty = fila.querySelector('input[name^="qty_"]');
|
||||
if (inputQty) {
|
||||
if (parseInt(inputQty.value) < 0) inputQty.value = 0;
|
||||
const cantidad = parseInt(inputQty.value) || 0;
|
||||
const precioTexto = fila.cells[1].innerText.replace(/\D/g, '');
|
||||
const precio = parseInt(precioTexto) || 0;
|
||||
granTotal += (cantidad * precio);
|
||||
}
|
||||
});
|
||||
displayTotalProductos.value = granTotal.toLocaleString('es-CL');
|
||||
checkWarnings();
|
||||
}
|
||||
|
||||
inputsCantidad.forEach(input => {
|
||||
input.addEventListener('keydown', function (e) {
|
||||
if (['Backspace', 'Tab', 'ArrowLeft', 'ArrowRight', 'Delete', 'Enter'].includes(e.key) || e.ctrlKey || e.metaKey) return;
|
||||
if (e.key < '0' || e.key > '9') e.preventDefault();
|
||||
});
|
||||
|
||||
input.addEventListener('input', function () {
|
||||
this.value = this.value.replace(/\D/g, '');
|
||||
calcularVentaProductos();
|
||||
});
|
||||
});
|
||||
|
||||
const inputsVenta = document.querySelectorAll('.sale-input');
|
||||
const displayDigital = document.getElementById('total_digital');
|
||||
const displayGeneral = document.getElementById('total_general');
|
||||
|
||||
function calcularTotales() {
|
||||
const debito = getVal('venta_debito');
|
||||
const credito = getVal('venta_credito');
|
||||
const mp = getVal('venta_mp');
|
||||
const efectivo = getVal('venta_efectivo');
|
||||
|
||||
const totalDigital = debito + credito + mp;
|
||||
const totalGeneral = totalDigital + efectivo;
|
||||
|
||||
if (displayDigital) displayDigital.value = totalDigital.toLocaleString('es-CL');
|
||||
if (displayGeneral) displayGeneral.value = totalGeneral.toLocaleString('es-CL');
|
||||
|
||||
checkWarnings();
|
||||
}
|
||||
|
||||
inputsVenta.forEach(input => {
|
||||
input.addEventListener('input', calcularTotales);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.money-input').forEach(function (input) {
|
||||
input.addEventListener('keydown', function (e) {
|
||||
if (['Backspace', 'Tab', 'ArrowLeft', 'ArrowRight', 'Delete', 'Enter'].includes(e.key) || e.ctrlKey || e.metaKey) return;
|
||||
if (e.key < '0' || e.key > '9') e.preventDefault();
|
||||
});
|
||||
|
||||
input.addEventListener('focus', function () {
|
||||
if (this.value === '0') this.value = '';
|
||||
});
|
||||
|
||||
input.addEventListener('blur', function () {
|
||||
if (this.value.trim() === '' || this.value.trim() === '0') this.value = '0';
|
||||
calcularTotales();
|
||||
});
|
||||
|
||||
input.addEventListener('input', function () {
|
||||
let value = this.value.replace(/\D/g, '');
|
||||
if (value !== '') this.value = parseInt(value, 10).toLocaleString('es-CL');
|
||||
calcularTotales();
|
||||
});
|
||||
});
|
||||
|
||||
const submitModal = document.getElementById('confirmSubmitModal');
|
||||
const mainForm = document.querySelector('form');
|
||||
const alertModalEl = document.getElementById('globalAlertModal');
|
||||
const alertModal = alertModalEl ? new bootstrap.Modal(alertModalEl) : null;
|
||||
|
||||
function mostrarError(mensaje) {
|
||||
const body = document.getElementById('globalAlertModalBody');
|
||||
if (body) body.textContent = mensaje;
|
||||
if (alertModal) alertModal.show();
|
||||
}
|
||||
|
||||
function validarFormulario() {
|
||||
if (!mainForm) return false;
|
||||
const requiredInputs = mainForm.querySelectorAll('[required]');
|
||||
let valid = true;
|
||||
|
||||
requiredInputs.forEach(input => {
|
||||
const isMoney = input.classList.contains('money-input');
|
||||
if (!input.value.trim() || (isMoney && input.value === '')) {
|
||||
input.classList.add('is-invalid');
|
||||
valid = false;
|
||||
} else {
|
||||
input.classList.remove('is-invalid');
|
||||
}
|
||||
});
|
||||
return valid;
|
||||
}
|
||||
|
||||
if (submitModal) {
|
||||
const confirmBtn = submitModal.querySelector('button[type="submit"]');
|
||||
if (confirmBtn) {
|
||||
confirmBtn.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
if (validarFormulario()) {
|
||||
mainForm.submit();
|
||||
} else {
|
||||
const submitInstance = bootstrap.Modal.getInstance(submitModal);
|
||||
if (submitInstance) submitInstance.hide();
|
||||
mostrarError("Por favor, rellena los campos obligatorios (Fecha y Hora) antes de enviar.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (mainForm) {
|
||||
mainForm.addEventListener('submit', function (e) {
|
||||
const requiredInputs = this.querySelectorAll('[required]');
|
||||
let valid = true;
|
||||
|
||||
requiredInputs.forEach(input => {
|
||||
const isMoney = input.classList.contains('money-input');
|
||||
if (!input.value.trim() || (isMoney && input.value === '')) {
|
||||
input.classList.add('is-invalid');
|
||||
valid = false;
|
||||
} else {
|
||||
input.classList.remove('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
if (!valid) {
|
||||
e.preventDefault();
|
||||
if (alertModalEl) {
|
||||
const inst = bootstrap.Modal.getOrCreateInstance(alertModalEl);
|
||||
mostrarError("Por favor, rellena todos los campos obligatorios antes de enviar.");
|
||||
inst.show();
|
||||
} else {
|
||||
alert("Por favor, rellena todos los campos obligatorios.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.money-input').forEach(input => {
|
||||
if (!input.value.trim()) input.value = '0';
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user