Instantly share code, notes, and snippets.
Created
November 3, 2025 19:17
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save iDavidMorales/436c7c814e1060c00638fb460c7ace87 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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">×</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