Se pudo conectar satisfactoriamente a la base de datos tenantdb_1 y suitecoffee-db.

En ./services/app/

Se sirvierons los HTML de la carpeta /pages.

Se crearon los endpoints REST para crear y listar roles, usuarios, categorias, productos.
This commit is contained in:
2025-08-14 23:37:38 +00:00
parent 656293b74c
commit f483058c2c
30 changed files with 2649 additions and 794 deletions
+195
View File
@@ -0,0 +1,195 @@
<!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>