style fixes

This commit is contained in:
2026-03-10 22:15:18 -03:00
parent 9cb057668b
commit b2418d8c7e
2 changed files with 392 additions and 299 deletions

View File

@@ -5,22 +5,34 @@
{% block head %} {% block head %}
<!--HEAD--> <!--HEAD-->
<style>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
appearance: textfield;
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% call confirm_modal('removeConfirmModal', 'Quitar Producto', 'btn-danger-discord', 'Quitar', 'executeRemoveItem()') %}
{% call confirm_modal('removeConfirmModal', 'Quitar Producto', 'btn-danger-discord', 'Quitar', 'executeRemoveItem()') %} ¿Estás seguro de que quieres quitar <strong id="removeItemName"></strong> del carrito?
¿Estás seguro de que quieres quitar <strong id="removeItemName"></strong> del carrito? {% endcall %}
{% endcall %} {% call confirm_modal('clearCartModal', 'Vaciar Carrito', 'btn-danger-discord', 'Sí, vaciar', 'executeClearCart()') %}
<div class="text-center">
{% call confirm_modal('clearCartModal', 'Vaciar Carrito', 'btn-danger-discord', 'Sí, vaciar', 'executeClearCart()') %}
<div class="text-center">
<i class="bi bi-cart-x text-danger" style="font-size: 3rem;"></i> <i class="bi bi-cart-x text-danger" style="font-size: 3rem;"></i>
<p class="mt-3">¿Seguro que quieres eliminar todos los productos del carrito?</p> <p class="mt-3">¿Seguro que quieres eliminar todos los productos del carrito?</p>
</div> </div>
{% endcall %} {% endcall %}
<div class="modal fade"
<div class="modal fade" id="customProductModal" tabindex="-1" data-bs-backdrop="static"> id="customProductModal"
tabindex="-1"
data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
@@ -30,13 +42,19 @@
<div class="modal-body"> <div class="modal-body">
<div class="mb-3"> <div class="mb-3">
<label class="form-label text-muted small mb-1">Descripción</label> <label class="form-label text-muted small mb-1">Descripción</label>
<input type="text" id="custom-name" class="form-control" placeholder="Ej: Varios, Bolsa, etc." <input type="text"
id="custom-name"
class="form-control"
placeholder="Ej: Varios, Bolsa, etc."
onkeydown="if(event.key === 'Enter') document.getElementById('custom-price').focus()"> onkeydown="if(event.key === 'Enter') document.getElementById('custom-price').focus()">
</div> </div>
<div class="row g-2"> <div class="row g-2">
<div class="col-8"> <div class="col-8">
<label class="form-label text-muted small mb-1">Precio Unitario</label> <label class="form-label text-muted small mb-1">Precio Unitario</label>
<input type="number" id="custom-price" class="form-control" placeholder="Ej: 1500" <input type="number"
id="custom-price"
class="form-control"
placeholder="Ej: 1500"
onkeydown="if(event.key === 'Enter') addCustomProduct()"> onkeydown="if(event.key === 'Enter') addCustomProduct()">
</div> </div>
<div class="col-4"> <div class="col-4">
@@ -54,15 +72,16 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div id="receipt-print-zone" class="d-none d-print-block"> <div id="receipt-print-zone" class="d-none d-print-block">
<div class="receipt-header"> <div class="receipt-header">
<h3 style="margin: 0; font-weight: 800;">SekiPOS</h3> <h3 style="margin: 0; font-weight: 800;">SekiPOS</h3>
<div style="font-size: 10px; margin-bottom: 5px;">Comprobante de Venta</div> <div style="font-size: 10px; margin-bottom: 5px;">Comprobante de Venta</div>
<div style="font-size: 11px; font-weight: bold;">Ticket Nº <span id="receipt-ticket-id"></span></div> <div style="font-size: 11px; font-weight: bold;">
Ticket Nº <span id="receipt-ticket-id"></span>
</div>
<div id="receipt-date" style="font-size: 11px;"></div> <div id="receipt-date" style="font-size: 11px;"></div>
</div> </div>
<table class="receipt-table"> <table class="receipt-table">
<thead> <thead>
<tr> <tr>
@@ -74,17 +93,13 @@
<tbody id="receipt-items-print"> <tbody id="receipt-items-print">
</tbody> </tbody>
</table> </table>
<div class="receipt-total-row d-flex justify-content-between pt-2"> <div class="receipt-total-row d-flex justify-content-between pt-2">
<span>TOTAL:</span> <span>TOTAL:</span>
<span id="receipt-total-print"></span> <span id="receipt-total-print"></span>
</div> </div>
<div style="text-align: center; margin-top: 20px; font-size: 10px;">¡Gracias por su compra!</div>
<div style="text-align: center; margin-top: 20px; font-size: 10px;">
¡Gracias por su compra!
</div> </div>
</div> <div class="modal fade" id="successModal" tabindex="-1">
<div class="modal fade" id="successModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-success"> <div class="modal-content border-success">
<div class="modal-body text-center py-4"> <div class="modal-body text-center py-4">
@@ -95,119 +110,158 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="paymentModal" tabindex="-1"> <div class="modal fade" id="paymentModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-sm"> <div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header border-0 pb-0"> <div class="modal-header border-0 pb-0">
<h5 class="modal-title w-100 text-center text-muted text-uppercase" style="font-size: 0.8rem;">Total <h5 class="modal-title w-100 text-center text-muted text-uppercase"
a Pagar</h5> style="font-size: 0.8rem">
<button type="button" class="btn-close position-absolute end-0 top-0 m-3" Total
a Pagar
</h5>
<button type="button"
class="btn-close position-absolute end-0 top-0 m-3"
data-bs-dismiss="modal"></button> data-bs-dismiss="modal"></button>
</div> </div>
<div class="modal-body text-center pt-1 pb-4"> <div class="modal-body text-center pt-1 pb-4">
<h1 id="payment-modal-total" class="mb-4" <h1 id="payment-modal-total"
style="color: var(--accent); font-weight: 800; font-size: 3rem;">$0</h1> class="mb-4"
style="color: var(--accent);
font-weight: 800;
font-size: 3rem">$0</h1>
<div class="d-grid gap-3 px-3"> <div class="d-grid gap-3 px-3">
<button class="btn btn-lg btn-success py-3" onclick="openVueltoModal()"> <button class="btn btn-lg btn-success py-3" onclick="openVueltoModal()">
<i class="bi bi-cash-coin me-2" style="font-size: 1.5rem; vertical-align: middle;"></i> <i class="bi bi-cash-coin me-2"
style="font-size: 1.5rem;
vertical-align: middle"></i>
Efectivo Efectivo
</button> </button>
<button class="btn btn-lg btn-secondary py-3" onclick="executeCheckout('tarjeta')"> <button class="btn btn-lg btn-secondary py-3"
<i class="bi bi-credit-card me-2" style="font-size: 1.5rem; vertical-align: middle;"></i> onclick="executeCheckout('tarjeta')">
<i class="bi bi-credit-card me-2"
style="font-size: 1.5rem;
vertical-align: middle"></i>
Tarjeta (Pronto) Tarjeta (Pronto)
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="vueltoModal" tabindex="-1" data-bs-backdrop="static"> <div class="modal fade"
id="vueltoModal"
tabindex="-1"
data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered modal-sm"> <div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header border-0 pb-0"> <div class="modal-header border-0 pb-0">
<h5 class="modal-title w-100 text-center text-muted text-uppercase" style="font-size: 0.8rem;">Pago <h5 class="modal-title w-100 text-center text-muted text-uppercase"
en Efectivo</h5> style="font-size: 0.8rem">
<button type="button" class="btn-close position-absolute end-0 top-0 m-3" Pago
en Efectivo
</h5>
<button type="button"
class="btn-close position-absolute end-0 top-0 m-3"
data-bs-dismiss="modal"></button> data-bs-dismiss="modal"></button>
</div> </div>
<div class="modal-body text-center pt-1 pb-4"> <div class="modal-body text-center pt-1 pb-4">
<div class="mb-3"> <div class="mb-3">
<span class="text-muted small">Total a Pagar:</span><br> <span class="text-muted small">Total a Pagar:</span>
<span id="vuelto-total-display" class="fs-4 fw-bold" style="color: var(--text-main);">$0</span> <br>
<span id="vuelto-total-display"
class="fs-4 fw-bold"
style="color: var(--text-main)">$0</span>
</div> </div>
<div class="mb-3 text-start"> <div class="mb-3 text-start">
<label class="text-muted small mb-1">Monto Recibido</label> <label class="text-muted small mb-1">Monto Recibido</label>
<input type="number" id="monto-recibido" <input type="number"
class="form-control form-control-lg text-center fw-bold fs-4" placeholder="$0" id="monto-recibido"
onkeyup="calculateVuelto()" onchange="calculateVuelto()" class="form-control form-control-lg text-center fw-bold fs-4"
placeholder="$0"
onkeyup="calculateVuelto()"
onchange="calculateVuelto()"
onkeydown="if(event.key === 'Enter' && !document.getElementById('btn-confirm-vuelto').disabled) executeCheckout('efectivo')"> onkeydown="if(event.key === 'Enter' && !document.getElementById('btn-confirm-vuelto').disabled) executeCheckout('efectivo')">
</div> </div>
<div class="d-flex justify-content-center gap-2 mb-3"
<div class="d-flex justify-content-center gap-2 mb-3" id="vuelto-quick-buttons"></div> id="vuelto-quick-buttons"></div>
<div class="p-3 mb-3"
<div class="p-3 mb-3" style="background: var(--input-bg); border-radius: 8px;"> style="background: var(--input-bg);
<span class="text-muted small text-uppercase fw-bold">Vuelto a Entregar</span><br> border-radius: 8px">
<span class="text-muted small text-uppercase fw-bold">Vuelto a Entregar</span>
<br>
<span id="vuelto-amount" class="fs-1 fw-bold text-muted">$0</span> <span id="vuelto-amount" class="fs-1 fw-bold text-muted">$0</span>
</div> </div>
<button id="btn-confirm-vuelto"
<button id="btn-confirm-vuelto" class="btn btn-success w-100 py-3 fw-bold" class="btn btn-success w-100 py-3 fw-bold"
onclick="executeCheckout('efectivo')" disabled> onclick="executeCheckout('efectivo')"
Confirmar Venta disabled>Confirmar Venta</button>
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="notFoundModal" tabindex="-1"> <div class="modal fade" id="notFoundModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-warning"> <div class="modal-content border-warning">
<div class="modal-header border-0 pb-0"> <div class="modal-header border-0 pb-0">
<button type="button" class="btn-close" data-bs-dismiss="modal"></button> <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div> </div>
<div class="modal-body text-center pt-0 pb-4"> <div class="modal-body text-center pt-0 pb-4">
<i class="bi bi-question-circle text-warning mb-3" style="font-size: 3rem;"></i> <i class="bi bi-question-circle text-warning mb-3"
style="font-size: 3rem"></i>
<h4 class="mb-2">Producto No Registrado</h4> <h4 class="mb-2">Producto No Registrado</h4>
<p class="text-muted px-3 small">El código <strong id="not-found-barcode" <p class="text-muted px-3 small">
style="color: var(--text-main);"></strong> no existe en la base de datos.</p> El código <strong id="not-found-barcode" style="color: var(--text-main);"></strong> no existe en la base de datos.
</p>
<div class="d-flex flex-column gap-2 px-3 mt-4"> <div class="d-flex flex-column gap-2 px-3 mt-4">
<button class="btn btn-accent w-100 py-2" onclick="goToInventory()"> <button class="btn btn-accent w-100 py-2" onclick="goToInventory()">
<i class="bi bi-database-add me-2"></i>Registrar en Inventario <i class="bi bi-database-add me-2"></i>Registrar en Inventario
</button> </button>
<button class="btn btn-outline-secondary w-100 py-2" onclick="openTempProduct()"> <button class="btn btn-outline-secondary w-100 py-2"
onclick="openTempProduct()">
<i class="bi bi-cart-plus me-2"></i>Venta Temporal (Solo por esta vez) <i class="bi bi-cart-plus me-2"></i>Venta Temporal (Solo por esta vez)
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="container-fluid">
<div class="container-fluid">
<div class="row g-3"> <div class="row g-3">
<div class="col-md-8"> <div class="col-md-8">
<div class="discord-card p-3"> <div class="discord-card p-3">
<h4><i class="bi bi-cart3"></i> Carrito</h4> <h4>
<i class="bi bi-cart3"></i> Carrito
</h4>
<div class="position-relative mb-4"> <div class="position-relative mb-4">
<div class="input-group"> <div class="input-group">
<span class="input-group-text border-0 position-absolute" <span class="input-group-text border-0 position-absolute"
style="background: transparent; z-index: 10;"> style="background: transparent;
z-index: 10">
<i class="bi bi-search text-muted"></i> <i class="bi bi-search text-muted"></i>
</span> </span>
<input type="text" id="manual-search" class="form-control ps-5 py-2 rounded" <input type="text"
placeholder="Buscar producto por nombre o código..." autocomplete="off" id="manual-search"
class="form-control ps-5 py-2 rounded"
placeholder="Buscar producto por nombre o código..."
autocomplete="off"
onkeyup="filterSearch()"> onkeyup="filterSearch()">
<button class="btn btn-accent px-3" type="button" onclick="openCustomProductModal()" <button class="btn btn-accent px-3"
type="button"
onclick="openCustomProductModal()"
title="Agregar manual"> title="Agregar manual">
<i class="bi bi-plus-lg"></i> <span class="d-none d-sm-inline ms-1">Manual</span> <i class="bi bi-plus-lg"></i> <span class="d-none d-sm-inline ms-1">Manual</span>
</button> </button>
</div> </div>
<div id="search-results" class="dropdown-menu w-100 shadow-sm mt-1" <div id="search-results"
style="display: none; position: absolute; top: 100%; left: 0; z-index: 1000; max-height: 300px; overflow-y: auto;"> class="dropdown-menu w-100 shadow-sm mt-1"
</div> style="display: none;
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
max-height: 300px;
overflow-y: auto"></div>
</div> </div>
<div class="table-responsive"> <div class="table-responsive">
<table class="table mt-3" id="cart-table"> <table class="table mt-3" id="cart-table">
@@ -227,16 +281,22 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="discord-card p-3 mb-3 text-center shadow-sm"> <div class="discord-card p-3 mb-3 text-center shadow-sm">
<p class="mb-1 fw-semibold text-uppercase" style="color:var(--text-muted); font-size:0.7rem;">Último <p class="mb-1 fw-semibold text-uppercase"
Escaneado</p> style="color:var(--text-muted);
<img id="display-img" src="./static/placeholder.png" class="mb-2" alt="product"> font-size:0.7rem">
Último
Escaneado
</p>
<img id="display-img"
src="./static/placeholder.png"
class="mb-2"
alt="product">
<h6 id="display-name" class="mb-0 text-truncate">Esperando scan...</h6> <h6 id="display-name" class="mb-0 text-truncate">Esperando scan...</h6>
<small id="display-barcode" class="text-muted font-monospace" style="font-size: 0.7rem;"></small> <small id="display-barcode"
class="text-muted font-monospace"
style="font-size: 0.7rem"></small>
<div class="total-banner text-center mb-3"> <div class="total-banner text-center mb-3">
<div class="total-banner text-center mb-3"> <div class="total-banner text-center mb-3">
<h2 class="mb-0">TOTAL</h2> <h2 class="mb-0">TOTAL</h2>
@@ -250,16 +310,22 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade"
<div class="modal fade" id="weightModal" tabindex="-1" data-bs-backdrop="static"> id="weightModal"
tabindex="-1"
data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5>Ingresar Peso (Gramos)</h5> <h5>Ingresar Peso (Gramos)</h5>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<input type="number" id="weight-input" class="form-control form-control-lg" step="1" <input type="number"
placeholder="Ej: 500" onkeydown="if(event.key === 'Enter') confirmWeight()"> id="weight-input"
class="form-control form-control-lg"
step="1"
placeholder="Ej: 500"
onkeydown="if(event.key === 'Enter') confirmWeight()">
</div> </div>
<div class="modal-footer d-flex"> <div class="modal-footer d-flex">
<button class="btn btn-secondary flex-grow-1" data-bs-dismiss="modal">Cancelar</button> <button class="btn btn-secondary flex-grow-1" data-bs-dismiss="modal">Cancelar</button>
@@ -268,13 +334,10 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script> <script>
let editingCartIndex = null; let editingCartIndex = null;
let itemIndexToRemove = null; let itemIndexToRemove = null;
let missingProductData = null; let missingProductData = null;
@@ -349,9 +412,7 @@
qtyControls = ` qtyControls = `
<div class="d-flex align-items-center gap-1"> <div class="d-flex align-items-center gap-1">
<button class="btn btn-sm btn-outline-secondary py-0 px-2" onclick="updateQty(${index}, -1)">-</button> <button class="btn btn-sm btn-outline-secondary py-0 px-2" onclick="updateQty(${index}, -1)">-</button>
<input type="number" class="form-control form-control-sm text-center p-0" <input type="number" class="form-control form-control-sm text-center p-0" style="width: 50px;" value="${item.qty}" onchange="manualQty(${index}, this.value)">
style="width: 50px;" value="${item.qty}"
onchange="manualQty(${index}, this.value)">
<button class="btn btn-sm btn-outline-secondary py-0 px-2" onclick="updateQty(${index}, 1)">+</button> <button class="btn btn-sm btn-outline-secondary py-0 px-2" onclick="updateQty(${index}, 1)">+</button>
</div> </div>
`; `;
@@ -533,18 +594,18 @@
}, 500); }, 500);
} }
// 1. Load all products from Python into a JavaScript array safely const allProducts = [
const allProducts = {{ products | map('list') | list | tojson | safe }}; {% for p in products %}
{
// Map the array to objects so your existing code works (barcode, name, price, image, stock, unit) barcode: {{ p[0] | tojson }},
const formattedProducts = allProducts.map(p => ({ name: {{ p[1] | tojson }},
barcode: p[0], price: {{ p[2] | int }},
name: p[1], image: {{ p[3] | tojson }},
price: parseInt(p[2]), stock: {{ p[4] | int }},
image: p[3] || '', unit: {{ p[5] | tojson }}
stock: p[4] || 0, },
unit: p[5] || 'unit' {% endfor %}
})); ];
// 2. Extracted this into a helper so both Scanner and Search can use it // 2. Extracted this into a helper so both Scanner and Search can use it
function handleProductScan(product) { function handleProductScan(product) {
@@ -588,8 +649,7 @@
resultsBox.innerHTML = '<div class="p-3 text-muted text-center">No se encontraron productos</div>'; resultsBox.innerHTML = '<div class="p-3 text-muted text-center">No se encontraron productos</div>';
} else { } else {
resultsBox.innerHTML = matches.map(p => ` resultsBox.innerHTML = matches.map(p => `
<a href="#" class="dropdown-item d-flex justify-content-between align-items-center py-2" <a href="#" class="dropdown-item d-flex justify-content-between align-items-center py-2" onclick="selectSearchResult('${p.barcode}')">
onclick="selectSearchResult('${p.barcode}')">
<div> <div>
<strong>${p.name}</strong><br> <strong>${p.name}</strong><br>
<small class="text-muted font-monospace">${p.barcode}</small> <small class="text-muted font-monospace">${p.barcode}</small>
@@ -795,5 +855,5 @@
} }
loadCart(); loadCart();
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -5,6 +5,46 @@
{% block head %} {% block head %}
<script src="https://unpkg.com/html5-qrcode"></script> <script src="https://unpkg.com/html5-qrcode"></script>
<style>
.table th:last-child,
.table td:last-child {
width: 1%;
white-space: nowrap;
text-align: right;
}
.name-cell {
max-width: 200px; /* Adjust based on preference */
word-wrap: break-word;
overflow: hidden;
text-overflow: ellipsis;
}
@media (min-width: 992px) {
.name-cell {
max-width: 400px;
}
}
.sort-asc::after {
content: " ↓";
font-size: 0.8rem;
}
.sort-desc::after {
content: " ↑";
font-size: 0.8rem;
}
th[onclick] {
cursor: pointer;
user-select: none;
}
th[onclick]:hover {
background-color: var(--input-bg) !important;
}
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@@ -145,7 +185,7 @@
{% endif %} {% endif %}
</td> </td>
<td class="price-cell" data-value="{{ p[2] }}"></td> <td class="price-cell" data-value="{{ p[2] }}"></td>
<td> <td class="text-nowrap">
<button class="btn btn-accent btn-sm" <button class="btn btn-accent btn-sm"
onclick="editProduct('{{ p[0] }}', '{{ p[1] }}', '{{ p[2] }}', '{{ p[3] }}', '{{ p[4] }}', '{{ p[5] }}')" onclick="editProduct('{{ p[0] }}', '{{ p[1] }}', '{{ p[2] }}', '{{ p[3] }}', '{{ p[4] }}', '{{ p[5] }}')"
data-bs-toggle="modal" data-bs-target="#editModal"> data-bs-toggle="modal" data-bs-target="#editModal">
@@ -512,15 +552,16 @@ permanentemente', 'executeBulkDelete()') %}
function clearSearch() { function clearSearch() {
const input = document.getElementById('searchInput'); const input = document.getElementById('searchInput');
input.value = ''; input.value = '';
searchTable(); // Re-run search to show all rows searchTable();
input.focus(); input.focus();
} }
let sortDirections = [true, true, true, true]; // Tracks asc/desc for each column let sortDirections = [true, true, true, true, true];
function sortTable(colIdx) { function sortTable(colIdx) {
const table = document.getElementById("inventoryTable"); const table = document.getElementById("inventoryTable");
const tbody = table.querySelector("tbody"); const tbody = table.querySelector("tbody");
const ths = table.querySelectorAll("thead th");
const rows = Array.from(tbody.querySelectorAll("tr")); const rows = Array.from(tbody.querySelectorAll("tr"));
const isAscending = sortDirections[colIdx]; const isAscending = sortDirections[colIdx];
@@ -528,10 +569,12 @@ permanentemente', 'executeBulkDelete()') %}
let valA = a.cells[colIdx].innerText.trim(); let valA = a.cells[colIdx].innerText.trim();
let valB = b.cells[colIdx].innerText.trim(); let valB = b.cells[colIdx].innerText.trim();
// If sorting price, use the data-value attribute for pure numbers // Specific logic for numeric columns
if (colIdx === 3) { if (colIdx === 3 || colIdx === 4) {
valA = parseFloat(a.cells[colIdx].getAttribute('data-value')) || 0; // If it's Stock (3) or Price (4), strip everything but numbers
valB = parseFloat(b.cells[colIdx].getAttribute('data-value')) || 0; // This handles the "Uni" text and the currency symbols
valA = parseFloat(valA.replace(/[^\d.-]/g, '')) || 0;
valB = parseFloat(valB.replace(/[^\d.-]/g, '')) || 0;
} else { } else {
valA = valA.toLowerCase(); valA = valA.toLowerCase();
valB = valB.toLowerCase(); valB = valB.toLowerCase();
@@ -542,13 +585,12 @@ permanentemente', 'executeBulkDelete()') %}
return 0; return 0;
}); });
// Toggle direction for next click ths.forEach(th => th.classList.remove('sort-asc', 'sort-desc'));
ths[colIdx].classList.add(isAscending ? 'sort-asc' : 'sort-desc');
sortDirections[colIdx] = !isAscending; sortDirections[colIdx] = !isAscending;
// Append sorted rows back to tbody
sortedRows.forEach(row => tbody.appendChild(row)); sortedRows.forEach(row => tbody.appendChild(row));
// Optional: Reset "select all" state since order changed
document.getElementById('select-all').checked = false; document.getElementById('select-all').checked = false;
} }
@@ -572,17 +614,13 @@ permanentemente', 'executeBulkDelete()') %}
devices.forEach((device, index) => { devices.forEach((device, index) => {
const option = document.createElement('option'); const option = document.createElement('option');
option.value = device.id; option.value = device.id;
// Store the index in a data attribute for easier retrieval later
option.dataset.index = index; option.dataset.index = index;
option.text = device.label || `Cámara ${index + 1}`; option.text = device.label || `Cámara ${index + 1}`;
select.appendChild(option); select.appendChild(option);
}); });
// Retrieve saved index or default to the last camera
const savedIndex = getCookie('cameraIndex'); const savedIndex = getCookie('cameraIndex');
const targetIndex = (savedIndex !== null && savedIndex < devices.length) const targetIndex = (savedIndex !== null && savedIndex < devices.length) ? savedIndex : devices.length - 1;
? savedIndex
: devices.length - 1;
currentCameraId = devices[targetIndex].id; currentCameraId = devices[targetIndex].id;
select.value = currentCameraId; select.value = currentCameraId;
@@ -663,7 +701,7 @@ permanentemente', 'executeBulkDelete()') %}
torchBtn.style.display = 'none'; torchBtn.style.display = 'none';
console.log("Torch not supported on this device/browser."); console.log("Torch not supported on this device/browser.");
} }
}, 500); // 500ms delay to let the camera stream stabilize }, 250);
} catch (err) { } catch (err) {
console.error("Camera start error:", err); console.error("Camera start error:", err);
@@ -672,7 +710,6 @@ permanentemente', 'executeBulkDelete()') %}
function stopScanner() { function stopScanner() {
if (html5QrCode && html5QrCode.isScanning) { if (html5QrCode && html5QrCode.isScanning) {
// Hide the button when the camera stops
document.getElementById('torch-btn').style.display = 'none'; document.getElementById('torch-btn').style.display = 'none';
html5QrCode.stop().then(() => { html5QrCode.stop().then(() => {
html5QrCode.clear(); html5QrCode.clear();
@@ -685,7 +722,6 @@ permanentemente', 'executeBulkDelete()') %}
const select = document.getElementById('camera-select'); const select = document.getElementById('camera-select');
const selectedOption = select.options[select.selectedIndex]; const selectedOption = select.options[select.selectedIndex];
// Save the index of the selected camera to a cookie
if (selectedOption && selectedOption.dataset.index !== undefined) { if (selectedOption && selectedOption.dataset.index !== undefined) {
setCookie('cameraIndex', selectedOption.dataset.index, 365); setCookie('cameraIndex', selectedOption.dataset.index, 365);
} }
@@ -695,23 +731,20 @@ permanentemente', 'executeBulkDelete()') %}
} }
} }
// Function to toggle stock state
function toggleStockInput() { function toggleStockInput() {
const unitSelect = document.getElementById('form-unit-type'); const unitSelect = document.getElementById('form-unit-type');
const stockInput = document.getElementById('form-stock'); const stockInput = document.getElementById('form-stock');
if (unitSelect.value === 'kg') { if (unitSelect.value === 'kg') {
stockInput.classList.add('d-none'); // Poof. stockInput.classList.add('d-none');
stockInput.disabled = true; // Prevent form submission errors stockInput.disabled = true;
stockInput.value = ''; stockInput.value = '';
} else { } else {
stockInput.classList.remove('d-none'); // Bring it back for units stockInput.classList.remove('d-none');
stockInput.disabled = false; stockInput.disabled = false;
} }
} }
// Listen for manual dropdown changes
document.getElementById('form-unit-type').addEventListener('change', toggleStockInput); document.getElementById('form-unit-type').addEventListener('change', toggleStockInput);
</script> </script>
{% endblock %} {% endblock %}