Skip to content

Instantly share code, notes, and snippets.

@iDavidMorales
Created November 3, 2025 19:17
Show Gist options
  • Select an option

  • Save iDavidMorales/436c7c814e1060c00638fb460c7ace87 to your computer and use it in GitHub Desktop.

Select an option

Save iDavidMorales/436c7c814e1060c00638fb460c7ace87 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Menú de Pedidos</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
:root {
--primary-color: #058f4a; /* Shopify Green */
--secondary-color: #f6f6f6;
--text-color: #262626;
--subtle-text: #6b6b6b;
--background-color: #f7f7f7;
--card-bg-color: #ffffff;
--border-color: #e8e8e8;
}
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--text-color);
}
.main-container {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
padding: 20px;
max-width: 1200px;
margin: auto;
}
h1 {
font-size: 2.2em;
font-weight: 700;
text-align: center;
color: var(--text-color);
margin-bottom: 25px;
}
h2 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-color);
margin-top: 30px;
margin-bottom: 15px;
}
.menu-section {
margin-bottom: 25px;
}
.item-card {
background-color: var(--card-bg-color);
border-radius: 12px;
padding: 15px;
margin-bottom: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
gap: 10px;
}
.item-card-top {
display: flex;
justify-content: space-between;
align-items: center;
}
.item-info {
flex-grow: 1;
}
.item-name {
font-weight: 600;
font-size: 1.1em;
margin: 0;
}
.item-description {
color: var(--subtle-text);
font-size: 0.9em;
margin-top: 5px;
}
.item-price {
font-weight: 600;
font-size: 1.1em;
color: var(--primary-color);
margin-left: 10px;
}
/* Cantidad en el menú */
.item-actions {
display: flex;
align-items: center;
gap: 10px;
}
.quantity-control {
display: flex;
align-items: center;
gap: 5px;
}
.quantity-btn {
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 50%;
width: 35px;
height: 35px;
font-size: 1.1em;
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
cursor: pointer;
transition: background-color 0.3s;
}
.quantity-btn:hover {
background-color: #046e3a;
}
.item-quantity-display {
font-weight: 600;
min-width: 15px;
text-align: center;
}
.add-to-cart {
padding: 10px 24px;
cursor: pointer;
background-color: var(--primary-color);
color: white;
border: none;
border-radius: 25px;
font-weight: bold;
transition: background-color 0.3s;
}
.add-to-cart:hover {
background-color: #046e3a;
}
.add-to-cart:disabled {
background-color: #c0c0c0;
cursor: not-allowed;
}
.item-options {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.item-options select {
flex: 1;
padding: 10px;
border-radius: 8px;
border: 1px solid var(--border-color);
}
/* Modal y Botón Flotante */
.cart-icon-container {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1001;
display: flex;
justify-content: center;
align-items: center;
}
.cart-icon {
position: relative;
background-color: #262626;
color: white;
border: none;
border-radius: 50%;
width: 60px;
height: 60px;
font-size: 1.5em;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.3s;
}
.cart-icon:hover {
transform: scale(1.1);
}
.cart-count {
position: absolute;
top: -5px;
right: -5px;
background-color: #e53935;
color: white;
font-size: 0.8em;
font-weight: bold;
border-radius: 50%;
width: 25px;
height: 25px;
display: flex;
justify-content: center;
align-items: center;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.modal-overlay.open {
display: flex;
opacity: 1;
}
.modal-content {
background-color: var(--card-bg-color);
padding: 25px;
border-radius: 12px;
width: 90%;
max-width: 500px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
position: relative;
transform: translateY(-50px);
transition: transform 0.3s ease-in-out;
}
.modal-overlay.open .modal-content {
transform: translateY(0);
}
.close-btn {
position: absolute;
top: 15px;
right: 15px;
background: transparent;
border: none;
font-size: 1.5em;
cursor: pointer;
color: var(--text-color);
transition: transform 0.2s;
}
.close-btn:hover {
transform: scale(1.2);
}
#cart-items {
list-style: none;
padding: 0;
}
.cart-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px dotted var(--border-color);
}
.cart-item-info {
flex: 1;
}
.cart-item-name {
font-weight: 600;
}
.cart-item-price {
font-size: 0.9em;
color: var(--subtle-text);
}
.cart-quantity-control {
display: flex;
align-items: center;
gap: 10px;
}
.cart-quantity-btn {
background-color: var(--secondary-color);
border: 1px solid var(--border-color);
color: var(--text-color);
border-radius: 50%;
width: 30px;
height: 30px;
font-size: 1.1em;
font-weight: bold;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
}
.cart-quantity-btn:hover {
background-color: #e9ecef;
}
.cart-quantity-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
#cart-total {
font-size: 1.3em;
font-weight: bold;
margin-top: 15px;
text-align: right;
color: var(--text-color);
}
.optional-info {
margin-top: 20px;
}
.optional-info input, .optional-info textarea {
width: 100%;
padding: 12px;
margin-bottom: 10px;
border-radius: 8px;
border: 1px solid #ced4da;
box-sizing: border-box;
background-color: var(--secondary-color);
}
.optional-info input::placeholder, .optional-info textarea::placeholder {
color: #b0b0b0;
}
.optional-info textarea {
resize: vertical;
}
#send-whatsapp {
display: block;
width: 80%;
padding: 10px;
background-color: #25D366;
color: white;
text-align: center;
text-decoration: none;
border-radius: 50px;
margin-top: 20px;
font-size: 1em;
font-weight: bold;
transition: background-color 0.3s;
margin-left: auto;
margin-right: auto;
}
#send-whatsapp:hover {
background-color: #1DA851;
}
/* Estilos de SweetAlert */
.swal2-popup {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
border-radius: 12px !important;
}
.swal2-title {
color: var(--text-color) !important;
font-size: 1.5rem !important;
font-weight: 600 !important;
}
.swal2-html-container {
color: var(--subtle-text) !important;
font-size: 1rem !important;
}
.swal2-confirm.swal2-styled {
background-color: var(--primary-color) !important;
border-radius: 25px !important;
padding: 10px 20px !important;
box-shadow: none !important;
}
</style>
</head>
<body>
<div class="main-container">
<div class="menu-column">
<h1>Menú del Día</h1>
<center>
<div class="col-8 col-md-4">
<img src="https://i.imgur.com/lwdDsE5.png" class="img-fluid" alt="Imagen Responsiva" style="width:80%;">
</div>
</center>
<div id="menu-content"></div>
</div>
</div>
<!-- Modal para el Carrito -->
<div class="modal-overlay" id="cart-modal">
<div class="modal-content">
<button class="close-btn" id="close-cart-btn">&times;</button>
<h2>Tu Pedido</h2>
<ul id="cart-items"></ul>
<p id="cart-total">Total: $0</p>
<div class="optional-info">
<input type="text" id="nombre" placeholder="Nombre (Opcional)">
<input type="tel" id="telefono" placeholder="Teléfono (Opcional)">
<input type="email" id="correo" placeholder="Correo (Opcional)">
<textarea id="notas" placeholder="Notas o instrucciones especiales..."></textarea>
</div>
<a id="send-whatsapp" href="#" target="_blank">Enviar Pedido por WhatsApp</a>
</div>
</div>
<!-- Botón flotante para abrir el carrito -->
<div class="cart-icon-container">
<button class="cart-icon" id="open-cart-btn">
<i class="fas fa-shopping-cart"></i>
<span class="cart-count" id="item-count">0</span>
</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const menuContent = document.getElementById('menu-content');
const cartItems = document.getElementById('cart-items');
const cartTotal = document.getElementById('cart-total');
const sendWhatsappBtn = document.getElementById('send-whatsapp');
const nombreInput = document.getElementById('nombre');
const telefonoInput = document.getElementById('telefono');
const correoInput = document.getElementById('correo');
const notasInput = document.getElementById('notas');
const openCartBtn = document.getElementById('open-cart-btn');
const closeCartBtn = document.getElementById('close-cart-btn');
const cartModal = document.getElementById('cart-modal');
const itemCountDisplay = document.getElementById('item-count');
let cart = [];
let pizzaPrices = {};
const productElements = {};
// Manejo de eventos para el modal del carrito
openCartBtn.addEventListener('click', () => {
cartModal.classList.add('open');
});
closeCartBtn.addEventListener('click', () => {
cartModal.classList.remove('open');
});
cartModal.addEventListener('click', (e) => {
if (e.target.classList.contains('modal-overlay')) {
cartModal.classList.remove('open');
}
});
// Carga y renderización del menú
fetch('menu_completo.php')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Cargar precios de pizzas
data.pizzas.items.forEach(pizza => {
pizzaPrices.hasOwnProperty(pizza.nombre) ? pizzaPrices : pizzaPrices = {...pizzaPrices, [pizza.nombre]: pizza.precio};
});
// Asegurar que el precio de los "Huevos" sea 100
const desayunos = data.desayunos.items;
desayunos.forEach(item => {
if (item.nombre.toLowerCase().includes("huevos")) {
item.precio = 100;
}
});
renderMenu(data);
})
.catch(error => {
console.error('Error al cargar el menú:', error);
Swal.fire({
icon: 'error',
title: 'Error de conexión',
text: 'No se pudo cargar el menú. Por favor, inténtalo de nuevo más tarde.',
confirmButtonText: 'Aceptar'
});
});
function renderMenu(menuData) {
for (const sectionKey in menuData) {
const section = menuData[sectionKey];
if (section.items) {
const sectionDiv = document.createElement('div');
sectionDiv.className = 'menu-section';
const sectionTitle = document.createElement('h2');
sectionTitle.innerHTML = section.titulo;
sectionDiv.appendChild(sectionTitle);
if (section.descripcion) {
const sectionDesc = document.createElement('p');
sectionDesc.textContent = section.descripcion;
sectionDiv.appendChild(sectionDesc);
}
// Solo pizzas tienen el selector de tamaño
if (sectionKey === 'tipos_pizza') {
section.items.forEach(item => {
const itemCard = document.createElement('div');
itemCard.className = 'item-card';
itemCard.dataset.name = item.nombre;
productElements[item.nombre] = itemCard;
const itemCardTop = document.createElement('div');
itemCardTop.className = 'item-card-top';
const itemInfoDiv = document.createElement('div');
itemInfoDiv.className = 'item-info';
const itemNameSpan = document.createElement('h3');
itemNameSpan.className = 'item-name';
itemNameSpan.textContent = item.nombre;
itemInfoDiv.appendChild(itemNameSpan);
const itemDescDiv = document.createElement('div');
itemDescDiv.className = 'item-description';
itemDescDiv.textContent = item.ingredientes || '';
itemInfoDiv.appendChild(itemDescDiv);
const defaultSize = Object.keys(pizzaPrices)[0] || '';
const defaultPrice = pizzaPrices[defaultSize] || 0;
const itemPriceSpan = document.createElement('div');
itemPriceSpan.className = 'item-price';
itemPriceSpan.textContent = `$${defaultPrice.toFixed(2)}`;
itemInfoDiv.appendChild(itemPriceSpan);
itemCardTop.appendChild(itemInfoDiv);
itemCard.appendChild(itemCardTop);
const optionsDiv = document.createElement('div');
optionsDiv.className = 'item-options';
const selectElement = document.createElement('select');
selectElement.innerHTML = '<option value="">Selecciona el tamaño</option>';
const pizzaSizes = Object.keys(pizzaPrices);
pizzaSizes.forEach(size => {
const option = document.createElement('option');
option.value = size;
option.textContent = `${size} - $${pizzaPrices[size].toFixed(2)}`;
selectElement.appendChild(option);
});
selectElement.value = defaultSize;
optionsDiv.appendChild(selectElement);
const addButton = document.createElement('button');
addButton.className = 'add-to-cart';
addButton.textContent = 'Agregar';
addButton.dataset.name = `${defaultSize} de ${item.nombre}`;
addButton.dataset.price = defaultPrice;
optionsDiv.appendChild(addButton);
itemCard.appendChild(optionsDiv);
sectionDiv.appendChild(itemCard);
selectElement.addEventListener('change', (e) => {
const selectedSize = e.target.value;
if (selectedSize) {
const price = pizzaPrices[selectedSize] || 0;
itemPriceSpan.textContent = `$${price.toFixed(2)}`;
addButton.dataset.name = `${selectedSize} de ${item.nombre}`;
addButton.dataset.price = price;
addButton.disabled = false;
} else {
itemPriceSpan.textContent = `$0.00`;
addButton.dataset.name = '';
addButton.dataset.price = 0;
addButton.disabled = true;
}
});
addButton.addEventListener('click', (e) => {
const name = e.target.dataset.name;
const price = parseFloat(e.target.dataset.price);
if(name && price > 0) {
addToCart(name, price);
}
});
});
} else {
// Este es el código para el resto de los elementos (incluyendo Huevos)
section.items.forEach(item => {
const itemCard = document.createElement('div');
itemCard.className = 'item-card';
itemCard.dataset.name = item.nombre;
productElements[item.nombre] = itemCard;
const itemCardTop = document.createElement('div');
itemCardTop.className = 'item-card-top';
const itemInfoDiv = document.createElement('div');
itemInfoDiv.className = 'item-info';
const itemNameSpan = document.createElement('h3');
itemNameSpan.className = 'item-name';
itemNameSpan.textContent = item.nombre;
itemInfoDiv.appendChild(itemNameSpan);
if (item.ingredientes) {
const itemDescDiv = document.createElement('div');
itemDescDiv.className = 'item-description';
itemDescDiv.textContent = item.ingredientes;
itemInfoDiv.appendChild(itemDescDiv);
}
const itemPriceSpan = document.createElement('div');
itemPriceSpan.className = 'item-price';
itemPriceSpan.textContent = `$${(item.precio || 0).toFixed(2)}`;
itemInfoDiv.appendChild(itemPriceSpan);
itemCardTop.appendChild(itemInfoDiv);
const actionsDiv = document.createElement('div');
actionsDiv.className = 'item-actions';
const addButton = document.createElement('button');
addButton.className = 'add-to-cart';
addButton.textContent = 'Agregar';
addButton.dataset.name = item.nombre;
addButton.dataset.price = item.precio || 0;
actionsDiv.appendChild(addButton);
itemCardTop.appendChild(actionsDiv);
itemCard.appendChild(itemCardTop);
addButton.addEventListener('click', (e) => {
const name = e.target.dataset.name;
const price = parseFloat(e.target.dataset.price);
if(name && price > 0) {
addToCart(name, price);
}
});
sectionDiv.appendChild(itemCard);
});
}
menuContent.appendChild(sectionDiv);
}
}
}
function addToCart(name, price) {
const existingItem = cart.find(item => item.name === name);
if (existingItem) {
existingItem.quantity++;
} else {
cart.push({ name, price, quantity: 1 });
}
updateCart();
Swal.fire({
toast: true,
position: 'bottom-end',
showConfirmButton: false,
timer: 2000,
timerProgressBar: true,
icon: 'success',
title: `¡${name} añadido!`,
});
}
function updateCart() {
cartItems.innerHTML = '';
let total = 0;
let orderItems = [];
let totalQuantity = 0;
cart.forEach((item, index) => {
const li = document.createElement('li');
li.className = 'cart-item';
li.innerHTML = `
<div class="cart-item-info">
<span class="cart-item-name">${item.name}</span>
<div class="cart-item-price">$${item.price.toFixed(2)} c/u</div>
</div>
<div class="cart-quantity-control">
<button class="cart-quantity-btn" data-action="decrease" data-index="${index}">-</button>
<span class="item-quantity">${item.quantity}</span>
<button class="cart-quantity-btn" data-action="increase" data-index="${index}">+</button>
</div>
`;
cartItems.appendChild(li);
total += item.price * item.quantity;
totalQuantity += item.quantity;
orderItems.push(`${item.quantity} ${item.name} - $${(item.price * item.quantity).toFixed(2)}`);
});
itemCountDisplay.textContent = totalQuantity;
cartTotal.textContent = `Total: $${total.toFixed(2)}`;
document.querySelectorAll('.cart-quantity-btn').forEach(button => {
button.addEventListener('click', (e) => {
const action = e.target.dataset.action;
const index = parseInt(e.target.dataset.index);
if (action === 'increase') {
cart[index].quantity++;
} else if (action === 'decrease') {
cart[index].quantity--;
if (cart[index].quantity <= 0) {
cart.splice(index, 1);
}
}
updateCart();
});
});
let message = `¡Hola! Me gustaría hacer un pedido:\n\n${orderItems.join('\n')}\n\nTotal: $${total.toFixed(2)}`;
const nombre = nombreInput.value.trim();
const telefono = telefonoInput.value.trim();
const correo = correoInput.value.trim();
const notas = notasInput.value.trim();
if (nombre) {
message += `\n\nNombre: ${nombre}`;
}
if (telefono) {
message += `\nTeléfono: ${telefono}`;
}
if (correo) {
message += `\nCorreo: ${correo}`;
}
if (notas) {
message += `\n\nNotas: ${notas}`;
}
message += `\n\nPor favor, confírmenme el pedido.`;
const whatsappLink = `https://wa.me/529841400774?text=${encodeURIComponent(message)}`;
sendWhatsappBtn.href = whatsappLink;
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment