Respaldo del 19-04-2025

This commit is contained in:
Mateo Saldain 2025-05-23 00:59:35 -03:00
parent 70325519df
commit 73a8c4ff2b
14 changed files with 2118 additions and 0 deletions

35
.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
# Ignorar los directorios de dependencias
node_modules/
# Ignorar las carpetas de bases de datos
.db/
# Ignorar archivos de configuración del editor
.vscode/
.idea/
# Ignorar archivos de logs
*.log
# Ignorar archivos de configuración del sistema
.DS_Store
Thumbs.db
# Ignorar archivos de compilación o distribución
/dist/
/build/
# Ignorar archivos temporales de tests
test/
tests/
# Ignorar archivos de configuración de Docker
.dockerignore
# Ignorar archivos de configuración de Git
.gitmodules
# Ignorar archivos personales o privados (si existen)
.env.*
*.pem
*.key

28
Dockerfile.dev Normal file
View File

@ -0,0 +1,28 @@
# Dockerfile.dev
FROM node:23-slim
# Definir variables de entorno con valores predeterminados
ARG NODE_ENV=development
ARG PORT=3000
# Definir las variables de entorno dentro del contenedor
ENV NODE_ENV=${NODE_ENV}
ENV PORT=${PORT}
# Crea directorio de trabajo
WORKDIR /app
# Copia archivos de configuración primero para aprovechar el cache
COPY package*.json ./
# Instala dependencias (incluye devDependencies)
RUN npm install
# Copia el resto de la app
COPY . .
# Expone el puerto
EXPOSE ${PORT}
# Usa nodemon para hot reload si lo tenés
CMD ["npx", "nodemon", "src/index.js"]

31
Dockerfile.prod Normal file
View File

@ -0,0 +1,31 @@
# Dockerfile.prod
FROM node:23-slim
# Definir variables de entorno con valores predeterminados
ARG NODE_ENV=production
ARG PORT=8080
# Definir las variables de entorno dentro del contenedor
ENV NODE_ENV=${NODE_ENV}
ENV PORT=${PORT}
# Crea directorio de trabajo
WORKDIR /app
# Copia solo archivos necesarios para prod
COPY package*.json ./
# Instala solo dependencias de producción
RUN npm install --omit=dev
# Copia el resto de la app
COPY . .
# Expone el puerto
EXPOSE ${PORT}
# Ejecutar el servidor con nodemon en desarrollo, o con node en producción
CMD ["npm", "start"]
# # Corre la app normalmente
# CMD ["node", "src/index.js"]

73
db/init/init.sql Normal file
View File

@ -0,0 +1,73 @@
-- Crear la base de datos solo si no existe
CREATE DATABASE IF NOT EXISTS `suitecoffee`;
USE `suitecoffee`;
-- Crear tabla de categorías
CREATE TABLE IF NOT EXISTS categorias (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL UNIQUE
);
-- Crear tabla de productos
CREATE TABLE IF NOT EXISTS productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
precio DECIMAL(10,2) NOT NULL,
categoria_id INT,
FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);
-- Crear tabla de mesas
CREATE TABLE IF NOT EXISTS mesas (
id INT AUTO_INCREMENT PRIMARY KEY,
numero INT NOT NULL UNIQUE
);
-- Crear tabla de comandas con productos en JSON
CREATE TABLE IF NOT EXISTS comandas (
id INT AUTO_INCREMENT PRIMARY KEY,
mesa_id INT NOT NULL,
productos JSON NOT NULL, -- Array de productos con cantidad y precio
fecha DATETIME DEFAULT CURRENT_TIMESTAMP,
total DECIMAL(10,2),
FOREIGN KEY (mesa_id) REFERENCES mesas(id)
);
-- Insertar categoría 'Café' en la tabla categorias
INSERT INTO categorias (nombre) VALUES ('cafe');
-- Insertar mesa '1, 2 y 3' en la tabla mesas
INSERT INTO mesas (numero)
VALUES
(1),
(2),
(3);
-- Insertar cappuccino en la tabla productos, asociándolo con la categoría 'Café'
INSERT INTO productos (nombre, precio, categoria_id)
VALUES
('Cappuccino', 200.00, (SELECT id FROM categorias WHERE nombre = 'Café')),
('Latte', 200.00, (SELECT id FROM categorias WHERE nombre = 'Café')),
('Espresso', 120.00, (SELECT id FROM categorias WHERE nombre = 'Café'));
('Frappe', 290.00, (SELECT id FROM categorias WHERE nombre = 'Café'));
-- Insertar una comanda en la tabla comandas para la mesa 1
INSERT INTO comandas (mesa_id, productos, total)
VALUES
(
2, -- mesa_id
JSON_ARRAY(
JSON_OBJECT('producto_id', (SELECT id FROM productos WHERE nombre = 'Expresso'), 'cantidad', 2, 'precio_unitario', 111.00),
JSON_OBJECT('producto_id', (SELECT id FROM productos WHERE nombre = 'Latte'), 'cantidad', 1, 'precio_unitario', 666.00)
),
208457935.00 -- total (2 Cappuccinos * 200 + 1 Latte * 220)
),
(
3, -- mesa_id
JSON_ARRAY(
JSON_OBJECT('producto_id', (SELECT id FROM productos WHERE nombre = 'Cappuccino'), 'cantidad', 2, 'precio_unitario', 444.00),
JSON_OBJECT('producto_id', (SELECT id FROM productos WHERE nombre = 'Frappe'), 'cantidad', 4, 'precio_unitario', 222.00)
),
93826.00 -- total (2 Cappuccinos * 200 + 1 Latte * 220)
);

34
docker-compose.dev.yml Normal file
View File

@ -0,0 +1,34 @@
# docker-compose.dev.yml
services:
suitecoffee-app:
container_name: suitecoffee-app
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
ports:
- "${PORT}:${PORT}" # Usa la variable de entorno PORT
environment:
- NODE_ENV=development
- PORT=${PORT}
command: npm run dev # Usa nodemon para desarrollo
restart: unless-stopped
suitecoffee-db:
container_name: suitecoffee-db
image: mysql:latest
env_file:
- .env.${NODE_ENV}
environment:
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PASS
MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
MYSQL_DATABASE: $DB_NAME
volumes:
- ./db/dev-db:/var/lib/mysql
- ./db/init:/docker-entrypoint-initdb.d
ports:
- "$DB_LOCAL_PORT:$DB_DOCKER_PORT"
restart: unless-stopped

32
docker-compose.prod.yml Normal file
View File

@ -0,0 +1,32 @@
# docker-compose.prod.yml
services:
suitecoffee-app:
container_name: suitecoffee-app
build:
context: .
dockerfile: Dockerfile.prod
ports:
- "${PORT}:${PORT}" # Usa la variable de entorno PORT
environment:
- NODE_ENV=production
- PORT=${PORT}
command: npm start # Usa el comando de inicio en producción
restart: unless-stopped
suitecoffee-db:
container_name: suitecoffee-db
image: mysql:latest
env_file:
- .env.${NODE_ENV}
environment:
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PASS
MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
MYSQL_DATABASE: $DB_NAME
volumes:
- ./db/app-db/mysql_prod:/var/lib/mysql
- ./db/init:/docker-entrypoint-initdb.d
ports:
- "$DB_LOCAL_PORT:$DB_DOCKER_PORT"
restart: unless-stopped

250
index.js Normal file
View File

@ -0,0 +1,250 @@
// index.js
const express = require('express');
const path = require('path');
const dotenv = require('dotenv');
const mysql = require('mysql2/promise');
const cors = require('cors');
const app = express();
const port = process.env.PORT || 3000;
// Cargar las variables de entorno dependiendo del entorno
const envFile = process.env.NODE_ENV === 'production' ? '.env.production' : '.env.development';
dotenv.config({ path: envFile });
// Configuración de conexión MySQL
const dbConfig = {
host: process.env.DB_HOST || 'db',
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
port: process.env.DB_DOCKER_PORT || 3306
};
app.use(cors());
app.use(express.json());
// Servir archivos estáticos de la carpeta 'src'
app.use(express.static(path.join(__dirname, 'src')));
// --------------------------------------------------------------------------------------
// --------------------------------- RENDERIZADO --------------------------------------
// --------------------------------------------------------------------------------------
// Ruta principal
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'src', 'index.html'));
});
// Ruta para comandas
app.get('/comandas', (req, res) => {
res.sendFile(path.join(__dirname, 'src', 'pages', 'comandas.html'));
});
// Ruta para dashboard
app.get('/lectura', (req, res) => {
res.sendFile(path.join(__dirname, 'src', 'pages', 'lectura.html'));
});
// Ruta para dashboard
app.get('/carga', (req, res) => {
res.sendFile(path.join(__dirname, 'src', 'pages', 'carga.html'));
});
// Ruta para obtener las tablas de la base de datos
app.get('/tablas', async (req, res) => {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const [rows] = await connection.execute(
`SHOW TABLES FROM \`${dbConfig.database}\``
);
const tablas = rows.map(row => Object.values(row)[0]);
res.json({ tablas });
} catch (error) {
console.error('Error al conectar o consultar la base de datos:', error);
res.status(500).json({ error: 'Error interno al consultar la base de datos' });
} finally {
if (connection) {
await connection.end();
}
}
});
// --------------------------------------------------------------------------------------
// ----------------------------------- LECTURAS ---------------------------------------
// --------------------------------------------------------------------------------------
// Obtener mesas
app.get('/api/obtenerMesas', async (req, res) => {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const [results] = await connection.query('SELECT * FROM mesas');
res.json(results);
} catch (error) {
console.error('Error al obtener mesas:', error);
res.status(500).json({ error: 'Error al obtener mesas' });
} finally {
if (connection) await connection.end();
}
});
// Obtener productos
app.get('/api/obtenerProductos', async (req, res) => {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const [results] = await connection.query('SELECT * FROM productos');
res.json(results);
} catch (error) {
console.error('Error al obtener productos:', error);
res.status(500).json({ error: 'Error al obtener productos' });
} finally {
if (connection) await connection.end();
}
});
// Obtener categorías
app.get('/api/obtenerCategorias', async (req, res) => {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const [results] = await connection.query('SELECT * FROM categorias');
res.json(results);
} catch (error) {
console.error('Error al obtener categorías:', error);
res.status(500).json({ error: 'Error al obtener categorías' });
} finally {
if (connection) await connection.end();
}
});
// Obtener comandas
app.get('/api/obtenerComandas', async (req, res) => {
let connection;
try {
connection = await mysql.createConnection(dbConfig);
const [results] = await connection.execute('SELECT * FROM comandas');
res.json(results);
} catch (error) {
console.error('Error al obtener comandas:', error);
res.status(500).json({ error: 'Error al obtener comandas' });
} finally {
if (connection) await connection.end();
}
});
// --------------------------------------------------------------------------------------
// ------------------------------------ CARGAS ----------------------------------------
// --------------------------------------------------------------------------------------
// Cargar nueva mesa
app.post('/api/cargarMesas', async (req, res) => {
const { numero } = req.body;
if (!numero) return res.status(400).json({ error: 'Falta el número de mesa' });
let connection;
try {
connection = await mysql.createConnection(dbConfig);
await connection.execute('INSERT INTO mesas (numero) VALUES (?)', [numero]);
res.status(201).json({ mensaje: 'Mesa cargada correctamente' });
} catch (error) {
console.error('Error al cargar mesa:', error);
res.status(500).json({ error: 'Error al cargar mesa' });
} finally {
if (connection) await connection.end();
}
});
// Cargar nuevo producto
app.post('/api/cargarProductos', async (req, res) => {
const { nombre, precio, categoria_id } = req.body;
if (!nombre || !precio || !categoria_id) {
return res.status(400).json({ error: 'Faltan datos para cargar el producto' });
}
let connection;
try {
connection = await mysql.createConnection(dbConfig);
await connection.execute(
'INSERT INTO productos (nombre, precio, categoria_id) VALUES (?, ?, ?)',
[nombre, precio, categoria_id]
);
res.status(201).json({ mensaje: 'Producto cargado correctamente' });
} catch (error) {
console.error('Error al cargar producto:', error);
res.status(500).json({ error: 'Error al cargar producto' });
} finally {
if (connection) await connection.end();
}
});
// Cargar nueva categoría
app.post('/api/cargarCategorias', async (req, res) => {
const { nombre } = req.body;
if (!nombre) return res.status(400).json({ error: 'Falta el nombre de la categoría' });
let connection;
try {
connection = await mysql.createConnection(dbConfig);
await connection.execute('INSERT INTO categorias (nombre) VALUES (?)', [nombre]);
res.status(201).json({ mensaje: 'Categoría cargada correctamente' });
} catch (error) {
console.error('Error al cargar categoría:', error);
res.status(500).json({ error: 'Error al cargar categoría' });
} finally {
if (connection) await connection.end();
}
});
// Cargar nueva comanda
app.post('/api/cargarComandas', async (req, res) => {
const { mesa_id, productos, total } = req.body;
if (!mesa_id || !productos || !Array.isArray(productos) || total == null) {
return res.status(400).json({ error: 'Datos inválidos para cargar comanda' });
}
let connection;
try {
connection = await mysql.createConnection(dbConfig);
await connection.execute(
'INSERT INTO comandas (mesa_id, productos, total, fecha) VALUES (?, ?, ?, NOW())',
[mesa_id, JSON.stringify(productos), total]
);
res.status(201).json({ mensaje: 'Comanda cargada correctamente' });
} catch (error) {
console.error('Error al cargar comanda:', error);
res.status(500).json({ error: 'Error al cargar comanda' });
} finally {
if (connection) await connection.end();
}
});
// --------------------------------------------------------------------------------------
// --------------------------------- VERIFICACIONES -----------------------------------
// --------------------------------------------------------------------------------------
async function verificarConexion() {
try {
const connection = await mysql.createConnection(dbConfig);
const [rows] = await connection.execute('SELECT NOW() AS hora');
console.log('Conexión con la base de datos fue exitosa.');
console.log('Fecha y hora actual de la base de datos:', rows[0].hora);
await connection.end();
} catch (error) {
console.error('Error al conectar con la base de datos al iniciar:', error.message);
}
}
// Iniciar servidor
app.listen(port, () => {
console.log(`Servidor corriendo en http://localhost:${port}`);
console.log('Estableciendo conexión...');
verificarConexion();
});

1313
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

23
package.json Normal file
View File

@ -0,0 +1,23 @@
{
"name": "suitecoffee",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.5.0",
"express": "^5.1.0",
"mysql2": "^3.14.0"
},
"devDependencies": {
"nodemon": "^3.1.9"
}
}

40
src/index.html Normal file
View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Login Bootstrap</title>
<!-- Bootstrap CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-light d-flex justify-content-center align-items-center vh-100">
<div class="card shadow p-4" style="width: 100%; max-width: 350px;">
<h4 class="text-center mb-4">Iniciar Sesión</h4>
<form>
<div class="mb-3">
<label for="usuario" class="form-label">Usuario</label>
<input type="text" class="form-control" id="usuario" placeholder="Ingrese su usuario" required>
</div>
<div class="mb-3">
<label for="clave" class="form-label">Contraseña</label>
<input type="password" class="form-control" id="clave" placeholder="Ingrese su contraseña" required>
</div>
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="recordarme">
<label class="form-check-label" for="recordarme">
Recordarme
</label>
</div>
<a href="#" class="small">¿Olvidaste tu contraseña?</a>
</div>
<button type="submit" class="btn btn-primary w-100">Entrar</button>
</form>
</div>
<!-- Bootstrap JS (opcional) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

116
src/pages/carga.html Normal file
View File

@ -0,0 +1,116 @@
<!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>

100
src/pages/comandas.html Normal file
View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Comanda - Cafetería</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<div class="container my-4">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">🧾 Comanda de Cafetería</h4>
</div>
<div class="card-body">
<form>
<!-- Datos generales -->
<div class="row g-3 mb-4">
<div class="col-12 col-md-6">
<label for="mesa" class="form-label">Número de Mesa</label>
<select class="form-select" id="mesa" required>
<option value="">Seleccionar mesa</option>
<option>Mesa 1</option>
<option>Mesa 2</option>
<option>Mesa 3</option>
<option>Mesa 4</option>
<option>Mesa 5</option>
</select>
</div>
<div class="col-12 col-md-6">
<label for="mozo" class="form-label">Mozo/a</label>
<input type="text" class="form-control" id="mozo" placeholder="Nombre del mozo/a" required>
</div>
</div>
<!-- Productos -->
<div class="mb-4">
<label class="form-label">Productos</label>
<!-- Producto 1 -->
<div class="row g-2 mb-2">
<div class="col-12 col-md-6">
<select class="form-select">
<option value="">Seleccionar producto</option>
<option>Café</option>
<option>Café con leche</option>
<option>Capuccino</option>
<option>Medialuna</option>
<option>Jugo natural</option>
<option>Tostado</option>
</select>
</div>
<div class="col-6 col-md-3">
<input type="number" class="form-control" placeholder="Cant.">
</div>
<div class="col-6 col-md-3">
<input type="text" class="form-control" placeholder="Notas">
</div>
</div>
<!-- Producto 2 -->
<div class="row g-2 mb-2">
<div class="col-12 col-md-6">
<select class="form-select">
<option value="">Seleccionar producto</option>
<option>Café</option>
<option>Café con leche</option>
<option>Capuccino</option>
<option>Medialuna</option>
<option>Jugo natural</option>
<option>Tostado</option>
</select>
</div>
<div class="col-6 col-md-3">
<input type="number" class="form-control" placeholder="Cant.">
</div>
<div class="col-6 col-md-3">
<input type="text" class="form-control" placeholder="Notas">
</div>
</div>
</div>
<!-- Observaciones -->
<div class="mb-4">
<label for="observaciones" class="form-label">Observaciones</label>
<textarea class="form-control" id="observaciones" rows="3" placeholder="Ej: Sin azúcar, entregar cuando esté completo"></textarea>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-success">Enviar Comanda</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

43
src/pages/lectura.html Normal file
View File

@ -0,0 +1,43 @@
<!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>

0
suitecoffee.py Normal file
View File