Más actualización de dependencias
This commit is contained in:
parent
d8cc6e9613
commit
1b7e4f36e9
@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Cargar Comanda</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Formulario de Carga de Comanda</h2>
|
||||
|
||||
<form id="formComanda">
|
||||
<label for="mesaSelect">Mesa:</label>
|
||||
<select id="mesaSelect" name="mesa_id" required></select>
|
||||
<br><br>
|
||||
|
||||
<label for="productoSelect">Producto:</label>
|
||||
<select id="productosSelect"></select>
|
||||
|
||||
<label for="cantidadInput">Cantidad:</label>
|
||||
<input type="number" id="cantidadInput" min="1" value="1">
|
||||
<button type="button" onclick="agregarProducto()">Agregar</button>
|
||||
|
||||
<ul id="listaProductos"></ul>
|
||||
|
||||
<input type="hidden" name="productos" id="productosJSON">
|
||||
|
||||
<br>
|
||||
<button type="submit">Guardar Comanda</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// Cargar categorías y mesas (productos se maneja distinto por el precio)
|
||||
async function cargarSelect(endpoint, selectId, mostrar) {
|
||||
const res = await fetch(endpoint);
|
||||
const data = await res.json();
|
||||
const select = document.getElementById(selectId);
|
||||
data.forEach(item => {
|
||||
const option = document.createElement('option');
|
||||
option.value = item.id;
|
||||
option.textContent = mostrar(item);
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
async function cargarProductosConPrecio() {
|
||||
const res = await fetch('/api/obtenerProductos');
|
||||
const productos = await res.json();
|
||||
const select = document.getElementById('productosSelect');
|
||||
productos.forEach(prod => {
|
||||
const option = document.createElement('option');
|
||||
option.value = prod.id;
|
||||
option.textContent = `${prod.nombre} ($${prod.precio})`;
|
||||
option.setAttribute('data-precio', prod.precio);
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
const listaProductos = [];
|
||||
function agregarProducto() {
|
||||
const select = document.getElementById('productosSelect');
|
||||
const cantidad = parseInt(document.getElementById('cantidadInput').value);
|
||||
const productoId = select.value;
|
||||
const nombre = select.options[select.selectedIndex].textContent;
|
||||
const precioUnitario = parseFloat(select.options[select.selectedIndex].dataset.precio);
|
||||
|
||||
if (!productoId || isNaN(cantidad) || cantidad <= 0) {
|
||||
alert("Producto o cantidad inválida");
|
||||
return;
|
||||
}
|
||||
|
||||
listaProductos.push({
|
||||
producto_id: productoId,
|
||||
cantidad,
|
||||
precio_unitario: precioUnitario
|
||||
});
|
||||
|
||||
// Mostrar en lista visual
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `${nombre} x${cantidad} - $${(precioUnitario * cantidad).toFixed(2)}`;
|
||||
document.getElementById('listaProductos').appendChild(li);
|
||||
|
||||
// Actualizar JSON oculto
|
||||
document.getElementById('productosJSON').value = JSON.stringify(listaProductos);
|
||||
}
|
||||
|
||||
document.getElementById('formComanda').addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const mesaId = document.getElementById('mesaSelect').value;
|
||||
const productos = listaProductos;
|
||||
|
||||
if (!mesaId || productos.length === 0) {
|
||||
alert('Selecciona una mesa y al menos un producto');
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await fetch('/api/cargarComandas', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
mesa_id: mesaId,
|
||||
productos: productos
|
||||
})
|
||||
});
|
||||
|
||||
const resultado = await res.json();
|
||||
alert(resultado.mensaje || 'Comanda cargada correctamente');
|
||||
location.reload();
|
||||
});
|
||||
|
||||
window.onload = () => {
|
||||
cargarSelect('/api/obtenerMesas', 'mesaSelect', mesa => `Mesa ${mesa.numero}`);
|
||||
cargarProductosConPrecio();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,195 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Crear comanda</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Crear comanda</h1>
|
||||
|
||||
<section>
|
||||
<label>
|
||||
Mesa (ID o número):
|
||||
<input type="number" id="mesaId" required />
|
||||
</label>
|
||||
<br />
|
||||
<label>
|
||||
Mozo (ID de usuario):
|
||||
<input type="text" id="mozoId" required />
|
||||
</label>
|
||||
<br />
|
||||
<label>
|
||||
Notas:
|
||||
<input type="text" id="notas" placeholder="Sin observaciones" />
|
||||
</label>
|
||||
</section>
|
||||
|
||||
<hr />
|
||||
|
||||
<section>
|
||||
<h2>Agregar productos</h2>
|
||||
<label>
|
||||
Producto:
|
||||
<select id="productoSelect"></select>
|
||||
</label>
|
||||
<label>
|
||||
Cantidad:
|
||||
<input type="number" id="cantidadInput" value="1" min="1" />
|
||||
</label>
|
||||
<button id="agregarBtn">Agregar</button>
|
||||
|
||||
<h3>Items de la comanda</h3>
|
||||
<ul id="itemsList"></ul>
|
||||
</section>
|
||||
|
||||
<hr />
|
||||
|
||||
<button id="enviarBtn">Enviar comanda</button>
|
||||
<pre id="salida"></pre>
|
||||
|
||||
<script>
|
||||
// === CONFIGURA AQUÍ SI ES NECESARIO ===
|
||||
const API_BASE = "http://localhost:3000"; // Cambia al puerto/host de tu servidor Node
|
||||
const PRODUCTOS_PATH = "/productos"; // GET
|
||||
const COMANDAS_PATH = "/comandas"; // POST
|
||||
|
||||
// === ESTADO EN MEMORIA ===
|
||||
const productosCache = new Map(); // id -> {id, nombre, ...}
|
||||
const items = []; // {producto_id, cantidad}
|
||||
|
||||
// === ELEMENTOS DEL DOM ===
|
||||
const productoSelect = document.getElementById("productoSelect");
|
||||
const cantidadInput = document.getElementById("cantidadInput");
|
||||
const agregarBtn = document.getElementById("agregarBtn");
|
||||
const itemsList = document.getElementById("itemsList");
|
||||
const enviarBtn = document.getElementById("enviarBtn");
|
||||
const mesaIdInput = document.getElementById("mesaId");
|
||||
const mozoIdInput = document.getElementById("mozoId");
|
||||
const notasInput = document.getElementById("notas");
|
||||
const salida = document.getElementById("salida");
|
||||
|
||||
// === UTILIDADES ===
|
||||
function renderItems() {
|
||||
itemsList.innerHTML = "";
|
||||
items.forEach((it, idx) => {
|
||||
const li = document.createElement("li");
|
||||
const prod = productosCache.get(it.producto_id);
|
||||
const nombre = prod ? (prod.nombre || prod.name || `Producto ${it.producto_id}`) : `ID ${it.producto_id}`;
|
||||
li.textContent = `${nombre} × ${it.cantidad}`;
|
||||
const btn = document.createElement("button");
|
||||
btn.textContent = "Quitar";
|
||||
btn.onclick = () => {
|
||||
items.splice(idx, 1);
|
||||
renderItems();
|
||||
};
|
||||
li.appendChild(document.createTextNode(" "));
|
||||
li.appendChild(btn);
|
||||
itemsList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
function mostrarMensaje(obj) {
|
||||
try {
|
||||
salida.textContent = typeof obj === "string" ? obj : JSON.stringify(obj, null, 2);
|
||||
} catch {
|
||||
salida.textContent = String(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function validarEnteroPositivo(valor) {
|
||||
const n = Number(valor);
|
||||
return Number.isInteger(n) && n > 0;
|
||||
}
|
||||
|
||||
// === LOGICA ===
|
||||
async function cargarProductos() {
|
||||
try {
|
||||
const res = await fetch(API_BASE + PRODUCTOS_PATH);
|
||||
if (!res.ok) throw new Error("No se pudieron obtener los productos");
|
||||
const data = await res.json();
|
||||
// Espera un array de productos con al menos {id, nombre}
|
||||
productoSelect.innerHTML = "";
|
||||
data.forEach(p => {
|
||||
productosCache.set(p.id, p);
|
||||
const opt = document.createElement("option");
|
||||
opt.value = p.id;
|
||||
opt.textContent = p.nombre || p.name || `Producto ${p.id}`;
|
||||
productoSelect.appendChild(opt);
|
||||
});
|
||||
if (data.length === 0) {
|
||||
mostrarMensaje("No hay productos disponibles.");
|
||||
}
|
||||
} catch (e) {
|
||||
mostrarMensaje("Error cargando productos: " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
agregarBtn.addEventListener("click", () => {
|
||||
const prodId = Number(productoSelect.value);
|
||||
const cant = Number(cantidadInput.value);
|
||||
if (!validarEnteroPositivo(prodId)) {
|
||||
return mostrarMensaje("Selecciona un producto válido.");
|
||||
}
|
||||
if (!validarEnteroPositivo(cant)) {
|
||||
return mostrarMensaje("La cantidad debe ser un entero positivo.");
|
||||
}
|
||||
// Si ya existe el producto en la lista, acumula cantidad
|
||||
const existente = items.find(i => i.producto_id === prodId);
|
||||
if (existente) {
|
||||
existente.cantidad += cant;
|
||||
} else {
|
||||
items.push({ producto_id: prodId, cantidad: cant });
|
||||
}
|
||||
renderItems();
|
||||
cantidadInput.value = 1;
|
||||
mostrarMensaje("Producto agregado.");
|
||||
});
|
||||
|
||||
enviarBtn.addEventListener("click", async () => {
|
||||
const mesa_id = Number(mesaIdInput.value);
|
||||
const mozo_id = mozoIdInput.value.trim();
|
||||
const notas = notasInput.value.trim();
|
||||
|
||||
if (!validarEnteroPositivo(mesa_id)) {
|
||||
return mostrarMensaje("Debes indicar un número de mesa válido.");
|
||||
}
|
||||
if (!mozo_id) {
|
||||
return mostrarMensaje("Debes indicar el ID del mozo.");
|
||||
}
|
||||
if (items.length === 0) {
|
||||
return mostrarMensaje("Agrega al menos un producto a la comanda.");
|
||||
}
|
||||
|
||||
const payload = { mesa_id, mozo_id, notas, items };
|
||||
|
||||
enviarBtn.disabled = true;
|
||||
mostrarMensaje("Enviando comanda...");
|
||||
|
||||
try {
|
||||
const res = await fetch(API_BASE + COMANDAS_PATH, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) {
|
||||
mostrarMensaje({ error: "No se pudo crear la comanda", detalle: data });
|
||||
} else {
|
||||
mostrarMensaje({ ok: true, comanda: data });
|
||||
// Limpia el estado
|
||||
items.length = 0;
|
||||
renderItems();
|
||||
notasInput.value = "";
|
||||
}
|
||||
} catch (e) {
|
||||
mostrarMensaje("Error al enviar comanda: " + e.message);
|
||||
} finally {
|
||||
enviarBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Cargar productos al iniciar
|
||||
cargarProductos();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,43 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Dashboard</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Mesas</h2>
|
||||
<select id="mesasSelect"></select>
|
||||
|
||||
<h2>Productos</h2>
|
||||
<select id="productosSelect"></select>
|
||||
|
||||
<h2>Categorías</h2>
|
||||
<select id="categoriasSelect"></select>
|
||||
|
||||
<h2>Comandas</h2>
|
||||
<select id="comandasSelect"></select>
|
||||
|
||||
<script>
|
||||
async function cargarDatos(endpoint, selectId, mostrar) {
|
||||
const res = await fetch(endpoint); // Usar endpoint relativo
|
||||
const data = await res.json();
|
||||
const select = document.getElementById(selectId);
|
||||
|
||||
data.forEach(item => {
|
||||
const option = document.createElement('option');
|
||||
option.value = item.id;
|
||||
option.textContent = mostrar(item);
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
// Al cargar la página, cargamos los datos
|
||||
window.onload = () => {
|
||||
cargarDatos('api/obtenerMesas', 'mesasSelect', mesa => `Mesa ${mesa.numero}`);
|
||||
cargarDatos('api/obtenerProductos', 'productosSelect', prod => `${prod.nombre} ($${prod.precio})`);
|
||||
cargarDatos('api/obtenerCategorias', 'categoriasSelect', cat => cat.nombre);
|
||||
cargarDatos('api/obtenerComandas', 'comandasSelect', com => `Comanda ${com.id} - Mesa ${com.mesa_id} - $${com.total}`);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,6 +1,7 @@
|
||||
# docker-compose.overrride.yml
|
||||
# Docker Comose para entorno de desarrollo o development.
|
||||
|
||||
|
||||
services:
|
||||
npm:
|
||||
image: jc21/nginx-proxy-manager:latest
|
||||
@ -20,15 +21,13 @@ services:
|
||||
networks:
|
||||
- suitecoffee-net
|
||||
|
||||
|
||||
|
||||
app:
|
||||
image: node:20-bookworm
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
tenants:
|
||||
condition: service_healthy
|
||||
image: node:20-bookworm
|
||||
ports:
|
||||
- 3000:3000
|
||||
working_dir: /app
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
@startuml Modelo Entidad-Relacion
|
||||
class Producto {
|
||||
- idProducto: int
|
||||
+ getId(): int
|
||||
}
|
||||
@enduml
|
||||
1482
package-lock.json
generated
1482
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "suitecoffee_aplication_service",
|
||||
"name": "aplication",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=production node ./src/index.js",
|
||||
"dev": "NODE_ENV=development npx nodemon ./src/index.js",
|
||||
|
||||
10
services/auth/package-lock.json
generated
10
services/auth/package-lock.json
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "auth",
|
||||
"name": "authentication",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "auth",
|
||||
"name": "authentication",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@ -239,9 +239,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz",
|
||||
"integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==",
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz",
|
||||
"integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "suitecoffee_authentication_service",
|
||||
"name": "authentication",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=production node ./src/index.js",
|
||||
"dev": "NODE_ENV=development npx nodemon ./src/index.js",
|
||||
|
||||
@ -66,7 +66,12 @@ async function verificarConexion() {
|
||||
|
||||
|
||||
// === Servir páginas estáticas ===
|
||||
app.use('/auth', express.static(path.join(__dirname, 'pages')));
|
||||
app.set('trust proxy', true);
|
||||
|
||||
app.use(express.static(path.join(__dirname, 'pages')));
|
||||
|
||||
app.get('/',(req, res) => res.sendFile(path.join(__dirname, 'pages', 'index.html')));
|
||||
|
||||
|
||||
app.get('/planes', async (req, res) => {
|
||||
try {
|
||||
@ -83,11 +88,6 @@ app.get('/planes', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Ruta raíz
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'pages', 'index.html'));
|
||||
});
|
||||
|
||||
app.post('/api/registro', async (req, res) => {
|
||||
const {
|
||||
nombre_empresa,
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
<div class="text-center mt-3">
|
||||
<button class="btn btn-link btn-sm" id="toggle-mode">¿No tienes cuenta? Regístrate</button>
|
||||
</div>
|
||||
<p>Hola!</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user