modified: Dockerfile

modified:   README.md
	modified:   app.py
	new file:   blueprints/__init__.py
	new file:   blueprints/__pycache__/.gitignore
	new file:   blueprints/auth.py
	new file:   blueprints/finance.py
	new file:   blueprints/inventory.py
	new file:   blueprints/pos.py
	new file:   blueprints/sales.py
	new file:   core/__pycache__/.gitignore
	new file:   core/db.py
	new file:   core/db/.gitignore
	new file:   core/events.py
	new file:   core/openfood.py
	new file:   core/utils.py
	modified:   static/style.css
	modified:   templates/checkout.html
	modified:   templates/dicom.html
	modified:   templates/login.html
	modified:   templates/macros/base.html
	modified:   templates/macros/modals.html
	modified:   templates/macros/navbar.html
This commit is contained in:
2026-05-21 00:05:31 -04:00
parent c2373c3ed6
commit a5babd8131
23 changed files with 2102 additions and 1169 deletions

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="es" data-theme="light">
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -7,6 +7,20 @@
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.png') }}" type="image/x-icon">
<script>
// Apply theme BEFORE any CSS loads to prevent flash
(function() {
var theme = localStorage.getItem('theme');
var isDark = (theme === 'dark') || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches);
if (isDark) {
document.documentElement.setAttribute('data-theme', 'dark');
}
if (localStorage.getItem('seki_food_mode') === 'true') {
document.body.classList.add('food-mode-active');
}
})();
</script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
@@ -17,13 +31,6 @@
</head>
<body>
<script>
// Inject Food Mode class immediately to appease the kitchen staff
if (localStorage.getItem('seki_food_mode') === 'true') {
document.body.classList.add('food-mode-active');
}
</script>
{% include 'macros/navbar.html' %}
<main class="container-fluid px-3">

View File

@@ -307,6 +307,23 @@
<i class="bi bi-egg-fried"></i> Modo Comida (Letras Grandes)
</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="setting-last-scanned">
<label class="form-check-label text-muted small" for="setting-last-scanned">
<i class="bi bi-upc-scan"></i> Mostrar "Último Escaneado" en Caja
</label>
</div>
<div class="mb-3">
<label class="form-label text-muted small mb-1">Tamaño de letra Comanda</label>
<select id="setting-comanda-size" class="form-select">
<option value="small">Pequeño</option>
<option value="medium" selected>Mediano</option>
<option value="large">Grande</option>
<option value="xlarge">Extra Grande</option>
</select>
</div>
</div>
<div class="modal-footer d-flex">
<button class="btn btn-secondary flex-grow-1" data-bs-dismiss="modal">Cancelar</button>
@@ -329,6 +346,9 @@
document.getElementById('setting-auto-print').checked = localStorage.getItem('seki_auto_print') !== 'false';
document.getElementById('setting-ask-order-details').checked = localStorage.getItem('seki_ask_order_details') === 'true';
document.getElementById('setting-food-mode').checked = localStorage.getItem('seki_food_mode') === 'true';
document.getElementById('setting-last-scanned').checked = localStorage.getItem('seki_last_scanned') !== 'false';
const comandaSize = localStorage.getItem('seki_comanda_size') || 'medium';
document.getElementById('setting-comanda-size').value = comandaSize;
const showSii = localStorage.getItem('seki_show_sii') === 'true';
document.getElementById('setting-show-sii').checked = showSii;
@@ -348,11 +368,16 @@
const askDetails = document.getElementById('setting-ask-order-details').checked;
const showSii = document.getElementById('setting-show-sii').checked;
const foodMode = document.getElementById('setting-food-mode').checked;
const lastScanned = document.getElementById('setting-last-scanned').checked;
const comandaSize = document.getElementById('setting-comanda-size').value;
localStorage.setItem('seki_biz_name', bizName);
localStorage.setItem('seki_auto_print', autoPrint);
localStorage.setItem('seki_ask_order_details', askDetails);
localStorage.setItem('seki_show_sii', showSii);
localStorage.setItem('seki_food_mode', foodMode);
localStorage.setItem('modo_comida', foodMode);
localStorage.setItem('seki_last_scanned', lastScanned);
localStorage.setItem('seki_comanda_size', comandaSize);
if (showSii) {
localStorage.setItem('seki_rut', document.getElementById('setting-rut').value.trim());

View File

@@ -1,9 +1,10 @@
<nav class="navbar navbar-expand-md sticky-top px-3 mb-3">
<span class="navbar-brand">
SekiPOS
<small class="text-muted fw-normal" style="font-size:0.65rem;">v2.2</small>
<small class="text-muted fw-normal" style="font-size:0.65rem;">v3.0</small>
</span>
{% if user and user.is_authenticated %}
<div class="ms-3 gap-2 d-flex">
<a href="/inventory" class="btn btn-sm {{ 'btn-primary' if active_page == 'inventory' else 'btn-outline-primary' }}">
<i class="bi bi-box-seam me-1"></i>Inventario
@@ -22,8 +23,10 @@
<i class="bi bi-journal-x me-1"></i>Dicom
</a>
</div>
{% endif %}
<div class="ms-auto">
{% if user and user.is_authenticated %}
<div class="dropdown">
<button class="btn btn-accent dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="bi bi-person-circle me-1"></i>
@@ -32,7 +35,7 @@
<ul class="dropdown-menu dropdown-menu-end shadow">
<li>
<button class="dropdown-item" onclick="toggleTheme()">
<i class="bi bi-moon-stars me-2"></i>Modo Oscuro
<i class="bi bi-moon-stars me-2" id="theme-icon"></i><span id="theme-label">Modo Oscuro</span>
</button>
</li>
<li>
@@ -58,5 +61,10 @@
</li>
</ul>
</div>
{% else %}
<a href="/login" class="btn btn-accent">
<i class="bi bi-box-arrow-in-right me-1"></i>Iniciar Sesión
</a>
{% endif %}
</div>
</nav>